Fix: race with index file creation
[lttng-tools.git] / src / common / runas.c
index 3a89cc9ab8d1f73795ca2d9f963fd34423911cbb..9029f8f74d7802416a97a5f22a0650da9378ce68 100644 (file)
@@ -30,7 +30,8 @@
 #include <sched.h>
 #include <sys/signal.h>
 
-#include <common/error.h>
+#include <common/common.h>
+#include <common/utils.h>
 #include <common/compat/mman.h>
 #include <common/compat/clone.h>
 
@@ -84,63 +85,26 @@ int _mkdir_recursive(void *_data)
 {
        struct run_as_mkdir_data *data = _data;
        const char *path;
-       char *p, tmp[PATH_MAX];
-       struct stat statbuf;
        mode_t mode;
-       size_t len;
-       int ret;
 
        path = data->path;
        mode = data->mode;
 
-       ret = snprintf(tmp, sizeof(tmp), "%s", path);
-       if (ret < 0) {
-               PERROR("snprintf mkdir");
-               goto error;
-       }
-
-       len = ret;
-       if (tmp[len - 1] == '/') {
-               tmp[len - 1] = 0;
-       }
-
-       for (p = tmp + 1; *p; p++) {
-               if (*p == '/') {
-                       *p = 0;
-                       ret = stat(tmp, &statbuf);
-                       if (ret < 0) {
-                               ret = mkdir(tmp, mode);
-                               if (ret < 0) {
-                                       if (!(errno == EEXIST)) {
-                                               PERROR("mkdir recursive");
-                                               ret = -errno;
-                                               goto error;
-                                       }
-                               }
-                       }
-                       *p = '/';
-               }
-       }
-
-       ret = mkdir(tmp, mode);
-       if (ret < 0) {
-               if (!(errno == EEXIST)) {
-                       PERROR("mkdir recursive last piece");
-                       ret = -errno;
-               } else {
-                       ret = 0;
-               }
-       }
-
-error:
-       return ret;
+       return utils_mkdir_recursive(path, mode);
 }
 
 static
 int _mkdir(void *_data)
 {
+       int ret;
        struct run_as_mkdir_data *data = _data;
-       return mkdir(data->path, data->mode);
+
+       ret = mkdir(data->path, data->mode);
+       if (ret < 0) {
+               ret = -errno;
+       }
+
+       return ret;
 }
 
 static
@@ -156,11 +120,7 @@ int child_run_as(void *_data)
        int ret;
        struct run_as_data *data = _data;
        ssize_t writelen;
-       size_t writeleft, index;
-       union {
-               int i;
-               char c[sizeof(int)];
-       } sendret;
+       int sendret;
 
        /*
         * Child: it is safe to drop egid and euid while sharing the
@@ -173,35 +133,33 @@ int child_run_as(void *_data)
                ret = setegid(data->gid);
                if (ret < 0) {
                        PERROR("setegid");
-                       return EXIT_FAILURE;
+                       sendret = -1;
+                       goto write_return;
                }
        }
        if (data->uid != geteuid()) {
                ret = seteuid(data->uid);
                if (ret < 0) {
                        PERROR("seteuid");
-                       return EXIT_FAILURE;
+                       sendret = -1;
+                       goto write_return;
                }
        }
        /*
         * Also set umask to 0 for mkdir executable bit.
         */
        umask(0);
-       sendret.i = (*data->cmd)(data->data);
+       sendret = (*data->cmd)(data->data);
+
+write_return:
        /* send back return value */
-       writeleft = sizeof(sendret);
-       index = 0;
-       do {
-               writelen = write(data->retval_pipe, &sendret.c[index],
-                               writeleft);
-               if (writelen < 0) {
-                       PERROR("write");
-                       return EXIT_FAILURE;
-               }
-               writeleft -= writelen;
-               index += writelen;
-       } while (writeleft > 0);
-       return EXIT_SUCCESS;
+       writelen = lttng_write(data->retval_pipe, &sendret, sizeof(sendret));
+       if (writelen < sizeof(sendret)) {
+               PERROR("lttng_write error");
+               return EXIT_FAILURE;
+       } else {
+               return EXIT_SUCCESS;
+       }
 }
 
 static
@@ -209,15 +167,12 @@ int run_as_clone(int (*cmd)(void *data), void *data, uid_t uid, gid_t gid)
 {
        struct run_as_data run_as_data;
        int ret = 0;
+       ssize_t readlen;
        int status;
        pid_t pid;
        int retval_pipe[2];
-       ssize_t readlen, readleft, index;
        void *child_stack;
-       union {
-               int i;
-               char c[sizeof(int)];
-       } retval;
+       int retval;
 
        /*
         * If we are non-root, we can only deal with our own uid.
@@ -233,7 +188,7 @@ int run_as_clone(int (*cmd)(void *data), void *data, uid_t uid, gid_t gid)
        ret = pipe(retval_pipe);
        if (ret < 0) {
                PERROR("pipe");
-               retval.i = ret;
+               retval = ret;
                goto end;
        }
        run_as_data.data = data;
@@ -247,7 +202,7 @@ int run_as_clone(int (*cmd)(void *data), void *data, uid_t uid, gid_t gid)
                -1, 0);
        if (child_stack == MAP_FAILED) {
                PERROR("mmap");
-               retval.i = -ENOMEM;
+               retval = -ENOMEM;
                goto close_pipe;
        }
        /*
@@ -258,22 +213,14 @@ int run_as_clone(int (*cmd)(void *data), void *data, uid_t uid, gid_t gid)
                &run_as_data);
        if (pid < 0) {
                PERROR("clone");
-               retval.i = pid;
+               retval = pid;
                goto unmap_stack;
        }
        /* receive return value */
-       readleft = sizeof(retval);
-       index = 0;
-       do {
-               readlen = read(retval_pipe[0], &retval.c[index], readleft);
-               if (readlen < 0) {
-                       PERROR("read");
-                       ret = -1;
-                       break;
-               }
-               readleft -= readlen;
-               index += readlen;
-       } while (readleft > 0);
+       readlen = lttng_read(retval_pipe[0], &retval, sizeof(retval));
+       if (readlen < sizeof(retval)) {
+               ret = -1;
+       }
 
        /*
         * Parent: wait for child to return, in which case the
@@ -282,13 +229,13 @@ int run_as_clone(int (*cmd)(void *data), void *data, uid_t uid, gid_t gid)
        pid = waitpid(pid, &status, 0);
        if (pid < 0 || !WIFEXITED(status) || WEXITSTATUS(status) != 0) {
                PERROR("wait");
-               retval.i = -1;
+               retval = -1;
        }
 unmap_stack:
        ret = munmap(child_stack, RUNAS_CHILD_STACK_SIZE);
        if (ret < 0) {
                PERROR("munmap");
-               retval.i = ret;
+               retval = ret;
        }
 close_pipe:
        ret = close(retval_pipe[0]);
@@ -300,7 +247,7 @@ close_pipe:
                PERROR("close");
        }
 end:
-       return retval.i;
+       return retval;
 }
 
 /*
@@ -311,7 +258,14 @@ end:
 static
 int run_as_noclone(int (*cmd)(void *data), void *data, uid_t uid, gid_t gid)
 {
-       return cmd(data);
+       int ret;
+       mode_t old_mask;
+
+       old_mask = umask(0);
+       ret = cmd(data);
+       umask(old_mask);
+
+       return ret;
 }
 
 static
@@ -331,6 +285,7 @@ int run_as(int (*cmd)(void *data), void *data, uid_t uid, gid_t gid)
        }
 }
 
+LTTNG_HIDDEN
 int run_as_mkdir_recursive(const char *path, mode_t mode, uid_t uid, gid_t gid)
 {
        struct run_as_mkdir_data data;
@@ -342,6 +297,7 @@ int run_as_mkdir_recursive(const char *path, mode_t mode, uid_t uid, gid_t gid)
        return run_as(_mkdir_recursive, &data, uid, gid);
 }
 
+LTTNG_HIDDEN
 int run_as_mkdir(const char *path, mode_t mode, uid_t uid, gid_t gid)
 {
        struct run_as_mkdir_data data;
@@ -357,6 +313,7 @@ int run_as_mkdir(const char *path, mode_t mode, uid_t uid, gid_t gid)
  * Note: open_run_as is currently not working. We'd need to pass the fd
  * opened in the child to the parent.
  */
+LTTNG_HIDDEN
 int run_as_open(const char *path, int flags, mode_t mode, uid_t uid, gid_t gid)
 {
        struct run_as_open_data data;
This page took 0.0273 seconds and 4 git commands to generate.