X-Git-Url: http://git.efficios.com/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fcommon%2Frunas.c;h=3916d6754314eadd4947b576dbcb4d98273ad861;hp=863e824283fccfb159fad9150d859317e596618d;hb=0ef0325590ac65995f926a031e2f085531f74090;hpb=fe9f7760c61d1248a062138fd059c84ec03967f6 diff --git a/src/common/runas.c b/src/common/runas.c index 863e82428..3916d6754 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; } @@ -343,6 +437,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,6 +459,9 @@ 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; } @@ -374,6 +474,7 @@ int cleanup_received_fd(enum run_as_cmd cmd, int fd) return ret; } + /* * Return < 0 on error, 0 if OK, 1 on hangup. */ @@ -806,6 +907,73 @@ 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; + + 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; + + 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) {