X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fcommon%2Frunas.c;h=36be188fafb54036688930689d1d23781cbe000d;hp=d75eb21027ce0ae2b7df768698d8c913bb4297ea;hb=d77dded285b058e4242c8a3d2233f80e725ceefc;hpb=3fd15a7429ca3f5307a783e264155ae0218511ec diff --git a/src/common/runas.c b/src/common/runas.c index d75eb2102..36be188fa 100644 --- a/src/common/runas.c +++ b/src/common/runas.c @@ -17,6 +17,7 @@ */ #define _GNU_SOURCE +#define _LGPL_SOURCE #include #include #include @@ -30,10 +31,11 @@ #include #include -#include +#include #include #include #include +#include #include "runas.h" @@ -77,6 +79,31 @@ struct run_as_open_data { mode_t mode; }; +struct run_as_unlink_data { + const char *path; +}; + +struct run_as_recursive_rmdir_data { + const char *path; +}; + +#ifdef VALGRIND +static +int use_clone(void) +{ + return 0; +} +#else +static +int use_clone(void) +{ + return !lttng_secure_getenv("LTTNG_DEBUG_NOCLONE"); +} +#endif + +LTTNG_HIDDEN +int _utils_mkdir_recursive_unsafe(const char *path, mode_t mode); + /* * Create recursively directory using the FULL path. */ @@ -90,14 +117,22 @@ int _mkdir_recursive(void *_data) path = data->path; mode = data->mode; - return utils_mkdir_recursive(path, mode); + /* Safe to call as we have transitioned to the requested uid/gid. */ + return _utils_mkdir_recursive_unsafe(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 @@ -107,17 +142,41 @@ int _open(void *_data) return open(data->path, data->flags, data->mode); } +static +int _unlink(void *_data) +{ + int ret; + struct run_as_unlink_data *data = _data; + + ret = unlink(data->path); + if (ret < 0) { + ret = -errno; + } + + return ret; +} + +static +int _recursive_rmdir(void *_data) +{ + int ret; + struct run_as_recursive_rmdir_data *data = _data; + + ret = utils_recursive_rmdir(data->path); + if (ret < 0) { + ret = -errno; + } + + return ret; +} + static 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 @@ -130,37 +189,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 { - do { - writelen = write(data->retval_pipe, &sendret.c[index], - writeleft); - } while (writelen < 0 && errno == EINTR); - 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 @@ -168,15 +223,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. @@ -192,7 +244,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; @@ -206,7 +258,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; } /* @@ -217,22 +269,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 @@ -241,13 +285,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]); @@ -259,7 +303,7 @@ close_pipe: PERROR("close"); } end: - return retval.i; + return retval; } /* @@ -283,7 +327,7 @@ int run_as_noclone(int (*cmd)(void *data), void *data, uid_t uid, gid_t gid) static int run_as(int (*cmd)(void *data), void *data, uid_t uid, gid_t gid) { - if (!getenv("LTTNG_DEBUG_NOCLONE")) { + if (use_clone()) { int ret; DBG("Using run_as_clone"); @@ -297,7 +341,7 @@ int run_as(int (*cmd)(void *data), void *data, uid_t uid, gid_t gid) } } -__attribute__((visibility("hidden"))) +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; @@ -309,7 +353,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); } -__attribute__((visibility("hidden"))) +LTTNG_HIDDEN int run_as_mkdir(const char *path, mode_t mode, uid_t uid, gid_t gid) { struct run_as_mkdir_data data; @@ -325,7 +369,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. */ -__attribute__((visibility("hidden"))) +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; @@ -337,3 +381,25 @@ int run_as_open(const char *path, int flags, mode_t mode, uid_t uid, gid_t gid) data.mode = mode; return run_as(_open, &data, uid, gid); } + +LTTNG_HIDDEN +int run_as_unlink(const char *path, uid_t uid, gid_t gid) +{ + struct run_as_unlink_data data; + + DBG3("unlink() %s with for uid %d and gid %d", + path, uid, gid); + data.path = path; + return run_as(_unlink, &data, uid, gid); +} + +LTTNG_HIDDEN +int run_as_recursive_rmdir(const char *path, uid_t uid, gid_t gid) +{ + struct run_as_recursive_rmdir_data data; + + DBG3("recursive_rmdir() %s with for uid %d and gid %d", + path, uid, gid); + data.path = path; + return run_as(_recursive_rmdir, &data, uid, gid); +}