X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fcommon%2Frunas.c;h=4bd356a0499f2119a227a69b324ab5248d7ba8a0;hp=863e824283fccfb159fad9150d859317e596618d;hb=938c57de605e65da12654a4963e466eb3ea4a85e;hpb=fe9f7760c61d1248a062138fd059c84ec03967f6 diff --git a/src/common/runas.c b/src/common/runas.c index 863e82428..4bd356a04 100644 --- a/src/common/runas.c +++ b/src/common/runas.c @@ -32,12 +32,16 @@ #include #include +#include #include #include #include #include #include #include +#include + +#include #include "runas.h" @@ -64,6 +68,15 @@ struct run_as_rmdir_recursive_data { char path[PATH_MAX]; }; +struct run_as_extract_elf_symbol_offset_data { + char function[LTTNG_SYMBOL_NAME_LEN]; +}; + +struct run_as_extract_sdt_probe_offsets_data { + char probe_name[LTTNG_SYMBOL_NAME_LEN]; + char provider_name[LTTNG_SYMBOL_NAME_LEN]; +}; + struct run_as_mkdir_ret { int ret; }; @@ -80,12 +93,23 @@ struct run_as_rmdir_recursive_ret { int ret; }; +struct run_as_extract_elf_symbol_offset_ret { + uint64_t offset; +}; + +struct run_as_extract_sdt_probe_offsets_ret { + uint32_t num_offset; + uint64_t offsets[LTTNG_KERNEL_MAX_UPROBE_NUM]; +}; + enum run_as_cmd { RUN_AS_MKDIR, RUN_AS_OPEN, RUN_AS_UNLINK, RUN_AS_RMDIR_RECURSIVE, RUN_AS_MKDIR_RECURSIVE, + RUN_AS_EXTRACT_ELF_SYMBOL_OFFSET, + RUN_AS_EXTRACT_SDT_PROBE_OFFSETS, }; struct run_as_data { @@ -96,6 +120,8 @@ struct run_as_data { struct run_as_open_data open; struct run_as_unlink_data unlink; struct run_as_rmdir_recursive_data rmdir_recursive; + struct run_as_extract_elf_symbol_offset_data extract_elf_symbol_offset; + struct run_as_extract_sdt_probe_offsets_data extract_sdt_probe_offsets; } u; uid_t uid; gid_t gid; @@ -123,6 +149,8 @@ struct run_as_ret { struct run_as_open_ret open; struct run_as_unlink_ret unlink; struct run_as_rmdir_recursive_ret rmdir_recursive; + struct run_as_extract_elf_symbol_offset_ret extract_elf_symbol_offset; + struct run_as_extract_sdt_probe_offsets_ret extract_sdt_probe_offsets; } u; int _errno; bool _error; @@ -212,6 +240,65 @@ int _rmdir_recursive(struct run_as_data *data, struct run_as_ret *ret_value) return ret_value->u.rmdir_recursive.ret; } +static +int _extract_elf_symbol_offset(struct run_as_data *data, + struct run_as_ret *ret_value) +{ + int ret = 0; + ret_value->_error = false; + + ret = lttng_elf_get_symbol_offset(data->fd, + data->u.extract_elf_symbol_offset.function, + &ret_value->u.extract_elf_symbol_offset.offset); + if (ret) { + DBG("Failed to extract ELF function offset"); + ret_value->_error = true; + } + + return ret; +} + +static +int _extract_sdt_probe_offsets(struct run_as_data *data, + struct run_as_ret *ret_value) +{ + int ret = 0; + uint64_t *offsets = NULL; + uint32_t num_offset; + + ret_value->_error = false; + + /* On success, this call allocates the offsets paramater. */ + ret = lttng_elf_get_sdt_probe_offsets(data->fd, + data->u.extract_sdt_probe_offsets.provider_name, + data->u.extract_sdt_probe_offsets.probe_name, + &offsets, &num_offset); + + if (ret) { + DBG("Failed to extract SDT probe offsets"); + ret_value->_error = true; + goto end; + } + + if (num_offset <= 0 || num_offset > LTTNG_KERNEL_MAX_UPROBE_NUM) { + DBG("Wrong number of probes."); + ret = -1; + ret_value->_error = true; + goto free_offset; + } + + /* Copy the content of the offsets array to the ret struct. */ + memcpy(ret_value->u.extract_sdt_probe_offsets.offsets, + offsets, num_offset * sizeof(uint64_t)); + + ret_value->u.extract_sdt_probe_offsets.num_offset = num_offset; + +free_offset: + free(offsets); +end: + return ret; +} + static run_as_fct run_as_enum_to_fct(enum run_as_cmd cmd) { @@ -226,6 +313,10 @@ run_as_fct run_as_enum_to_fct(enum run_as_cmd cmd) 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: + return _extract_sdt_probe_offsets; default: ERR("Unknown command %d", (int) cmd); return NULL; @@ -277,6 +368,9 @@ int send_fd_to_worker(struct run_as_worker *worker, enum run_as_cmd cmd, int fd) int ret = 0; switch (cmd) { + case RUN_AS_EXTRACT_ELF_SYMBOL_OFFSET: + case RUN_AS_EXTRACT_SDT_PROBE_OFFSETS: + break; default: return 0; } @@ -308,11 +402,14 @@ int send_fd_to_master(struct run_as_worker *worker, enum run_as_cmd cmd, int fd) ret = -1; } + if (fd < 0) { + goto end; + } ret_close = close(fd); if (ret_close < 0) { PERROR("close"); } - +end: return ret; } @@ -343,6 +440,9 @@ int recv_fd_from_master(struct run_as_worker *worker, enum run_as_cmd cmd, int * int ret = 0; switch (cmd) { + case RUN_AS_EXTRACT_ELF_SYMBOL_OFFSET: + case RUN_AS_EXTRACT_SDT_PROBE_OFFSETS: + break; default: return 0; } @@ -362,10 +462,16 @@ int cleanup_received_fd(enum run_as_cmd cmd, int fd) int ret = 0; switch (cmd) { + case RUN_AS_EXTRACT_ELF_SYMBOL_OFFSET: + case RUN_AS_EXTRACT_SDT_PROBE_OFFSETS: + break; default: return 0; } + if (fd < 0) { + return 0; + } ret = close(fd); if (ret < 0) { PERROR("close error"); @@ -374,6 +480,7 @@ int cleanup_received_fd(enum run_as_cmd cmd, int fd) return ret; } + /* * Return < 0 on error, 0 if OK, 1 on hangup. */ @@ -387,6 +494,9 @@ int handle_one_cmd(struct run_as_worker *worker) run_as_fct cmd; uid_t prev_euid; + memset(&sendret, 0, sizeof(sendret)); + sendret.fd = -1; + /* * Stage 1: Receive run_as_data struct from the master. * The structure contains the command type and all the parameters needed for @@ -427,6 +537,8 @@ int handle_one_cmd(struct run_as_worker *worker) if (data.gid != getegid()) { ret = setegid(data.gid); if (ret < 0) { + sendret._error = true; + sendret._errno = errno; PERROR("setegid"); goto write_return; } @@ -434,6 +546,8 @@ int handle_one_cmd(struct run_as_worker *worker) if (data.uid != prev_euid) { ret = seteuid(data.uid); if (ret < 0) { + sendret._error = true; + sendret._errno = errno; PERROR("seteuid"); goto write_return; } @@ -609,6 +723,7 @@ int run_as_cmd(struct run_as_worker *worker, PERROR("Error reading response from run_as"); ret = -1; ret_value->_errno = errno; + goto end; } /* @@ -697,7 +812,6 @@ int run_as(enum run_as_cmd cmd, struct run_as_data *data, DBG("Socket closed unexpectedly... " "Restarting the worker process"); ret = run_as_restart_worker(global_worker); - if (ret == -1) { ERR("Failed to restart worker process."); goto err; @@ -806,6 +920,79 @@ int run_as_rmdir_recursive(const char *path, uid_t uid, gid_t gid) return ret.u.rmdir_recursive.ret; } +LTTNG_HIDDEN +int run_as_extract_elf_symbol_offset(int fd, const char* function, + uid_t uid, gid_t gid, uint64_t *offset) +{ + struct run_as_data data; + struct run_as_ret ret; + + memset(&data, 0, sizeof(data)); + memset(&ret, 0, sizeof(ret)); + + DBG3("extract_elf_symbol_offset() on fd=%d and function=%s " + "with for uid %d and gid %d", fd, function, (int) uid, (int) gid); + + data.fd = fd; + + strncpy(data.u.extract_elf_symbol_offset.function, function, LTTNG_SYMBOL_NAME_LEN - 1); + + data.u.extract_elf_symbol_offset.function[LTTNG_SYMBOL_NAME_LEN - 1] = '\0'; + + run_as(RUN_AS_EXTRACT_ELF_SYMBOL_OFFSET, &data, &ret, uid, gid); + + errno = ret._errno; + + if (ret._error) { + return -1; + } + + *offset = ret.u.extract_elf_symbol_offset.offset; + return 0; +} + +LTTNG_HIDDEN +int run_as_extract_sdt_probe_offsets(int fd, const char* provider_name, + const char* probe_name, uid_t uid, gid_t gid, + uint64_t **offsets, uint32_t *num_offset) +{ + struct run_as_data data; + struct run_as_ret ret; + + memset(&data, 0, sizeof(data)); + memset(&ret, 0, sizeof(ret)); + + DBG3("extract_sdt_probe_offsets() on fd=%d, probe_name=%s and " + "provider_name=%s with for uid %d and gid %d", fd, probe_name, + provider_name, (int) uid, (int) gid); + + data.fd = fd; + + strncpy(data.u.extract_sdt_probe_offsets.probe_name, probe_name, LTTNG_SYMBOL_NAME_LEN - 1); + strncpy(data.u.extract_sdt_probe_offsets.provider_name, provider_name, LTTNG_SYMBOL_NAME_LEN - 1); + + data.u.extract_sdt_probe_offsets.probe_name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0'; + data.u.extract_sdt_probe_offsets.provider_name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0'; + + run_as(RUN_AS_EXTRACT_SDT_PROBE_OFFSETS, &data, &ret, uid, gid); + + errno = ret._errno; + + if (ret._error) { + return -1; + } + + *num_offset = ret.u.extract_sdt_probe_offsets.num_offset; + + *offsets = zmalloc(*num_offset * sizeof(uint64_t)); + if (!*offsets) { + return -ENOMEM; + } + + memcpy(*offsets, ret.u.extract_sdt_probe_offsets.offsets, *num_offset * sizeof(uint64_t)); + return 0; +} + static int reset_sighandler(void) {