From: Mathieu Desnoyers Date: Tue, 20 Dec 2011 21:09:32 +0000 (-0500) Subject: Introduce run_as for mkdir_recursive X-Git-Tag: v2.0-pre16~11 X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=commitdiff_plain;h=fedf5c6b82a7bc13c358ab5b02a204631e3f94e1 Introduce run_as for mkdir_recursive Signed-off-by: Mathieu Desnoyers --- diff --git a/lttng-sessiond/utils.c b/lttng-sessiond/utils.c index fe1866ac7..489b61af8 100644 --- a/lttng-sessiond/utils.c +++ b/lttng-sessiond/utils.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -58,16 +59,14 @@ const char *get_home_dir(void) /* * Create recursively directory using the FULL path. */ -int mkdir_recursive(const char *path, mode_t mode, uid_t uid, gid_t gid) +static +int _mkdir_recursive(const char *path, mode_t mode, uid_t uid, gid_t gid) { int ret; char *p, tmp[PATH_MAX]; size_t len; mode_t old_umask; - DBG3("mkdir() recursive %s with mode %d for uid %d and gid %d", path, mode, - uid, gid); - ret = snprintf(tmp, sizeof(tmp), "%s", path); if (ret < 0) { PERROR("snprintf mkdir"); @@ -90,17 +89,6 @@ int mkdir_recursive(const char *path, mode_t mode, uid_t uid, gid_t gid) ret = -errno; goto umask_error; } - } else if (ret == 0) { - /* - * We created the directory. Set its ownership to the - * user/group specified. - */ - ret = chown(tmp, uid, gid); - if (ret < 0) { - PERROR("chown in mkdir recursive"); - ret = -errno; - goto umask_error; - } } *p = '/'; } @@ -114,17 +102,6 @@ int mkdir_recursive(const char *path, mode_t mode, uid_t uid, gid_t gid) } else { ret = 0; } - } else if (ret == 0) { - /* - * We created the directory. Set its ownership to the user/group - * specified. - */ - ret = chown(tmp, uid, gid); - if (ret < 0) { - PERROR("chown in mkdir recursive"); - ret = -errno; - goto umask_error; - } } umask_error: @@ -132,3 +109,67 @@ umask_error: error: return ret; } + +static +int run_as(int (*cmd)(const char *path, mode_t mode, uid_t uid, gid_t gid), + const char *path, mode_t mode, uid_t uid, gid_t gid) +{ + int ret = 0; + pid_t pid; + + /* + * If we are non-root, we can only deal with our own uid. + */ + if (geteuid() != 0) { + if (uid != geteuid()) { + ERR("Client (%d)/Server (%d) UID mismatch (and sessiond is not root)", + uid, geteuid()); + return -EPERM; + } + return (*cmd)(path, mode, uid, gid); + } + + pid = fork(); + if (pid > 0) { + int status; + + /* + * Parent: wait for child to return, in which case the + * shared memory map will have been created. + */ + pid = wait(&status); + if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { + ret = -1; + goto end; + } + goto end; + } else if (pid == 0) { + /* Child */ + setegid(gid); + if (ret < 0) { + perror("setegid"); + exit(EXIT_FAILURE); + } + ret = seteuid(uid); + if (ret < 0) { + perror("seteuid"); + exit(EXIT_FAILURE); + } + ret = (*cmd)(path, mode, uid, gid); + if (!ret) + exit(EXIT_SUCCESS); + else + exit(EXIT_FAILURE); + } else { + return -1; + } +end: + return ret; +} + +int mkdir_recursive(const char *path, mode_t mode, uid_t uid, gid_t gid) +{ + DBG3("mkdir() recursive %s with mode %d for uid %d and gid %d", + path, mode, uid, gid); + return run_as(_mkdir_recursive, path, mode, uid, gid); +}