X-Git-Url: https://git.lttng.org/?a=blobdiff_plain;f=src%2Fcommon%2Frunas.c;h=ef169d3207903367d6e38e9625b656b210f98d02;hb=0d88e04674ead21c741c6f4ed7fadf666c5e7bce;hp=adbbe3e97a8446b514f5ac7ec308f0d217730115;hpb=a01c682b9919f98d45a9127b6e02fd08dcc900bc;p=lttng-tools.git diff --git a/src/common/runas.c b/src/common/runas.c index adbbe3e97..ef169d320 100644 --- a/src/common/runas.c +++ b/src/common/runas.c @@ -49,7 +49,7 @@ struct run_as_data; struct run_as_ret; typedef int (*run_as_fct)(struct run_as_data *data, struct run_as_ret *ret_value); -struct run_as_mkdir_data { +struct run_as_mkdirat_data { char path[PATH_MAX]; mode_t mode; }; @@ -77,7 +77,7 @@ struct run_as_extract_sdt_probe_offsets_data { char provider_name[LTTNG_SYMBOL_NAME_LEN]; }; -struct run_as_mkdir_ret { +struct run_as_mkdirat_ret { int ret; }; @@ -104,10 +104,14 @@ struct run_as_extract_sdt_probe_offsets_ret { enum run_as_cmd { RUN_AS_MKDIR, + RUN_AS_MKDIRAT, + RUN_AS_MKDIR_RECURSIVE, + RUN_AS_MKDIRAT_RECURSIVE, RUN_AS_OPEN, + RUN_AS_OPENAT, RUN_AS_UNLINK, + RUN_AS_UNLINKAT, RUN_AS_RMDIR_RECURSIVE, - RUN_AS_MKDIR_RECURSIVE, RUN_AS_EXTRACT_ELF_SYMBOL_OFFSET, RUN_AS_EXTRACT_SDT_PROBE_OFFSETS, }; @@ -116,7 +120,7 @@ struct run_as_data { enum run_as_cmd cmd; int fd; union { - struct run_as_mkdir_data mkdir; + struct run_as_mkdirat_data mkdirat; struct run_as_open_data open; struct run_as_unlink_data unlink; struct run_as_rmdir_recursive_data rmdir_recursive; @@ -145,7 +149,7 @@ struct run_as_data { struct run_as_ret { int fd; union { - struct run_as_mkdir_ret mkdir; + struct run_as_mkdirat_ret mkdirat; struct run_as_open_ret open; struct run_as_unlink_ret unlink; struct run_as_rmdir_recursive_ret rmdir_recursive; @@ -181,41 +185,60 @@ int use_clone(void) } #endif -LTTNG_HIDDEN -int _utils_mkdir_recursive_unsafe(const char *path, mode_t mode); - /* * Create recursively directory using the FULL path. */ static -int _mkdir_recursive(struct run_as_data *data, struct run_as_ret *ret_value) +int _mkdirat_recursive(struct run_as_data *data, struct run_as_ret *ret_value) { const char *path; mode_t mode; + struct lttng_directory_handle handle; - path = data->u.mkdir.path; - mode = data->u.mkdir.mode; + path = data->u.mkdirat.path; + mode = data->u.mkdirat.mode; + (void) lttng_directory_handle_init_from_dirfd(&handle, data->fd); + /* Ownership of dirfd is transferred to the handle. */ + data->fd = -1; /* Safe to call as we have transitioned to the requested uid/gid. */ - ret_value->u.mkdir.ret = _utils_mkdir_recursive_unsafe(path, mode); + ret_value->u.mkdirat.ret = + lttng_directory_handle_create_subdirectory_recursive( + &handle, path, mode); ret_value->_errno = errno; - ret_value->_error = (ret_value->u.mkdir.ret) ? true : false; - return ret_value->u.mkdir.ret; + ret_value->_error = (ret_value->u.mkdirat.ret) ? true : false; + lttng_directory_handle_fini(&handle); + return ret_value->u.mkdirat.ret; } static -int _mkdir(struct run_as_data *data, struct run_as_ret *ret_value) +int _mkdirat(struct run_as_data *data, struct run_as_ret *ret_value) { - ret_value->u.mkdir.ret = mkdir(data->u.mkdir.path, data->u.mkdir.mode); + const char *path; + mode_t mode; + struct lttng_directory_handle handle; + + path = data->u.mkdirat.path; + mode = data->u.mkdirat.mode; + + (void) lttng_directory_handle_init_from_dirfd(&handle, data->fd); + /* Ownership of dirfd is transferred to the handle. */ + data->fd = -1; + /* Safe to call as we have transitioned to the requested uid/gid. */ + ret_value->u.mkdirat.ret = + lttng_directory_handle_create_subdirectory( + &handle, path, mode); ret_value->_errno = errno; - ret_value->_error = (ret_value->u.mkdir.ret) ? true : false; - return ret_value->u.mkdir.ret; + ret_value->_error = (ret_value->u.mkdirat.ret) ? true : false; + lttng_directory_handle_fini(&handle); + return ret_value->u.mkdirat.ret; } static int _open(struct run_as_data *data, struct run_as_ret *ret_value) { - ret_value->u.open.ret = open(data->u.open.path, data->u.open.flags, data->u.open.mode); + ret_value->u.open.ret = openat(data->fd, data->u.open.path, + data->u.open.flags, data->u.open.mode); ret_value->fd = ret_value->u.open.ret; ret_value->_errno = errno; ret_value->_error = ret_value->u.open.ret < 0; @@ -225,7 +248,7 @@ int _open(struct run_as_data *data, struct run_as_ret *ret_value) static int _unlink(struct run_as_data *data, struct run_as_ret *ret_value) { - ret_value->u.unlink.ret = unlink(data->u.unlink.path); + ret_value->u.unlink.ret = unlinkat(data->fd, data->u.unlink.path, 0); ret_value->_errno = errno; ret_value->_error = (ret_value->u.unlink.ret) ? true : false; return ret_value->u.unlink.ret; @@ -322,15 +345,19 @@ run_as_fct run_as_enum_to_fct(enum run_as_cmd cmd) { switch (cmd) { case RUN_AS_MKDIR: - return _mkdir; + case RUN_AS_MKDIRAT: + return _mkdirat; + case RUN_AS_MKDIR_RECURSIVE: + case RUN_AS_MKDIRAT_RECURSIVE: + return _mkdirat_recursive; case RUN_AS_OPEN: + case RUN_AS_OPENAT: return _open; case RUN_AS_UNLINK: + case RUN_AS_UNLINKAT: return _unlink; case RUN_AS_RMDIR_RECURSIVE: return _rmdir_recursive; - case RUN_AS_MKDIR_RECURSIVE: - return _mkdir_recursive; case RUN_AS_EXTRACT_ELF_SYMBOL_OFFSET: return _extract_elf_symbol_offset; case RUN_AS_EXTRACT_SDT_PROBE_OFFSETS: @@ -390,6 +417,10 @@ int send_fd_to_worker(struct run_as_worker *worker, enum run_as_cmd cmd, int fd) switch (cmd) { case RUN_AS_EXTRACT_ELF_SYMBOL_OFFSET: case RUN_AS_EXTRACT_SDT_PROBE_OFFSETS: + case RUN_AS_MKDIRAT: + case RUN_AS_MKDIRAT_RECURSIVE: + case RUN_AS_OPENAT: + case RUN_AS_UNLINKAT: break; default: return 0; @@ -416,6 +447,7 @@ int send_fd_to_master(struct run_as_worker *worker, enum run_as_cmd cmd, int fd) switch (cmd) { case RUN_AS_OPEN: + case RUN_AS_OPENAT: break; default: return 0; @@ -446,6 +478,7 @@ int recv_fd_from_worker(struct run_as_worker *worker, enum run_as_cmd cmd, int * switch (cmd) { case RUN_AS_OPEN: + case RUN_AS_OPENAT: break; default: return 0; @@ -468,7 +501,17 @@ int recv_fd_from_master(struct run_as_worker *worker, enum run_as_cmd cmd, int * switch (cmd) { case RUN_AS_EXTRACT_ELF_SYMBOL_OFFSET: case RUN_AS_EXTRACT_SDT_PROBE_OFFSETS: + case RUN_AS_MKDIRAT: + case RUN_AS_MKDIRAT_RECURSIVE: + case RUN_AS_OPENAT: + case RUN_AS_UNLINKAT: break; + case RUN_AS_MKDIR: + case RUN_AS_MKDIR_RECURSIVE: + case RUN_AS_OPEN: + case RUN_AS_UNLINK: + *fd = AT_FDCWD; + /* fall-through */ default: return 0; } @@ -490,6 +533,12 @@ int cleanup_received_fd(enum run_as_cmd cmd, int fd) switch (cmd) { case RUN_AS_EXTRACT_ELF_SYMBOL_OFFSET: case RUN_AS_EXTRACT_SDT_PROBE_OFFSETS: + case RUN_AS_MKDIRAT: + case RUN_AS_MKDIRAT_RECURSIVE: + case RUN_AS_OPEN: + case RUN_AS_OPENAT: + case RUN_AS_UNLINK: + case RUN_AS_UNLINKAT: break; default: return 0; @@ -1101,43 +1150,86 @@ err: LTTNG_HIDDEN int run_as_mkdir_recursive(const char *path, mode_t mode, uid_t uid, gid_t gid) { + return run_as_mkdirat_recursive(AT_FDCWD, path, mode, uid, gid); +} + +LTTNG_HIDDEN +int run_as_mkdirat_recursive(int dirfd, const char *path, mode_t mode, + uid_t uid, gid_t gid) +{ + int ret; struct run_as_data data; - struct run_as_ret ret; + struct run_as_ret run_as_ret; memset(&data, 0, sizeof(data)); - memset(&ret, 0, sizeof(ret)); - DBG3("mkdir() recursive %s with mode %d for uid %d and gid %d", + memset(&run_as_ret, 0, sizeof(run_as_ret)); + DBG3("mkdirat() recursive fd = %d%s, path = %s, mode = %d, uid = %d, gid = %d", + dirfd, dirfd == AT_FDCWD ? " (AT_FDCWD)" : "", path, (int) mode, (int) uid, (int) gid); - strncpy(data.u.mkdir.path, path, PATH_MAX - 1); - data.u.mkdir.path[PATH_MAX - 1] = '\0'; - data.u.mkdir.mode = mode; - - run_as(RUN_AS_MKDIR_RECURSIVE, &data, &ret, uid, gid); - errno = ret._errno; - return ret.u.mkdir.ret; + ret = lttng_strncpy(data.u.mkdirat.path, path, + sizeof(data.u.mkdirat.path)); + if (ret) { + ERR("Failed to copy path argument of mkdirat recursive command"); + goto error; + } + data.u.mkdirat.path[PATH_MAX - 1] = '\0'; + data.u.mkdirat.mode = mode; + data.fd = dirfd; + run_as(dirfd == AT_FDCWD ? RUN_AS_MKDIR_RECURSIVE : RUN_AS_MKDIRAT_RECURSIVE, + &data, &run_as_ret, uid, gid); + errno = run_as_ret._errno; + ret = run_as_ret.u.mkdirat.ret; +error: + return ret; } LTTNG_HIDDEN int run_as_mkdir(const char *path, mode_t mode, uid_t uid, gid_t gid) { + return run_as_mkdirat(AT_FDCWD, path, mode, uid, gid); +} + +LTTNG_HIDDEN +int run_as_mkdirat(int dirfd, const char *path, mode_t mode, + uid_t uid, gid_t gid) +{ + int ret; struct run_as_data data; - struct run_as_ret ret; + struct run_as_ret run_as_ret; memset(&data, 0, sizeof(data)); - memset(&ret, 0, sizeof(ret)); + memset(&run_as_ret, 0, sizeof(run_as_ret)); - DBG3("mkdir() %s with mode %d for uid %d and gid %d", + DBG3("mkdirat() recursive fd = %d%s, path = %s, mode = %d, uid = %d, gid = %d", + dirfd, dirfd == AT_FDCWD ? " (AT_FDCWD)" : "", path, (int) mode, (int) uid, (int) gid); - strncpy(data.u.mkdir.path, path, PATH_MAX - 1); - data.u.mkdir.path[PATH_MAX - 1] = '\0'; - data.u.mkdir.mode = mode; - run_as(RUN_AS_MKDIR, &data, &ret, uid, gid); - errno = ret._errno; - return ret.u.mkdir.ret; + ret = lttng_strncpy(data.u.mkdirat.path, path, + sizeof(data.u.mkdirat.path)); + if (ret) { + ERR("Failed to copy path argument of mkdirat command"); + goto error; + } + data.u.mkdirat.path[PATH_MAX - 1] = '\0'; + data.u.mkdirat.mode = mode; + data.fd = dirfd; + run_as(dirfd == AT_FDCWD ? RUN_AS_MKDIR : RUN_AS_MKDIRAT, + &data, &run_as_ret, uid, gid); + errno = run_as_ret._errno; + ret = run_as_ret.u.mkdirat.ret; +error: + return ret; +} + +LTTNG_HIDDEN +int run_as_open(const char *path, int flags, mode_t mode, uid_t uid, + gid_t gid) +{ + return run_as_openat(AT_FDCWD, path, flags, mode, uid, gid); } LTTNG_HIDDEN -int run_as_open(const char *path, int flags, mode_t mode, uid_t uid, gid_t gid) +int run_as_openat(int dirfd, const char *path, int flags, mode_t mode, + uid_t uid, gid_t gid) { struct run_as_data data; struct run_as_ret ret; @@ -1145,13 +1237,16 @@ int run_as_open(const char *path, int flags, mode_t mode, uid_t uid, gid_t gid) memset(&data, 0, sizeof(data)); memset(&ret, 0, sizeof(ret)); - DBG3("open() %s with flags %X mode %d for uid %d and gid %d", + DBG3("openat() fd = %d%s, path = %s, flags = %X, mode = %d, uid %d, gid %d", + dirfd, dirfd == AT_FDCWD ? " (AT_FDCWD)" : "", path, flags, (int) mode, (int) uid, (int) gid); strncpy(data.u.open.path, path, PATH_MAX - 1); data.u.open.path[PATH_MAX - 1] = '\0'; data.u.open.flags = flags; data.u.open.mode = mode; - run_as(RUN_AS_OPEN, &data, &ret, uid, gid); + data.fd = dirfd; + run_as(dirfd == AT_FDCWD ? RUN_AS_OPEN : RUN_AS_OPENAT, + &data, &ret, uid, gid); errno = ret._errno; ret.u.open.ret = ret.fd; return ret.u.open.ret; @@ -1159,6 +1254,12 @@ int run_as_open(const char *path, int flags, mode_t mode, uid_t uid, gid_t gid) LTTNG_HIDDEN int run_as_unlink(const char *path, uid_t uid, gid_t gid) +{ + return run_as_unlinkat(AT_FDCWD, path, uid, gid); +} + +LTTNG_HIDDEN +int run_as_unlinkat(int dirfd, const char *path, uid_t uid, gid_t gid) { struct run_as_data data; struct run_as_ret ret; @@ -1166,10 +1267,12 @@ int run_as_unlink(const char *path, uid_t uid, gid_t gid) memset(&data, 0, sizeof(data)); memset(&ret, 0, sizeof(ret)); - DBG3("unlink() %s with for uid %d and gid %d", + DBG3("unlinkat() fd = %d%s, path = %s, uid = %d, gid = %d", + dirfd, dirfd == AT_FDCWD ? " (AT_FDCWD)" : "", path, (int) uid, (int) gid); strncpy(data.u.unlink.path, path, PATH_MAX - 1); data.u.unlink.path[PATH_MAX - 1] = '\0'; + data.fd = dirfd; run_as(RUN_AS_UNLINK, &data, &ret, uid, gid); errno = ret._errno; return ret.u.unlink.ret;