X-Git-Url: http://git.efficios.com/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fcommon%2Frunas.c;h=e0c317c4e40347fb7001b74fb9900e9bcfafe32f;hp=07912a7d68bf7ce97cf7ba765194fd66e28334c8;hb=e71aad1fa4b06a5f91ddceace42366f3d79bd77e;hpb=ca4537d385628d3568a918409d909d3042ca7a38 diff --git a/src/common/runas.c b/src/common/runas.c index 07912a7d6..e0c317c4e 100644 --- a/src/common/runas.c +++ b/src/common/runas.c @@ -28,16 +28,29 @@ #include #include #include -#include +#include #include +#include +#include #include "runas.h" #define RUNAS_CHILD_STACK_SIZE 10485760 -#ifndef MAP_STACK -#define MAP_STACK 0 +#ifdef __FreeBSD__ +/* FreeBSD MAP_STACK always return -ENOMEM */ +#define LTTNG_MAP_STACK 0 +#else +#define LTTNG_MAP_STACK MAP_STACK +#endif + +#ifndef MAP_GROWSDOWN +#define MAP_GROWSDOWN 0 +#endif + +#ifndef MAP_ANONYMOUS +#define MAP_ANONYMOUS MAP_ANON #endif struct run_as_data { @@ -154,14 +167,14 @@ int child_run_as(void *_data) if (data->gid != getegid()) { ret = setegid(data->gid); if (ret < 0) { - perror("setegid"); + PERROR("setegid"); return EXIT_FAILURE; } } if (data->uid != geteuid()) { ret = seteuid(data->uid); if (ret < 0) { - perror("seteuid"); + PERROR("seteuid"); return EXIT_FAILURE; } } @@ -177,7 +190,7 @@ int child_run_as(void *_data) writelen = write(data->retval_pipe, &sendret.c[index], writeleft); if (writelen < 0) { - perror("write"); + PERROR("write"); return EXIT_FAILURE; } writeleft -= writelen; @@ -187,7 +200,7 @@ int child_run_as(void *_data) } static -int run_as(int (*cmd)(void *data), void *data, uid_t uid, gid_t gid) +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; @@ -214,7 +227,8 @@ int run_as(int (*cmd)(void *data), void *data, uid_t uid, gid_t gid) ret = pipe(retval_pipe); if (ret < 0) { - perror("pipe"); + PERROR("pipe"); + retval.i = ret; goto end; } run_as_data.data = data; @@ -224,23 +238,22 @@ int run_as(int (*cmd)(void *data), void *data, uid_t uid, gid_t gid) run_as_data.retval_pipe = retval_pipe[1]; /* write end */ child_stack = mmap(NULL, RUNAS_CHILD_STACK_SIZE, PROT_WRITE | PROT_READ, - MAP_PRIVATE | MAP_GROWSDOWN | MAP_ANONYMOUS | MAP_STACK, + MAP_PRIVATE | MAP_GROWSDOWN | MAP_ANONYMOUS | LTTNG_MAP_STACK, -1, 0); if (child_stack == MAP_FAILED) { - perror("mmap"); - ret = -ENOMEM; + PERROR("mmap"); + retval.i = -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 + (RUNAS_CHILD_STACK_SIZE / 2), - CLONE_FILES | SIGCHLD, - &run_as_data, NULL); + pid = lttng_clone_files(child_run_as, child_stack + (RUNAS_CHILD_STACK_SIZE / 2), + &run_as_data); if (pid < 0) { - perror("clone"); - ret = pid; + PERROR("clone"); + retval.i = pid; goto unmap_stack; } /* receive return value */ @@ -249,7 +262,7 @@ int run_as(int (*cmd)(void *data), void *data, uid_t uid, gid_t gid) do { readlen = read(retval_pipe[0], &retval.c[index], readleft); if (readlen < 0) { - perror("read"); + PERROR("read"); ret = -1; break; } @@ -263,21 +276,51 @@ int run_as(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"); - ret = -1; + PERROR("wait"); + retval.i = -1; } unmap_stack: ret = munmap(child_stack, RUNAS_CHILD_STACK_SIZE); if (ret < 0) { - perror("munmap"); + PERROR("munmap"); + retval.i = ret; } close_pipe: - close(retval_pipe[0]); - close(retval_pipe[1]); + ret = close(retval_pipe[0]); + if (ret) { + PERROR("close"); + } + ret = close(retval_pipe[1]); + if (ret) { + PERROR("close"); + } end: return retval.i; } +/* + * To be used on setups where gdb has issues debugging programs using + * clone/rfork. Note that this is for debuging ONLY, and should not be + * considered secure. + */ +static +int run_as_noclone(int (*cmd)(void *data), void *data, uid_t uid, gid_t gid) +{ + return cmd(data); +} + +static +int run_as(int (*cmd)(void *data), void *data, uid_t uid, gid_t gid) +{ + if (!getenv("LTTNG_DEBUG_NOCLONE")) { + DBG("Using run_as_clone"); + return run_as_clone(cmd, data, uid, gid); + } else { + DBG("Using run_as_noclone"); + return run_as_noclone(cmd, data, uid, gid); + } +} + int run_as_mkdir_recursive(const char *path, mode_t mode, uid_t uid, gid_t gid) { struct run_as_mkdir_data data;