*/
#define _LGPL_SOURCE
-#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <common/lttng-kernel.h>
#include <common/common.h>
#include <common/utils.h>
+#include <common/compat/errno.h>
#include <common/compat/getenv.h>
-#include <common/compat/prctl.h>
+#include <common/compat/string.h>
#include <common/unix.h>
#include <common/defaults.h>
#include <common/lttng-elf.h>
+#include <common/thread.h>
#include <lttng/constant.h>
+#include <common/sessiond-comm/sessiond-comm.h>
+#include <common/filter/filter-ast.h>
+#include <common/filter/filter-bytecode.h>
+
#include "runas.h"
struct run_as_data;
RUN_AS_RENAMEAT,
RUN_AS_EXTRACT_ELF_SYMBOL_OFFSET,
RUN_AS_EXTRACT_SDT_PROBE_OFFSETS,
+ RUN_AS_GENERATE_FILTER_BYTECODE,
};
struct run_as_mkdir_data {
struct run_as_rmdir_data {
int dirfd;
char path[LTTNG_PATH_MAX];
- int flags; /* enum lttng_directory_handle_rmdir_recursive_flags */
+ int flags; /* enum lttng_directory_handle_rmdir_recursive_flags. */
} LTTNG_PACKED;
struct run_as_extract_elf_symbol_offset_data {
char provider_name[LTTNG_SYMBOL_NAME_LEN];
} LTTNG_PACKED;
+struct run_as_generate_filter_bytecode_data {
+ char filter_expression[LTTNG_FILTER_MAX_LEN];
+} LTTNG_PACKED;
+
struct run_as_rename_data {
/*
* [0] = old_dirfd
uint64_t offsets[LTTNG_KERNEL_MAX_UPROBE_NUM];
} LTTNG_PACKED;
+struct run_as_generate_filter_bytecode_ret {
+ /* A lttng_bytecode_filter struct with 'dynamic' payload. */
+ char bytecode[LTTNG_FILTER_MAX_LEN];
+} LTTNG_PACKED;
+
struct run_as_data {
enum run_as_cmd cmd;
union {
struct run_as_rename_data rename;
struct run_as_extract_elf_symbol_offset_data extract_elf_symbol_offset;
struct run_as_extract_sdt_probe_offsets_data extract_sdt_probe_offsets;
+ struct run_as_generate_filter_bytecode_data generate_filter_bytecode;
} u;
uid_t uid;
gid_t gid;
struct run_as_open_ret open;
struct run_as_extract_elf_symbol_offset_ret extract_elf_symbol_offset;
struct run_as_extract_sdt_probe_offsets_ret extract_sdt_probe_offsets;
+ struct run_as_generate_filter_bytecode_ret generate_filter_bytecode;
} u;
int _errno;
bool _error;
.out_fd_count = 0,
.use_cwd_fd = false,
},
+ [RUN_AS_GENERATE_FILTER_BYTECODE] = {
+ .in_fds_offset = -1,
+ .in_fd_count = 0,
+ .out_fds_offset = -1,
+ .out_fd_count = 0,
+ .use_cwd_fd = false,
+ },
};
struct run_as_worker {
}
#endif
+static
+int _generate_filter_bytecode(struct run_as_data *data,
+ struct run_as_ret *ret_value) {
+ int ret = 0;
+ const char *filter_expression = NULL;
+ struct filter_parser_ctx *ctx = NULL;
+
+ ret_value->_error = false;
+
+ filter_expression = data->u.generate_filter_bytecode.filter_expression;
+
+ if (lttng_strnlen(filter_expression, LTTNG_FILTER_MAX_LEN - 1) == LTTNG_FILTER_MAX_LEN - 1) {
+ ret_value->_error = true;
+ ret = -1;
+ goto end;
+ }
+
+ ret = filter_parser_ctx_create_from_filter_expression(filter_expression, &ctx);
+ if (ret < 0) {
+ ret_value->_error = true;
+ ret = -1;
+ goto end;
+ }
+
+ DBG("Size of bytecode generated: %u bytes.",
+ bytecode_get_len(&ctx->bytecode->b));
+
+ /* Copy the lttng_bytecode_filter object to the return structure. */
+ memcpy(ret_value->u.generate_filter_bytecode.bytecode,
+ &ctx->bytecode->b,
+ sizeof(ctx->bytecode->b) +
+ bytecode_get_len(&ctx->bytecode->b));
+
+end:
+ if (ctx) {
+ filter_bytecode_free(ctx);
+ filter_ir_free(ctx);
+ filter_parser_ctx_free(ctx);
+ }
+
+ return ret;
+}
static
run_as_fct run_as_enum_to_fct(enum run_as_cmd cmd)
{
return _extract_elf_symbol_offset;
case RUN_AS_EXTRACT_SDT_PROBE_OFFSETS:
return _extract_sdt_probe_offsets;
+ case RUN_AS_GENERATE_FILTER_BYTECODE:
+ return _generate_filter_bytecode;
default:
ERR("Unknown command %d", (int) cmd);
return NULL;
ERR("Invalid file descriptor received from worker (fd = %i)", fds[i]);
/* Return 0 as this is not a fatal error. */
}
- }
+ }
end:
- return ret;
+ return ret;
}
static
ret = -1;
goto end;
}
- }
+ }
- ret = do_send_fds(worker->sockpair[0], COMMAND_IN_FDS(data),
+ ret = do_send_fds(worker->sockpair[0], COMMAND_IN_FDS(data),
COMMAND_IN_FD_COUNT(data));
if (ret < 0) {
PERROR("Failed to send file descriptor to run-as worker");
goto end;
}
+ if (COMMAND_IN_FD_COUNT(data) == 0) {
+ goto end;
+ }
+
ret = do_recv_fds(worker->sockpair[1], COMMAND_IN_FDS(data),
COMMAND_IN_FD_COUNT(data));
if (ret < 0) {
int handle_one_cmd(struct run_as_worker *worker)
{
int ret = 0;
- struct run_as_data data = {};
- ssize_t readlen, writelen;
- struct run_as_ret sendret = {};
- run_as_fct cmd;
+ struct run_as_data data = {};
+ ssize_t readlen, writelen;
+ struct run_as_ret sendret = {};
+ run_as_fct cmd;
uid_t prev_euid;
/*
memset(worker->procname, 0, proc_orig_len);
strncpy(worker->procname, DEFAULT_RUN_AS_WORKER_NAME, proc_orig_len);
- ret = lttng_prctl(PR_SET_NAME,
- (unsigned long) DEFAULT_RUN_AS_WORKER_NAME, 0, 0, 0);
+ ret = lttng_thread_setname(DEFAULT_RUN_AS_WORKER_NAME);
if (ret && ret != -ENOSYS) {
/* Don't fail as this is not essential. */
- PERROR("prctl PR_SET_NAME");
+ DBG("Failed to set pthread name attribute");
}
memset(&sendret, 0, sizeof(sendret));
ret = -1;
}
worker->sockpair[1] = -1;
- free(worker->procname);
+ free(worker->procname);
free(worker);
LOG(ret ? PRINT_ERR : PRINT_DBG, "run_as worker exiting (ret = %d)", ret);
exit(ret ? EXIT_FAILURE : EXIT_SUCCESS);
if (WIFEXITED(status)) {
LOG(WEXITSTATUS(status) == 0 ? PRINT_DBG : PRINT_ERR,
DEFAULT_RUN_AS_WORKER_NAME " terminated with status code %d",
- WEXITSTATUS(status));
+ WEXITSTATUS(status));
break;
} else if (WIFSIGNALED(status)) {
ERR(DEFAULT_RUN_AS_WORKER_NAME " was killed by signal %d",
LTTNG_HIDDEN
int run_as_open(const char *path, int flags, mode_t mode, uid_t uid,
- gid_t gid)
+ gid_t gid)
{
return run_as_openat(AT_FDCWD, path, flags, mode, uid, gid);
}
uid_t uid, gid_t gid)
{
int ret;
- struct run_as_data data = {};
- struct run_as_ret run_as_ret = {};
+ struct run_as_data data = {};
+ struct run_as_ret run_as_ret = {};
DBG3("openat() fd = %d%s, path = %s, flags = %X, mode = %d, uid %d, gid %d",
dirfd, dirfd == AT_FDCWD ? " (AT_FDCWD)" : "",
{
int ret;
struct run_as_data data = {};
- struct run_as_ret run_as_ret = {};
+ struct run_as_ret run_as_ret = {};
DBG3("extract_elf_symbol_offset() on fd=%d and function=%s "
"with for uid %d and gid %d", fd, function,
return ret;
}
+LTTNG_HIDDEN
+int run_as_generate_filter_bytecode(const char *filter_expression,
+ uid_t uid,
+ gid_t gid,
+ struct lttng_filter_bytecode **bytecode)
+{
+ int ret;
+ struct run_as_data data = {};
+ struct run_as_ret run_as_ret = {};
+ const struct lttng_filter_bytecode *view_bytecode = NULL;
+ struct lttng_filter_bytecode *local_bytecode = NULL;
+
+ DBG3("generate_filter_bytecode() from expression=\"%s\" for uid %d and gid %d",
+ filter_expression, (int) uid, (int) gid);
+
+ ret = lttng_strncpy(data.u.generate_filter_bytecode.filter_expression, filter_expression,
+ sizeof(data.u.generate_filter_bytecode.filter_expression));
+ if (ret) {
+ goto error;
+ }
+
+ run_as(RUN_AS_GENERATE_FILTER_BYTECODE, &data, &run_as_ret, uid, gid);
+ errno = run_as_ret._errno;
+ if (run_as_ret._error) {
+ ret = -1;
+ goto error;
+ }
+
+ view_bytecode = (const struct lttng_filter_bytecode *) run_as_ret.u.generate_filter_bytecode.bytecode;
+
+ local_bytecode = zmalloc(sizeof(*local_bytecode) + view_bytecode->len);
+ if (!local_bytecode) {
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ memcpy(local_bytecode, run_as_ret.u.generate_filter_bytecode.bytecode,
+ sizeof(*local_bytecode) + view_bytecode->len);
+ *bytecode = local_bytecode;
+error:
+ return ret;
+}
+
LTTNG_HIDDEN
int run_as_create_worker(const char *procname,
post_fork_cleanup_cb clean_up_func,