Move hash table to common/ directory
[lttng-tools.git] / librunas / runas.c
index 12327c1111fd15715174d41947f5e41db26beca3..f612ccc7554590a44fdeca167a33f29d4b0ee0d0 100644 (file)
 #include <unistd.h>
 #include <fcntl.h>
 #include <sched.h>
+#include <sys/mman.h>
 
 #include <lttngerr.h>
 
-/*
- * We allocate a stack of twice this size and point in the middle of it
- * to support archs with stack growing up and down.
- */
-#define CHILD_STACK_SIZE 2048
+#define CHILD_STACK_SIZE       10485760
 
 struct run_as_data {
        int (*cmd)(void *data);
@@ -148,15 +145,19 @@ int child_run_as(void *_data)
         * cannot attach to this process with, e.g. ptrace, nor map this
         * process memory.
         */
-       ret = setegid(data->gid);
-       if (ret < 0) {
-               perror("setegid");
-               exit(EXIT_FAILURE);
+       if (data->gid != getegid()) {
+               ret = setegid(data->gid);
+               if (ret < 0) {
+                       perror("setegid");
+                       return EXIT_FAILURE;
+               }
        }
-       ret = seteuid(data->uid);
-       if (ret < 0) {
-               perror("seteuid");
-               exit(EXIT_FAILURE);
+       if (data->uid != geteuid()) {
+               ret = seteuid(data->uid);
+               if (ret < 0) {
+                       perror("seteuid");
+                       return EXIT_FAILURE;
+               }
        }
        /*
         * Also set umask to 0 for mkdir executable bit.
@@ -171,13 +172,12 @@ int child_run_as(void *_data)
                                writeleft);
                if (writelen < 0) {
                        perror("write");
-                       exit(EXIT_FAILURE);
+                       return EXIT_FAILURE;
                }
                writeleft -= writelen;
                index += writelen;
        } while (writeleft > 0);
-
-       exit(EXIT_SUCCESS);
+       return EXIT_SUCCESS;
 }
 
 static
@@ -187,9 +187,9 @@ int run_as(int (*cmd)(void *data), void *data, uid_t uid, gid_t gid)
        int ret = 0;
        int status;
        pid_t pid;
-       char *child_stack;
        int retval_pipe[2];
        ssize_t readlen, readleft, index;
+       void *child_stack;
        union {
                int i;
                char c[sizeof(int)];
@@ -204,13 +204,8 @@ int run_as(int (*cmd)(void *data), void *data, uid_t uid, gid_t gid)
                                uid, geteuid());
                        return -EPERM;
                }
-               return (*cmd)(data);
        }
 
-       child_stack = malloc(CHILD_STACK_SIZE * 2);
-       if (!child_stack) {
-               return -ENOMEM;
-       }
        ret = pipe(retval_pipe);
        if (ret < 0) {
                perror("pipe");
@@ -221,13 +216,26 @@ int run_as(int (*cmd)(void *data), void *data, uid_t uid, gid_t gid)
        run_as_data.uid = uid;
        run_as_data.gid = gid;
        run_as_data.retval_pipe = retval_pipe[1];       /* write end */
-
-       pid = clone(child_run_as, child_stack + CHILD_STACK_SIZE,
-               CLONE_FILES | SIGCHLD, &run_as_data, NULL);
+       child_stack = mmap(NULL, CHILD_STACK_SIZE,
+               PROT_WRITE | PROT_READ,
+               MAP_PRIVATE | MAP_GROWSDOWN | MAP_ANONYMOUS | MAP_STACK,
+               -1, 0);
+       if (child_stack == MAP_FAILED) {
+               perror("mmap");
+               ret = -ENOMEM;
+               goto close_pipe;
+       }
+       /*
+        * Pointing to the middle of the stack to support architectures
+        * where the stack grows up (HPPA).
+        */
+       pid = clone(child_run_as, child_stack + (CHILD_STACK_SIZE / 2),
+               CLONE_FILES | SIGCHLD | CLONE_VM,
+               &run_as_data, NULL);
        if (pid < 0) {
                perror("clone");
                ret = pid;
-               goto close_pipe;
+               goto unmap_stack;
        }
        /* receive return value */
        readleft = sizeof(retval);
@@ -247,16 +255,20 @@ int run_as(int (*cmd)(void *data), void *data, uid_t uid, gid_t gid)
         * Parent: wait for child to return, in which case the
         * shared memory map will have been created.
         */
-       pid = wait(&status);
+       pid = waitpid(pid, &status, 0);
        if (pid < 0 || !WIFEXITED(status) || WEXITSTATUS(status) != 0) {
                perror("wait");
                ret = -1;
        }
+unmap_stack:
+       ret = munmap(child_stack, CHILD_STACK_SIZE);
+       if (ret < 0) {
+               perror("munmap");
+       }
 close_pipe:
        close(retval_pipe[0]);
        close(retval_pipe[1]);
 end:
-       free(child_stack);
        return retval.i;
 }
 
@@ -290,6 +302,8 @@ int open_run_as(const char *path, int flags, mode_t mode, uid_t uid, gid_t gid)
 {
        struct open_data data;
 
+       DBG3("open() %s with flags %X mode %d for uid %d and gid %d",
+                       path, flags, mode, uid, gid);
        data.path = path;
        data.flags = flags;
        data.mode = mode;
This page took 0.024677 seconds and 4 git commands to generate.