X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=lttng-sessiond%2Futils.c;h=1e08de77d4ca2854611c6a7372a769a9c7bdeb5e;hb=67f747d8095da3f240f71e33c4a1eb0f84aa5e41;hp=0da5642109fcc5ddf7eeced026a0d441cb685594;hpb=322585731ced1adba36cddcb8bdd5d997d1b2e3e;p=lttng-tools.git diff --git a/lttng-sessiond/utils.c b/lttng-sessiond/utils.c index 0da564210..1e08de77d 100644 --- a/lttng-sessiond/utils.c +++ b/lttng-sessiond/utils.c @@ -22,14 +22,27 @@ #include #include #include +#include #include #include #include +#include #include #include "utils.h" +struct mkdir_data { + const char *path; + mode_t mode; +}; + +struct open_data { + const char *path; + int flags; + mode_t mode; +}; + /* * Write to writable pipe used to notify a thread. */ @@ -58,12 +71,19 @@ 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(void *_data) { - int ret; + struct mkdir_data *data = _data; + const char *path; char *p, tmp[PATH_MAX]; + struct stat statbuf; + mode_t mode; size_t len; - mode_t old_umask; + int ret; + + path = data->path; + mode = data->mode; ret = snprintf(tmp, sizeof(tmp), "%s", path); if (ret < 0) { @@ -76,27 +96,18 @@ int mkdir_recursive(const char *path, mode_t mode, uid_t uid, gid_t gid) tmp[len - 1] = 0; } - old_umask = umask(0); for (p = tmp + 1; *p; p++) { if (*p == '/') { *p = 0; - ret = mkdir(tmp, mode); + ret = stat(tmp, &statbuf); if (ret < 0) { - if (!(errno == EEXIST)) { - PERROR("mkdir recursive"); - 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); + ret = mkdir(tmp, mode); if (ret < 0) { - PERROR("chown in mkdir recursive"); - ret = -errno; - goto umask_error; + if (!(errno == EEXIST)) { + PERROR("mkdir recursive"); + ret = -errno; + goto error; + } } } *p = '/'; @@ -111,21 +122,113 @@ int mkdir_recursive(const char *path, mode_t mode, uid_t uid, gid_t gid) } else { ret = 0; } - } else if (ret == 0) { + } + +error: + return ret; +} + +static +int _mkdir(void *_data) +{ + struct mkdir_data *data = _data; + return mkdir(data->path, data->mode); +} + +static +int _open(void *_data) +{ + struct open_data *data = _data; + return open(data->path, data->flags, data->mode); +} + +static +int run_as(int (*cmd)(void *data), void *data, 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)(data); + } + + pid = fork(); + if (pid > 0) { + int status; + /* - * We created the directory. Set its ownership to the user/group - * specified. + * Parent: wait for child to return, in which case the + * shared memory map will have been created. */ - ret = chown(tmp, uid, gid); + 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("chown in mkdir recursive"); - ret = -errno; - goto umask_error; + perror("setegid"); + exit(EXIT_FAILURE); } + ret = seteuid(uid); + if (ret < 0) { + perror("seteuid"); + exit(EXIT_FAILURE); + } + umask(0); + ret = (*cmd)(data); + if (!ret) + exit(EXIT_SUCCESS); + else + exit(EXIT_FAILURE); + } else { + return -1; } - -umask_error: - umask(old_umask); -error: +end: return ret; } + +int mkdir_recursive_run_as(const char *path, mode_t mode, uid_t uid, gid_t gid) +{ + struct mkdir_data data; + + DBG3("mkdir() recursive %s with mode %d for uid %d and gid %d", + path, mode, uid, gid); + data.path = path; + data.mode = mode; + return run_as(_mkdir_recursive, &data, uid, gid); +} + +int mkdir_run_as(const char *path, mode_t mode, uid_t uid, gid_t gid) +{ + struct mkdir_data data; + + DBG3("mkdir() %s with mode %d for uid %d and gid %d", + path, mode, uid, gid); + data.path = path; + data.mode = mode; + return run_as(_mkdir, &data, uid, gid); +} + +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 %d mode %d for uid %d and gid %d", + path, flags, mode, uid, gid); + data.path = path; + data.flags = flags; + data.mode = mode; + return run_as(_open, &data, uid, gid); +}