2 * Copyright (C) 2011 EfficiOS Inc.
3 * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
4 * Copyright (C) 2019 Jérémie Galarneau <jeremie.galarneau@efficios.com>
6 * SPDX-License-Identifier: LGPL-2.1-only
21 #include <sys/types.h>
25 #include <common/bytecode/bytecode.hpp>
26 #include <common/lttng-kernel.hpp>
27 #include <common/common.hpp>
28 #include <common/utils.hpp>
29 #include <common/compat/errno.hpp>
30 #include <common/compat/getenv.hpp>
31 #include <common/compat/string.hpp>
32 #include <common/unix.hpp>
33 #include <common/defaults.hpp>
34 #include <common/lttng-elf.hpp>
35 #include <common/thread.hpp>
37 #include <lttng/constant.h>
39 #include <common/sessiond-comm/sessiond-comm.hpp>
40 #include <common/filter/filter-ast.hpp>
44 #define GETPW_BUFFER_FALLBACK_SIZE 4096
48 typedef int (*run_as_fct
)(struct run_as_data
*data
, struct run_as_ret
*ret_value
);
53 RUN_AS_MKDIR_RECURSIVE
,
54 RUN_AS_MKDIRAT_RECURSIVE
,
61 RUN_AS_RMDIR_RECURSIVE
,
62 RUN_AS_RMDIRAT_RECURSIVE
,
65 RUN_AS_EXTRACT_ELF_SYMBOL_OFFSET
,
66 RUN_AS_EXTRACT_SDT_PROBE_OFFSETS
,
67 RUN_AS_GENERATE_FILTER_BYTECODE
,
70 struct run_as_mkdir_data
{
72 char path
[LTTNG_PATH_MAX
];
76 struct run_as_open_data
{
78 char path
[LTTNG_PATH_MAX
];
83 struct run_as_unlink_data
{
85 char path
[LTTNG_PATH_MAX
];
88 struct run_as_rmdir_data
{
90 char path
[LTTNG_PATH_MAX
];
91 int flags
; /* enum lttng_directory_handle_rmdir_recursive_flags. */
94 struct run_as_extract_elf_symbol_offset_data
{
96 char function
[LTTNG_SYMBOL_NAME_LEN
];
99 struct run_as_extract_sdt_probe_offsets_data
{
101 char probe_name
[LTTNG_SYMBOL_NAME_LEN
];
102 char provider_name
[LTTNG_SYMBOL_NAME_LEN
];
105 struct run_as_generate_filter_bytecode_data
{
106 char filter_expression
[LTTNG_FILTER_MAX_LEN
];
109 struct run_as_rename_data
{
115 char old_path
[LTTNG_PATH_MAX
];
116 char new_path
[LTTNG_PATH_MAX
];
119 struct run_as_open_ret
{
123 struct run_as_extract_elf_symbol_offset_ret
{
127 struct run_as_extract_sdt_probe_offsets_ret
{
129 uint64_t offsets
[LTTNG_KERNEL_ABI_MAX_UPROBE_NUM
];
132 struct run_as_generate_filter_bytecode_ret
{
133 /* A lttng_bytecode_filter struct with 'dynamic' payload. */
134 char bytecode
[LTTNG_FILTER_MAX_LEN
];
140 struct run_as_mkdir_data mkdir
;
141 struct run_as_open_data open
;
142 struct run_as_unlink_data unlink
;
143 struct run_as_rmdir_data rmdir
;
144 struct run_as_rename_data rename
;
145 struct run_as_extract_elf_symbol_offset_data extract_elf_symbol_offset
;
146 struct run_as_extract_sdt_probe_offsets_data extract_sdt_probe_offsets
;
147 struct run_as_generate_filter_bytecode_data generate_filter_bytecode
;
154 * The run_as_ret structure holds the returned value and status of the command.
156 * The `u` union field holds the return value of the command; in most cases it
157 * represents the success or the failure of the command. In more complex
158 * commands, it holds a computed value.
160 * The _errno field is the errno recorded after the execution of the command.
162 * The _error fields is used the signify that return status of the command. For
163 * simple commands returning `int` the _error field will be the same as the
164 * ret_int field. In complex commands, it signify the success or failure of the
171 struct run_as_open_ret open
;
172 struct run_as_extract_elf_symbol_offset_ret extract_elf_symbol_offset
;
173 struct run_as_extract_sdt_probe_offsets_ret extract_sdt_probe_offsets
;
174 struct run_as_generate_filter_bytecode_ret generate_filter_bytecode
;
180 #define COMMAND_IN_FDS(data_ptr) ({ \
182 if (command_properties[data_ptr->cmd].in_fds_offset != -1) { \
183 fds = (int *) ((char *) data_ptr + command_properties[data_ptr->cmd].in_fds_offset); \
188 #define COMMAND_OUT_FDS(cmd, ret_ptr) ({ \
190 if (command_properties[cmd].out_fds_offset != -1) { \
191 fds = (int *) ((char *) ret_ptr + command_properties[cmd].out_fds_offset); \
196 #define COMMAND_IN_FD_COUNT(data_ptr) ({ \
197 command_properties[data_ptr->cmd].in_fd_count; \
200 #define COMMAND_OUT_FD_COUNT(cmd) ({ \
201 command_properties[cmd].out_fd_count; \
204 #define COMMAND_USE_CWD_FD(data_ptr) command_properties[data_ptr->cmd].use_cwd_fd
206 struct run_as_command_properties
{
207 /* Set to -1 when not applicable. */
208 ptrdiff_t in_fds_offset
, out_fds_offset
;
209 unsigned int in_fd_count
, out_fd_count
;
213 static const struct run_as_command_properties command_properties
[] = {
215 .in_fds_offset
= offsetof(struct run_as_data
, u
.mkdir
.dirfd
),
216 .out_fds_offset
= -1,
222 .in_fds_offset
= offsetof(struct run_as_data
, u
.mkdir
.dirfd
),
223 .out_fds_offset
= -1,
229 .in_fds_offset
= offsetof(struct run_as_data
, u
.mkdir
.dirfd
),
230 .out_fds_offset
= -1,
236 .in_fds_offset
= offsetof(struct run_as_data
, u
.mkdir
.dirfd
),
237 .out_fds_offset
= -1,
243 .in_fds_offset
= offsetof(struct run_as_data
, u
.open
.dirfd
),
244 .out_fds_offset
= offsetof(struct run_as_ret
, u
.open
.fd
),
250 .in_fds_offset
= offsetof(struct run_as_data
, u
.open
.dirfd
),
251 .out_fds_offset
= offsetof(struct run_as_ret
, u
.open
.fd
),
257 .in_fds_offset
= offsetof(struct run_as_data
, u
.unlink
.dirfd
),
258 .out_fds_offset
= -1,
264 .in_fds_offset
= offsetof(struct run_as_data
, u
.unlink
.dirfd
),
265 .out_fds_offset
= -1,
271 .in_fds_offset
= offsetof(struct run_as_data
, u
.rmdir
.dirfd
),
272 .out_fds_offset
= -1,
278 .in_fds_offset
= offsetof(struct run_as_data
, u
.rmdir
.dirfd
),
279 .out_fds_offset
= -1,
285 .in_fds_offset
= offsetof(struct run_as_data
, u
.rmdir
.dirfd
),
286 .out_fds_offset
= -1,
292 .in_fds_offset
= offsetof(struct run_as_data
, u
.rmdir
.dirfd
),
293 .out_fds_offset
= -1,
299 .in_fds_offset
= offsetof(struct run_as_data
, u
.rename
.dirfds
),
300 .out_fds_offset
= -1,
306 .in_fds_offset
= offsetof(struct run_as_data
, u
.rename
.dirfds
),
307 .out_fds_offset
= -1,
313 .in_fds_offset
= offsetof(struct run_as_data
,
314 u
.extract_elf_symbol_offset
.fd
),
315 .out_fds_offset
= -1,
321 .in_fds_offset
= offsetof(struct run_as_data
,
322 u
.extract_sdt_probe_offsets
.fd
),
323 .out_fds_offset
= -1,
330 .out_fds_offset
= -1,
337 struct run_as_worker_data
{
338 pid_t pid
; /* Worker PID. */
343 /* Single global worker per process (for now). */
344 static run_as_worker_data
*global_worker
;
345 /* Lock protecting the worker. */
346 static pthread_mutex_t worker_lock
= PTHREAD_MUTEX_INITIALIZER
;
358 return !lttng_secure_getenv("LTTNG_DEBUG_NOCLONE");
363 * Create recursively directory using the FULL path.
366 int _mkdirat_recursive(struct run_as_data
*data
, struct run_as_ret
*ret_value
)
370 struct lttng_directory_handle
*handle
;
372 path
= data
->u
.mkdir
.path
;
373 mode
= data
->u
.mkdir
.mode
;
375 handle
= lttng_directory_handle_create_from_dirfd(data
->u
.mkdir
.dirfd
);
377 ret_value
->_errno
= errno
;
378 ret_value
->_error
= true;
379 ret_value
->u
.ret
= -1;
382 /* Ownership of dirfd is transferred to the handle. */
383 data
->u
.mkdir
.dirfd
= -1;
384 /* Safe to call as we have transitioned to the requested uid/gid. */
385 ret_value
->u
.ret
= lttng_directory_handle_create_subdirectory_recursive(
387 ret_value
->_errno
= errno
;
388 ret_value
->_error
= (ret_value
->u
.ret
) ? true : false;
389 lttng_directory_handle_put(handle
);
391 return ret_value
->u
.ret
;
395 int _mkdirat(struct run_as_data
*data
, struct run_as_ret
*ret_value
)
399 struct lttng_directory_handle
*handle
;
401 path
= data
->u
.mkdir
.path
;
402 mode
= data
->u
.mkdir
.mode
;
404 handle
= lttng_directory_handle_create_from_dirfd(data
->u
.mkdir
.dirfd
);
406 ret_value
->u
.ret
= -1;
407 ret_value
->_errno
= errno
;
408 ret_value
->_error
= true;
411 /* Ownership of dirfd is transferred to the handle. */
412 data
->u
.mkdir
.dirfd
= -1;
413 /* Safe to call as we have transitioned to the requested uid/gid. */
414 ret_value
->u
.ret
= lttng_directory_handle_create_subdirectory(
416 ret_value
->_errno
= errno
;
417 ret_value
->_error
= (ret_value
->u
.ret
) ? true : false;
418 lttng_directory_handle_put(handle
);
420 return ret_value
->u
.ret
;
424 int _open(struct run_as_data
*data
, struct run_as_ret
*ret_value
)
427 struct lttng_directory_handle
*handle
;
429 handle
= lttng_directory_handle_create_from_dirfd(data
->u
.open
.dirfd
);
431 ret_value
->_errno
= errno
;
432 ret_value
->_error
= true;
433 ret_value
->u
.ret
= -1;
436 /* Ownership of dirfd is transferred to the handle. */
437 data
->u
.open
.dirfd
= -1;
439 fd
= lttng_directory_handle_open_file(handle
,
440 data
->u
.open
.path
, data
->u
.open
.flags
,
443 ret_value
->u
.ret
= -1;
444 ret_value
->u
.open
.fd
= -1;
446 ret_value
->u
.ret
= 0;
447 ret_value
->u
.open
.fd
= fd
;
450 ret_value
->_errno
= errno
;
451 ret_value
->_error
= fd
< 0;
452 lttng_directory_handle_put(handle
);
454 return ret_value
->u
.ret
;
458 int _unlink(struct run_as_data
*data
, struct run_as_ret
*ret_value
)
460 struct lttng_directory_handle
*handle
;
462 handle
= lttng_directory_handle_create_from_dirfd(data
->u
.unlink
.dirfd
);
464 ret_value
->u
.ret
= -1;
465 ret_value
->_errno
= errno
;
466 ret_value
->_error
= true;
470 /* Ownership of dirfd is transferred to the handle. */
471 data
->u
.unlink
.dirfd
= -1;
473 ret_value
->u
.ret
= lttng_directory_handle_unlink_file(handle
,
474 data
->u
.unlink
.path
);
475 ret_value
->_errno
= errno
;
476 ret_value
->_error
= (ret_value
->u
.ret
) ? true : false;
477 lttng_directory_handle_put(handle
);
479 return ret_value
->u
.ret
;
483 int _rmdir(struct run_as_data
*data
, struct run_as_ret
*ret_value
)
485 struct lttng_directory_handle
*handle
;
487 handle
= lttng_directory_handle_create_from_dirfd(data
->u
.rmdir
.dirfd
);
489 ret_value
->u
.ret
= -1;
490 ret_value
->_errno
= errno
;
491 ret_value
->_error
= true;
495 /* Ownership of dirfd is transferred to the handle. */
496 data
->u
.rmdir
.dirfd
= -1;
498 ret_value
->u
.ret
= lttng_directory_handle_remove_subdirectory(
499 handle
, data
->u
.rmdir
.path
);
500 ret_value
->_errno
= errno
;
501 ret_value
->_error
= (ret_value
->u
.ret
) ? true : false;
502 lttng_directory_handle_put(handle
);
504 return ret_value
->u
.ret
;
508 int _rmdir_recursive(struct run_as_data
*data
, struct run_as_ret
*ret_value
)
510 struct lttng_directory_handle
*handle
;
512 handle
= lttng_directory_handle_create_from_dirfd(data
->u
.rmdir
.dirfd
);
514 ret_value
->u
.ret
= -1;
515 ret_value
->_errno
= errno
;
516 ret_value
->_error
= true;
520 /* Ownership of dirfd is transferred to the handle. */
521 data
->u
.rmdir
.dirfd
= -1;
523 ret_value
->u
.ret
= lttng_directory_handle_remove_subdirectory_recursive(
524 handle
, data
->u
.rmdir
.path
, data
->u
.rmdir
.flags
);
525 ret_value
->_errno
= errno
;
526 ret_value
->_error
= (ret_value
->u
.ret
) ? true : false;
527 lttng_directory_handle_put(handle
);
529 return ret_value
->u
.ret
;
533 int _rename(struct run_as_data
*data
, struct run_as_ret
*ret_value
)
535 const char *old_path
, *new_path
;
536 struct lttng_directory_handle
*old_handle
= NULL
, *new_handle
= NULL
;
538 old_path
= data
->u
.rename
.old_path
;
539 new_path
= data
->u
.rename
.new_path
;
541 old_handle
= lttng_directory_handle_create_from_dirfd(
542 data
->u
.rename
.dirfds
[0]);
544 ret_value
->u
.ret
= -1;
547 new_handle
= lttng_directory_handle_create_from_dirfd(
548 data
->u
.rename
.dirfds
[1]);
550 ret_value
->u
.ret
= -1;
554 /* Ownership of dirfds are transferred to the handles. */
555 data
->u
.rename
.dirfds
[0] = data
->u
.rename
.dirfds
[1] = -1;
557 /* Safe to call as we have transitioned to the requested uid/gid. */
558 ret_value
->u
.ret
= lttng_directory_handle_rename(
559 old_handle
, old_path
, new_handle
, new_path
);
561 lttng_directory_handle_put(old_handle
);
562 lttng_directory_handle_put(new_handle
);
563 ret_value
->_errno
= errno
;
564 ret_value
->_error
= (ret_value
->u
.ret
) ? true : false;
565 return ret_value
->u
.ret
;
570 int _extract_elf_symbol_offset(struct run_as_data
*data
,
571 struct run_as_ret
*ret_value
)
576 ret_value
->_error
= false;
577 ret
= lttng_elf_get_symbol_offset(data
->u
.extract_elf_symbol_offset
.fd
,
578 data
->u
.extract_elf_symbol_offset
.function
,
581 DBG("Failed to extract ELF function offset");
582 ret_value
->_error
= true;
584 ret_value
->u
.extract_elf_symbol_offset
.offset
= offset
;
590 int _extract_sdt_probe_offsets(struct run_as_data
*data
,
591 struct run_as_ret
*ret_value
)
594 uint64_t *offsets
= NULL
;
597 ret_value
->_error
= false;
599 /* On success, this call allocates the offsets paramater. */
600 ret
= lttng_elf_get_sdt_probe_offsets(
601 data
->u
.extract_sdt_probe_offsets
.fd
,
602 data
->u
.extract_sdt_probe_offsets
.provider_name
,
603 data
->u
.extract_sdt_probe_offsets
.probe_name
,
604 &offsets
, &num_offset
);
607 DBG("Failed to extract SDT probe offsets");
608 ret_value
->_error
= true;
612 if (num_offset
<= 0 || num_offset
> LTTNG_KERNEL_ABI_MAX_UPROBE_NUM
) {
613 DBG("Wrong number of probes.");
615 ret_value
->_error
= true;
619 /* Copy the content of the offsets array to the ret struct. */
620 memcpy(ret_value
->u
.extract_sdt_probe_offsets
.offsets
,
621 offsets
, num_offset
* sizeof(uint64_t));
623 ret_value
->u
.extract_sdt_probe_offsets
.num_offset
= num_offset
;
632 int _extract_elf_symbol_offset(
633 struct run_as_data
*data
__attribute__((unused
)),
634 struct run_as_ret
*ret_value
__attribute__((unused
)))
636 ERR("Unimplemented runas command RUN_AS_EXTRACT_ELF_SYMBOL_OFFSET");
641 int _extract_sdt_probe_offsets(
642 struct run_as_data
*data
__attribute__((unused
)),
643 struct run_as_ret
*ret_value
__attribute__((unused
)))
645 ERR("Unimplemented runas command RUN_AS_EXTRACT_SDT_PROBE_OFFSETS");
651 int _generate_filter_bytecode(struct run_as_data
*data
,
652 struct run_as_ret
*ret_value
) {
654 const char *filter_expression
= NULL
;
655 struct filter_parser_ctx
*ctx
= NULL
;
657 ret_value
->_error
= false;
659 filter_expression
= data
->u
.generate_filter_bytecode
.filter_expression
;
661 if (lttng_strnlen(filter_expression
, LTTNG_FILTER_MAX_LEN
- 1) == LTTNG_FILTER_MAX_LEN
- 1) {
662 ret_value
->_error
= true;
667 ret
= filter_parser_ctx_create_from_filter_expression(filter_expression
, &ctx
);
669 ret_value
->_error
= true;
674 DBG("Size of bytecode generated: %u bytes.",
675 bytecode_get_len(&ctx
->bytecode
->b
));
677 /* Copy the lttng_bytecode_filter object to the return structure. */
678 memcpy(ret_value
->u
.generate_filter_bytecode
.bytecode
,
680 sizeof(ctx
->bytecode
->b
) +
681 bytecode_get_len(&ctx
->bytecode
->b
));
685 filter_bytecode_free(ctx
);
687 filter_parser_ctx_free(ctx
);
693 run_as_fct
run_as_enum_to_fct(enum run_as_cmd cmd
)
699 case RUN_AS_MKDIR_RECURSIVE
:
700 case RUN_AS_MKDIRAT_RECURSIVE
:
701 return _mkdirat_recursive
;
706 case RUN_AS_UNLINKAT
:
711 case RUN_AS_RMDIR_RECURSIVE
:
712 case RUN_AS_RMDIRAT_RECURSIVE
:
713 return _rmdir_recursive
;
715 case RUN_AS_RENAMEAT
:
717 case RUN_AS_EXTRACT_ELF_SYMBOL_OFFSET
:
718 return _extract_elf_symbol_offset
;
719 case RUN_AS_EXTRACT_SDT_PROBE_OFFSETS
:
720 return _extract_sdt_probe_offsets
;
721 case RUN_AS_GENERATE_FILTER_BYTECODE
:
722 return _generate_filter_bytecode
;
724 ERR("Unknown command %d", (int) cmd
);
730 int do_send_fds(int sock
, const int *fds
, unsigned int fd_count
)
735 for (i
= 0; i
< fd_count
; i
++) {
737 DBG("Attempt to send invalid file descriptor (fd = %i)",
739 /* Return 0 as this is not a fatal error. */
744 len
= lttcomm_send_fds_unix_sock(sock
, fds
, fd_count
);
745 return len
< 0 ? -1 : 0;
749 int do_recv_fds(int sock
, int *fds
, unsigned int fd_count
)
755 len
= lttcomm_recv_fds_unix_sock(sock
, fds
, fd_count
);
759 } else if (len
< 0) {
760 PERROR("Failed to receive file descriptors from socket");
765 for (i
= 0; i
< fd_count
; i
++) {
767 ERR("Invalid file descriptor received from worker (fd = %i)", fds
[i
]);
768 /* Return 0 as this is not a fatal error. */
776 int send_fds_to_worker(const run_as_worker_data
*worker
,
777 const struct run_as_data
*data
)
782 if (COMMAND_USE_CWD_FD(data
) || COMMAND_IN_FD_COUNT(data
) == 0) {
786 for (i
= 0; i
< COMMAND_IN_FD_COUNT(data
); i
++) {
787 if (COMMAND_IN_FDS(data
)[i
] < 0) {
788 ERR("Refusing to send invalid fd to worker (fd = %i)",
789 COMMAND_IN_FDS(data
)[i
]);
795 ret
= do_send_fds(worker
->sockpair
[0], COMMAND_IN_FDS(data
),
796 COMMAND_IN_FD_COUNT(data
));
798 PERROR("Failed to send file descriptor to run-as worker");
807 int send_fds_to_master(run_as_worker_data
*worker
, enum run_as_cmd cmd
,
808 struct run_as_ret
*run_as_ret
)
813 if (COMMAND_OUT_FD_COUNT(cmd
) == 0) {
817 ret
= do_send_fds(worker
->sockpair
[1], COMMAND_OUT_FDS(cmd
, run_as_ret
),
818 COMMAND_OUT_FD_COUNT(cmd
));
820 PERROR("Failed to send file descriptor to master process");
824 for (i
= 0; i
< COMMAND_OUT_FD_COUNT(cmd
); i
++) {
825 int fd
= COMMAND_OUT_FDS(cmd
, run_as_ret
)[i
];
827 int ret_close
= close(fd
);
830 PERROR("Failed to close result file descriptor (fd = %i)",
840 int recv_fds_from_worker(const run_as_worker_data
*worker
, enum run_as_cmd cmd
,
841 struct run_as_ret
*run_as_ret
)
845 if (COMMAND_OUT_FD_COUNT(cmd
) == 0) {
849 ret
= do_recv_fds(worker
->sockpair
[0], COMMAND_OUT_FDS(cmd
, run_as_ret
),
850 COMMAND_OUT_FD_COUNT(cmd
));
852 PERROR("Failed to receive file descriptor from run-as worker");
860 int recv_fds_from_master(run_as_worker_data
*worker
, struct run_as_data
*data
)
864 if (COMMAND_USE_CWD_FD(data
)) {
867 for (i
= 0; i
< COMMAND_IN_FD_COUNT(data
); i
++) {
868 COMMAND_IN_FDS(data
)[i
] = AT_FDCWD
;
873 if (COMMAND_IN_FD_COUNT(data
) == 0) {
877 ret
= do_recv_fds(worker
->sockpair
[1], COMMAND_IN_FDS(data
),
878 COMMAND_IN_FD_COUNT(data
));
880 PERROR("Failed to receive file descriptors from master process");
888 int cleanup_received_fds(struct run_as_data
*data
)
892 for (i
= 0; i
< COMMAND_IN_FD_COUNT(data
); i
++) {
893 if (COMMAND_IN_FDS(data
)[i
] == -1) {
896 ret
= close(COMMAND_IN_FDS(data
)[i
]);
898 PERROR("Failed to close file descriptor received fd in run-as worker");
906 static int get_user_infos_from_uid(
907 uid_t uid
, char **username
, gid_t
*primary_gid
)
911 long raw_get_pw_buf_size
;
912 size_t get_pw_buf_size
;
914 struct passwd
*result
= NULL
;
916 /* Fetch the max size for the temporary buffer. */
918 raw_get_pw_buf_size
= sysconf(_SC_GETPW_R_SIZE_MAX
);
919 if (raw_get_pw_buf_size
< 0) {
921 PERROR("Failed to query _SC_GETPW_R_SIZE_MAX");
925 /* Limit is indeterminate. */
926 WARN("Failed to query _SC_GETPW_R_SIZE_MAX as it is "
927 "indeterminate; falling back to default buffer size");
928 raw_get_pw_buf_size
= GETPW_BUFFER_FALLBACK_SIZE
;
931 get_pw_buf_size
= (size_t) raw_get_pw_buf_size
;
933 buf
= (char *) zmalloc(get_pw_buf_size
);
935 PERROR("Failed to allocate buffer to get password file entries");
939 ret
= getpwuid_r(uid
, &pwd
, buf
, get_pw_buf_size
, &result
);
941 PERROR("Failed to get user information for user: uid = %d",
946 if (result
== NULL
) {
947 ERR("Failed to find user information in password entries: uid = %d",
953 *username
= strdup(result
->pw_name
);
954 if (*username
== NULL
) {
955 PERROR("Failed to copy user name");
959 *primary_gid
= result
->pw_gid
;
971 static int demote_creds(
972 uid_t prev_uid
, gid_t prev_gid
, uid_t new_uid
, gid_t new_gid
)
976 char *username
= NULL
;
978 /* Change the group id. */
979 if (prev_gid
!= new_gid
) {
980 ret
= setegid(new_gid
);
982 PERROR("Failed to set effective group id: new_gid = %d",
988 /* Change the user id. */
989 if (prev_uid
!= new_uid
) {
990 ret
= get_user_infos_from_uid(new_uid
, &username
, &primary_gid
);
996 * Initialize the supplementary group access list.
998 * This is needed to handle cases where the supplementary groups
999 * of the user the process is demoting-to would give it access
1000 * to a given file/folder, but not it's primary group.
1004 * Primary Group: User1
1005 * Secondary group: Disk, Network
1007 * mkdir inside the following directory must work since User1
1008 * is part of the Network group.
1010 * drwxrwx--- 2 root Network 4096 Jul 23 17:17 /tmp/my_folder/
1013 * The order of the following initgroups and seteuid calls is
1015 * Only a root process or one with CAP_SETGID capability can
1016 * call the the initgroups() function. We must initialize the
1017 * supplementary groups before we change the effective
1018 * UID to a less-privileged user.
1020 ret
= initgroups(username
, primary_gid
);
1022 PERROR("Failed to init the supplementary group access list: "
1023 "username = `%s`, primary gid = %d", username
,
1028 ret
= seteuid(new_uid
);
1030 PERROR("Failed to set effective user id: new_uid = %d",
1040 static int promote_creds(
1041 uid_t prev_uid
, gid_t prev_gid
, uid_t new_uid
, gid_t new_gid
)
1045 char *username
= NULL
;
1047 /* Change the group id. */
1048 if (prev_gid
!= new_gid
) {
1049 ret
= setegid(new_gid
);
1051 PERROR("Failed to set effective group id: new_gid = %d",
1057 /* Change the user id. */
1058 if (prev_uid
!= new_uid
) {
1059 ret
= get_user_infos_from_uid(new_uid
, &username
, &primary_gid
);
1065 * seteuid call must be done before the initgroups call because
1066 * we need to be privileged (CAP_SETGID) to call initgroups().
1068 ret
= seteuid(new_uid
);
1070 PERROR("Failed to set effective user id: new_uid = %d",
1076 * Initialize the supplementary group access list.
1078 * There is a possibility the groups we set in the following
1079 * initgroups() call are not exactly the same as the ones we
1080 * had when we originally demoted. This can happen if the
1081 * /etc/group file is modified after the runas process is
1082 * forked. This is very unlikely.
1084 ret
= initgroups(username
, primary_gid
);
1086 PERROR("Failed to init the supplementary group access "
1087 "list: username = `%s`, primary gid = %d",
1088 username
, (int) primary_gid
)
1098 * Return < 0 on error, 0 if OK, 1 on hangup.
1101 int handle_one_cmd(run_as_worker_data
*worker
)
1103 int ret
= 0, promote_ret
;
1104 struct run_as_data data
= {};
1105 ssize_t readlen
, writelen
;
1106 struct run_as_ret sendret
= {};
1108 const uid_t prev_ruid
= getuid();
1109 const gid_t prev_rgid
= getgid();
1112 * Stage 1: Receive run_as_data struct from the master.
1113 * The structure contains the command type and all the parameters needed for
1116 readlen
= lttcomm_recv_unix_sock(worker
->sockpair
[1], &data
,
1123 if (readlen
< sizeof(data
)) {
1124 PERROR("lttcomm_recv_unix_sock error");
1129 cmd
= run_as_enum_to_fct(data
.cmd
);
1136 * Stage 2: Receive file descriptor from master.
1137 * Some commands need a file descriptor as input so if it's needed we
1138 * receive the fd using the Unix socket.
1140 ret
= recv_fds_from_master(worker
, &data
);
1142 PERROR("recv_fd_from_master error");
1147 ret
= demote_creds(prev_ruid
, prev_rgid
, data
.uid
, data
.gid
);
1153 * Also set umask to 0 for mkdir executable bit.
1158 * Stage 3: Execute the command
1160 ret
= (*cmd
)(&data
, &sendret
);
1162 DBG("Execution of command returned an error");
1166 ret
= cleanup_received_fds(&data
);
1168 ERR("Error cleaning up FD");
1173 * Stage 4: Send run_as_ret structure to the master.
1174 * This structure contain the return value of the command and the errno.
1176 writelen
= lttcomm_send_unix_sock(worker
->sockpair
[1], &sendret
,
1178 if (writelen
< sizeof(sendret
)) {
1179 PERROR("lttcomm_send_unix_sock error");
1185 * Stage 5: Send resulting file descriptors to the master.
1187 ret
= send_fds_to_master(worker
, data
.cmd
, &sendret
);
1189 DBG("Sending FD to master returned an error");
1195 /* Return to previous uid/gid. */
1196 promote_ret
= promote_creds(data
.uid
, data
.gid
, prev_ruid
, prev_rgid
);
1197 if (promote_ret
< 0) {
1198 ERR("Failed to promote back to the initial credentials");
1206 int run_as_worker(run_as_worker_data
*worker
)
1210 struct run_as_ret sendret
;
1211 size_t proc_orig_len
;
1214 * Initialize worker. Set a different process cmdline.
1216 proc_orig_len
= strlen(worker
->procname
);
1217 memset(worker
->procname
, 0, proc_orig_len
);
1218 strncpy(worker
->procname
, DEFAULT_RUN_AS_WORKER_NAME
, proc_orig_len
);
1220 ret
= lttng_thread_setname(DEFAULT_RUN_AS_WORKER_NAME
);
1221 if (ret
&& ret
!= -ENOSYS
) {
1222 /* Don't fail as this is not essential. */
1223 DBG("Failed to set pthread name attribute");
1226 memset(&sendret
, 0, sizeof(sendret
));
1228 writelen
= lttcomm_send_unix_sock(worker
->sockpair
[1], &sendret
,
1230 if (writelen
< sizeof(sendret
)) {
1231 PERROR("lttcomm_send_unix_sock error");
1237 ret
= handle_one_cmd(worker
);
1241 } else if (ret
> 0) {
1244 continue; /* Next command. */
1253 int run_as_cmd(run_as_worker_data
*worker
,
1254 enum run_as_cmd cmd
,
1255 struct run_as_data
*data
,
1256 struct run_as_ret
*ret_value
,
1257 uid_t uid
, gid_t gid
)
1260 ssize_t readlen
, writelen
;
1263 * If we are non-root, we can only deal with our own uid.
1265 if (geteuid() != 0) {
1266 if (uid
!= geteuid()) {
1268 ret_value
->_errno
= EPERM
;
1269 ERR("Client (%d)/Server (%d) UID mismatch (and sessiond is not root)",
1270 (int) uid
, (int) geteuid());
1280 * Stage 1: Send the run_as_data struct to the worker process
1282 writelen
= lttcomm_send_unix_sock(worker
->sockpair
[0], data
,
1284 if (writelen
< sizeof(*data
)) {
1285 PERROR("Error writing message to run_as");
1287 ret_value
->_errno
= EIO
;
1292 * Stage 2: Send file descriptor to the worker process if needed
1294 ret
= send_fds_to_worker(worker
, data
);
1296 PERROR("do_send_fd error");
1298 ret_value
->_errno
= EIO
;
1303 * Stage 3: Wait for the execution of the command
1307 * Stage 4: Receive the run_as_ret struct containing the return value and
1310 readlen
= lttcomm_recv_unix_sock(worker
->sockpair
[0], ret_value
,
1311 sizeof(*ret_value
));
1313 ERR("Run-as worker has hung-up during run_as_cmd");
1315 ret_value
->_errno
= EIO
;
1317 } else if (readlen
< sizeof(*ret_value
)) {
1318 PERROR("Error reading response from run_as");
1320 ret_value
->_errno
= errno
;
1324 if (ret_value
->_error
) {
1325 /* Skip stage 5 on error as there will be no fd to receive. */
1330 * Stage 5: Receive file descriptor if needed
1332 ret
= recv_fds_from_worker(worker
, cmd
, ret_value
);
1334 ERR("Error receiving fd");
1336 ret_value
->_errno
= EIO
;
1344 * This is for debugging ONLY and should not be considered secure.
1347 int run_as_noworker(enum run_as_cmd cmd
,
1348 struct run_as_data
*data
, struct run_as_ret
*ret_value
,
1349 uid_t uid
__attribute__((unused
)), gid_t gid
__attribute__((unused
)))
1351 int ret
, saved_errno
;
1355 fct
= run_as_enum_to_fct(cmd
);
1361 old_mask
= umask(0);
1362 ret
= fct(data
, ret_value
);
1363 saved_errno
= ret_value
->_errno
;
1365 errno
= saved_errno
;
1371 int reset_sighandler(void)
1375 DBG("Resetting run_as worker signal handlers to default");
1376 for (sig
= 1; sig
<= 31; sig
++) {
1377 (void) signal(sig
, SIG_DFL
);
1383 void worker_sighandler(int sig
)
1385 const char *signame
;
1388 * The worker will inherit its parent's signals since they are part of
1389 * the same process group. However, in the case of SIGINT and SIGTERM,
1390 * we want to give the worker a chance to teardown gracefully when its
1391 * parent closes the command socket.
1398 signame
= "SIGTERM";
1405 DBG("run_as worker received signal %s", signame
);
1407 DBG("run_as_worker received signal %d", sig
);
1412 int set_worker_sighandlers(void)
1416 struct sigaction sa
;
1418 if ((ret
= sigemptyset(&sigset
)) < 0) {
1419 PERROR("sigemptyset");
1423 sa
.sa_handler
= worker_sighandler
;
1424 sa
.sa_mask
= sigset
;
1426 if ((ret
= sigaction(SIGINT
, &sa
, NULL
)) < 0) {
1427 PERROR("sigaction SIGINT");
1431 if ((ret
= sigaction(SIGTERM
, &sa
, NULL
)) < 0) {
1432 PERROR("sigaction SIGTERM");
1436 DBG("run_as signal handler set for SIGTERM and SIGINT");
1442 int run_as_create_worker_no_lock(const char *procname
,
1443 post_fork_cleanup_cb clean_up_func
,
1444 void *clean_up_user_data
)
1449 struct run_as_ret recvret
;
1450 run_as_worker_data
*worker
;
1452 LTTNG_ASSERT(!global_worker
);
1455 * Don't initialize a worker, all run_as tasks will be performed
1456 * in the current process.
1461 worker
= (run_as_worker_data
*) zmalloc(sizeof(*worker
));
1466 worker
->procname
= strdup(procname
);
1467 if (!worker
->procname
) {
1469 goto error_procname_alloc
;
1471 /* Create unix socket. */
1472 if (lttcomm_create_anon_unix_socketpair(worker
->sockpair
) < 0) {
1483 } else if (pid
== 0) {
1488 set_worker_sighandlers();
1490 logger_set_thread_name("Run-as worker", true);
1492 if (clean_up_func
) {
1493 if (clean_up_func(clean_up_user_data
) < 0) {
1494 ERR("Run-as post-fork clean-up failed, exiting.");
1499 /* Just close, no shutdown. */
1500 if (close(worker
->sockpair
[0])) {
1506 * Close all FDs aside from STDIN, STDOUT, STDERR and sockpair[1]
1507 * Sockpair[1] is used as a control channel with the master
1509 for (i
= 3; i
< sysconf(_SC_OPEN_MAX
); i
++) {
1510 if (i
!= worker
->sockpair
[1]) {
1515 worker
->sockpair
[0] = -1;
1516 ret
= run_as_worker(worker
);
1517 if (lttcomm_close_unix_sock(worker
->sockpair
[1])) {
1521 worker
->sockpair
[1] = -1;
1522 free(worker
->procname
);
1524 LOG(ret
? PRINT_ERR
: PRINT_DBG
, "run_as worker exiting (ret = %d)", ret
);
1525 exit(ret
? EXIT_FAILURE
: EXIT_SUCCESS
);
1529 /* Just close, no shutdown. */
1530 if (close(worker
->sockpair
[1])) {
1535 worker
->sockpair
[1] = -1;
1537 /* Wait for worker to become ready. */
1538 readlen
= lttcomm_recv_unix_sock(worker
->sockpair
[0],
1539 &recvret
, sizeof(recvret
));
1540 if (readlen
< sizeof(recvret
)) {
1541 ERR("readlen: %zd", readlen
);
1542 PERROR("Error reading response from run_as at creation");
1546 global_worker
= worker
;
1551 /* Error handling. */
1553 for (i
= 0; i
< 2; i
++) {
1554 if (worker
->sockpair
[i
] < 0) {
1557 if (lttcomm_close_unix_sock(worker
->sockpair
[i
])) {
1560 worker
->sockpair
[i
] = -1;
1563 free(worker
->procname
);
1564 error_procname_alloc
:
1570 void run_as_destroy_worker_no_lock(void)
1572 run_as_worker_data
*worker
= global_worker
;
1574 DBG("Destroying run_as worker");
1578 /* Close unix socket */
1579 DBG("Closing run_as worker socket");
1580 if (lttcomm_close_unix_sock(worker
->sockpair
[0])) {
1583 worker
->sockpair
[0] = -1;
1584 /* Wait for worker. */
1589 wait_ret
= waitpid(worker
->pid
, &status
, 0);
1591 if (errno
== EINTR
) {
1598 if (WIFEXITED(status
)) {
1599 LOG(WEXITSTATUS(status
) == 0 ? PRINT_DBG
: PRINT_ERR
,
1600 DEFAULT_RUN_AS_WORKER_NAME
" terminated with status code %d",
1601 WEXITSTATUS(status
));
1603 } else if (WIFSIGNALED(status
)) {
1604 ERR(DEFAULT_RUN_AS_WORKER_NAME
" was killed by signal %d",
1609 free(worker
->procname
);
1611 global_worker
= NULL
;
1615 int run_as_restart_worker(run_as_worker_data
*worker
)
1618 char *procname
= NULL
;
1620 procname
= worker
->procname
;
1622 /* Close socket to run_as worker process and clean up the zombie process */
1623 run_as_destroy_worker_no_lock();
1625 /* Create a new run_as worker process*/
1626 ret
= run_as_create_worker_no_lock(procname
, NULL
, NULL
);
1628 ERR("Restarting the worker process failed");
1637 int run_as(enum run_as_cmd cmd
, struct run_as_data
*data
,
1638 struct run_as_ret
*ret_value
, uid_t uid
, gid_t gid
)
1640 int ret
, saved_errno
;
1642 pthread_mutex_lock(&worker_lock
);
1644 DBG("Using run_as worker");
1646 LTTNG_ASSERT(global_worker
);
1648 ret
= run_as_cmd(global_worker
, cmd
, data
, ret_value
, uid
, gid
);
1649 saved_errno
= ret_value
->_errno
;
1652 * If the worker thread crashed the errno is set to EIO. we log
1653 * the error and start a new worker process.
1655 if (ret
== -1 && saved_errno
== EIO
) {
1656 DBG("Socket closed unexpectedly... "
1657 "Restarting the worker process");
1658 ret
= run_as_restart_worker(global_worker
);
1660 ERR("Failed to restart worker process.");
1665 DBG("Using run_as without worker");
1666 ret
= run_as_noworker(cmd
, data
, ret_value
, uid
, gid
);
1669 pthread_mutex_unlock(&worker_lock
);
1673 int run_as_mkdir_recursive(const char *path
, mode_t mode
, uid_t uid
, gid_t gid
)
1675 return run_as_mkdirat_recursive(AT_FDCWD
, path
, mode
, uid
, gid
);
1678 int run_as_mkdirat_recursive(int dirfd
, const char *path
, mode_t mode
,
1679 uid_t uid
, gid_t gid
)
1682 struct run_as_data data
= {};
1683 struct run_as_ret run_as_ret
= {};
1685 DBG3("mkdirat() recursive fd = %d%s, path = %s, mode = %d, uid = %d, gid = %d",
1686 dirfd
, dirfd
== AT_FDCWD
? " (AT_FDCWD)" : "",
1687 path
, (int) mode
, (int) uid
, (int) gid
);
1688 ret
= lttng_strncpy(data
.u
.mkdir
.path
, path
,
1689 sizeof(data
.u
.mkdir
.path
));
1691 ERR("Failed to copy path argument of mkdirat recursive command");
1694 data
.u
.mkdir
.path
[sizeof(data
.u
.mkdir
.path
) - 1] = '\0';
1695 data
.u
.mkdir
.mode
= mode
;
1696 data
.u
.mkdir
.dirfd
= dirfd
;
1697 run_as(dirfd
== AT_FDCWD
? RUN_AS_MKDIR_RECURSIVE
: RUN_AS_MKDIRAT_RECURSIVE
,
1698 &data
, &run_as_ret
, uid
, gid
);
1699 errno
= run_as_ret
._errno
;
1700 ret
= run_as_ret
.u
.ret
;
1705 int run_as_mkdir(const char *path
, mode_t mode
, uid_t uid
, gid_t gid
)
1707 return run_as_mkdirat(AT_FDCWD
, path
, mode
, uid
, gid
);
1710 int run_as_mkdirat(int dirfd
, const char *path
, mode_t mode
,
1711 uid_t uid
, gid_t gid
)
1714 struct run_as_data data
= {};
1715 struct run_as_ret run_as_ret
= {};
1717 DBG3("mkdirat() recursive fd = %d%s, path = %s, mode = %d, uid = %d, gid = %d",
1718 dirfd
, dirfd
== AT_FDCWD
? " (AT_FDCWD)" : "",
1719 path
, (int) mode
, (int) uid
, (int) gid
);
1720 ret
= lttng_strncpy(data
.u
.mkdir
.path
, path
,
1721 sizeof(data
.u
.mkdir
.path
));
1723 ERR("Failed to copy path argument of mkdirat command");
1726 data
.u
.mkdir
.path
[sizeof(data
.u
.mkdir
.path
) - 1] = '\0';
1727 data
.u
.mkdir
.mode
= mode
;
1728 data
.u
.mkdir
.dirfd
= dirfd
;
1729 run_as(dirfd
== AT_FDCWD
? RUN_AS_MKDIR
: RUN_AS_MKDIRAT
,
1730 &data
, &run_as_ret
, uid
, gid
);
1731 errno
= run_as_ret
._errno
;
1732 ret
= run_as_ret
.u
.ret
;
1737 int run_as_open(const char *path
, int flags
, mode_t mode
, uid_t uid
,
1740 return run_as_openat(AT_FDCWD
, path
, flags
, mode
, uid
, gid
);
1743 int run_as_openat(int dirfd
, const char *path
, int flags
, mode_t mode
,
1744 uid_t uid
, gid_t gid
)
1747 struct run_as_data data
= {};
1748 struct run_as_ret run_as_ret
= {};
1750 DBG3("openat() fd = %d%s, path = %s, flags = %X, mode = %d, uid %d, gid %d",
1751 dirfd
, dirfd
== AT_FDCWD
? " (AT_FDCWD)" : "",
1752 path
, flags
, (int) mode
, (int) uid
, (int) gid
);
1753 ret
= lttng_strncpy(data
.u
.open
.path
, path
, sizeof(data
.u
.open
.path
));
1755 ERR("Failed to copy path argument of open command");
1758 data
.u
.open
.flags
= flags
;
1759 data
.u
.open
.mode
= mode
;
1760 data
.u
.open
.dirfd
= dirfd
;
1761 run_as(dirfd
== AT_FDCWD
? RUN_AS_OPEN
: RUN_AS_OPENAT
,
1762 &data
, &run_as_ret
, uid
, gid
);
1763 errno
= run_as_ret
._errno
;
1764 ret
= run_as_ret
.u
.ret
< 0 ? run_as_ret
.u
.ret
:
1765 run_as_ret
.u
.open
.fd
;
1770 int run_as_unlink(const char *path
, uid_t uid
, gid_t gid
)
1772 return run_as_unlinkat(AT_FDCWD
, path
, uid
, gid
);
1775 int run_as_unlinkat(int dirfd
, const char *path
, uid_t uid
, gid_t gid
)
1778 struct run_as_data data
= {};
1779 struct run_as_ret run_as_ret
= {};
1781 DBG3("unlinkat() fd = %d%s, path = %s, uid = %d, gid = %d",
1782 dirfd
, dirfd
== AT_FDCWD
? " (AT_FDCWD)" : "",
1783 path
, (int) uid
, (int) gid
);
1784 ret
= lttng_strncpy(data
.u
.unlink
.path
, path
,
1785 sizeof(data
.u
.unlink
.path
));
1789 data
.u
.unlink
.dirfd
= dirfd
;
1790 run_as(dirfd
== AT_FDCWD
? RUN_AS_UNLINK
: RUN_AS_UNLINKAT
, &data
,
1791 &run_as_ret
, uid
, gid
);
1792 errno
= run_as_ret
._errno
;
1793 ret
= run_as_ret
.u
.ret
;
1798 int run_as_rmdir(const char *path
, uid_t uid
, gid_t gid
)
1800 return run_as_rmdirat(AT_FDCWD
, path
, uid
, gid
);
1803 int run_as_rmdirat(int dirfd
, const char *path
, uid_t uid
, gid_t gid
)
1806 struct run_as_data data
= {};
1807 struct run_as_ret run_as_ret
= {};
1809 DBG3("rmdirat() fd = %d%s, path = %s, uid = %d, gid = %d",
1810 dirfd
, dirfd
== AT_FDCWD
? " (AT_FDCWD)" : "",
1811 path
, (int) uid
, (int) gid
);
1812 ret
= lttng_strncpy(data
.u
.rmdir
.path
, path
,
1813 sizeof(data
.u
.rmdir
.path
));
1817 data
.u
.rmdir
.dirfd
= dirfd
;
1818 run_as(dirfd
== AT_FDCWD
? RUN_AS_RMDIR
: RUN_AS_RMDIRAT
, &data
,
1819 &run_as_ret
, uid
, gid
);
1820 errno
= run_as_ret
._errno
;
1821 ret
= run_as_ret
.u
.ret
;
1826 int run_as_rmdir_recursive(const char *path
, uid_t uid
, gid_t gid
, int flags
)
1828 return run_as_rmdirat_recursive(AT_FDCWD
, path
, uid
, gid
, flags
);
1831 int run_as_rmdirat_recursive(int dirfd
, const char *path
, uid_t uid
, gid_t gid
, int flags
)
1834 struct run_as_data data
= {};
1835 struct run_as_ret run_as_ret
= {};
1837 DBG3("rmdirat() recursive fd = %d%s, path = %s, uid = %d, gid = %d",
1838 dirfd
, dirfd
== AT_FDCWD
? " (AT_FDCWD)" : "",
1839 path
, (int) uid
, (int) gid
);
1840 ret
= lttng_strncpy(data
.u
.rmdir
.path
, path
,
1841 sizeof(data
.u
.rmdir
.path
));
1845 data
.u
.rmdir
.dirfd
= dirfd
;
1846 data
.u
.rmdir
.flags
= flags
;
1847 run_as(dirfd
== AT_FDCWD
? RUN_AS_RMDIR_RECURSIVE
: RUN_AS_RMDIRAT_RECURSIVE
,
1848 &data
, &run_as_ret
, uid
, gid
);
1849 errno
= run_as_ret
._errno
;
1850 ret
= run_as_ret
.u
.ret
;
1855 int run_as_rename(const char *old_name
, const char *new_name
, uid_t uid
, gid_t gid
)
1857 return run_as_renameat(AT_FDCWD
, old_name
, AT_FDCWD
, new_name
, uid
, gid
);
1860 int run_as_renameat(int old_dirfd
, const char *old_name
,
1861 int new_dirfd
, const char *new_name
, uid_t uid
, gid_t gid
)
1864 struct run_as_data data
= {};
1865 struct run_as_ret run_as_ret
= {};
1867 DBG3("renameat() old_dirfd = %d%s, old_name = %s, new_dirfd = %d%s, new_name = %s, uid = %d, gid = %d",
1868 old_dirfd
, old_dirfd
== AT_FDCWD
? " (AT_FDCWD)" : "",
1870 new_dirfd
, new_dirfd
== AT_FDCWD
? " (AT_FDCWD)" : "",
1871 new_name
, (int) uid
, (int) gid
);
1872 ret
= lttng_strncpy(data
.u
.rename
.old_path
, old_name
,
1873 sizeof(data
.u
.rename
.old_path
));
1877 ret
= lttng_strncpy(data
.u
.rename
.new_path
, new_name
,
1878 sizeof(data
.u
.rename
.new_path
));
1883 data
.u
.rename
.dirfds
[0] = old_dirfd
;
1884 data
.u
.rename
.dirfds
[1] = new_dirfd
;
1885 run_as(old_dirfd
== AT_FDCWD
&& new_dirfd
== AT_FDCWD
?
1886 RUN_AS_RENAME
: RUN_AS_RENAMEAT
,
1887 &data
, &run_as_ret
, uid
, gid
);
1888 errno
= run_as_ret
._errno
;
1889 ret
= run_as_ret
.u
.ret
;
1894 int run_as_extract_elf_symbol_offset(int fd
, const char* function
,
1895 uid_t uid
, gid_t gid
, uint64_t *offset
)
1898 struct run_as_data data
= {};
1899 struct run_as_ret run_as_ret
= {};
1901 DBG3("extract_elf_symbol_offset() on fd=%d and function=%s "
1902 "with for uid %d and gid %d", fd
, function
,
1903 (int) uid
, (int) gid
);
1905 data
.u
.extract_elf_symbol_offset
.fd
= fd
;
1907 strncpy(data
.u
.extract_elf_symbol_offset
.function
, function
, LTTNG_SYMBOL_NAME_LEN
- 1);
1908 data
.u
.extract_elf_symbol_offset
.function
[LTTNG_SYMBOL_NAME_LEN
- 1] = '\0';
1909 ret
= lttng_strncpy(data
.u
.extract_elf_symbol_offset
.function
,
1911 sizeof(data
.u
.extract_elf_symbol_offset
.function
));
1916 run_as(RUN_AS_EXTRACT_ELF_SYMBOL_OFFSET
, &data
, &run_as_ret
, uid
, gid
);
1917 errno
= run_as_ret
._errno
;
1918 if (run_as_ret
._error
) {
1923 *offset
= run_as_ret
.u
.extract_elf_symbol_offset
.offset
;
1928 int run_as_extract_sdt_probe_offsets(int fd
, const char* provider_name
,
1929 const char* probe_name
, uid_t uid
, gid_t gid
,
1930 uint64_t **offsets
, uint32_t *num_offset
)
1933 struct run_as_data data
= {};
1934 struct run_as_ret run_as_ret
= {};
1936 DBG3("extract_sdt_probe_offsets() on fd=%d, probe_name=%s and "
1937 "provider_name=%s with for uid %d and gid %d", fd
,
1938 probe_name
, provider_name
, (int) uid
, (int) gid
);
1940 data
.u
.extract_sdt_probe_offsets
.fd
= fd
;
1942 ret
= lttng_strncpy(data
.u
.extract_sdt_probe_offsets
.probe_name
, probe_name
,
1943 sizeof(data
.u
.extract_sdt_probe_offsets
.probe_name
));
1947 ret
= lttng_strncpy(data
.u
.extract_sdt_probe_offsets
.provider_name
,
1949 sizeof(data
.u
.extract_sdt_probe_offsets
.provider_name
));
1954 run_as(RUN_AS_EXTRACT_SDT_PROBE_OFFSETS
, &data
, &run_as_ret
, uid
, gid
);
1955 errno
= run_as_ret
._errno
;
1956 if (run_as_ret
._error
) {
1961 *num_offset
= run_as_ret
.u
.extract_sdt_probe_offsets
.num_offset
;
1962 *offsets
= (uint64_t *) zmalloc(*num_offset
* sizeof(uint64_t));
1968 memcpy(*offsets
, run_as_ret
.u
.extract_sdt_probe_offsets
.offsets
,
1969 *num_offset
* sizeof(uint64_t));
1974 int run_as_generate_filter_bytecode(const char *filter_expression
,
1975 const struct lttng_credentials
*creds
,
1976 struct lttng_bytecode
**bytecode
)
1979 struct run_as_data data
= {};
1980 struct run_as_ret run_as_ret
= {};
1981 const struct lttng_bytecode
*view_bytecode
= NULL
;
1982 struct lttng_bytecode
*local_bytecode
= NULL
;
1983 const uid_t uid
= lttng_credentials_get_uid(creds
);
1984 const gid_t gid
= lttng_credentials_get_gid(creds
);
1986 DBG3("generate_filter_bytecode() from expression=\"%s\" for uid %d and gid %d",
1987 filter_expression
, (int) uid
, (int) gid
);
1989 ret
= lttng_strncpy(data
.u
.generate_filter_bytecode
.filter_expression
, filter_expression
,
1990 sizeof(data
.u
.generate_filter_bytecode
.filter_expression
));
1995 run_as(RUN_AS_GENERATE_FILTER_BYTECODE
, &data
, &run_as_ret
, uid
, gid
);
1996 errno
= run_as_ret
._errno
;
1997 if (run_as_ret
._error
) {
2002 view_bytecode
= (const struct lttng_bytecode
*) run_as_ret
.u
.generate_filter_bytecode
.bytecode
;
2004 local_bytecode
= (lttng_bytecode
*) zmalloc(sizeof(*local_bytecode
) + view_bytecode
->len
);
2005 if (!local_bytecode
) {
2010 memcpy(local_bytecode
, run_as_ret
.u
.generate_filter_bytecode
.bytecode
,
2011 sizeof(*local_bytecode
) + view_bytecode
->len
);
2012 *bytecode
= local_bytecode
;
2017 int run_as_create_worker(const char *procname
,
2018 post_fork_cleanup_cb clean_up_func
,
2019 void *clean_up_user_data
)
2023 pthread_mutex_lock(&worker_lock
);
2024 ret
= run_as_create_worker_no_lock(procname
, clean_up_func
,
2025 clean_up_user_data
);
2026 pthread_mutex_unlock(&worker_lock
);
2030 void run_as_destroy_worker(void)
2032 pthread_mutex_lock(&worker_lock
);
2033 run_as_destroy_worker_no_lock();
2034 pthread_mutex_unlock(&worker_lock
);