2 * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
3 * Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License, version 2 only,
7 * as published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 #include <sys/types.h>
35 #include <common/lttng-kernel.h>
36 #include <common/common.h>
37 #include <common/utils.h>
38 #include <common/compat/getenv.h>
39 #include <common/compat/prctl.h>
40 #include <common/unix.h>
41 #include <common/defaults.h>
42 #include <common/lttng-elf.h>
44 #include <lttng/constant.h>
50 typedef int (*run_as_fct
)(struct run_as_data
*data
, struct run_as_ret
*ret_value
);
52 struct run_as_mkdirat_data
{
57 struct run_as_open_data
{
63 struct run_as_unlink_data
{
67 struct run_as_rmdir_recursive_data
{
71 struct run_as_extract_elf_symbol_offset_data
{
72 char function
[LTTNG_SYMBOL_NAME_LEN
];
75 struct run_as_extract_sdt_probe_offsets_data
{
76 char probe_name
[LTTNG_SYMBOL_NAME_LEN
];
77 char provider_name
[LTTNG_SYMBOL_NAME_LEN
];
80 struct run_as_mkdirat_ret
{
84 struct run_as_open_ret
{
88 struct run_as_unlink_ret
{
92 struct run_as_rmdir_recursive_ret
{
96 struct run_as_extract_elf_symbol_offset_ret
{
100 struct run_as_extract_sdt_probe_offsets_ret
{
102 uint64_t offsets
[LTTNG_KERNEL_MAX_UPROBE_NUM
];
108 RUN_AS_MKDIR_RECURSIVE
,
109 RUN_AS_MKDIRAT_RECURSIVE
,
114 RUN_AS_RMDIR_RECURSIVE
,
115 RUN_AS_EXTRACT_ELF_SYMBOL_OFFSET
,
116 RUN_AS_EXTRACT_SDT_PROBE_OFFSETS
,
123 struct run_as_mkdirat_data mkdirat
;
124 struct run_as_open_data open
;
125 struct run_as_unlink_data unlink
;
126 struct run_as_rmdir_recursive_data rmdir_recursive
;
127 struct run_as_extract_elf_symbol_offset_data extract_elf_symbol_offset
;
128 struct run_as_extract_sdt_probe_offsets_data extract_sdt_probe_offsets
;
135 * The run_as_ret structure holds the returned value and status of the command.
137 * The `u` union field holds the return value of the command; in most cases it
138 * represents the success or the failure of the command. In more complex
139 * commands, it holds a computed value.
141 * The _errno field is the errno recorded after the execution of the command.
143 * The _error fields is used the signify that return status of the command. For
144 * simple commands returning `int` the _error field will be the same as the
145 * ret_int field. In complex commands, it signify the success or failure of the
152 struct run_as_mkdirat_ret mkdirat
;
153 struct run_as_open_ret open
;
154 struct run_as_unlink_ret unlink
;
155 struct run_as_rmdir_recursive_ret rmdir_recursive
;
156 struct run_as_extract_elf_symbol_offset_ret extract_elf_symbol_offset
;
157 struct run_as_extract_sdt_probe_offsets_ret extract_sdt_probe_offsets
;
163 struct run_as_worker
{
164 pid_t pid
; /* Worker PID. */
169 /* Single global worker per process (for now). */
170 static struct run_as_worker
*global_worker
;
171 /* Lock protecting the worker. */
172 static pthread_mutex_t worker_lock
= PTHREAD_MUTEX_INITIALIZER
;
184 return !lttng_secure_getenv("LTTNG_DEBUG_NOCLONE");
189 * Create recursively directory using the FULL path.
192 int _mkdirat_recursive(struct run_as_data
*data
, struct run_as_ret
*ret_value
)
196 struct lttng_directory_handle handle
;
198 path
= data
->u
.mkdirat
.path
;
199 mode
= data
->u
.mkdirat
.mode
;
201 (void) lttng_directory_handle_init_from_dirfd(&handle
, data
->fd
);
202 /* Ownership of dirfd is transferred to the handle. */
204 /* Safe to call as we have transitioned to the requested uid/gid. */
205 ret_value
->u
.mkdirat
.ret
=
206 lttng_directory_handle_create_subdirectory_recursive(
207 &handle
, path
, mode
);
208 ret_value
->_errno
= errno
;
209 ret_value
->_error
= (ret_value
->u
.mkdirat
.ret
) ? true : false;
210 lttng_directory_handle_fini(&handle
);
211 return ret_value
->u
.mkdirat
.ret
;
215 int _mkdirat(struct run_as_data
*data
, struct run_as_ret
*ret_value
)
219 struct lttng_directory_handle handle
;
221 path
= data
->u
.mkdirat
.path
;
222 mode
= data
->u
.mkdirat
.mode
;
224 (void) lttng_directory_handle_init_from_dirfd(&handle
, data
->fd
);
225 /* Ownership of dirfd is transferred to the handle. */
227 /* Safe to call as we have transitioned to the requested uid/gid. */
228 ret_value
->u
.mkdirat
.ret
=
229 lttng_directory_handle_create_subdirectory(
230 &handle
, path
, mode
);
231 ret_value
->_errno
= errno
;
232 ret_value
->_error
= (ret_value
->u
.mkdirat
.ret
) ? true : false;
233 lttng_directory_handle_fini(&handle
);
234 return ret_value
->u
.mkdirat
.ret
;
238 int _open(struct run_as_data
*data
, struct run_as_ret
*ret_value
)
240 ret_value
->u
.open
.ret
= openat(data
->fd
, data
->u
.open
.path
,
241 data
->u
.open
.flags
, data
->u
.open
.mode
);
242 ret_value
->fd
= ret_value
->u
.open
.ret
;
243 ret_value
->_errno
= errno
;
244 ret_value
->_error
= ret_value
->u
.open
.ret
< 0;
245 return ret_value
->u
.open
.ret
;
249 int _unlink(struct run_as_data
*data
, struct run_as_ret
*ret_value
)
251 ret_value
->u
.unlink
.ret
= unlinkat(data
->fd
, data
->u
.unlink
.path
, 0);
252 ret_value
->_errno
= errno
;
253 ret_value
->_error
= (ret_value
->u
.unlink
.ret
) ? true : false;
254 return ret_value
->u
.unlink
.ret
;
258 int _rmdir_recursive(struct run_as_data
*data
, struct run_as_ret
*ret_value
)
260 ret_value
->u
.rmdir_recursive
.ret
= utils_recursive_rmdir(data
->u
.rmdir_recursive
.path
);
261 ret_value
->_errno
= errno
;
262 ret_value
->_error
= (ret_value
->u
.rmdir_recursive
.ret
) ? true : false;
263 return ret_value
->u
.rmdir_recursive
.ret
;
268 int _extract_elf_symbol_offset(struct run_as_data
*data
,
269 struct run_as_ret
*ret_value
)
272 ret_value
->_error
= false;
274 ret
= lttng_elf_get_symbol_offset(data
->fd
,
275 data
->u
.extract_elf_symbol_offset
.function
,
276 &ret_value
->u
.extract_elf_symbol_offset
.offset
);
278 DBG("Failed to extract ELF function offset");
279 ret_value
->_error
= true;
286 int _extract_sdt_probe_offsets(struct run_as_data
*data
,
287 struct run_as_ret
*ret_value
)
290 uint64_t *offsets
= NULL
;
293 ret_value
->_error
= false;
295 /* On success, this call allocates the offsets paramater. */
296 ret
= lttng_elf_get_sdt_probe_offsets(data
->fd
,
297 data
->u
.extract_sdt_probe_offsets
.provider_name
,
298 data
->u
.extract_sdt_probe_offsets
.probe_name
,
299 &offsets
, &num_offset
);
302 DBG("Failed to extract SDT probe offsets");
303 ret_value
->_error
= true;
307 if (num_offset
<= 0 || num_offset
> LTTNG_KERNEL_MAX_UPROBE_NUM
) {
308 DBG("Wrong number of probes.");
310 ret_value
->_error
= true;
314 /* Copy the content of the offsets array to the ret struct. */
315 memcpy(ret_value
->u
.extract_sdt_probe_offsets
.offsets
,
316 offsets
, num_offset
* sizeof(uint64_t));
318 ret_value
->u
.extract_sdt_probe_offsets
.num_offset
= num_offset
;
327 int _extract_elf_symbol_offset(struct run_as_data
*data
,
328 struct run_as_ret
*ret_value
)
330 ERR("Unimplemented runas command RUN_AS_EXTRACT_ELF_SYMBOL_OFFSET");
335 int _extract_sdt_probe_offsets(struct run_as_data
*data
,
336 struct run_as_ret
*ret_value
)
338 ERR("Unimplemented runas command RUN_AS_EXTRACT_SDT_PROBE_OFFSETS");
344 run_as_fct
run_as_enum_to_fct(enum run_as_cmd cmd
)
350 case RUN_AS_MKDIR_RECURSIVE
:
351 case RUN_AS_MKDIRAT_RECURSIVE
:
352 return _mkdirat_recursive
;
357 case RUN_AS_UNLINKAT
:
359 case RUN_AS_RMDIR_RECURSIVE
:
360 return _rmdir_recursive
;
361 case RUN_AS_EXTRACT_ELF_SYMBOL_OFFSET
:
362 return _extract_elf_symbol_offset
;
363 case RUN_AS_EXTRACT_SDT_PROBE_OFFSETS
:
364 return _extract_sdt_probe_offsets
;
366 ERR("Unknown command %d", (int) cmd
);
372 int do_send_fd(int sock
, int fd
)
377 ERR("Attempt to send invalid file descriptor to master (fd = %i)", fd
);
378 /* Return 0 as this is not a fatal error. */
382 len
= lttcomm_send_fds_unix_sock(sock
, &fd
, 1);
384 PERROR("lttcomm_send_fds_unix_sock");
391 int do_recv_fd(int sock
, int *fd
)
395 len
= lttcomm_recv_fds_unix_sock(sock
, fd
, 1);
399 } else if (len
< 0) {
400 PERROR("lttcomm_recv_fds_unix_sock");
404 ERR("Invalid file descriptor received from worker (fd = %i)", *fd
);
405 /* Return 0 as this is not a fatal error. */
413 int send_fd_to_worker(struct run_as_worker
*worker
, enum run_as_cmd cmd
, int fd
)
418 case RUN_AS_EXTRACT_ELF_SYMBOL_OFFSET
:
419 case RUN_AS_EXTRACT_SDT_PROBE_OFFSETS
:
421 case RUN_AS_MKDIRAT_RECURSIVE
:
423 case RUN_AS_UNLINKAT
:
430 ERR("Refusing to send invalid fd to worker (fd = %i)", fd
);
434 ret
= do_send_fd(worker
->sockpair
[0], fd
);
436 PERROR("do_send_fd");
444 int send_fd_to_master(struct run_as_worker
*worker
, enum run_as_cmd cmd
, int fd
)
446 int ret
= 0, ret_close
= 0;
457 DBG("Not sending file descriptor to master as it is invalid (fd = %i)", fd
);
460 ret
= do_send_fd(worker
->sockpair
[1], fd
);
462 PERROR("do_send_fd error");
466 ret_close
= close(fd
);
475 int recv_fd_from_worker(struct run_as_worker
*worker
, enum run_as_cmd cmd
, int *fd
)
487 ret
= do_recv_fd(worker
->sockpair
[0], fd
);
489 PERROR("do_recv_fd error");
497 int recv_fd_from_master(struct run_as_worker
*worker
, enum run_as_cmd cmd
, int *fd
)
502 case RUN_AS_EXTRACT_ELF_SYMBOL_OFFSET
:
503 case RUN_AS_EXTRACT_SDT_PROBE_OFFSETS
:
505 case RUN_AS_MKDIRAT_RECURSIVE
:
507 case RUN_AS_UNLINKAT
:
510 case RUN_AS_MKDIR_RECURSIVE
:
519 ret
= do_recv_fd(worker
->sockpair
[1], fd
);
521 PERROR("do_recv_fd error");
529 int cleanup_received_fd(enum run_as_cmd cmd
, int fd
)
534 case RUN_AS_EXTRACT_ELF_SYMBOL_OFFSET
:
535 case RUN_AS_EXTRACT_SDT_PROBE_OFFSETS
:
537 case RUN_AS_MKDIRAT_RECURSIVE
:
541 case RUN_AS_UNLINKAT
:
552 PERROR("close error");
560 * Return < 0 on error, 0 if OK, 1 on hangup.
563 int handle_one_cmd(struct run_as_worker
*worker
)
566 struct run_as_data data
;
567 ssize_t readlen
, writelen
;
568 struct run_as_ret sendret
;
572 memset(&sendret
, 0, sizeof(sendret
));
576 * Stage 1: Receive run_as_data struct from the master.
577 * The structure contains the command type and all the parameters needed for
580 readlen
= lttcomm_recv_unix_sock(worker
->sockpair
[1], &data
,
587 if (readlen
< sizeof(data
)) {
588 PERROR("lttcomm_recv_unix_sock error");
593 cmd
= run_as_enum_to_fct(data
.cmd
);
600 * Stage 2: Receive file descriptor from master.
601 * Some commands need a file descriptor as input so if it's needed we
602 * receive the fd using the Unix socket.
604 ret
= recv_fd_from_master(worker
, data
.cmd
, &data
.fd
);
606 PERROR("recv_fd_from_master error");
611 prev_euid
= getuid();
612 if (data
.gid
!= getegid()) {
613 ret
= setegid(data
.gid
);
615 sendret
._error
= true;
616 sendret
._errno
= errno
;
621 if (data
.uid
!= prev_euid
) {
622 ret
= seteuid(data
.uid
);
624 sendret
._error
= true;
625 sendret
._errno
= errno
;
632 * Also set umask to 0 for mkdir executable bit.
637 * Stage 3: Execute the command
639 ret
= (*cmd
)(&data
, &sendret
);
641 DBG("Execution of command returned an error");
645 ret
= cleanup_received_fd(data
.cmd
, data
.fd
);
647 ERR("Error cleaning up FD");
652 * Stage 4: Send run_as_ret structure to the master.
653 * This structure contain the return value of the command and the errno.
655 writelen
= lttcomm_send_unix_sock(worker
->sockpair
[1], &sendret
,
657 if (writelen
< sizeof(sendret
)) {
658 PERROR("lttcomm_send_unix_sock error");
664 * Stage 5: Send file descriptor to the master
665 * Some commands return a file descriptor so if it's needed we pass it back
666 * to the master using the Unix socket.
668 ret
= send_fd_to_master(worker
, data
.cmd
, sendret
.fd
);
670 DBG("Sending FD to master returned an error");
674 if (seteuid(prev_euid
) < 0) {
685 int run_as_worker(struct run_as_worker
*worker
)
689 struct run_as_ret sendret
;
690 size_t proc_orig_len
;
693 * Initialize worker. Set a different process cmdline.
695 proc_orig_len
= strlen(worker
->procname
);
696 memset(worker
->procname
, 0, proc_orig_len
);
697 strncpy(worker
->procname
, DEFAULT_RUN_AS_WORKER_NAME
, proc_orig_len
);
699 ret
= lttng_prctl(PR_SET_NAME
,
700 (unsigned long) DEFAULT_RUN_AS_WORKER_NAME
, 0, 0, 0);
701 if (ret
&& ret
!= -ENOSYS
) {
702 /* Don't fail as this is not essential. */
703 PERROR("prctl PR_SET_NAME");
706 memset(&sendret
, 0, sizeof(sendret
));
708 writelen
= lttcomm_send_unix_sock(worker
->sockpair
[1], &sendret
,
710 if (writelen
< sizeof(sendret
)) {
711 PERROR("lttcomm_send_unix_sock error");
717 ret
= handle_one_cmd(worker
);
721 } else if (ret
> 0) {
724 continue; /* Next command. */
733 int run_as_cmd(struct run_as_worker
*worker
,
735 struct run_as_data
*data
,
736 struct run_as_ret
*ret_value
,
737 uid_t uid
, gid_t gid
)
740 ssize_t readlen
, writelen
;
743 * If we are non-root, we can only deal with our own uid.
745 if (geteuid() != 0) {
746 if (uid
!= geteuid()) {
748 ret_value
->_errno
= EPERM
;
749 ERR("Client (%d)/Server (%d) UID mismatch (and sessiond is not root)",
750 (int) uid
, (int) geteuid());
760 * Stage 1: Send the run_as_data struct to the worker process
762 writelen
= lttcomm_send_unix_sock(worker
->sockpair
[0], data
,
764 if (writelen
< sizeof(*data
)) {
765 PERROR("Error writing message to run_as");
767 ret_value
->_errno
= EIO
;
772 * Stage 2: Send file descriptor to the worker process if needed
774 ret
= send_fd_to_worker(worker
, data
->cmd
, data
->fd
);
776 PERROR("do_send_fd error");
778 ret_value
->_errno
= EIO
;
783 * Stage 3: Wait for the execution of the command
787 * Stage 4: Receive the run_as_ret struct containing the return value and
790 readlen
= lttcomm_recv_unix_sock(worker
->sockpair
[0], ret_value
,
793 ERR("Run-as worker has hung-up during run_as_cmd");
795 ret_value
->_errno
= EIO
;
797 } else if (readlen
< sizeof(*ret_value
)) {
798 PERROR("Error reading response from run_as");
800 ret_value
->_errno
= errno
;
804 if (ret_value
->_error
) {
805 /* Skip stage 5 on error as there will be no fd to receive. */
810 * Stage 5: Receive file descriptor if needed
812 ret
= recv_fd_from_worker(worker
, data
->cmd
, &ret_value
->fd
);
814 ERR("Error receiving fd");
816 ret_value
->_errno
= EIO
;
824 * This is for debugging ONLY and should not be considered secure.
827 int run_as_noworker(enum run_as_cmd cmd
,
828 struct run_as_data
*data
, struct run_as_ret
*ret_value
,
829 uid_t uid
, gid_t gid
)
831 int ret
, saved_errno
;
835 fct
= run_as_enum_to_fct(cmd
);
842 ret
= fct(data
, ret_value
);
843 saved_errno
= ret_value
->_errno
;
851 int reset_sighandler(void)
855 DBG("Resetting run_as worker signal handlers to default");
856 for (sig
= 1; sig
<= 31; sig
++) {
857 (void) signal(sig
, SIG_DFL
);
863 void worker_sighandler(int sig
)
868 * The worker will inherit its parent's signals since they are part of
869 * the same process group. However, in the case of SIGINT and SIGTERM,
870 * we want to give the worker a chance to teardown gracefully when its
871 * parent closes the command socket.
885 DBG("run_as worker received signal %s", signame
);
887 DBG("run_as_worker received signal %d", sig
);
892 int set_worker_sighandlers(void)
898 if ((ret
= sigemptyset(&sigset
)) < 0) {
899 PERROR("sigemptyset");
903 sa
.sa_handler
= worker_sighandler
;
906 if ((ret
= sigaction(SIGINT
, &sa
, NULL
)) < 0) {
907 PERROR("sigaction SIGINT");
911 if ((ret
= sigaction(SIGTERM
, &sa
, NULL
)) < 0) {
912 PERROR("sigaction SIGTERM");
916 DBG("run_as signal handler set for SIGTERM and SIGINT");
922 int run_as_create_worker_no_lock(const char *procname
,
923 post_fork_cleanup_cb clean_up_func
,
924 void *clean_up_user_data
)
929 struct run_as_ret recvret
;
930 struct run_as_worker
*worker
;
932 assert(!global_worker
);
935 * Don't initialize a worker, all run_as tasks will be performed
936 * in the current process.
941 worker
= zmalloc(sizeof(*worker
));
946 worker
->procname
= strdup(procname
);
947 if (!worker
->procname
) {
949 goto error_procname_alloc
;
951 /* Create unix socket. */
952 if (lttcomm_create_anon_unix_socketpair(worker
->sockpair
) < 0) {
963 } else if (pid
== 0) {
968 set_worker_sighandlers();
970 if (clean_up_func(clean_up_user_data
) < 0) {
971 ERR("Run-as post-fork clean-up failed, exiting.");
976 /* Just close, no shutdown. */
977 if (close(worker
->sockpair
[0])) {
983 * Close all FDs aside from STDIN, STDOUT, STDERR and sockpair[1]
984 * Sockpair[1] is used as a control channel with the master
986 for (i
= 3; i
< sysconf(_SC_OPEN_MAX
); i
++) {
987 if (i
!= worker
->sockpair
[1]) {
992 worker
->sockpair
[0] = -1;
993 ret
= run_as_worker(worker
);
994 if (lttcomm_close_unix_sock(worker
->sockpair
[1])) {
998 worker
->sockpair
[1] = -1;
999 free(worker
->procname
);
1001 LOG(ret
? PRINT_ERR
: PRINT_DBG
, "run_as worker exiting (ret = %d)", ret
);
1002 exit(ret
? EXIT_FAILURE
: EXIT_SUCCESS
);
1006 /* Just close, no shutdown. */
1007 if (close(worker
->sockpair
[1])) {
1012 worker
->sockpair
[1] = -1;
1014 /* Wait for worker to become ready. */
1015 readlen
= lttcomm_recv_unix_sock(worker
->sockpair
[0],
1016 &recvret
, sizeof(recvret
));
1017 if (readlen
< sizeof(recvret
)) {
1018 ERR("readlen: %zd", readlen
);
1019 PERROR("Error reading response from run_as at creation");
1023 global_worker
= worker
;
1028 /* Error handling. */
1030 for (i
= 0; i
< 2; i
++) {
1031 if (worker
->sockpair
[i
] < 0) {
1034 if (lttcomm_close_unix_sock(worker
->sockpair
[i
])) {
1037 worker
->sockpair
[i
] = -1;
1040 free(worker
->procname
);
1041 error_procname_alloc
:
1047 void run_as_destroy_worker_no_lock(void)
1049 struct run_as_worker
*worker
= global_worker
;
1051 DBG("Destroying run_as worker");
1055 /* Close unix socket */
1056 DBG("Closing run_as worker socket");
1057 if (lttcomm_close_unix_sock(worker
->sockpair
[0])) {
1060 worker
->sockpair
[0] = -1;
1061 /* Wait for worker. */
1066 wait_ret
= waitpid(worker
->pid
, &status
, 0);
1068 if (errno
== EINTR
) {
1075 if (WIFEXITED(status
)) {
1076 LOG(WEXITSTATUS(status
) == 0 ? PRINT_DBG
: PRINT_ERR
,
1077 DEFAULT_RUN_AS_WORKER_NAME
" terminated with status code %d",
1078 WEXITSTATUS(status
));
1080 } else if (WIFSIGNALED(status
)) {
1081 ERR(DEFAULT_RUN_AS_WORKER_NAME
" was killed by signal %d",
1086 free(worker
->procname
);
1088 global_worker
= NULL
;
1092 int run_as_restart_worker(struct run_as_worker
*worker
)
1095 char *procname
= NULL
;
1097 procname
= worker
->procname
;
1099 /* Close socket to run_as worker process and clean up the zombie process */
1100 run_as_destroy_worker_no_lock();
1102 /* Create a new run_as worker process*/
1103 ret
= run_as_create_worker_no_lock(procname
, NULL
, NULL
);
1105 ERR("Restarting the worker process failed");
1114 int run_as(enum run_as_cmd cmd
, struct run_as_data
*data
,
1115 struct run_as_ret
*ret_value
, uid_t uid
, gid_t gid
)
1117 int ret
, saved_errno
;
1119 pthread_mutex_lock(&worker_lock
);
1121 DBG("Using run_as worker");
1123 assert(global_worker
);
1125 ret
= run_as_cmd(global_worker
, cmd
, data
, ret_value
, uid
, gid
);
1126 saved_errno
= ret_value
->_errno
;
1129 * If the worker thread crashed the errno is set to EIO. we log
1130 * the error and start a new worker process.
1132 if (ret
== -1 && saved_errno
== EIO
) {
1133 DBG("Socket closed unexpectedly... "
1134 "Restarting the worker process");
1135 ret
= run_as_restart_worker(global_worker
);
1137 ERR("Failed to restart worker process.");
1142 DBG("Using run_as without worker");
1143 ret
= run_as_noworker(cmd
, data
, ret_value
, uid
, gid
);
1146 pthread_mutex_unlock(&worker_lock
);
1151 int run_as_mkdir_recursive(const char *path
, mode_t mode
, uid_t uid
, gid_t gid
)
1153 return run_as_mkdirat_recursive(AT_FDCWD
, path
, mode
, uid
, gid
);
1157 int run_as_mkdirat_recursive(int dirfd
, const char *path
, mode_t mode
,
1158 uid_t uid
, gid_t gid
)
1161 struct run_as_data data
;
1162 struct run_as_ret run_as_ret
;
1164 memset(&data
, 0, sizeof(data
));
1165 memset(&run_as_ret
, 0, sizeof(run_as_ret
));
1166 DBG3("mkdirat() recursive fd = %d%s, path = %s, mode = %d, uid = %d, gid = %d",
1167 dirfd
, dirfd
== AT_FDCWD
? " (AT_FDCWD)" : "",
1168 path
, (int) mode
, (int) uid
, (int) gid
);
1169 ret
= lttng_strncpy(data
.u
.mkdirat
.path
, path
,
1170 sizeof(data
.u
.mkdirat
.path
));
1172 ERR("Failed to copy path argument of mkdirat recursive command");
1175 data
.u
.mkdirat
.path
[PATH_MAX
- 1] = '\0';
1176 data
.u
.mkdirat
.mode
= mode
;
1178 run_as(dirfd
== AT_FDCWD
? RUN_AS_MKDIR_RECURSIVE
: RUN_AS_MKDIRAT_RECURSIVE
,
1179 &data
, &run_as_ret
, uid
, gid
);
1180 errno
= run_as_ret
._errno
;
1181 ret
= run_as_ret
.u
.mkdirat
.ret
;
1187 int run_as_mkdir(const char *path
, mode_t mode
, uid_t uid
, gid_t gid
)
1189 return run_as_mkdirat(AT_FDCWD
, path
, mode
, uid
, gid
);
1193 int run_as_mkdirat(int dirfd
, const char *path
, mode_t mode
,
1194 uid_t uid
, gid_t gid
)
1197 struct run_as_data data
;
1198 struct run_as_ret run_as_ret
;
1200 memset(&data
, 0, sizeof(data
));
1201 memset(&run_as_ret
, 0, sizeof(run_as_ret
));
1203 DBG3("mkdirat() recursive fd = %d%s, path = %s, mode = %d, uid = %d, gid = %d",
1204 dirfd
, dirfd
== AT_FDCWD
? " (AT_FDCWD)" : "",
1205 path
, (int) mode
, (int) uid
, (int) gid
);
1206 ret
= lttng_strncpy(data
.u
.mkdirat
.path
, path
,
1207 sizeof(data
.u
.mkdirat
.path
));
1209 ERR("Failed to copy path argument of mkdirat command");
1212 data
.u
.mkdirat
.path
[PATH_MAX
- 1] = '\0';
1213 data
.u
.mkdirat
.mode
= mode
;
1215 run_as(dirfd
== AT_FDCWD
? RUN_AS_MKDIR
: RUN_AS_MKDIRAT
,
1216 &data
, &run_as_ret
, uid
, gid
);
1217 errno
= run_as_ret
._errno
;
1218 ret
= run_as_ret
.u
.mkdirat
.ret
;
1224 int run_as_open(const char *path
, int flags
, mode_t mode
, uid_t uid
,
1227 return run_as_openat(AT_FDCWD
, path
, flags
, mode
, uid
, gid
);
1231 int run_as_openat(int dirfd
, const char *path
, int flags
, mode_t mode
,
1232 uid_t uid
, gid_t gid
)
1234 struct run_as_data data
;
1235 struct run_as_ret ret
;
1237 memset(&data
, 0, sizeof(data
));
1238 memset(&ret
, 0, sizeof(ret
));
1240 DBG3("openat() fd = %d%s, path = %s, flags = %X, mode = %d, uid %d, gid %d",
1241 dirfd
, dirfd
== AT_FDCWD
? " (AT_FDCWD)" : "",
1242 path
, flags
, (int) mode
, (int) uid
, (int) gid
);
1243 strncpy(data
.u
.open
.path
, path
, PATH_MAX
- 1);
1244 data
.u
.open
.path
[PATH_MAX
- 1] = '\0';
1245 data
.u
.open
.flags
= flags
;
1246 data
.u
.open
.mode
= mode
;
1248 run_as(dirfd
== AT_FDCWD
? RUN_AS_OPEN
: RUN_AS_OPENAT
,
1249 &data
, &ret
, uid
, gid
);
1251 ret
.u
.open
.ret
= ret
.fd
;
1252 return ret
.u
.open
.ret
;
1256 int run_as_unlink(const char *path
, uid_t uid
, gid_t gid
)
1258 return run_as_unlinkat(AT_FDCWD
, path
, uid
, gid
);
1262 int run_as_unlinkat(int dirfd
, const char *path
, uid_t uid
, gid_t gid
)
1264 struct run_as_data data
;
1265 struct run_as_ret ret
;
1267 memset(&data
, 0, sizeof(data
));
1268 memset(&ret
, 0, sizeof(ret
));
1270 DBG3("unlinkat() fd = %d%s, path = %s, uid = %d, gid = %d",
1271 dirfd
, dirfd
== AT_FDCWD
? " (AT_FDCWD)" : "",
1272 path
, (int) uid
, (int) gid
);
1273 strncpy(data
.u
.unlink
.path
, path
, PATH_MAX
- 1);
1274 data
.u
.unlink
.path
[PATH_MAX
- 1] = '\0';
1276 run_as(RUN_AS_UNLINK
, &data
, &ret
, uid
, gid
);
1278 return ret
.u
.unlink
.ret
;
1282 int run_as_rmdir_recursive(const char *path
, uid_t uid
, gid_t gid
)
1284 struct run_as_data data
;
1285 struct run_as_ret ret
;
1287 memset(&data
, 0, sizeof(data
));
1288 memset(&ret
, 0, sizeof(ret
));
1290 DBG3("rmdir_recursive() %s with for uid %d and gid %d",
1291 path
, (int) uid
, (int) gid
);
1292 strncpy(data
.u
.rmdir_recursive
.path
, path
, PATH_MAX
- 1);
1293 data
.u
.rmdir_recursive
.path
[PATH_MAX
- 1] = '\0';
1294 run_as(RUN_AS_RMDIR_RECURSIVE
, &data
, &ret
, uid
, gid
);
1296 return ret
.u
.rmdir_recursive
.ret
;
1300 int run_as_extract_elf_symbol_offset(int fd
, const char* function
,
1301 uid_t uid
, gid_t gid
, uint64_t *offset
)
1303 struct run_as_data data
;
1304 struct run_as_ret ret
;
1306 memset(&data
, 0, sizeof(data
));
1307 memset(&ret
, 0, sizeof(ret
));
1309 DBG3("extract_elf_symbol_offset() on fd=%d and function=%s "
1310 "with for uid %d and gid %d", fd
, function
, (int) uid
, (int) gid
);
1314 strncpy(data
.u
.extract_elf_symbol_offset
.function
, function
, LTTNG_SYMBOL_NAME_LEN
- 1);
1316 data
.u
.extract_elf_symbol_offset
.function
[LTTNG_SYMBOL_NAME_LEN
- 1] = '\0';
1318 run_as(RUN_AS_EXTRACT_ELF_SYMBOL_OFFSET
, &data
, &ret
, uid
, gid
);
1326 *offset
= ret
.u
.extract_elf_symbol_offset
.offset
;
1331 int run_as_extract_sdt_probe_offsets(int fd
, const char* provider_name
,
1332 const char* probe_name
, uid_t uid
, gid_t gid
,
1333 uint64_t **offsets
, uint32_t *num_offset
)
1335 struct run_as_data data
;
1336 struct run_as_ret ret
;
1338 memset(&data
, 0, sizeof(data
));
1339 memset(&ret
, 0, sizeof(ret
));
1341 DBG3("extract_sdt_probe_offsets() on fd=%d, probe_name=%s and "
1342 "provider_name=%s with for uid %d and gid %d", fd
, probe_name
,
1343 provider_name
, (int) uid
, (int) gid
);
1347 strncpy(data
.u
.extract_sdt_probe_offsets
.probe_name
, probe_name
, LTTNG_SYMBOL_NAME_LEN
- 1);
1348 strncpy(data
.u
.extract_sdt_probe_offsets
.provider_name
, provider_name
, LTTNG_SYMBOL_NAME_LEN
- 1);
1350 data
.u
.extract_sdt_probe_offsets
.probe_name
[LTTNG_SYMBOL_NAME_LEN
- 1] = '\0';
1351 data
.u
.extract_sdt_probe_offsets
.provider_name
[LTTNG_SYMBOL_NAME_LEN
- 1] = '\0';
1353 run_as(RUN_AS_EXTRACT_SDT_PROBE_OFFSETS
, &data
, &ret
, uid
, gid
);
1361 *num_offset
= ret
.u
.extract_sdt_probe_offsets
.num_offset
;
1363 *offsets
= zmalloc(*num_offset
* sizeof(uint64_t));
1368 memcpy(*offsets
, ret
.u
.extract_sdt_probe_offsets
.offsets
, *num_offset
* sizeof(uint64_t));
1373 int run_as_create_worker(const char *procname
,
1374 post_fork_cleanup_cb clean_up_func
,
1375 void *clean_up_user_data
)
1379 pthread_mutex_lock(&worker_lock
);
1380 ret
= run_as_create_worker_no_lock(procname
, clean_up_func
,
1381 clean_up_user_data
);
1382 pthread_mutex_unlock(&worker_lock
);
1387 void run_as_destroy_worker(void)
1389 pthread_mutex_lock(&worker_lock
);
1390 run_as_destroy_worker_no_lock();
1391 pthread_mutex_unlock(&worker_lock
);