]> git.proxmox.com Git - mirror_lxc.git/commitdiff
start: remove utmp watch
authorChristian Brauner <christian.brauner@ubuntu.com>
Mon, 31 Jul 2017 21:04:54 +0000 (23:04 +0200)
committerChristian Brauner <christian.brauner@ubuntu.com>
Tue, 1 Aug 2017 16:45:50 +0000 (18:45 +0200)
Closes #1616.

Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
src/lxc/Makefile.am
src/lxc/conf.h
src/lxc/lxcutmp.c [deleted file]
src/lxc/lxcutmp.h [deleted file]
src/lxc/start.c

index a55103ec5b61b713db808de0c14f916d4c84c33a..1937278b42d65564180de86fa3df779d13dbb49e 100644 (file)
@@ -127,7 +127,6 @@ liblxc_la_SOURCES = \
        mainloop.c mainloop.h \
        af_unix.c af_unix.h \
        \
-       lxcutmp.c lxcutmp.h \
        lxclock.h lxclock.c \
        lxccontainer.c lxccontainer.h \
        version.h \
index 8150c3744972ac00122e593c89b66139b59939c3..4d3f6d78ff65c2df9784d7679e7ec21718ecdde7 100644 (file)
@@ -317,7 +317,6 @@ struct lxc_conf {
        unsigned int tty;
        unsigned int pts;
        int reboot;
-       int need_utmp_watch;
        signed long personality;
        struct utsname *utsname;
        struct lxc_list cgroup;
diff --git a/src/lxc/lxcutmp.c b/src/lxc/lxcutmp.c
deleted file mode 100644 (file)
index ba65654..0000000
+++ /dev/null
@@ -1,489 +0,0 @@
-/*
- * lxc: linux Container library
- *
- * (C) Copyright IBM Corp. 2007, 2008
- *
- * Authors:
- * Daniel Lezcano <daniel.lezcano at free.fr>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "config.h"
-
-#include <stdio.h>
-#include <unistd.h>
-#include <errno.h>
-#include <signal.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <sys/inotify.h>
-#include <sys/ioctl.h>
-#ifdef HAVE_SYS_TIMERFD_H
-#include <sys/timerfd.h>
-#else
-#include <sys/syscall.h>
-#ifndef TFD_NONBLOCK
-#define TFD_NONBLOCK O_NONBLOCK
-#endif
-
-#ifndef TFD_CLOEXEC
-#define TFD_CLOEXEC O_CLOEXEC
-#endif
-static int timerfd_create (clockid_t __clock_id, int __flags) {
-       return syscall(__NR_timerfd_create, __clock_id, __flags);
-}
-
-static int timerfd_settime (int __ufd, int __flags,
-                           const struct itimerspec *__utmr,
-                           struct itimerspec *__otmr) {
-
-       return syscall(__NR_timerfd_settime, __ufd, __flags,
-                           __utmr, __otmr);
-}
-
-#endif
-
-#include "conf.h"
-#include "cgroup.h"
-#include "start.h"
-#include "mainloop.h"
-#include "lxc.h"
-#include "log.h"
-
-#ifndef __USE_GNU
-#define __USE_GNU
-#endif
-#ifdef HAVE_UTMPX_H
-#include <utmpx.h>
-#ifndef HAVE_UTMPXNAME
-#include <utmp.h>
-#endif
-
-#else
-#include <utmp.h>
-
-#ifndef RUN_LVL
-#define RUN_LVL 1
-#endif
-
-static void setutxent(void) {
-       return setutent();
-}
-
-static struct utmp * getutxent (void) {
-       return (struct utmp *) getutent();
-}
-
-static void endutxent (void) {
-#ifdef IS_BIONIC
-       /* bionic isn't exporting endutend */
-       return;
-#else
-       return endutent();
-#endif
-}
-#endif
-
-#ifndef HAVE_UTMPXNAME
-static int utmpxname(const char *file) {
-       int result;
-       result = utmpname(file);
-
-#ifdef IS_BIONIC
-       /* Yeah bionic is that weird */
-       result = result - 1;
-#endif
-
-       return result;
-}
-#endif
-
-#undef __USE_GNU
-
-/* This file watches the /var/run/utmp file in the container
- * (that should probably be configurable)
- * We use inotify to put a watch on the /var/run directory for
- * create and modify events. These can trigger a read of the
- * utmp file looking for runlevel changes. If a runlevel change
- * to reboot or halt states is detected, we set up an itimer to
- * regularly check for the container shutdown, and reboot or halt
- * as appropriate when we get down to 1 task remaining.
- */
-
-lxc_log_define(lxc_utmp, lxc);
-
-struct lxc_utmp {
-       struct lxc_handler *handler;
-#define CONTAINER_STARTING  0
-#define CONTAINER_REBOOTING 1
-#define CONTAINER_HALTING   2
-#define CONTAINER_RUNNING   4
-       char container_state;
-       int timer_fd;
-       int prev_runlevel, curr_runlevel;
-};
-
-typedef void (*lxc_mainloop_timer_t) (void *data);
-
-static int utmp_get_runlevel(struct lxc_utmp *utmp_data);
-static int utmp_get_ntasks(struct lxc_handler *handler);
-static int utmp_shutdown_handler(int fd, uint32_t events, void *data,
-                                struct lxc_epoll_descr *descr);
-static int lxc_utmp_add_timer(struct lxc_epoll_descr *descr,
-                             lxc_mainloop_callback_t callback, void *data);
-static int lxc_utmp_del_timer(struct lxc_epoll_descr *descr,
-                             struct lxc_utmp *utmp_data);
-
-static int utmp_handler(int fd, uint32_t events, void *data,
-                       struct lxc_epoll_descr *descr)
-{
-       struct inotify_event *ie;
-       int size, ret, length;
-
-       struct lxc_utmp *utmp_data = (struct lxc_utmp *)data;
-
-       /*
-        * we're monitoring a directory. ie->name is not included in
-        * sizeof(struct inotify_event) if we don't read it all at once,
-        * read gives us EINVAL, so we read and cast to struct ie
-        */
-       char buffer[MAXPATHLEN];
-
-       if (ioctl(fd, FIONREAD, &size) < 0) {
-               SYSERROR("cannot determine the size of this notification");
-               return -1;
-       }
-
-       if (read(fd, buffer, size) < size) {
-               SYSERROR("failed to read notification");
-               return -1;
-       }
-
-       ie = (struct inotify_event *)buffer;
-
-       if (ie->len <= 0) {
-
-               if (ie->mask & IN_UNMOUNT) {
-                       DEBUG("watched directory removed");
-                       goto out;
-               }
-
-               SYSERROR("inotify event with no name (mask %d)", ie->mask);
-               return -1;
-       }
-
-       ret = 0;
-
-       DEBUG("got inotify event %d for %s", ie->mask, ie->name);
-
-       length = (4 < ie->len) ? 4 : ie->len;
-
-       /* only care about utmp */
-
-       if (strncmp(ie->name, "utmp", length))
-               return 0;
-
-       if (ie->mask & (IN_MODIFY | IN_CREATE))
-               ret = utmp_get_runlevel(utmp_data);
-
-       if (ret < 0)
-               goto out;
-
-       /* container halting, from running or starting state */
-       if (utmp_data->curr_runlevel == '0'
-           && ((utmp_data->container_state == CONTAINER_RUNNING)
-               || (utmp_data->container_state == CONTAINER_STARTING))) {
-               utmp_data->container_state = CONTAINER_HALTING;
-               if (utmp_data->timer_fd == -1)
-                       lxc_utmp_add_timer(descr, utmp_shutdown_handler, data);
-               DEBUG("Container halting");
-               goto out;
-       }
-
-       /* container rebooting, from running or starting state */
-       if (utmp_data->curr_runlevel == '6'
-           && ((utmp_data->container_state == CONTAINER_RUNNING)
-               || (utmp_data->container_state == CONTAINER_STARTING))) {
-               utmp_data->container_state = CONTAINER_REBOOTING;
-               if (utmp_data->timer_fd == -1)
-                       lxc_utmp_add_timer(descr, utmp_shutdown_handler, data);
-               DEBUG("Container rebooting");
-               goto out;
-       }
-
-       /* normal operation, running, from starting state. */
-       if (utmp_data->curr_runlevel > '0' && utmp_data->curr_runlevel < '6') {
-               utmp_data->container_state = CONTAINER_RUNNING;
-               if (utmp_data->timer_fd > 0)
-                       lxc_utmp_del_timer(descr, utmp_data);
-               DEBUG("Container running");
-               goto out;
-       }
-
-out:
-       return 0;
-}
-
-static int utmp_get_runlevel(struct lxc_utmp *utmp_data)
-{
-       #if HAVE_UTMPX_H
-       struct utmpx *utmpx;
-       #else
-       struct utmp *utmpx;
-       #endif
-       char path[MAXPATHLEN];
-       struct lxc_handler *handler = utmp_data->handler;
-
-       if (snprintf(path, MAXPATHLEN, "/proc/%d/root/run/utmp",
-                    handler->pid) > MAXPATHLEN) {
-               ERROR("path is too long");
-               return -1;
-       }
-
-       if (!access(path, F_OK) && !utmpxname(path))
-               goto utmp_ok;
-
-       if (snprintf(path, MAXPATHLEN, "/proc/%d/root/var/run/utmp",
-                    handler->pid) > MAXPATHLEN) {
-               ERROR("path is too long");
-               return -1;
-       }
-
-       if (utmpxname(path)) {
-               SYSERROR("failed to 'utmpxname'");
-               return -1;
-       }
-
-utmp_ok:
-
-       setutxent();
-
-       while ((utmpx = getutxent())) {
-
-               if (utmpx->ut_type == RUN_LVL) {
-                       utmp_data->prev_runlevel = utmpx->ut_pid / 256;
-                       utmp_data->curr_runlevel = utmpx->ut_pid % 256;
-                       DEBUG("utmp handler - run level is %c/%c",
-                             utmp_data->prev_runlevel,
-                             utmp_data->curr_runlevel);
-               }
-       }
-
-       endutxent();
-
-       return 0;
-}
-
-static int utmp_get_ntasks(struct lxc_handler *handler)
-{
-       int ntasks;
-
-       ntasks = cgroup_nrtasks(handler);
-
-       if (ntasks < 0) {
-               ERROR("failed to get the number of tasks");
-               return -1;
-       }
-
-       DEBUG("there are %d tasks running", ntasks);
-
-       return ntasks;
-}
-
-int lxc_utmp_mainloop_add(struct lxc_epoll_descr *descr,
-                         struct lxc_handler *handler)
-{
-       char path[MAXPATHLEN];
-       char path2[MAXPATHLEN];
-       int fd, wd;
-       struct lxc_utmp *utmp_data;
-
-       /* We set up a watch for the /var/run directory. We're only interested
-        * in utmp at the moment, but want to watch for delete and create
-        * events as well.
-        */
-       if (snprintf(path, MAXPATHLEN, "/proc/%d/root/run",
-                    handler->pid) > MAXPATHLEN) {
-               ERROR("path is too long");
-               return -1;
-       }
-       if (snprintf(path2, MAXPATHLEN, "/proc/%d/root/run/utmp",
-                    handler->pid) > MAXPATHLEN) {
-               ERROR("path is too long");
-               return -1;
-       }
-       if (!access(path2, F_OK))
-               goto run_ok;
-
-       if (snprintf(path, MAXPATHLEN, "/proc/%d/root/var/run",
-                    handler->pid) > MAXPATHLEN) {
-               ERROR("path is too long");
-               return -1;
-       }
-
-       if (access(path, F_OK)) {
-               WARN("'%s' not found", path);
-               return 0;
-       }
-
-run_ok:
-
-       utmp_data = (struct lxc_utmp *)malloc(sizeof(struct lxc_utmp));
-
-       if (NULL == utmp_data) {
-               SYSERROR("failed to malloc handler utmp_data");
-               return -1;
-       }
-
-       memset(utmp_data, 0, sizeof(struct lxc_utmp));
-
-       fd = inotify_init();
-       if (fd < 0) {
-               SYSERROR("failed to inotify_init");
-               goto out;
-       }
-
-       if (fcntl(fd, F_SETFD, FD_CLOEXEC)) {
-               SYSERROR("failed to set inotify fd to close-on-exec");
-               goto out_close;
-
-       }
-
-       wd = inotify_add_watch(fd, path, IN_MODIFY | IN_CREATE);
-       if (wd < 0) {
-               SYSERROR("failed to add watch for '%s'", path);
-               goto out_close;
-       }
-
-       utmp_data->handler = handler;
-       utmp_data->container_state = CONTAINER_STARTING;
-       utmp_data->timer_fd = -1;
-       utmp_data->prev_runlevel = 'N';
-       utmp_data->curr_runlevel = 'N';
-
-       if (lxc_mainloop_add_handler
-           (descr, fd, utmp_handler, (void *)utmp_data)) {
-               SYSERROR("failed to add mainloop");
-               goto out_close;
-       }
-
-       DEBUG("Added '%s' to inotifywatch", path);
-
-       return 0;
-out_close:
-       close(fd);
-out:
-       free(utmp_data);
-       return -1;
-}
-
-static int utmp_shutdown_handler(int fd, uint32_t events, void *data,
-                                struct lxc_epoll_descr *descr)
-{
-       int ntasks;
-       ssize_t nread;
-       struct lxc_utmp *utmp_data = (struct lxc_utmp *)data;
-       struct lxc_handler *handler = utmp_data->handler;
-       struct lxc_conf *conf = handler->conf;
-       uint64_t expirations;
-
-       /* read and clear notifications */
-       nread = read(fd, &expirations, sizeof(expirations));
-       if (nread < 0)
-               SYSERROR("Failed to read timer notification");
-
-       ntasks = utmp_get_ntasks(handler);
-
-       if (ntasks == 1 && (utmp_data->container_state == CONTAINER_HALTING)) {
-               INFO("container has shutdown");
-               /* shutdown timer */
-               lxc_utmp_del_timer(descr, utmp_data);
-
-               kill(handler->pid, SIGKILL);
-       }
-
-       if (ntasks == 1 && (utmp_data->container_state == CONTAINER_REBOOTING)) {
-               INFO("container has rebooted");
-               conf->reboot = 1;
-               /* shutdown timer */
-               lxc_utmp_del_timer(descr, utmp_data);
-               /* this seems a bit rough. */
-               kill(handler->pid, SIGKILL);
-       }
-       return 0;
-
-}
-
-int lxc_utmp_add_timer(struct lxc_epoll_descr *descr,
-                      lxc_mainloop_callback_t callback, void *data)
-{
-       int fd, result;
-       struct itimerspec timeout;
-       struct lxc_utmp *utmp_data = (struct lxc_utmp *)data;
-
-       fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
-       if (fd < 0) {
-               SYSERROR("failed to create timer");
-               return -1;
-       }
-
-       DEBUG("Setting up utmp shutdown timer");
-
-       /* set a one second timeout. Repeated. */
-       timeout.it_value.tv_sec = 1;
-       timeout.it_value.tv_nsec = 0;
-
-       timeout.it_interval.tv_sec = 1;
-       timeout.it_interval.tv_nsec = 0;
-
-       result = timerfd_settime(fd, 0, &timeout, NULL);
-
-       if (result < 0) {
-               SYSERROR("timerfd_settime:");
-               return -1;
-       }
-
-       if (lxc_mainloop_add_handler(descr, fd, callback, utmp_data)) {
-               SYSERROR("failed to add utmp timer to mainloop");
-               close(fd);
-               return -1;
-       }
-
-       utmp_data->timer_fd = fd;
-
-       return 0;
-}
-
-int lxc_utmp_del_timer(struct lxc_epoll_descr *descr,
-                      struct lxc_utmp *utmp_data)
-{
-       int result;
-
-       DEBUG("Clearing utmp shutdown timer");
-
-       result = lxc_mainloop_del_handler(descr, utmp_data->timer_fd);
-       if (result < 0)
-               SYSERROR("failed to del utmp timer from mainloop");
-
-       /* shutdown timer_fd */
-       close(utmp_data->timer_fd);
-       utmp_data->timer_fd = -1;
-
-       if (result < 0)
-               return -1;
-       else
-               return 0;
-}
diff --git a/src/lxc/lxcutmp.h b/src/lxc/lxcutmp.h
deleted file mode 100644 (file)
index 062ecdf..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * lxc: linux Container library
- *
- * (C) Copyright IBM Corp. 2007, 2008
- *
- * Authors:
- * Daniel Lezcano <daniel.lezcano at free.fr>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef __LXC_LXCUTMP_H
-#define __LXC_LXCUTMP_H
-
-#include "config.h"
-
-struct lxc_handler;
-struct lxc_epoll_descr;
-
-int lxc_utmp_mainloop_add(struct lxc_epoll_descr *descr,
-                         struct lxc_handler *handler);
-#endif
index 9fa208f2bc2042e46bdbb117d15948ae2da26660..390dc56b8447aa7fc4980a2ab7a7ebca383fd6d0 100644 (file)
@@ -75,7 +75,6 @@
 #include "lxccontainer.h"
 #include "lxclock.h"
 #include "lxcseccomp.h"
-#include "lxcutmp.h"
 #include "mainloop.h"
 #include "monitor.h"
 #include "namespace.h"
@@ -489,16 +488,6 @@ int lxc_poll(const char *name, struct lxc_handler *handler)
                goto out_mainloop_open;
        }
 
-       if (handler->conf->need_utmp_watch) {
-               #if HAVE_LIBCAP
-               if (lxc_utmp_mainloop_add(&descr, handler)) {
-                       ERROR("Failed to add utmp handler to LXC mainloop.");
-                       goto out_mainloop_open;
-               }
-               #else
-                       DEBUG("Not starting utmp handler as CAP_SYS_BOOT cannot be dropped without capabilities support.");
-               #endif
-       }
        TRACE("lxc mainloop is ready");
 
        return lxc_mainloop(&descr, -1);
@@ -791,75 +780,6 @@ void lxc_abort(const char *name, struct lxc_handler *handler)
        }
 }
 
-#include <sys/reboot.h>
-#include <linux/reboot.h>
-
-/* reboot(LINUX_REBOOT_CMD_CAD_ON) will return -EINVAL in a child pid namespace
- * if container reboot support exists.  Otherwise, it will either succeed or
- * return -EPERM.
- */
-static int container_reboot_supported(void *arg)
-{
-       int *cmd = arg;
-       int ret;
-
-       ret = reboot(*cmd);
-       if (ret == -1 && errno == EINVAL)
-               return 1;
-       return 0;
-}
-
-static int must_drop_cap_sys_boot(struct lxc_conf *conf)
-{
-       FILE *f;
-       int ret, cmd, v, flags;
-       long stack_size = 4096;
-       void *stack = alloca(stack_size);
-       int status;
-       pid_t pid;
-
-       f = fopen("/proc/sys/kernel/ctrl-alt-del", "r");
-       if (!f) {
-               DEBUG("failed to open /proc/sys/kernel/ctrl-alt-del");
-               return 1;
-       }
-
-       ret = fscanf(f, "%d", &v);
-       fclose(f);
-       if (ret != 1) {
-               DEBUG("Failed to read /proc/sys/kernel/ctrl-alt-del.");
-               return 1;
-       }
-       cmd = v ? LINUX_REBOOT_CMD_CAD_ON : LINUX_REBOOT_CMD_CAD_OFF;
-
-       flags = CLONE_NEWPID | SIGCHLD;
-       if (!lxc_list_empty(&conf->id_map))
-               flags |= CLONE_NEWUSER;
-
-#ifdef __ia64__
-       pid = __clone2(container_reboot_supported, stack, stack_size, flags,  &cmd);
-#else
-       stack += stack_size;
-       pid = clone(container_reboot_supported, stack, flags, &cmd);
-#endif
-       if (pid < 0) {
-               if (flags & CLONE_NEWUSER)
-                       ERROR("Failed to clone (%#x): %s (includes CLONE_NEWUSER).", flags, strerror(errno));
-               else
-                       ERROR("Failed to clone (%#x): %s.", flags, strerror(errno));
-               return -1;
-       }
-       if (wait(&status) < 0) {
-               SYSERROR("Unexpected wait error: %s.", strerror(errno));
-               return -1;
-       }
-
-       if (WEXITSTATUS(status) != 1)
-               return 1;
-
-       return 0;
-}
-
 /* netpipe is used in the unprivileged case to transfer the ifindexes from
  * parent to child
  */
@@ -979,16 +899,6 @@ static int do_start(void *data)
                goto out_warn_father;
        }
 
-       #if HAVE_LIBCAP
-       if (handler->conf->need_utmp_watch) {
-               if (prctl(PR_CAPBSET_DROP, CAP_SYS_BOOT, 0, 0, 0)) {
-                       SYSERROR("Failed to remove the CAP_SYS_BOOT capability.");
-                       goto out_warn_father;
-               }
-               DEBUG("Dropped the CAP_SYS_BOOT capability.");
-       }
-       #endif
-
        ret = snprintf(path, sizeof(path), "%s/dev/null", handler->conf->rootfs.mount);
        if (ret < 0 || ret >= sizeof(path))
                goto out_warn_father;
@@ -1563,17 +1473,6 @@ int __lxc_start(const char *name, struct lxc_handler *handler,
        handler->backgrounded = backgrounded;
        handler->netnsfd = -1;
 
-       if (must_drop_cap_sys_boot(handler->conf)) {
-               #if HAVE_LIBCAP
-               DEBUG("Dropping CAP_SYS_BOOT capability.");
-               #else
-               DEBUG("Not dropping CAP_SYS_BOOT capability as capabilities aren't supported.");
-               #endif
-       } else {
-               DEBUG("Not dropping CAP_SYS_BOOT or watching utmp.");
-               handler->conf->need_utmp_watch = 0;
-       }
-
        if (!attach_block_device(handler->conf)) {
                ERROR("Failed to attach block device.");
                goto out_fini_nonet;
@@ -1708,7 +1607,6 @@ int lxc_start(const char *name, char *const argv[], struct lxc_handler *handler,
                .argv = argv,
        };
 
-       handler->conf->need_utmp_watch = 1;
        return __lxc_start(name, handler, &start_ops, &start_arg, lxcpath, backgrounded);
 }