]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
make heavier use of process_lock (v2)
authorSerge Hallyn <serge.hallyn@ubuntu.com>
Mon, 16 Sep 2013 23:28:41 +0000 (18:28 -0500)
committerSerge Hallyn <serge.hallyn@ubuntu.com>
Wed, 18 Sep 2013 18:49:08 +0000 (13:49 -0500)
pthread_mutex_lock() will only return an error if it was set to
PTHREAD_MUTEX_ERRORCHECK and we are recursively calling it (and
would otherwise have deadlocked).  If that's the case then log a
message for future debugging and exit.  Trying to "recover" is
nonsense at that point.

process_lock() was held over too long a time in lxcapi_start()
in the daemonize case.  (note the non-daemonized case still needs a
check to enforce that it must NOT be called while threaded).  Add
process_lock() at least across all open/close/socket() calls.

Anything done after a fork() doesn't need the locks as it is no
longer threaded - so some open/close/dups()s are not locked for
that reason.  However, some common functions are called from both
threaded and non-threaded contexts.  So after doing a fork(), do
a possibly-extraneous process_unlock() to make sure that, if we
were forked while pthread mutex was held, we aren't deadlocked by
nobody.

Tested that lp:~serge-hallyn/+junk/lxc-test still works with this
patch.

Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
Tested-by: S.Çağlar Onur <caglar@10ur.org>
Acked-by: Stéphane Graber <stgraber@ubuntu.com>
25 files changed:
src/lxc/af_unix.c
src/lxc/apparmor.c
src/lxc/attach.c
src/lxc/bdev.c
src/lxc/caps.c
src/lxc/cgroup.c
src/lxc/commands.c
src/lxc/conf.c
src/lxc/console.c
src/lxc/freezer.c
src/lxc/log.c
src/lxc/lxccontainer.c
src/lxc/lxclock.c
src/lxc/lxclock.h
src/lxc/lxcutmp.c
src/lxc/mainloop.c
src/lxc/monitor.c
src/lxc/network.c
src/lxc/nl.c
src/lxc/parse.c
src/lxc/seccomp.c
src/lxc/start.c
src/lxc/state.c
src/lxc/sync.c
src/lxc/utils.c

index 204658d32913d245e6bf7c101baca0e9c5a253c6..333f05eb34b293614ebbc5192df42ed709b6b407 100644 (file)
@@ -30,6 +30,7 @@
 #include <sys/un.h>
 
 #include "log.h"
+#include "lxclock.h"
 
 lxc_log_define(lxc_af_unix, lxc);
 
@@ -42,7 +43,9 @@ int lxc_af_unix_open(const char *path, int type, int flags)
        if (flags & O_TRUNC)
                unlink(path);
 
+       process_lock();
        fd = socket(PF_UNIX, type, 0);
+       process_unlock();
        if (fd < 0)
                return -1;
 
@@ -57,7 +60,9 @@ int lxc_af_unix_open(const char *path, int type, int flags)
        if (path[0]) {
                len = strlen(path);
                if (len >= sizeof(addr.sun_path)) {
+                       process_lock();
                        close(fd);
+                       process_unlock();
                        errno = ENAMETOOLONG;
                        return -1;
                }
@@ -66,14 +71,18 @@ int lxc_af_unix_open(const char *path, int type, int flags)
 
        if (bind(fd, (struct sockaddr *)&addr, sizeof(addr))) {
                int tmp = errno;
+               process_lock();
                close(fd);
+               process_unlock();
                errno = tmp;
                return -1;
        }
 
        if (type == SOCK_STREAM && listen(fd, 100)) {
                int tmp = errno;
+               process_lock();
                close(fd);
+               process_unlock();
                errno = tmp;
                return -1;
        }
@@ -90,7 +99,9 @@ int lxc_af_unix_close(int fd)
            addr.sun_path[0])
                unlink(addr.sun_path);
 
+       process_lock();
        close(fd);
+       process_unlock();
 
        return 0;
 }
@@ -100,7 +111,9 @@ int lxc_af_unix_connect(const char *path)
        int fd;
        struct sockaddr_un addr;
 
+       process_lock();
        fd = socket(PF_UNIX, SOCK_STREAM, 0);
+       process_unlock();
        if (fd < 0)
                return -1;
 
@@ -113,7 +126,9 @@ int lxc_af_unix_connect(const char *path)
 
        if (connect(fd, (struct sockaddr *)&addr, sizeof(addr))) {
                int tmp = errno;
+               process_lock();
                close(fd);
+               process_unlock();
                errno = tmp;
                return -1;
        }
index 4dad801ff458462666339f7e1bc11f7369aec33f..c31cce760cf975477757eef49a86e1b949fa54d4 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "log.h"
 #include "apparmor.h"
+#include "lxclock.h"
 
 lxc_log_define(lxc_apparmor, lxc);
 
@@ -53,7 +54,9 @@ extern char *aa_get_profile(pid_t pid)
                return NULL;
        }
 again:
+       process_lock();
        f = fopen(path, "r");
+       process_unlock();
        if (!f) {
                SYSERROR("opening %s\n", path);
                if (buf)
@@ -65,11 +68,15 @@ again:
        memset(buf, 0, sz);
        if (!buf) {
                ERROR("out of memory");
+               process_lock();
                fclose(f);
+               process_unlock();
                return NULL;
        }
        ret = fread(buf, 1, sz - 1, f);
+       process_lock();
        fclose(f);
+       process_unlock();
        if (ret >= sz)
                goto again;
        if (ret < 0) {
@@ -108,11 +115,15 @@ static int check_apparmor_enabled(void)
        ret = stat(AA_MOUNT_RESTR, &statbuf);
        if (ret != 0)
                return 0;
+       process_lock();
        fin = fopen(AA_ENABLED_FILE, "r");
+       process_unlock();
        if (!fin)
                return 0;
        ret = fscanf(fin, "%c", &e);
+       process_lock();
        fclose(fin);
+       process_unlock();
        if (ret == 1 && e == 'Y')
                return 1;
        return 0;
index 6f3325237fef0af16eb9fa527295c5a6db0542af..cc95079a5674c61fa044d6e11b6cbc5a39bb1661 100644 (file)
@@ -50,6 +50,7 @@
 #include "utils.h"
 #include "commands.h"
 #include "cgroup.h"
+#include "lxclock.h"
 
 #if HAVE_SYS_PERSONALITY_H
 #include <sys/personality.h>
@@ -78,7 +79,9 @@ struct lxc_proc_context_info *lxc_proc_get_context_info(pid_t pid)
        /* read capabilities */
        snprintf(proc_fn, MAXPATHLEN, "/proc/%d/status", pid);
 
+       process_lock();
        proc_file = fopen(proc_fn, "r");
+       process_unlock();
        if (!proc_file) {
                SYSERROR("Could not open %s", proc_fn);
                goto out_error;
@@ -95,7 +98,9 @@ struct lxc_proc_context_info *lxc_proc_get_context_info(pid_t pid)
 
        if (line)
                free(line);
+       process_lock();
        fclose(proc_file);
+       process_unlock();
 
        if (!found) {
                SYSERROR("Could not read capability bounding set from %s", proc_fn);
@@ -106,14 +111,18 @@ struct lxc_proc_context_info *lxc_proc_get_context_info(pid_t pid)
        /* read personality */
        snprintf(proc_fn, MAXPATHLEN, "/proc/%d/personality", pid);
 
+       process_lock();
        proc_file = fopen(proc_fn, "r");
+       process_unlock();
        if (!proc_file) {
                SYSERROR("Could not open %s", proc_fn);
                goto out_error;
        }
 
        ret = fscanf(proc_file, "%lx", &info->personality);
+       process_lock();
        fclose(proc_file);
+       process_unlock();
 
        if (ret == EOF || ret == 0) {
                SYSERROR("Could not read personality from %s", proc_fn);
@@ -162,15 +171,19 @@ int lxc_attach_to_ns(pid_t pid, int which)
                }
 
                snprintf(path, MAXPATHLEN, "/proc/%d/ns/%s", pid, ns[i]);
+               process_lock();
                fd[i] = open(path, O_RDONLY | O_CLOEXEC);
+               process_unlock();
                if (fd[i] < 0) {
                        saved_errno = errno;
 
                        /* close all already opened file descriptors before
                         * we return an error, so we don't leak them
                         */
+                       process_lock();
                        for (j = 0; j < i; j++)
                                close(fd[j]);
+                       process_unlock();
 
                        errno = saved_errno;
                        SYSERROR("failed to open '%s'", path);
@@ -190,7 +203,9 @@ int lxc_attach_to_ns(pid_t pid, int which)
                        return -1;
                }
 
+               process_lock();
                close(fd[i]);
+               process_unlock();
        }
 
        return 0;
@@ -378,14 +393,18 @@ char *lxc_attach_getpwshell(uid_t uid)
         * getent program, and we need to capture its
         * output, so we use a pipe for that purpose
         */
+       process_lock();
        ret = pipe(pipes);
+       process_unlock();
        if (ret < 0)
                return NULL;
 
        pid = fork();
        if (pid < 0) {
+               process_lock();
                close(pipes[0]);
                close(pipes[1]);
+               process_unlock();
                return NULL;
        }
 
@@ -397,9 +416,13 @@ char *lxc_attach_getpwshell(uid_t uid)
                int found = 0;
                int status;
 
+               process_lock();
                close(pipes[1]);
+               process_unlock();
 
+               process_lock();
                pipe_f = fdopen(pipes[0], "r");
+               process_unlock();
                while (getline(&line, &line_bufsz, pipe_f) != -1) {
                        char *token;
                        char *saveptr = NULL;
@@ -456,7 +479,9 @@ char *lxc_attach_getpwshell(uid_t uid)
                }
 
                free(line);
+               process_lock();
                fclose(pipe_f);
+               process_unlock();
        again:
                if (waitpid(pid, &status, 0) < 0) {
                        if (errno == EINTR)
@@ -489,6 +514,7 @@ char *lxc_attach_getpwshell(uid_t uid)
                        NULL
                };
 
+               process_unlock(); // we're no longer sharing
                close(pipes[0]);
 
                /* we want to capture stdout */
@@ -651,7 +677,9 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
         *   close socket                                 close socket
         *                                                run program
         */
+       process_lock();
        ret = socketpair(PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets);
+       process_unlock();
        if (ret < 0) {
                SYSERROR("could not set up required IPC mechanism for attaching");
                free(cwd);
@@ -689,7 +717,9 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
                /* inital thread, we close the socket that is for the
                 * subprocesses
                 */
+               process_lock();
                close(ipc_sockets[1]);
+               process_unlock();
                free(cwd);
 
                /* get pid from intermediate process */
@@ -761,7 +791,9 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
 
                /* now shut down communication with child, we're done */
                shutdown(ipc_sockets[0], SHUT_RDWR);
+               process_lock();
                close(ipc_sockets[0]);
+               process_unlock();
                free(init_ctx->aa_profile);
                free(init_ctx);
 
@@ -778,7 +810,9 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
                 * otherwise the pid we're waiting for may never exit
                 */
                shutdown(ipc_sockets[0], SHUT_RDWR);
+               process_lock();
                close(ipc_sockets[0]);
+               process_unlock();
                if (to_cleanup_pid)
                        (void) wait_for_pid(to_cleanup_pid);
                free(init_ctx->aa_profile);
@@ -786,6 +820,7 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
                return -1;
        }
 
+       process_unlock(); // we're no longer sharing
        /* first subprocess begins here, we close the socket that is for the
         * initial thread
         */
index b45f2cb06a6afce2c51f79a2c4fc48cabfcc874b..b643bb7b5d9e96204ad1d7551a8842dde71372c0 100644 (file)
@@ -70,6 +70,8 @@ static int do_rsync(const char *src, const char *dest)
                return -1;
        if (pid > 0)
                return wait_for_pid(pid);
+
+       process_unlock(); // we're no longer sharing
        l = strlen(src) + 2;
        s = malloc(l);
        if (!s)
@@ -93,11 +95,15 @@ static int blk_getsize(struct bdev *bdev, unsigned long *size)
        if (strcmp(bdev->type, "loop") == 0)
                path = bdev->src + 5;
 
+       process_lock();
        fd = open(path, O_RDONLY);
+       process_unlock();
        if (fd < 0)
                return -1;
        ret = ioctl(fd, BLKGETSIZE64, size);
+       process_lock();
        close(fd);
+       process_unlock();
        return ret;
 }
 
@@ -194,6 +200,7 @@ static int do_mkfs(const char *path, const char *fstype)
        if (pid > 0)
                return wait_for_pid(pid);
 
+       process_unlock(); // we're no longer sharing
        // If the file is not a block device, we don't want mkfs to ask
        // us about whether to proceed.
        close(0);
@@ -252,16 +259,23 @@ static int detect_fs(struct bdev *bdev, char *type, int len)
        if (strcmp(bdev->type, "loop") == 0)
                srcdev = bdev->src + 5;
 
-       if (pipe(p) < 0)
+       process_lock();
+       ret = pipe(p);
+       process_unlock();
+       if (ret < 0)
                return -1;
        if ((pid = fork()) < 0)
                return -1;
        if (pid > 0) {
                int status;
+               process_lock();
                close(p[1]);
+               process_unlock();
                memset(type, 0, len);
                ret = read(p[0], type, len-1);
+               process_lock();
                close(p[0]);
+               process_unlock();
                if (ret < 0) {
                        SYSERROR("error reading from pipe");
                        wait(&status);
@@ -277,6 +291,7 @@ static int detect_fs(struct bdev *bdev, char *type, int len)
                return ret;
        }
 
+       process_unlock(); // we're no longer sharing
        if (unshare(CLONE_NEWNS) < 0)
                exit(1);
 
@@ -488,7 +503,10 @@ static int zfs_list_entry(const char *path, char *output, size_t inlen)
        FILE *f;
        int found=0;
 
-       if ((f = popen("zfs list 2> /dev/null", "r")) == NULL) {
+       process_lock();
+       f = popen("zfs list 2> /dev/null", "r");
+       process_unlock();
+       if (f == NULL) {
                SYSERROR("popen failed");
                return 0;
        }
@@ -498,7 +516,9 @@ static int zfs_list_entry(const char *path, char *output, size_t inlen)
                        break;
                }
        }
+       process_lock();
        (void) pclose(f);
+       process_unlock();
 
        return found;
 }
@@ -566,6 +586,8 @@ static int zfs_clone(const char *opath, const char *npath, const char *oname,
                        return -1;
                if (!pid) {
                        char dev[MAXPATHLEN];
+
+                       process_unlock(); // we're no longer sharing
                        ret = snprintf(dev, MAXPATHLEN, "%s/%s", zfsroot, nname);
                        if (ret < 0  || ret >= MAXPATHLEN)
                                exit(1);
@@ -589,6 +611,7 @@ static int zfs_clone(const char *opath, const char *npath, const char *oname,
                if ((pid = fork()) < 0)
                        return -1;
                if (!pid) {
+                       process_unlock(); // we're no longer sharing
                        execlp("zfs", "zfs", "destroy", path1, NULL);
                        exit(1);
                }
@@ -599,6 +622,7 @@ static int zfs_clone(const char *opath, const char *npath, const char *oname,
                if ((pid = fork()) < 0)
                        return -1;
                if (!pid) {
+                       process_unlock(); // we're no longer sharing
                        execlp("zfs", "zfs", "snapshot", path1, NULL);
                        exit(1);
                }
@@ -609,6 +633,7 @@ static int zfs_clone(const char *opath, const char *npath, const char *oname,
                if ((pid = fork()) < 0)
                        return -1;
                if (!pid) {
+                       process_unlock(); // we're no longer sharing
                        execlp("zfs", "zfs", "clone", option, path1, path2, NULL);
                        exit(1);
                }
@@ -659,6 +684,7 @@ static int zfs_destroy(struct bdev *orig)
        if (pid)
                return wait_for_pid(pid);
 
+       process_unlock(); // we're no longer sharing
        if (!zfs_list_entry(orig->src, output, MAXPATHLEN)) {
                ERROR("Error: zfs entry for %s not found", orig->src);
                return -1;
@@ -703,6 +729,7 @@ static int zfs_create(struct bdev *bdev, const char *dest, const char *n,
        if (pid)
                return wait_for_pid(pid);
 
+       process_unlock(); // we're no longer sharing
        char dev[MAXPATHLEN];
        ret = snprintf(dev, MAXPATHLEN, "%s/%s", zfsroot, n);
        if (ret < 0  || ret >= MAXPATHLEN)
@@ -750,11 +777,15 @@ static int lvm_detect(const char *path)
                ERROR("lvm uuid pathname too long");
                return 0;
        }
+       process_lock();
        fout = fopen(devp, "r");
+       process_unlock();
        if (!fout)
                return 0;
        ret = fread(buf, 1, 4, fout);
+       process_lock();
        fclose(fout);
+       process_unlock();
        if (ret != 4 || strncmp(buf, "LVM-", 4) != 0)
                return 0;
        return 1;
@@ -797,6 +828,7 @@ static int do_lvm_create(const char *path, unsigned long size)
        if (pid > 0)
                return wait_for_pid(pid);
 
+       process_unlock(); // we're no longer sharing
        // lvcreate default size is in M, not bytes.
        ret = snprintf(sz, 24, "%lu", size/1000000);
        if (ret < 0 || ret >= 24)
@@ -832,6 +864,8 @@ static int lvm_snapshot(const char *orig, const char *path, unsigned long size)
        }
        if (pid > 0)
                return wait_for_pid(pid);
+
+       process_unlock(); // we're no longer sharing
        // lvcreate default size is in M, not bytes.
        ret = snprintf(sz, 24, "%lu", size/1000000);
        if (ret < 0 || ret >= 24)
@@ -952,6 +986,7 @@ static int lvm_destroy(struct bdev *orig)
        if ((pid = fork()) < 0)
                return -1;
        if (!pid) {
+               process_unlock(); // we're no longer sharing
                execlp("lvremove", "lvremove", "-f", orig->src, NULL);
                exit(1);
        }
@@ -1052,13 +1087,17 @@ static bool is_btrfs_fs(const char *path)
        struct btrfs_ioctl_space_args sargs;
 
        // make sure this is a btrfs filesystem
+       process_lock();
        fd = open(path, O_RDONLY);
+       process_unlock();
        if (fd < 0)
                return false;
        sargs.space_slots = 0;
        sargs.total_spaces = 0;
        ret = ioctl(fd, BTRFS_IOC_SPACE_INFO, &sargs);
+       process_lock();
        close(fd);
+       process_unlock();
        if (ret < 0)
                return false;
 
@@ -1155,7 +1194,10 @@ static int btrfs_subvolume_create(const char *path)
        }
        *p = '\0';
 
-       if ((fd = open(newfull, O_RDONLY)) < 0) {
+       process_lock();
+       fd = open(newfull, O_RDONLY);
+       process_unlock();
+       if (fd < 0) {
                ERROR("Error opening %s", newfull);
                free(newfull);
                return -1;
@@ -1168,7 +1210,9 @@ static int btrfs_subvolume_create(const char *path)
        INFO("btrfs: snapshot create ioctl returned %d", ret);
 
        free(newfull);
+       process_lock();
        close(fd);
+       process_unlock();
        return ret;
 }
 
@@ -1190,12 +1234,14 @@ static int btrfs_snapshot(const char *orig, const char *new)
        }
        newname = basename(newfull);
        newdir = dirname(newfull);
+       process_lock();
        fd = open(orig, O_RDONLY);
+       fddst = open(newdir, O_RDONLY);
+       process_unlock();
        if (fd < 0) {
                SYSERROR("Error opening original rootfs %s", orig);
                goto out;
        }
-       fddst = open(newdir, O_RDONLY);
        if (fddst < 0) {
                SYSERROR("Error opening new container dir %s", newdir);
                goto out;
@@ -1209,10 +1255,12 @@ static int btrfs_snapshot(const char *orig, const char *new)
        INFO("btrfs: snapshot create ioctl returned %d", ret);
 
 out:
+       process_lock();
        if (fddst != -1)
                close(fddst);
        if (fd != -1)
                close(fd);
+       process_unlock();
        if (newfull)
                free(newfull);
        return ret;
@@ -1282,7 +1330,10 @@ static int btrfs_destroy(struct bdev *orig)
        }
        *p = '\0';
 
-       if ((fd = open(newfull, O_RDONLY)) < 0) {
+       process_lock();
+       fd = open(newfull, O_RDONLY);
+       process_unlock();
+       if (fd < 0) {
                ERROR("Error opening %s", newfull);
                free(newfull);
                return -1;
@@ -1295,7 +1346,9 @@ static int btrfs_destroy(struct bdev *orig)
        INFO("btrfs: snapshot create ioctl returned %d", ret);
 
        free(newfull);
+       process_lock();
        close(fd);
+       process_unlock();
        return ret;
 }
 
@@ -1335,7 +1388,10 @@ static int find_free_loopdev(int *retfd, char *namep)
        DIR *dir;
        int fd = -1;
 
-       if (!(dir = opendir("/dev"))) {
+       process_lock();
+       dir = opendir("/dev");
+       process_unlock();
+       if (!dir) {
                SYSERROR("Error opening /dev");
                return -1;
        }
@@ -1345,10 +1401,15 @@ static int find_free_loopdev(int *retfd, char *namep)
                        break;
                if (strncmp(direntp->d_name, "loop", 4) != 0)
                        continue;
-               if ((fd = openat(dirfd(dir), direntp->d_name, O_RDWR)) < 0)
+               process_lock();
+               fd = openat(dirfd(dir), direntp->d_name, O_RDWR);
+               process_unlock();
+               if (fd < 0)
                        continue;
                if (ioctl(fd, LOOP_GET_STATUS64, &lo) == 0 || errno != ENXIO) {
+                       process_lock();
                        close(fd);
+                       process_unlock();
                        fd = -1;
                        continue;
                }
@@ -1356,7 +1417,9 @@ static int find_free_loopdev(int *retfd, char *namep)
                snprintf(namep, 100, "/dev/%s", direntp->d_name);
                break;
        }
+       process_lock();
        closedir(dir);
+       process_unlock();
        if (fd == -1) {
                ERROR("No loop device found");
                return -1;
@@ -1379,7 +1442,10 @@ static int loop_mount(struct bdev *bdev)
        if (find_free_loopdev(&lfd, loname) < 0)
                return -22;
 
-       if ((ffd = open(bdev->src + 5, O_RDWR)) < 0) {
+       process_lock();
+       ffd = open(bdev->src + 5, O_RDWR);
+       process_unlock();
+       if (ffd < 0) {
                SYSERROR("Error opening backing file %s\n", bdev->src);
                goto out;
        }
@@ -1402,12 +1468,14 @@ static int loop_mount(struct bdev *bdev)
                bdev->lofd = lfd;
 
 out:
+       process_lock();
        if (ffd > -1)
                close(ffd);
        if (ret < 0) {
                close(lfd);
                bdev->lofd = -1;
        }
+       process_unlock();
        return ret;
 }
 
@@ -1421,7 +1489,9 @@ static int loop_umount(struct bdev *bdev)
                return -22;
        ret = umount(bdev->dest);
        if (bdev->lofd >= 0) {
+               process_lock();
                close(bdev->lofd);
+               process_unlock();
                bdev->lofd = -1;
        }
        return ret;
@@ -1429,9 +1499,11 @@ static int loop_umount(struct bdev *bdev)
 
 static int do_loop_create(const char *path, unsigned long size, const char *fstype)
 {
-       int fd;
+       int fd, ret;
        // create the new loopback file.
+       process_lock();
        fd = creat(path, S_IRUSR|S_IWUSR);
+       process_unlock();
        if (fd < 0)
                return -1;
        if (lseek(fd, size, SEEK_SET) < 0) {
@@ -1444,7 +1516,10 @@ static int do_loop_create(const char *path, unsigned long size, const char *fsty
                close(fd);
                return -1;
        }
-       if (close(fd) < 0) {
+       process_lock();
+       ret = close(fd);
+       process_unlock();
+       if (ret < 0) {
                SYSERROR("Error closing new loop file");
                return -1;
        }
@@ -1975,6 +2050,7 @@ struct bdev *bdev_copy(const char *src, const char *oldname, const char *cname,
                return new;
        }
 
+       process_unlock(); // we're no longer sharing
        if (unshare(CLONE_NEWNS) < 0) {
                SYSERROR("unshare CLONE_NEWNS");
                exit(1);
index 006172d1ded5c2af5865a83f2e726106f7ab6aac..bcbb859fffd818721c57796734a98b8b45dd73e9 100644 (file)
@@ -31,6 +31,7 @@
 
 #include "config.h"
 #include "log.h"
+#include "lxclock.h"
 
 lxc_log_define(lxc_caps, lxc);
 
@@ -191,7 +192,9 @@ static int _real_caps_last_cap(void)
 
        /* try to get the maximum capability over the kernel
        * interface introduced in v3.2 */
+       process_lock();
        fd = open("/proc/sys/kernel/cap_last_cap", O_RDONLY);
+       process_unlock();
        if (fd >= 0) {
                char buf[32];
                char *ptr;
@@ -205,7 +208,9 @@ static int _real_caps_last_cap(void)
                                result = -1;
                }
 
+               process_lock();
                close(fd);
+               process_unlock();
        }
 
        /* try to get it manually by trying to get the status of
index 9417e7769a9dcf2bd2ac4e3be145a2830947bf3a..fe1a4c357fdd7c2dc61b1157559032bb2adc4467 100644 (file)
@@ -45,6 +45,7 @@
 #include "conf.h"
 #include "utils.h"
 #include "bdev.h"
+#include "lxclock.h"
 
 #include <lxc/log.h>
 #include <lxc/cgroup.h>
@@ -148,7 +149,9 @@ struct cgroup_meta_data *lxc_cgroup_load_meta2(const char **subsystem_whitelist)
        meta_data->ref = 1;
 
        /* Step 1: determine all kernel subsystems */
+       process_lock();
        proc_cgroups = fopen_cloexec("/proc/cgroups", "r");
+       process_unlock();
        if (!proc_cgroups)
                goto out_error;
 
@@ -186,18 +189,22 @@ struct cgroup_meta_data *lxc_cgroup_load_meta2(const char **subsystem_whitelist)
                kernel_subsystems_count++;
        }
 
+       process_lock();
        fclose(proc_cgroups);
+       process_unlock();
        proc_cgroups = NULL;
 
        /* Step 2: determine all hierarchies (by reading /proc/self/cgroup),
         *         since mount points don't specify hierarchy number and
         *         /proc/cgroups does not contain named hierarchies
         */
+       process_lock();
        proc_self_cgroup = fopen_cloexec("/proc/self/cgroup", "r");
        /* if for some reason (because of setns() and pid namespace for example),
         * /proc/self is not valid, we try /proc/1/cgroup... */
        if (!proc_self_cgroup)
                proc_self_cgroup = fopen_cloexec("/proc/1/cgroup", "r");
+       process_unlock();
        if (!proc_self_cgroup)
                goto out_error;
 
@@ -274,15 +281,19 @@ struct cgroup_meta_data *lxc_cgroup_load_meta2(const char **subsystem_whitelist)
                }
        }
 
+       process_lock();
        fclose(proc_self_cgroup);
+       process_unlock();
        proc_self_cgroup = NULL;
        
        /* Step 3: determine all mount points of each hierarchy */
+       process_lock();
        proc_self_mountinfo = fopen_cloexec("/proc/self/mountinfo", "r");
        /* if for some reason (because of setns() and pid namespace for example),
         * /proc/self is not valid, we try /proc/1/cgroup... */
        if (!proc_self_mountinfo)
                proc_self_mountinfo = fopen_cloexec("/proc/1/mountinfo", "r");
+       process_unlock();
        if (!proc_self_mountinfo)
                goto out_error;
 
@@ -395,12 +406,14 @@ struct cgroup_meta_data *lxc_cgroup_load_meta2(const char **subsystem_whitelist)
 
 out_error:
        saved_errno = errno;
+       process_lock();
        if (proc_cgroups)
                fclose(proc_cgroups);
        if (proc_self_cgroup)
                fclose(proc_self_cgroup);
        if (proc_self_mountinfo)
                fclose(proc_self_mountinfo);
+       process_unlock();
        free(line);
        free(tokens);
        lxc_free_array((void **)kernel_subsystems, free);
@@ -1367,7 +1380,9 @@ struct cgroup_process_info *lxc_cgroup_process_info_getx(const char *proc_pid_cg
        struct cgroup_process_info **cptr = &result;
        struct cgroup_process_info *entry = NULL;
 
+       process_lock();
        proc_pid_cgroup = fopen_cloexec(proc_pid_cgroup_str, "r");
+       process_unlock();
        if (!proc_pid_cgroup)
                return NULL;
 
@@ -1437,14 +1452,18 @@ struct cgroup_process_info *lxc_cgroup_process_info_getx(const char *proc_pid_cg
                entry = NULL;
        }
 
+       process_lock();
        fclose(proc_pid_cgroup);
+       process_unlock();
        free(line);
        return result;
 
 out_error:
        saved_errno = errno;
+       process_lock();
        if (proc_pid_cgroup)
                fclose(proc_pid_cgroup);
+       process_unlock();
        lxc_cgroup_process_info_free(result);
        lxc_cgroup_process_info_free(entry);
        free(line);
@@ -1702,7 +1721,9 @@ bool cgroup_devices_has_allow_or_deny(struct lxc_handler *h, char *v, bool for_a
                return false;
        }
 
+       process_lock();
        devices_list = fopen_cloexec(path, "r");
+       process_unlock();
        if (!devices_list) {
                free(path);
                return false;
@@ -1722,7 +1743,9 @@ bool cgroup_devices_has_allow_or_deny(struct lxc_handler *h, char *v, bool for_a
        }
 
 out:
+       process_lock();
        fclose(devices_list);
+       process_unlock();
        free(line);
        free(path);
        return ret;
@@ -1744,7 +1767,9 @@ int cgroup_recursive_task_count(const char *cgroup_path)
        if (!dent_buf)
                return -1;
 
+       process_lock();
        d = opendir(cgroup_path);
+       process_unlock();
        if (!d)
                return 0;
 
@@ -1761,13 +1786,17 @@ int cgroup_recursive_task_count(const char *cgroup_path)
                        continue;
                sub_path = lxc_string_join("/", parts, false);
                if (!sub_path) {
+                       process_lock();
                        closedir(d);
+                       process_unlock();
                        free(dent_buf);
                        return -1;
                }
                r = stat(sub_path, &st);
                if (r < 0) {
+                       process_lock();
                        closedir(d);
+                       process_unlock();
                        free(dent_buf);
                        free(sub_path);
                        return -1;
@@ -1783,7 +1812,9 @@ int cgroup_recursive_task_count(const char *cgroup_path)
                }
                free(sub_path);
        }
+       process_lock();
        closedir(d);
+       process_unlock();
        free(dent_buf);
 
        return n;
@@ -1796,7 +1827,9 @@ int count_lines(const char *fn)
        size_t sz = 0;
        int n = 0;
 
+       process_lock();
        f = fopen_cloexec(fn, "r");
+       process_unlock();
        if (!f)
                return -1;
 
@@ -1804,7 +1837,9 @@ int count_lines(const char *fn)
                n++;
        }
        free(line);
+       process_lock();
        fclose(f);
+       process_unlock();
        return n;
 }
 
index f12ae2dece926cd8fb180428a3f910cf38828506..f481a55ce39df758aa783c725cafb3ec5a9d9f0a 100644 (file)
@@ -46,6 +46,7 @@
 #include "mainloop.h"
 #include "af_unix.h"
 #include "config.h"
+#include "lxclock.h"
 
 /*
  * This file provides the different functions for clients to
@@ -716,7 +717,9 @@ static void lxc_cmd_fd_cleanup(int fd, struct lxc_handler *handler,
 {
        lxc_console_free(handler->conf, fd);
        lxc_mainloop_del_handler(descr, fd);
+       process_lock();
        close(fd);
+       process_unlock();
 }
 
 static int lxc_cmd_handler(int fd, void *data, struct lxc_epoll_descr *descr)
@@ -787,7 +790,9 @@ static int lxc_cmd_accept(int fd, void *data, struct lxc_epoll_descr *descr)
 {
        int opt = 1, ret = -1, connection;
 
+       process_lock();
        connection = accept(fd, NULL, 0);
+       process_unlock();
        if (connection < 0) {
                SYSERROR("failed to accept connection");
                return -1;
@@ -814,7 +819,9 @@ out:
        return ret;
 
 out_close:
+       process_lock();
        close(connection);
+       process_unlock();
        goto out;
 }
 
@@ -843,7 +850,9 @@ int lxc_cmd_init(const char *name, struct lxc_handler *handler,
 
        if (fcntl(fd, F_SETFD, FD_CLOEXEC)) {
                SYSERROR("failed to set sigfd to close-on-exec");
+               process_lock();
                close(fd);
+               process_unlock();
                return -1;
        }
 
@@ -860,7 +869,9 @@ int lxc_cmd_mainloop_add(const char *name,
        ret = lxc_mainloop_add_handler(descr, fd, lxc_cmd_accept, handler);
        if (ret) {
                ERROR("failed to add handler for command socket");
+               process_lock();
                close(fd);
+               process_unlock();
        }
 
        return ret;
index 79220d1ff4d985a9844d7e3831cadbf1f4a06889..e933c9a3a561172d44588d3b1e713c13ba257b78 100644 (file)
@@ -73,6 +73,7 @@
 #include "caps.h"       /* for lxc_caps_last_cap() */
 #include "bdev.h"
 #include "cgroup.h"
+#include "lxclock.h"
 
 #if HAVE_APPARMOR
 #include <apparmor.h>
@@ -296,11 +297,15 @@ static char *mkifname(char *template)
        getifaddrs(&ifaddr);
 
        /* Initialize the random number generator */
+       process_lock();
        urandom = fopen ("/dev/urandom", "r");
+       process_unlock();
        if (urandom != NULL) {
                if (fread (&seed, sizeof(seed), 1, urandom) <= 0)
                        seed = time(0);
+               process_lock();
                fclose(urandom);
+               process_unlock();
        }
        else
                seed = time(0);
@@ -350,7 +355,9 @@ static int run_buffer(char *buffer)
        char *output;
        int ret;
 
+       process_lock();
        f = popen(buffer, "r");
+       process_unlock();
        if (!f) {
                SYSERROR("popen failed");
                return -1;
@@ -359,7 +366,9 @@ static int run_buffer(char *buffer)
        output = malloc(LXC_LOG_BUFFER_SIZE);
        if (!output) {
                ERROR("failed to allocate memory for script output");
+               process_lock();
                pclose(f);
+               process_unlock();
                return -1;
        }
 
@@ -368,7 +377,9 @@ static int run_buffer(char *buffer)
 
        free(output);
 
+       process_lock();
        ret = pclose(f);
+       process_unlock();
        if (ret == -1) {
                SYSERROR("Script exited on error");
                return -1;
@@ -573,7 +584,9 @@ static int setup_lodev(const char *rootfs, int fd, struct loop_info64 *loinfo)
        int rfd;
        int ret = -1;
 
+       process_lock();
        rfd = open(rootfs, O_RDWR);
+       process_unlock();
        if (rfd < 0) {
                SYSERROR("failed to open '%s'", rootfs);
                return -1;
@@ -595,7 +608,9 @@ static int setup_lodev(const char *rootfs, int fd, struct loop_info64 *loinfo)
 
        ret = 0;
 out:
+       process_lock();
        close(rfd);
+       process_unlock();
 
        return ret;
 }
@@ -608,7 +623,9 @@ static int mount_rootfs_file(const char *rootfs, const char *target)
        DIR *dir;
        char path[MAXPATHLEN];
 
+       process_lock();
        dir = opendir("/dev");
+       process_unlock();
        if (!dir) {
                SYSERROR("failed to open '/dev'");
                return -1;
@@ -632,19 +649,25 @@ static int mount_rootfs_file(const char *rootfs, const char *target)
                if (rc < 0 || rc >= MAXPATHLEN)
                        continue;
 
+               process_lock();
                fd = open(path, O_RDWR);
+               process_unlock();
                if (fd < 0)
                        continue;
 
                if (ioctl(fd, LOOP_GET_STATUS64, &loinfo) == 0) {
+                       process_lock();
                        close(fd);
+                       process_unlock();
                        continue;
                }
 
                if (errno != ENXIO) {
                        WARN("unexpected error for ioctl on '%s': %m",
                             direntp->d_name);
+                       process_lock();
                        close(fd);
+                       process_unlock();
                        continue;
                }
 
@@ -653,13 +676,17 @@ static int mount_rootfs_file(const char *rootfs, const char *target)
                ret = setup_lodev(rootfs, fd, &loinfo);
                if (!ret)
                        ret = mount_unknow_fs(path, target, 0);
+               process_lock();
                close(fd);
+               process_unlock();
 
                break;
        }
 
+       process_lock();
        if (closedir(dir))
                WARN("failed to close directory");
+       process_unlock();
 
        return ret;
 }
@@ -705,7 +732,9 @@ int pin_rootfs(const char *rootfs)
        if (ret >= MAXPATHLEN)
                return -1;
 
+       process_lock();
        fd = open(absrootfspin, O_CREAT | O_RDWR, S_IWUSR|S_IRUSR);
+       process_unlock();
        if (fd < 0)
                return fd;
        (void)unlink(absrootfspin);
@@ -881,13 +910,17 @@ static int setup_tty(const struct lxc_rootfs *rootfs,
                                ERROR("pathname too long for ttys");
                                return -1;
                        }
+                       process_lock();
                        ret = creat(lxcpath, 0660);
+                       process_unlock();
                        if (ret==-1 && errno != EEXIST) {
                                SYSERROR("error creating %s\n", lxcpath);
                                return -1;
                        }
+                       process_lock();
                        if (ret >= 0)
                                close(ret);
+                       process_unlock();
                        ret = unlink(path);
                        if (ret && errno != ENOENT) {
                                SYSERROR("error unlinking %s\n", path);
@@ -913,12 +946,17 @@ static int setup_tty(const struct lxc_rootfs *rootfs,
                } else {
                        /* If we populated /dev, then we need to create /dev/ttyN */
                        if (access(path, F_OK)) {
+                               process_lock();
                                ret = creat(path, 0660);
+                               process_unlock();
                                if (ret==-1) {
                                        SYSERROR("error creating %s\n", path);
                                        /* this isn't fatal, continue */
-                               } else
+                               } else {
+                                       process_lock();
                                        close(ret);
+                                       process_unlock();
+                               }
                        }
                        if (mount(pty_info->name, path, "none", MS_BIND, 0)) {
                                WARN("failed to mount '%s'->'%s'",
@@ -1226,7 +1264,9 @@ int detect_shared_rootfs(void)
        int i;
        char *p2;
 
+       process_lock();
        f = fopen("/proc/self/mountinfo", "r");
+       process_unlock();
        if (!f)
                return 0;
        while ((p = fgets(buf, LINELEN, f))) {
@@ -1244,12 +1284,16 @@ int detect_shared_rootfs(void)
                        // this is '/'.  is it shared?
                        p = index(p2+1, ' ');
                        if (p && strstr(p, "shared:")) {
+                               process_lock();
                                fclose(f);
+                               process_unlock();
                                return 1;
                        }
                }
        }
+       process_lock();
        fclose(f);
+       process_unlock();
        return 0;
 }
 
@@ -1505,13 +1549,17 @@ static int setup_ttydir_console(const struct lxc_rootfs *rootfs,
                return -1;
        }
 
+       process_lock();
        ret = creat(lxcpath, 0660);
+       process_unlock();
        if (ret==-1 && errno != EEXIST) {
                SYSERROR("error %d creating %s\n", errno, lxcpath);
                return -1;
        }
+       process_lock();
        if (ret >= 0)
                close(ret);
+       process_unlock();
 
        if (console->master < 0) {
                INFO("no console");
@@ -1827,7 +1875,9 @@ static int setup_mount(const struct lxc_rootfs *rootfs, const char *fstab,
        if (!fstab)
                return 0;
 
+       process_lock();
        file = setmntent(fstab, "r");
+       process_unlock();
        if (!file) {
                SYSERROR("failed to use '%s'", fstab);
                return -1;
@@ -1835,7 +1885,9 @@ static int setup_mount(const struct lxc_rootfs *rootfs, const char *fstab,
 
        ret = mount_file_entries(rootfs, file, lxc_name);
 
+       process_lock();
        endmntent(file);
+       process_unlock();
        return ret;
 }
 
@@ -1847,7 +1899,9 @@ static int setup_mount_entries(const struct lxc_rootfs *rootfs, struct lxc_list
        char *mount_entry;
        int ret;
 
+       process_lock();
        file = tmpfile();
+       process_unlock();
        if (!file) {
                ERROR("tmpfile error: %m");
                return -1;
@@ -1862,7 +1916,9 @@ static int setup_mount_entries(const struct lxc_rootfs *rootfs, struct lxc_list
 
        ret = mount_file_entries(rootfs, file, lxc_name);
 
+       process_lock();
        fclose(file);
+       process_unlock();
        return ret;
 }
 
@@ -2007,14 +2063,18 @@ static int setup_hw_addr(char *hwaddr, const char *ifname)
        memcpy(ifr.ifr_name, ifname, IFNAMSIZ);
        memcpy((char *) &ifr.ifr_hwaddr, (char *) &sockaddr, sizeof(sockaddr));
 
+       process_lock();
        fd = socket(AF_INET, SOCK_DGRAM, 0);
+       process_unlock();
        if (fd < 0) {
                ERROR("socket failure : %s", strerror(errno));
                return -1;
        }
 
        ret = ioctl(fd, SIOCSIFHWADDR, &ifr);
+       process_lock();
        close(fd);
+       process_unlock();
        if (ret)
                ERROR("ioctl failure : %s", strerror(errno));
 
@@ -2261,20 +2321,26 @@ static int setup_private_host_hw_addr(char *veth1)
        int err;
        int sockfd;
 
+       process_lock();
        sockfd = socket(AF_INET, SOCK_DGRAM, 0);
+       process_unlock();
        if (sockfd < 0)
                return -errno;
 
        snprintf((char *)ifr.ifr_name, IFNAMSIZ, "%s", veth1);
        err = ioctl(sockfd, SIOCGIFHWADDR, &ifr);
        if (err < 0) {
+               process_lock();
                close(sockfd);
+               process_unlock();
                return -errno;
        }
 
        ifr.ifr_hwaddr.sa_data[0] = 0xfe;
        err = ioctl(sockfd, SIOCSIFHWADDR, &ifr);
+       process_lock();
        close(sockfd);
+       process_unlock();
        if (err < 0)
                return -errno;
 
@@ -2716,7 +2782,9 @@ static int write_id_mapping(enum idtype idtype, pid_t pid, const char *buf,
                fprintf(stderr, "%s: path name too long", __func__);
                return -E2BIG;
        }
+       process_lock();
        f = fopen(path, "w");
+       process_unlock();
        if (!f) {
                perror("open");
                return -EINVAL;
@@ -2724,7 +2792,9 @@ static int write_id_mapping(enum idtype idtype, pid_t pid, const char *buf,
        ret = fwrite(buf, buf_size, 1, f);
        if (ret < 0)
                SYSERROR("writing id mapping");
+       process_lock();
        closeret = fclose(f);
+       process_unlock();
        if (closeret)
                SYSERROR("writing id mapping");
        return ret < 0 ? ret : closeret;
@@ -2822,7 +2892,7 @@ int lxc_find_gateway_addresses(struct lxc_handler *handler)
 int lxc_create_tty(const char *name, struct lxc_conf *conf)
 {
        struct lxc_tty_info *tty_info = &conf->tty_info;
-       int i;
+       int i, ret;
 
        /* no tty in the configuration */
        if (!conf->tty)
@@ -2839,8 +2909,11 @@ int lxc_create_tty(const char *name, struct lxc_conf *conf)
 
                struct lxc_pty_info *pty_info = &tty_info->pty_info[i];
 
-               if (openpty(&pty_info->master, &pty_info->slave,
-                           pty_info->name, NULL, NULL)) {
+               process_lock();
+               ret = openpty(&pty_info->master, &pty_info->slave,
+                           pty_info->name, NULL, NULL);
+               process_unlock();
+               if (ret) {
                        SYSERROR("failed to create pty #%d", i);
                        tty_info->nbtty = i;
                        lxc_delete_tty(tty_info);
@@ -2871,8 +2944,10 @@ void lxc_delete_tty(struct lxc_tty_info *tty_info)
        for (i = 0; i < tty_info->nbtty; i++) {
                struct lxc_pty_info *pty_info = &tty_info->pty_info[i];
 
+               process_lock();
                close(pty_info->master);
                close(pty_info->slave);
+               process_unlock();
        }
 
        free(tty_info->pty_info);
index e35a811aa91191aba454ee76b5a68da87a61c8f7..a32e9cfa0a38bd737ab3db827c6acaf4cf86f74c 100644 (file)
@@ -100,16 +100,16 @@ static void lxc_console_winch(struct lxc_tty_state *ts)
 
 void lxc_console_sigwinch(int sig)
 {
-       if (process_lock() == 0) {
-               struct lxc_list *it;
-               struct lxc_tty_state *ts;
+       struct lxc_list *it;
+       struct lxc_tty_state *ts;
 
-               lxc_list_for_each(it, &lxc_ttys) {
-                       ts = it->elem;
-                       lxc_console_winch(ts);
-               }
-               process_unlock();
+       process_lock();
+
+       lxc_list_for_each(it, &lxc_ttys) {
+               ts = it->elem;
+               lxc_console_winch(ts);
        }
+       process_unlock();
 }
 
 static int lxc_console_cb_sigwinch_fd(int fd, void *cbdata,
@@ -204,8 +204,11 @@ out:
  */
 static void lxc_console_sigwinch_fini(struct lxc_tty_state *ts)
 {
-       if (ts->sigfd >= 0)
+       if (ts->sigfd >= 0) {
+               process_lock();
                close(ts->sigfd);
+               process_unlock();
+       }
        lxc_list_del(&ts->node);
        sigprocmask(SIG_SETMASK, &ts->oldmask, NULL);
        free(ts);
@@ -227,7 +230,9 @@ static int lxc_console_cb_con(int fd, void *data,
        if (!r) {
                INFO("console client on fd %d has exited", fd);
                lxc_mainloop_del_handler(descr, fd);
+               process_lock();
                close(fd);
+               process_unlock();
                return 0;
        }
 
@@ -343,8 +348,10 @@ static void lxc_console_peer_proxy_free(struct lxc_console *console)
                lxc_console_sigwinch_fini(console->tty_state);
                console->tty_state = NULL;
        }
+       process_lock();
        close(console->peerpty.master);
        close(console->peerpty.slave);
+       process_unlock();
        console->peerpty.master = -1;
        console->peerpty.slave = -1;
        console->peerpty.busy = -1;
@@ -356,6 +363,7 @@ static int lxc_console_peer_proxy_alloc(struct lxc_console *console, int sockfd)
 {
        struct termios oldtermio;
        struct lxc_tty_state *ts;
+       int ret;
 
        if (console->master < 0) {
                ERROR("console not set up");
@@ -373,8 +381,11 @@ static int lxc_console_peer_proxy_alloc(struct lxc_console *console, int sockfd)
        /* this is the proxy pty that will be given to the client, and that
         * the real pty master will send to / recv from
         */
-       if (openpty(&console->peerpty.master, &console->peerpty.slave,
-                   console->peerpty.name, NULL, NULL)) {
+       process_lock();
+       ret = openpty(&console->peerpty.master, &console->peerpty.slave,
+                   console->peerpty.name, NULL, NULL);
+       process_unlock();
+       if (ret) {
                SYSERROR("failed to create proxy pty");
                return -1;
        }
@@ -488,19 +499,23 @@ static void lxc_console_peer_default(struct lxc_console *console)
         */
        if (!path && !access("/dev/tty", F_OK)) {
                int fd;
+               process_lock();
                fd = open("/dev/tty", O_RDWR);
                if (fd >= 0) {
                        close(fd);
                        path = "/dev/tty";
                }
+               process_unlock();
        }
 
        if (!path)
                goto out;
 
        DEBUG("opening %s for console peer", path);
+       process_lock();
        console->peer = lxc_unpriv(open(path, O_CLOEXEC | O_RDWR | O_CREAT |
                                        O_APPEND, 0600));
+       process_unlock();
        if (console->peer < 0)
                goto out;
 
@@ -531,7 +546,9 @@ err2:
        free(console->tios);
        console->tios = NULL;
 err1:
+       process_lock();
        close(console->peer);
+       process_unlock();
        console->peer = -1;
 out:
        DEBUG("no console peer");
@@ -545,24 +562,24 @@ void lxc_console_delete(struct lxc_console *console)
        free(console->tios);
        console->tios = NULL;
 
+       process_lock();
        close(console->peer);
-       console->peer = -1;
-
-       if (console->log_fd >= 0) {
+       close(console->master);
+       close(console->slave);
+       if (console->log_fd >= 0)
                close(console->log_fd);
-               console->log_fd = -1;
-       }
+       process_unlock();
 
-       close(console->master);
+       console->peer = -1;
        console->master = -1;
-
-       close(console->slave);
        console->slave = -1;
+       console->log_fd = -1;
 }
 
 int lxc_console_create(struct lxc_conf *conf)
 {
        struct lxc_console *console = &conf->console;
+       int ret;
 
        if (conf->is_execute) {
                INFO("no console for lxc-execute.");
@@ -575,8 +592,11 @@ int lxc_console_create(struct lxc_conf *conf)
        if (console->path && !strcmp(console->path, "none"))
                return 0;
 
-       if (openpty(&console->master, &console->slave,
-                   console->name, NULL, NULL)) {
+       process_lock();
+       ret = openpty(&console->master, &console->slave,
+                   console->name, NULL, NULL);
+       process_unlock();
+       if (ret) {
                SYSERROR("failed to allocate a pty");
                return -1;
        }
@@ -594,9 +614,11 @@ int lxc_console_create(struct lxc_conf *conf)
        lxc_console_peer_default(console);
 
        if (console->log_path) {
+               process_lock();
                console->log_fd = lxc_unpriv(open(console->log_path,
                                                  O_CLOEXEC | O_RDWR |
                                                  O_CREAT | O_APPEND, 0600));
+               process_unlock();
                if (console->log_fd < 0) {
                        SYSERROR("failed to open '%s'", console->log_path);
                        goto err;
@@ -693,6 +715,7 @@ int lxc_console(struct lxc_container *c, int ttynum,
 
        process_lock();
        ttyfd = lxc_cmd_console(c->name, &ttynum, &masterfd, c->config_path);
+       process_unlock();
        if (ttyfd < 0) {
                ret = ttyfd;
                goto err1;
@@ -747,9 +770,9 @@ int lxc_console(struct lxc_container *c, int ttynum,
                goto err4;
        }
 
-       process_unlock();
-       ret = lxc_mainloop(&descr, -1);
        process_lock();
+       ret = lxc_mainloop(&descr, -1);
+       process_unlock();
        if (ret) {
                ERROR("mainloop returned an error");
                goto err4;
@@ -762,11 +785,12 @@ err4:
 err3:
        lxc_console_sigwinch_fini(ts);
 err2:
+       process_lock();
        close(masterfd);
        close(ttyfd);
+       process_unlock();
 err1:
        tcsetattr(stdinfd, TCSAFLUSH, &oldtios);
-       process_unlock();
 
        return ret;
 }
index be97d757e71949cf0a366b7f98aac5fe507c40b8..41dc61e84321c39a841c4367d3e8882591cab6a9 100644 (file)
@@ -34,6 +34,7 @@
 #include "error.h"
 #include "state.h"
 #include "monitor.h"
+#include "lxclock.h"
 
 #include <lxc/log.h>
 #include <lxc/cgroup.h>
@@ -52,7 +53,9 @@ static int do_unfreeze(const char *nsgroup, int freeze, const char *name, const
                return -1;
        }
 
+       process_lock();
        fd = open(freezer, O_RDWR);
+       process_unlock();
        if (fd < 0) {
                SYSERROR("failed to open freezer at '%s'", nsgroup);
                return -1;
@@ -114,7 +117,9 @@ static int do_unfreeze(const char *nsgroup, int freeze, const char *name, const
        }
 
 out:
+       process_lock();
        close(fd);
+       process_unlock();
        return ret;
 }
 
index 9bbaa69fc411ed2e26f3f93c994c530fe81f97ec..2da8b32240341b04b918de433d04b4c40dc8c061 100644 (file)
@@ -36,6 +36,7 @@
 #include "log.h"
 #include "caps.h"
 #include "utils.h"
+#include "lxclock.h"
 
 #define LXC_LOG_PREFIX_SIZE    32
 #define LXC_LOG_BUFFER_SIZE    512
@@ -159,8 +160,10 @@ static int log_open(const char *name)
        int fd;
        int newfd;
 
+       process_lock();
        fd = lxc_unpriv(open(name, O_CREAT | O_WRONLY |
                             O_APPEND | O_CLOEXEC, 0666));
+       process_unlock();
        if (fd == -1) {
                ERROR("failed to open log file \"%s\" : %s", name,
                      strerror(errno));
@@ -174,7 +177,9 @@ static int log_open(const char *name)
        if (newfd == -1)
                ERROR("failed to dup log fd %d : %s", fd, strerror(errno));
 
+       process_lock();
        close(fd);
+       process_unlock();
        return newfd;
 }
 
@@ -241,7 +246,9 @@ static int __lxc_log_set_file(const char *fname, int create_dirs)
 {
        if (lxc_log_fd != -1) {
                // we are overriding the default.
+               process_lock();
                close(lxc_log_fd);
+               process_unlock();
                free(log_fname);
        }
 
index 79237dff4d004c333f7b042599543532778438bf..d77ce37baf4cd2b598deb25c8a77e5f04d219307 100644 (file)
@@ -100,12 +100,12 @@ int ongoing_create(struct lxc_container *c)
 
        if (!file_exists(path))
                return 0;
-       if (process_lock())
-               return -1;
-       if ((fd = open(path, O_RDWR)) < 0) {
+       process_lock();
+       fd = open(path, O_RDWR);
+       process_unlock();
+       if (fd < 0) {
                // give benefit of the doubt
                SYSERROR("Error opening partial file");
-               process_unlock();
                return 0;
        }
        lk.l_type = F_WRLCK;
@@ -115,11 +115,13 @@ int ongoing_create(struct lxc_container *c)
        lk.l_pid = -1;
        if (fcntl(fd, F_GETLK, &lk) == 0 && lk.l_pid != -1) {
                // create is still ongoing
+               process_lock();
                close(fd);
                process_unlock();
                return 1;
        }
        // create completed but partial is still there.
+       process_lock();
        close(fd);
        process_unlock();
        return 2;
@@ -138,8 +140,7 @@ int create_partial(struct lxc_container *c)
                ERROR("Error writing partial pathname");
                return -1;
        }
-       if (process_lock())
-               return -1;
+       process_lock();
        if ((fd=open(path, O_RDWR | O_CREAT | O_EXCL, 0755)) < 0) {
                SYSERROR("Erorr creating partial file");
                process_unlock();
@@ -167,17 +168,16 @@ void remove_partial(struct lxc_container *c, int fd)
        char *path = alloca(len);
        int ret;
 
+       process_lock();
        close(fd);
+       process_unlock();
        ret = snprintf(path, len, "%s/%s/partial", c->config_path, c->name);
        if (ret < 0 || ret >= len) {
                ERROR("Error writing partial pathname");
                return;
        }
-       if (process_lock())
-               return;
        if (unlink(path) < 0)
                SYSERROR("Error unlink partial file %s", path);
-       process_unlock();
 }
 
 /* LOCKING
@@ -546,20 +546,15 @@ static bool lxcapi_start(struct lxc_container *c, int useinit, char * const argv
                        return false;
                lxc_monitord_spawn(c->config_path);
 
-               if (process_lock())
-                       return false;
                pid_t pid = fork();
                if (pid < 0) {
                        lxc_container_put(c);
-                       process_unlock();
                        return false;
                }
-               if (pid != 0) {
-                       ret = wait_on_daemonized_start(c);
-                       process_unlock();
-                       return ret;
-               }
-               process_unlock();
+               if (pid != 0)
+                       return wait_on_daemonized_start(c);
+
+               process_unlock(); // we're no longer sharing
                /* second fork to be reparented by init */
                pid = fork();
                if (pid < 0) {
@@ -778,6 +773,7 @@ static bool create_run_template(struct lxc_container *c, char *tpath, bool quiet
                int ret, len, nargs = 0;
                char **newargv;
 
+               process_unlock(); // we're no longer sharing
                if (quiet) {
                        close(0);
                        close(1);
@@ -880,56 +876,44 @@ bool prepend_lxc_header(char *path, const char *t, char *const argv[])
        long flen;
        char *contents;
        FILE *f;
+       int ret = -1;
 #if HAVE_LIBGNUTLS
-       int i, ret;
+       int i;
        unsigned char md_value[SHA_DIGEST_LENGTH];
        char *tpath;
        bool have_tpath = false;
 #endif
 
-       if ((f = fopen(path, "r")) == NULL) {
-               SYSERROR("Opening old config");
-               return false;
-       }
-       if (fseek(f, 0, SEEK_END) < 0) {
-               SYSERROR("Seeking to end of old config file");
-               fclose(f);
-               return false;
-       }
-       if ((flen = ftell(f)) < 0) {
-               SYSERROR("telling size of old config");
-               fclose(f);
-               return false;
-       }
-       if (fseek(f, 0, SEEK_SET) < 0) {
-               SYSERROR("rewinding old config");
-               fclose(f);
-               return false;
-       }
-       if ((contents = malloc(flen + 1)) == NULL) {
-               SYSERROR("out of memory");
-               fclose(f);
-               return false;
-       }
-       if (fread(contents, 1, flen, f) != flen) {
-               SYSERROR("Reading old config");
-               free(contents);
-               fclose(f);
+       process_lock();
+       f = fopen(path, "r");
+       process_unlock();
+       if (f == NULL)
                return false;
-       }
+
+       if (fseek(f, 0, SEEK_END) < 0)
+               goto out_error;
+       if ((flen = ftell(f)) < 0)
+               goto out_error;
+       if (fseek(f, 0, SEEK_SET) < 0)
+               goto out_error;
+       if ((contents = malloc(flen + 1)) == NULL)
+               goto out_error;
+       if (fread(contents, 1, flen, f) != flen)
+               goto out_free_contents;
+
        contents[flen] = '\0';
-       if (fclose(f) < 0) {
-               SYSERROR("closing old config");
-               free(contents);
-               return false;
-       }
+       process_lock();
+       ret = fclose(f);
+       process_unlock();
+       f = NULL;
+       if (ret < 0)
+               goto out_free_contents;
 
 #if HAVE_LIBGNUTLS
        tpath = get_template_path(t);
        if (tpath == (char *) -1) {
                ERROR("bad template: %s\n", t);
-               free(contents);
-               return false;
+               goto out_free_contents;
        }
 
        if (tpath) {
@@ -937,14 +921,16 @@ bool prepend_lxc_header(char *path, const char *t, char *const argv[])
                ret = sha1sum_file(tpath, md_value);
                if (ret < 0) {
                        ERROR("Error getting sha1sum of %s", tpath);
-                       free(contents);
-                       return false;
+                       goto out_free_contents;
                }
                free(tpath);
        }
 #endif
 
-       if ((f = fopen(path, "w")) == NULL) {
+       process_lock();
+       f = fopen(path, "w");
+       process_unlock();
+       if (f == NULL) {
                SYSERROR("reopening config for writing");
                free(contents);
                return false;
@@ -969,12 +955,25 @@ bool prepend_lxc_header(char *path, const char *t, char *const argv[])
        if (fwrite(contents, 1, flen, f) != flen) {
                SYSERROR("Writing original contents");
                free(contents);
+               process_lock();
                fclose(f);
+               process_unlock();
                return false;
        }
+       ret = 0;
+out_free_contents:
        free(contents);
-       if (fclose(f) < 0) {
-               SYSERROR("Closing config file after write");
+out_error:
+       if (f) {
+               int newret;
+               process_lock();
+               newret = fclose(f);
+               process_unlock();
+               if (ret == 0)
+                       ret = newret;
+       }
+       if (ret < 0) {
+               SYSERROR("Error prepending header");
                return false;
        }
        return true;
@@ -1044,6 +1043,7 @@ static bool lxcapi_create(struct lxc_container *c, const char *t,
        if (pid == 0) { // child
                struct bdev *bdev = NULL;
 
+               process_unlock(); // we're no longer sharing
                if (!(bdev = do_bdev_create(c, bdevtype, specs))) {
                        ERROR("Error creating backing store type %s for %s",
                                bdevtype ? bdevtype : "(none)", c->name);
@@ -1194,7 +1194,9 @@ char** lxcapi_get_ips(struct lxc_container *c, char* interface, char* family, in
                goto out;
 
        /* Save reference to old netns */
+       process_lock();
        old_netns = open("/proc/self/ns/net", O_RDONLY);
+       process_unlock();
        if (old_netns < 0) {
                SYSERROR("failed to open /proc/self/ns/net");
                goto out;
@@ -1205,7 +1207,9 @@ char** lxcapi_get_ips(struct lxc_container *c, char* interface, char* family, in
        if (ret < 0 || ret >= MAXPATHLEN)
                goto out;
 
+       process_lock();
        new_netns = open(new_netns_path, O_RDONLY);
+       process_unlock();
        if (new_netns < 0) {
                SYSERROR("failed to open %s", new_netns_path);
                goto out;
@@ -1268,10 +1272,12 @@ out:
        /* Switch back to original netns */
        if (old_netns >= 0 && setns(old_netns, CLONE_NEWNET))
                SYSERROR("failed to setns");
+       process_lock();
        if (new_netns >= 0)
                close(new_netns);
        if (old_netns >= 0)
                close(old_netns);
+       process_unlock();
 
        /* Append NULL to the array */
        if (count) {
@@ -1390,25 +1396,36 @@ static bool mod_rdep(struct lxc_container *c, bool inc)
                        c->name);
        if (ret < 0 || ret > MAXPATHLEN)
                goto out;
+       process_lock();
        f = fopen(path, "r");
+       process_unlock();
        if (f) {
                ret = fscanf(f, "%d", &v);
+               process_lock();
                fclose(f);
+               process_unlock();
                if (ret != 1) {
                        ERROR("Corrupted file %s", path);
                        goto out;
                }
        }
        v += inc ? 1 : -1;
+       process_lock();
        f = fopen(path, "w");
+       process_unlock();
        if (!f)
                goto out;
        if (fprintf(f, "%d\n", v) < 0) {
                ERROR("Error writing new snapshots value");
+               process_lock();
                fclose(f);
+               process_unlock();
                goto out;
        }
-       if (fclose(f) != 0) {
+       process_lock();
+       ret = fclose(f);
+       process_unlock();
+       if (ret != 0) {
                SYSERROR("Error writing to or closing snapshots file");
                goto out;
        }
@@ -1443,7 +1460,10 @@ static void mod_all_rdeps(struct lxc_container *c, bool inc)
                ERROR("Path name too long");
                return;
        }
-       if ((f = fopen(path, "r")) == NULL)
+       process_lock();
+       f = fopen(path, "r");
+       process_unlock();
+       if (f == NULL)
                return;
        while (getline(&lxcpath, &pathlen, f) != -1) {
                if (getline(&lxcname, &namelen, f) == -1) {
@@ -1465,7 +1485,9 @@ static void mod_all_rdeps(struct lxc_container *c, bool inc)
 out:
        if (lxcpath) free(lxcpath);
        if (lxcname) free(lxcname);
+       process_lock();
        fclose(f);
+       process_unlock();
 }
 
 static bool has_snapshots(struct lxc_container *c)
@@ -1479,11 +1501,15 @@ static bool has_snapshots(struct lxc_container *c)
                        c->name);
        if (ret < 0 || ret > MAXPATHLEN)
                goto out;
+       process_lock();
        f = fopen(path, "r");
+       process_unlock();
        if (!f)
                goto out;
        ret = fscanf(f, "%d", &v);
+       process_lock();
        fclose(f);
+       process_unlock();
        if (ret != 1)
                goto out;
        bret = v != 0;
@@ -1735,15 +1761,21 @@ static int copy_file(char *old, char *new)
                return -1;
        }
 
+       process_lock();
        in = open(old, O_RDONLY);
+       process_unlock();
        if (in < 0) {
                SYSERROR("Error opening original file %s", old);
                return -1;
        }
+       process_lock();
        out = open(new, O_CREAT | O_EXCL | O_WRONLY, 0644);
+       process_unlock();
        if (out < 0) {
                SYSERROR("Error opening new file %s", new);
+               process_lock();
                close(in);
+               process_unlock();
                return -1;
        }
 
@@ -1761,8 +1793,10 @@ static int copy_file(char *old, char *new)
                        goto err;
                }
        }
+       process_lock();
        close(in);
        close(out);
+       process_unlock();
 
        // we set mode, but not owner/group
        ret = chmod(new, sbuf.st_mode);
@@ -1774,8 +1808,10 @@ static int copy_file(char *old, char *new)
        return 0;
 
 err:
+       process_lock();
        close(in);
        close(out);
+       process_unlock();
        return -1;
 }
 
@@ -1815,13 +1851,18 @@ static int copyhooks(struct lxc_container *oldc, struct lxc_container *c)
 
 static void new_hwaddr(char *hwaddr)
 {
-       FILE *f = fopen("/dev/urandom", "r");
+       FILE *f;
+       process_lock();
+       f = fopen("/dev/urandom", "r");
+       process_unlock();
        if (f) {
                unsigned int seed;
                int ret = fread(&seed, sizeof(seed), 1, f);
                if (ret != 1)
                        seed = time(NULL);
+               process_lock();
                fclose(f);
+               process_unlock();
                srand(seed);
        } else
                srand(time(NULL));
@@ -1911,15 +1952,19 @@ static bool add_rdepends(struct lxc_container *c, struct lxc_container *c0)
                c->name);
        if (ret < 0 || ret >= MAXPATHLEN)
                return false;
+       process_lock();
        f = fopen(path, "a");
+       process_unlock();
        if (!f)
                return false;
        bret = true;
        // if anything goes wrong, just return an error
        if (fprintf(f, "%s\n%s\n", c0->config_path, c0->name) < 0)
                bret = false;
+       process_lock();
        if (fclose(f) != 0)
                bret = false;
+       process_unlock();
        return bret;
 }
 
@@ -1976,6 +2021,7 @@ static int clone_update_rootfs(struct lxc_container *c0,
        if (pid > 0)
                return wait_for_pid(pid);
 
+       process_unlock(); // we're no longer sharing
        if (unshare(CLONE_NEWNS) < 0) {
                ERROR("error unsharing mounts");
                exit(1);
@@ -2097,13 +2143,17 @@ struct lxc_container *lxcapi_clone(struct lxc_container *c, const char *newname,
        }
 
        // copy the configuration, tweak it as needed,
+       process_lock();
        fout = fopen(newpath, "w");
+       process_unlock();
        if (!fout) {
                SYSERROR("open %s", newpath);
                goto out;
        }
        write_config(fout, c->lxc_conf);
+       process_lock();
        fclose(fout);
+       process_unlock();
 
        sprintf(newpath, "%s/%s/rootfs", l, n);
        if (mkdir(newpath, 0755) < 0) {
@@ -2250,6 +2300,7 @@ static int lxcapi_snapshot(struct lxc_container *c, char *commentfile)
        time_t timer;
        char buffer[25];
        struct tm* tm_info;
+       FILE *f;
 
        time(&timer);
        tm_info = localtime(&timer);
@@ -2258,7 +2309,9 @@ static int lxcapi_snapshot(struct lxc_container *c, char *commentfile)
 
        char *dfnam = alloca(strlen(snappath) + strlen(newname) + 5);
        sprintf(dfnam, "%s/%s/ts", snappath, newname);
-       FILE *f = fopen(dfnam, "w");
+       process_lock();
+       f = fopen(dfnam, "w");
+       process_unlock();
        if (!f) {
                ERROR("Failed to open %s\n", dfnam);
                return -1;
@@ -2268,7 +2321,10 @@ static int lxcapi_snapshot(struct lxc_container *c, char *commentfile)
                fclose(f);
                return -1;
        }
-       if (fclose(f) != 0) {
+       process_lock();
+       ret = fclose(f);
+       process_unlock();
+       if (ret != 0) {
                SYSERROR("Writing timestamp");
                return -1;
        }
@@ -2321,7 +2377,10 @@ static char *get_timestamp(char* snappath, char *name)
        ret = snprintf(path, MAXPATHLEN, "%s/%s/ts", snappath, name);
        if (ret < 0 || ret >= MAXPATHLEN)
                return NULL;
-       if ((fin = fopen(path, "r")) == NULL)
+       process_lock();
+       fin = fopen(path, "r");
+       process_unlock();
+       if (!fin)
                return NULL;
        (void) fseek(fin, 0, SEEK_END);
        len = ftell(fin);
@@ -2337,7 +2396,9 @@ static char *get_timestamp(char* snappath, char *name)
                        }
                }
        }
+       process_lock();
        fclose(fin);
+       process_unlock();
        return s;
 }
 
@@ -2357,7 +2418,10 @@ static int lxcapi_snapshot_list(struct lxc_container *c, struct lxc_snapshot **r
                ERROR("path name too long");
                return -1;
        }
-       if (!(dir = opendir(snappath))) {
+       process_lock();
+       dir = opendir(snappath);
+       process_unlock();
+       if (!dir) {
                INFO("failed to open %s - assuming no snapshots", snappath);
                return 0;
        }
@@ -2399,8 +2463,10 @@ static int lxcapi_snapshot_list(struct lxc_container *c, struct lxc_snapshot **r
                count++;
        }
 
+       process_lock();
        if (closedir(dir))
                WARN("failed to close directory");
+       process_unlock();
 
        *ret_snaps = snaps;
        return count;
index 1d6a86c61297bfa97215415ea8dbddcb6b537876..1733fd1c62bf21407f52a1e747cd4dd881a525a1 100644 (file)
@@ -271,13 +271,14 @@ void lxc_putlock(struct lxc_lock *l)
        free(l);
 }
 
-int process_lock(void)
+void process_lock(void)
 {
        int ret;
-       ret = pthread_mutex_lock(&thread_mutex);
-       if (ret != 0)
+
+       if ((ret = pthread_mutex_lock(&thread_mutex)) != 0) {
                ERROR("pthread_mutex_lock returned:%d %s", ret, strerror(ret));
-       return ret;
+               exit(1);
+       }
 }
 
 void process_unlock(void)
index fae7e4d97967e1ba054756de6f765e3d084c09df..dcdf79d2d8cd3f453b951f8230ed8110f424b2ac 100644 (file)
@@ -85,7 +85,7 @@ extern int lxcunlock(struct lxc_lock *lock);
 
 extern void lxc_putlock(struct lxc_lock *l);
 
-extern int process_lock(void);
+extern void process_lock(void);
 extern void process_unlock(void);
 struct lxc_container;
 extern int container_mem_lock(struct lxc_container *c);
index 8736f3fa02766280171c8736379d7faad3525ba0..bfebe55f30cfd6ea34db5f84ff29189f9bffc55e 100644 (file)
@@ -62,6 +62,7 @@ static int timerfd_settime (int __ufd, int __flags,
 #include "mainloop.h"
 #include "lxc.h"
 #include "log.h"
+#include "lxclock.h"
 
 #ifndef __USE_GNU
 #define __USE_GNU
@@ -342,7 +343,9 @@ run_ok:
 
        memset(utmp_data, 0, sizeof(struct lxc_utmp));
 
+       process_lock();
        fd = inotify_init();
+       process_unlock();
        if (fd < 0) {
                SYSERROR("failed to inotify_init");
                goto out;
@@ -376,7 +379,9 @@ run_ok:
 
        return 0;
 out_close:
+       process_lock();
        close(fd);
+       process_unlock();
 out:
        free(utmp_data);
        return -1;
@@ -426,7 +431,9 @@ int lxc_utmp_add_timer(struct lxc_epoll_descr *descr,
        struct itimerspec timeout;
        struct lxc_utmp *utmp_data = (struct lxc_utmp *)data;
 
+       process_lock();
        fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
+       process_unlock();
        if (fd < 0) {
                SYSERROR("failed to create timer");
                return -1;
@@ -450,7 +457,9 @@ int lxc_utmp_add_timer(struct lxc_epoll_descr *descr,
 
        if (lxc_mainloop_add_handler(descr, fd, callback, utmp_data)) {
                SYSERROR("failed to add utmp timer to mainloop");
+               process_lock();
                close(fd);
+               process_unlock();
                return -1;
        }
 
@@ -471,7 +480,9 @@ int lxc_utmp_del_timer(struct lxc_epoll_descr *descr,
                SYSERROR("failed to del utmp timer from mainloop");
 
        /* shutdown timer_fd */
+       process_lock();
        close(utmp_data->timer_fd);
+       process_unlock();
        utmp_data->timer_fd = -1;
 
        if (result < 0)
index 2ac49964b271ca02e660c63eef6abbf5732bdfd0..9ba98ee0dd9e361bfabdf2bdedaa68f80cf37cc7 100644 (file)
@@ -29,6 +29,7 @@
 #include <sys/epoll.h>
 
 #include "mainloop.h"
+#include "lxclock.h"
 
 struct mainloop_handler {
        lxc_mainloop_callback_t callback;
@@ -132,12 +133,16 @@ int lxc_mainloop_del_handler(struct lxc_epoll_descr *descr, int fd)
 int lxc_mainloop_open(struct lxc_epoll_descr *descr)
 {
        /* hint value passed to epoll create */
+       process_lock();
        descr->epfd = epoll_create(2);
+       process_unlock();
        if (descr->epfd < 0)
                return -1;
 
        if (fcntl(descr->epfd, F_SETFD, FD_CLOEXEC)) {
+               process_lock();
                close(descr->epfd);
+               process_unlock();
                return -1;
        }
 
@@ -148,6 +153,7 @@ int lxc_mainloop_open(struct lxc_epoll_descr *descr)
 int lxc_mainloop_close(struct lxc_epoll_descr *descr)
 {
        struct lxc_list *iterator, *next;
+       int ret;
 
        iterator = descr->handlers.next;
        while (iterator != &descr->handlers) {
@@ -159,6 +165,9 @@ int lxc_mainloop_close(struct lxc_epoll_descr *descr)
                iterator = next;
        }
 
-       return close(descr->epfd);
+       process_lock();
+       ret = close(descr->epfd);
+       process_unlock();
+       return ret;
 }
 
index 64e9987fc1d187f8272357fc53b7769efccc59de..e736937c406d52503714ae39977d9e86d3075748 100644 (file)
@@ -90,7 +90,9 @@ static void lxc_monitor_fifo_send(struct lxc_msg *msg, const char *lxcpath)
        if (ret < 0)
                return;
 
+       process_lock();
        fd = open(fifo_path, O_WRONLY);
+       process_unlock();
        if (fd < 0) {
                /* it is normal for this open to fail when there is no monitor
                 * running, so we don't log it
@@ -100,12 +102,16 @@ static void lxc_monitor_fifo_send(struct lxc_msg *msg, const char *lxcpath)
 
        ret = write(fd, msg, sizeof(*msg));
        if (ret != sizeof(*msg)) {
+               process_lock();
                close(fd);
+               process_unlock();
                SYSERROR("failed to write monitor fifo %s", fifo_path);
                return;
        }
 
+       process_lock();
        close(fd);
+       process_unlock();
 }
 
 void lxc_monitor_send_state(const char *name, lxc_state_t state, const char *lxcpath)
@@ -122,7 +128,12 @@ void lxc_monitor_send_state(const char *name, lxc_state_t state, const char *lxc
 /* routines used by monitor subscribers (lxc-monitor) */
 int lxc_monitor_close(int fd)
 {
-       return close(fd);
+       int ret;
+
+       process_lock();
+       ret = close(fd);
+       process_unlock();
+       return ret;
 }
 
 /* Note we don't use SHA-1 here as we don't want to depend on HAVE_GNUTLS.
@@ -187,7 +198,9 @@ int lxc_monitor_open(const char *lxcpath)
        if (lxc_monitor_sock_name(lxcpath, &addr) < 0)
                return -1;
 
+       process_lock();
        fd = socket(PF_UNIX, SOCK_STREAM, 0);
+       process_unlock();
        if (fd < 0) {
                ERROR("socket : %s", strerror(errno));
                return -1;
@@ -207,7 +220,9 @@ int lxc_monitor_open(const char *lxcpath)
        }
        return fd;
 err1:
+       process_lock();
        close(fd);
+       process_unlock();
        return ret;
 }
 
@@ -293,6 +308,7 @@ int lxc_monitord_spawn(const char *lxcpath)
                return 0;
        }
 
+       process_unlock(); // we're no longer sharing
        if (pipe(pipefd) < 0) {
                SYSERROR("failed to create pipe");
                exit(EXIT_FAILURE);
index f7c9ce4ce8aa912973d211bb55f4ec0db4d0930f..1be231d3bc190bd6c4dc9554c6217719ee36d163 100644 (file)
@@ -48,6 +48,7 @@
 #include "nl.h"
 #include "network.h"
 #include "conf.h"
+#include "lxclock.h"
 
 #ifndef IFLA_LINKMODE
 #  define IFLA_LINKMODE 17
@@ -569,14 +570,18 @@ static int proc_sys_net_write(const char *path, const char *value)
 {
        int fd, err = 0;
 
+       process_lock();
        fd = open(path, O_WRONLY);
+       process_unlock();
        if (fd < 0)
                return -errno;
 
        if (write(fd, value, strlen(value)) < 0)
                err = -errno;
 
+       process_lock();
        close(fd);
+       process_unlock();
        return err;
 }
 
@@ -994,14 +999,18 @@ int lxc_bridge_attach(const char *bridge, const char *ifname)
        if (!index)
                return -EINVAL;
 
+       process_lock();
        fd = socket(AF_INET, SOCK_STREAM, 0);
+       process_unlock();
        if (fd < 0)
                return -errno;
 
        strncpy(ifr.ifr_name, bridge, IFNAMSIZ);
        ifr.ifr_ifindex = index;
        err = ioctl(fd, SIOCBRADDIF, &ifr);
+       process_lock();
        close(fd);
+       process_unlock();
        if (err)
                err = -errno;
 
index 7c0f1e53b6482d701b2850a9674515d27ad3bb93..6153161672d0a0344bb1fe3d0f24b8c1dc905cc3 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/rtnetlink.h>
 
 #include "nl.h"
+#include "lxclock.h"
 
 #define NLMSG_TAIL(nmsg) \
         ((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
@@ -222,7 +223,9 @@ extern int netlink_open(struct nl_handler *handler, int protocol)
 
         memset(handler, 0, sizeof(*handler));
 
+       process_lock();
         handler->fd = socket(AF_NETLINK, SOCK_RAW, protocol);
+       process_unlock();
         if (handler->fd < 0)
                 return -errno;
 
@@ -260,7 +263,9 @@ extern int netlink_open(struct nl_handler *handler, int protocol)
 
 extern int netlink_close(struct nl_handler *handler)
 {
+       process_lock();
        close(handler->fd);
+       process_unlock();
        handler->fd = -1;
        return 0;
 }
index 26cbbdd00b427971effcfcfdcd0528b9cfc28bb3..7875c8969ce772c4a6f35351e3beafb168c6cee8 100644 (file)
@@ -31,6 +31,7 @@
 #include "parse.h"
 #include "config.h"
 #include "utils.h"
+#include "lxclock.h"
 #include <lxc/log.h>
 
 /* Workaround for the broken signature of alphasort() in bionic.
@@ -90,7 +91,9 @@ int lxc_file_for_each_line(const char *file, lxc_file_cb callback, void *data)
        char *line = NULL;
        size_t len = 0;
 
+       process_lock();
        f = fopen(file, "r");
+       process_unlock();
        if (!f) {
                SYSERROR("failed to open %s", file);
                return -1;
@@ -104,7 +107,9 @@ int lxc_file_for_each_line(const char *file, lxc_file_cb callback, void *data)
 
        if (line)
                free(line);
+       process_lock();
        fclose(f);
+       process_unlock();
        return err;
 }
 
index 1abd697118ca31cb68352aea9661eded51e55128..9246f2d7db5c9a31dd0eca6ce6fdfb2d900359d6 100644 (file)
@@ -29,6 +29,7 @@
 #include <seccomp.h>
 #include "config.h"
 #include "lxcseccomp.h"
+#include "lxclock.h"
 
 #include "log.h"
 
@@ -114,13 +115,17 @@ int lxc_read_seccomp_config(struct lxc_conf *conf)
                return -1;
        }
 
+       process_lock();
        f = fopen(conf->seccomp, "r");
+       process_unlock();
        if (!f) {
                SYSERROR("failed to open seccomp policy file %s\n", conf->seccomp);
                return -1;
        }
        ret = parse_config(f, conf);
+       process_lock();
        fclose(f);
+       process_unlock();
        return ret;
 }
 
index 48a06cfa89ac01afd76930a52c0a6b292994715f..c968bb13445e600fa3ec7ae2fd9e82411b51fe08 100644 (file)
@@ -71,6 +71,7 @@
 #include "apparmor.h"
 #include "lxcseccomp.h"
 #include "caps.h"
+#include "lxclock.h"
 
 lxc_log_define(lxc_start, lxc);
 
@@ -86,7 +87,9 @@ int lxc_check_inherited(struct lxc_conf *conf, int fd_to_ignore)
        DIR *dir;
 
 restart:
+       process_lock();
        dir = opendir("/proc/self/fd");
+       process_unlock();
        if (!dir) {
                WARN("failed to open directory: %m");
                return -1;
@@ -113,15 +116,19 @@ restart:
                        continue;
 
                if (conf->close_all_fds) {
+                       process_lock();
                        close(fd);
                        closedir(dir);
+                       process_unlock();
                        INFO("closed inherited fd %d", fd);
                        goto restart;
                }
                WARN("inherited fd %d", fd);
        }
 
+       process_lock();
        closedir(dir); /* cannot fail */
+       process_unlock();
        return 0;
 }
 
@@ -258,7 +265,9 @@ int lxc_poll(const char *name, struct lxc_handler *handler)
 out_mainloop_open:
        lxc_mainloop_close(&descr);
 out_sigfd:
+       process_lock();
        close(sigfd);
+       process_unlock();
        return -1;
 }
 
@@ -353,7 +362,9 @@ out_delete_tty:
 out_aborting:
        lxc_set_state(name, handler, ABORTING);
 out_close_maincmd_fd:
+       process_lock();
        close(conf->maincmd_fd);
+       process_unlock();
        conf->maincmd_fd = -1;
 out_free_name:
        free(handler->name);
@@ -380,7 +391,9 @@ static void lxc_fini(const char *name, struct lxc_handler *handler)
 
        lxc_console_delete(&handler->conf->console);
        lxc_delete_tty(&handler->conf->tty_info);
+       process_lock();
        close(handler->conf->maincmd_fd);
+       process_unlock();
        handler->conf->maincmd_fd = -1;
        free(handler->name);
        if (handler->cgroup) {
@@ -421,20 +434,25 @@ static int container_reboot_supported(void *arg)
 
 static int must_drop_cap_sys_boot(struct lxc_conf *conf)
 {
-       FILE *f = fopen("/proc/sys/kernel/ctrl-alt-del", "r");
+       FILE *f;
        int ret, cmd, v, flags;
         long stack_size = 4096;
         void *stack = alloca(stack_size);
         int status;
         pid_t pid;
 
+       process_lock();
+       f = fopen("/proc/sys/kernel/ctrl-alt-del", "r");
+       process_unlock();
        if (!f) {
                DEBUG("failed to open /proc/sys/kernel/ctrl-alt-del");
                return 1;
        }
 
        ret = fscanf(f, "%d", &v);
+       process_lock();
        fclose(f);
+       process_unlock();
        if (ret != 1) {
                DEBUG("Failed to read /proc/sys/kernel/ctrl-alt-del");
                return 1;
@@ -489,8 +507,11 @@ static int do_start(void *data)
        lxc_sync_fini_parent(handler);
 
        /* don't leak the pinfd to the container */
-       if (handler->pinfd >= 0)
+       if (handler->pinfd >= 0) {
+               process_lock();
                close(handler->pinfd);
+               process_unlock();
+       }
 
        /* Tell the parent task it can begin to configure the
         * container and wait for it to finish
@@ -560,7 +581,9 @@ static int do_start(void *data)
                goto out_warn_father;
        }
 
+       process_lock();
        close(handler->sigfd);
+       process_unlock();
 
        /* after this call, we are in error because this
         * ops should not return as it execs */
@@ -780,7 +803,9 @@ out_abort:
        lxc_abort(name, handler);
        lxc_sync_fini(handler);
        if (handler->pinfd >= 0) {
+               process_lock();
                close(handler->pinfd);
+               process_unlock();
                handler->pinfd = -1;
        }
 
@@ -852,7 +877,9 @@ int __lxc_start(const char *name, struct lxc_conf *conf,
        lxc_rename_phys_nics_on_shutdown(handler->conf);
 
        if (handler->pinfd >= 0) {
+               process_lock();
                close(handler->pinfd);
+               process_unlock();
                handler->pinfd = -1;
        }
 
index 398833aa99e2c1f615d4f9f764ab93d041badc89..92be56053252681bede4bbc33b78571b24653847 100644 (file)
@@ -39,6 +39,7 @@
 #include <lxc/monitor.h>
 #include "commands.h"
 #include "config.h"
+#include "lxclock.h"
 
 lxc_log_define(lxc_state, lxc);
 
@@ -83,14 +84,18 @@ static lxc_state_t freezer_state(const char *name, const char *lxcpath)
        if (ret < 0 || ret >= MAXPATHLEN)
                goto out;
 
+       process_lock();
        file = fopen(freezer, "r");
+       process_unlock();
        if (!file) {
                ret = -1;
                goto out;
        }
 
        ret = fscanf(file, "%s", status);
+       process_lock();
        fclose(file);
+       process_unlock();
 
        if (ret == EOF) {
                SYSERROR("failed to read %s", freezer);
index 4df2b5fad4fea8634ad30174143dd0452933de09..a3b4a1af353bd89265d9dcde9e1da28915be1807 100644 (file)
@@ -29,6 +29,7 @@
 
 #include "log.h"
 #include "start.h"
+#include "lxclock.h"
 
 lxc_log_define(lxc_sync, lxc);
 
@@ -99,7 +100,12 @@ int lxc_sync_wake_child(struct lxc_handler *handler, int sequence)
 
 int lxc_sync_init(struct lxc_handler *handler)
 {
-       if (socketpair(AF_LOCAL, SOCK_STREAM, 0, handler->sv)) {
+       int ret;
+
+       process_lock();
+       ret = socketpair(AF_LOCAL, SOCK_STREAM, 0, handler->sv);
+       process_unlock();
+       if (ret) {
                SYSERROR("failed to create synchronization socketpair");
                return -1;
        }
@@ -113,7 +119,9 @@ int lxc_sync_init(struct lxc_handler *handler)
 void lxc_sync_fini_child(struct lxc_handler *handler)
 {
        if (handler->sv[0] != -1) {
+               process_lock();
                close(handler->sv[0]);
+               process_unlock();
                handler->sv[0] = -1;
        }
 }
@@ -121,7 +129,9 @@ void lxc_sync_fini_child(struct lxc_handler *handler)
 void lxc_sync_fini_parent(struct lxc_handler *handler)
 {
        if (handler->sv[1] != -1) {
+               process_lock();
                close(handler->sv[1]);
+               process_unlock();
                handler->sv[1] = -1;
        }
 }
index 78b234d98313ae316e55c9bab6131e87445ef044..00e13d595263855387fe9da5b5a0619f4716e743 100644 (file)
@@ -47,6 +47,7 @@
 
 #include "utils.h"
 #include "log.h"
+#include "lxclock.h"
 
 lxc_log_define(lxc_utils, lxc);
 
@@ -57,7 +58,9 @@ static int _recursive_rmdir_onedev(char *dirname, dev_t pdev)
        int ret, failed=0;
        char pathname[MAXPATHLEN];
 
+       process_lock();
        dir = opendir(dirname);
+       process_unlock();
        if (!dir) {
                ERROR("%s: failed to open %s", __func__, dirname);
                return 0;
@@ -104,7 +107,10 @@ static int _recursive_rmdir_onedev(char *dirname, dev_t pdev)
                failed=1;
        }
 
-       if (closedir(dir)) {
+       process_lock();
+       ret = closedir(dir);
+       process_unlock();
+       if (ret) {
                ERROR("%s: failed to close directory %s", __func__, dirname);
                failed=1;
        }
@@ -253,7 +259,9 @@ const char *lxc_global_config_value(const char *option_name)
        if (values[i])
                return values[i];
 
+       process_lock();
        fin = fopen_cloexec(LXC_GLOBAL_CONF, "r");
+       process_unlock();
        if (fin) {
                while (fgets(buf, 1024, fin)) {
                        if (buf[0] == '#')
@@ -299,8 +307,10 @@ const char *lxc_global_config_value(const char *option_name)
                errno = 0;
 
 out:
+       process_lock();
        if (fin)
                fclose(fin);
+       process_unlock();
        return values[i];
 }
 
@@ -397,6 +407,15 @@ ssize_t lxc_read_nointr_expect(int fd, void* buf, size_t count, const void* expe
        return ret;
 }
 
+static inline int lock_fclose(FILE *f)
+{
+       int ret;
+       process_lock();
+       ret = fclose(f);
+       process_unlock();
+       return ret;
+}
+
 #if HAVE_LIBGNUTLS
 #include <gnutls/gnutls.h>
 #include <gnutls/crypto.h>
@@ -409,37 +428,40 @@ int sha1sum_file(char *fnam, unsigned char *digest)
 
        if (!fnam)
                return -1;
-       if ((f = fopen_cloexec(fnam, "r")) < 0) {
+       process_lock();
+       f = fopen_cloexec(fnam, "r");
+       process_unlock();
+       if (f < 0) {
                SYSERROR("Error opening template");
                return -1;
        }
        if (fseek(f, 0, SEEK_END) < 0) {
                SYSERROR("Error seeking to end of template");
-               fclose(f);
+               lock_fclose(f);
                return -1;
        }
        if ((flen = ftell(f)) < 0) {
                SYSERROR("Error telling size of template");
-               fclose(f);
+               lock_fclose(f);
                return -1;
        }
        if (fseek(f, 0, SEEK_SET) < 0) {
                SYSERROR("Error seeking to start of template");
-               fclose(f);
+               lock_fclose(f);
                return -1;
        }
        if ((buf = malloc(flen+1)) == NULL) {
                SYSERROR("Out of memory");
-               fclose(f);
+               lock_fclose(f);
                return -1;
        }
        if (fread(buf, 1, flen, f) != flen) {
                SYSERROR("Failure reading template");
                free(buf);
-               fclose(f);
+               lock_fclose(f);
                return -1;
        }
-       if (fclose(f) < 0) {
+       if (lock_fclose(f) < 0) {
                SYSERROR("Failre closing template");
                free(buf);
                return -1;
@@ -496,6 +518,10 @@ const char** lxc_va_arg_list_to_argv_const(va_list ap, size_t skip)
        return (const char**)lxc_va_arg_list_to_argv(ap, skip, 0);
 }
 
+/*
+ * fopen_cloexec: must be called with process_lock() held
+ * if it is needed.
+ */
 FILE *fopen_cloexec(const char *path, const char *mode)
 {
        int open_mode = 0;
@@ -847,7 +873,9 @@ int lxc_write_to_file(const char *filename, const void* buf, size_t count, bool
        int fd, saved_errno;
        ssize_t ret;
 
+       process_lock();
        fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT | O_CLOEXEC, 0666);
+       process_unlock();
        if (fd < 0)
                return -1;
        ret = lxc_write_nointr(fd, buf, count);
@@ -860,12 +888,16 @@ int lxc_write_to_file(const char *filename, const void* buf, size_t count, bool
                if (ret != 1)
                        goto out_error;
        }
+       process_lock();
        close(fd);
+       process_unlock();
        return 0;
 
 out_error:
        saved_errno = errno;
+       process_lock();
        close(fd);
+       process_unlock();
        errno = saved_errno;
        return -1;
 }
@@ -875,7 +907,9 @@ int lxc_read_from_file(const char *filename, void* buf, size_t count)
        int fd = -1, saved_errno;
        ssize_t ret;
 
+       process_lock();
        fd = open(filename, O_RDONLY | O_CLOEXEC);
+       process_unlock();
        if (fd < 0)
                return -1;
 
@@ -895,7 +929,9 @@ int lxc_read_from_file(const char *filename, void* buf, size_t count)
                ERROR("read %s: %s", filename, strerror(errno));
 
        saved_errno = errno;
+       process_lock();
        close(fd);
+       process_unlock();
        errno = saved_errno;
        return ret;
 }