Fix: syscall event rule: emission sites not compared in is_equal
[lttng-tools.git] / src / common / runas.cpp
1 /*
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>
5 *
6 * SPDX-License-Identifier: LGPL-2.1-only
7 *
8 */
9
10 #define _LGPL_SOURCE
11 #include "runas.hpp"
12
13 #include <common/bytecode/bytecode.hpp>
14 #include <common/common.hpp>
15 #include <common/compat/errno.hpp>
16 #include <common/compat/getenv.hpp>
17 #include <common/compat/string.hpp>
18 #include <common/defaults.hpp>
19 #include <common/filter/filter-ast.hpp>
20 #include <common/lttng-elf.hpp>
21 #include <common/lttng-kernel.hpp>
22 #include <common/sessiond-comm/sessiond-comm.hpp>
23 #include <common/thread.hpp>
24 #include <common/unix.hpp>
25 #include <common/utils.hpp>
26
27 #include <lttng/constant.h>
28
29 #include <fcntl.h>
30 #include <grp.h>
31 #include <limits.h>
32 #include <pwd.h>
33 #include <sched.h>
34 #include <signal.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <sys/stat.h>
39 #include <sys/types.h>
40 #include <sys/wait.h>
41 #include <unistd.h>
42
43 #define GETPW_BUFFER_FALLBACK_SIZE 4096
44
45 enum run_as_cmd {
46 RUN_AS_MKDIR,
47 RUN_AS_MKDIRAT,
48 RUN_AS_MKDIR_RECURSIVE,
49 RUN_AS_MKDIRAT_RECURSIVE,
50 RUN_AS_OPEN,
51 RUN_AS_OPENAT,
52 RUN_AS_UNLINK,
53 RUN_AS_UNLINKAT,
54 RUN_AS_RMDIR,
55 RUN_AS_RMDIRAT,
56 RUN_AS_RMDIR_RECURSIVE,
57 RUN_AS_RMDIRAT_RECURSIVE,
58 RUN_AS_RENAME,
59 RUN_AS_RENAMEAT,
60 RUN_AS_EXTRACT_ELF_SYMBOL_OFFSET,
61 RUN_AS_EXTRACT_SDT_PROBE_OFFSETS,
62 RUN_AS_GENERATE_FILTER_BYTECODE,
63 };
64
65 namespace {
66 struct run_as_data;
67 struct run_as_ret;
68 using run_as_fct = int (*)(struct run_as_data *, struct run_as_ret *);
69
70 struct run_as_mkdir_data {
71 int dirfd;
72 char path[LTTNG_PATH_MAX];
73 mode_t mode;
74 } LTTNG_PACKED;
75
76 struct run_as_open_data {
77 int dirfd;
78 char path[LTTNG_PATH_MAX];
79 int flags;
80 mode_t mode;
81 } LTTNG_PACKED;
82
83 struct run_as_unlink_data {
84 int dirfd;
85 char path[LTTNG_PATH_MAX];
86 } LTTNG_PACKED;
87
88 struct run_as_rmdir_data {
89 int dirfd;
90 char path[LTTNG_PATH_MAX];
91 int flags; /* enum lttng_directory_handle_rmdir_recursive_flags. */
92 } LTTNG_PACKED;
93
94 struct run_as_extract_elf_symbol_offset_data {
95 int fd;
96 char function[LTTNG_SYMBOL_NAME_LEN];
97 } LTTNG_PACKED;
98
99 struct run_as_extract_sdt_probe_offsets_data {
100 int fd;
101 char probe_name[LTTNG_SYMBOL_NAME_LEN];
102 char provider_name[LTTNG_SYMBOL_NAME_LEN];
103 } LTTNG_PACKED;
104
105 struct run_as_generate_filter_bytecode_data {
106 char filter_expression[LTTNG_FILTER_MAX_LEN];
107 } LTTNG_PACKED;
108
109 struct run_as_rename_data {
110 /*
111 * [0] = old_dirfd
112 * [1] = new_dirfd
113 */
114 int dirfds[2];
115 char old_path[LTTNG_PATH_MAX];
116 char new_path[LTTNG_PATH_MAX];
117 } LTTNG_PACKED;
118
119 struct run_as_open_ret {
120 int fd;
121 } LTTNG_PACKED;
122
123 struct run_as_extract_elf_symbol_offset_ret {
124 uint64_t offset;
125 } LTTNG_PACKED;
126
127 struct run_as_extract_sdt_probe_offsets_ret {
128 uint32_t num_offset;
129 uint64_t offsets[LTTNG_KERNEL_ABI_MAX_UPROBE_NUM];
130 } LTTNG_PACKED;
131
132 struct run_as_generate_filter_bytecode_ret {
133 /* A lttng_bytecode_filter struct with 'dynamic' payload. */
134 char bytecode[LTTNG_FILTER_MAX_LEN];
135 } LTTNG_PACKED;
136
137 struct run_as_data {
138 enum run_as_cmd cmd;
139 union {
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;
148 } u;
149 uid_t uid;
150 gid_t gid;
151 } LTTNG_PACKED;
152
153 /*
154 * The run_as_ret structure holds the returned value and status of the command.
155 *
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.
159 *
160 * The _errno field is the errno recorded after the execution of the command.
161 *
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
165 * command.
166 *
167 */
168 struct run_as_ret {
169 union {
170 int ret;
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;
175 } u;
176 int _errno;
177 bool _error;
178 } LTTNG_PACKED;
179
180 #define COMMAND_IN_FDS(data_ptr) \
181 ({ \
182 int *fds = NULL; \
183 if (command_properties[(data_ptr)->cmd].in_fds_offset != -1) { \
184 fds = (int *) ((char *) (data_ptr) + \
185 command_properties[(data_ptr)->cmd].in_fds_offset); \
186 } \
187 fds; \
188 })
189
190 #define COMMAND_OUT_FDS(cmd, ret_ptr) \
191 ({ \
192 int *fds = NULL; \
193 if (command_properties[cmd].out_fds_offset != -1) { \
194 fds = (int *) ((char *) (ret_ptr) + \
195 command_properties[cmd].out_fds_offset); \
196 } \
197 fds; \
198 })
199
200 #define COMMAND_IN_FD_COUNT(data_ptr) ({ command_properties[(data_ptr)->cmd].in_fd_count; })
201
202 #define COMMAND_OUT_FD_COUNT(cmd) ({ command_properties[cmd].out_fd_count; })
203
204 #define COMMAND_USE_CWD_FD(data_ptr) command_properties[(data_ptr)->cmd].use_cwd_fd
205
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;
210 bool use_cwd_fd;
211 };
212
213 const struct run_as_command_properties command_properties[] = {
214 {
215 .in_fds_offset = offsetof(struct run_as_data, u.mkdir.dirfd),
216 .out_fds_offset = -1,
217 .in_fd_count = 1,
218 .out_fd_count = 0,
219 .use_cwd_fd = true,
220 },
221 {
222 .in_fds_offset = offsetof(struct run_as_data, u.mkdir.dirfd),
223 .out_fds_offset = -1,
224 .in_fd_count = 1,
225 .out_fd_count = 0,
226 .use_cwd_fd = false,
227 },
228 {
229 .in_fds_offset = offsetof(struct run_as_data, u.mkdir.dirfd),
230 .out_fds_offset = -1,
231 .in_fd_count = 1,
232 .out_fd_count = 0,
233 .use_cwd_fd = true,
234 },
235 {
236 .in_fds_offset = offsetof(struct run_as_data, u.mkdir.dirfd),
237 .out_fds_offset = -1,
238 .in_fd_count = 1,
239 .out_fd_count = 0,
240 .use_cwd_fd = false,
241 },
242 {
243 .in_fds_offset = offsetof(struct run_as_data, u.open.dirfd),
244 .out_fds_offset = offsetof(struct run_as_ret, u.open.fd),
245 .in_fd_count = 1,
246 .out_fd_count = 1,
247 .use_cwd_fd = true,
248 },
249 {
250 .in_fds_offset = offsetof(struct run_as_data, u.open.dirfd),
251 .out_fds_offset = offsetof(struct run_as_ret, u.open.fd),
252 .in_fd_count = 1,
253 .out_fd_count = 1,
254 .use_cwd_fd = false,
255 },
256 {
257 .in_fds_offset = offsetof(struct run_as_data, u.unlink.dirfd),
258 .out_fds_offset = -1,
259 .in_fd_count = 1,
260 .out_fd_count = 0,
261 .use_cwd_fd = true,
262 },
263 {
264 .in_fds_offset = offsetof(struct run_as_data, u.unlink.dirfd),
265 .out_fds_offset = -1,
266 .in_fd_count = 1,
267 .out_fd_count = 0,
268 .use_cwd_fd = false,
269 },
270 {
271 .in_fds_offset = offsetof(struct run_as_data, u.rmdir.dirfd),
272 .out_fds_offset = -1,
273 .in_fd_count = 1,
274 .out_fd_count = 0,
275 .use_cwd_fd = true,
276 },
277 {
278 .in_fds_offset = offsetof(struct run_as_data, u.rmdir.dirfd),
279 .out_fds_offset = -1,
280 .in_fd_count = 1,
281 .out_fd_count = 0,
282 .use_cwd_fd = false,
283 },
284 {
285 .in_fds_offset = offsetof(struct run_as_data, u.rmdir.dirfd),
286 .out_fds_offset = -1,
287 .in_fd_count = 1,
288 .out_fd_count = 0,
289 .use_cwd_fd = true,
290 },
291 {
292 .in_fds_offset = offsetof(struct run_as_data, u.rmdir.dirfd),
293 .out_fds_offset = -1,
294 .in_fd_count = 1,
295 .out_fd_count = 0,
296 .use_cwd_fd = false,
297 },
298 {
299 .in_fds_offset = offsetof(struct run_as_data, u.rename.dirfds),
300 .out_fds_offset = -1,
301 .in_fd_count = 2,
302 .out_fd_count = 0,
303 .use_cwd_fd = true,
304 },
305 {
306 .in_fds_offset = offsetof(struct run_as_data, u.rename.dirfds),
307 .out_fds_offset = -1,
308 .in_fd_count = 2,
309 .out_fd_count = 0,
310 .use_cwd_fd = false,
311 },
312 {
313 .in_fds_offset = offsetof(struct run_as_data, u.extract_elf_symbol_offset.fd),
314 .out_fds_offset = -1,
315 .in_fd_count = 1,
316 .out_fd_count = 0,
317 .use_cwd_fd = false,
318 },
319 {
320 .in_fds_offset = offsetof(struct run_as_data, u.extract_sdt_probe_offsets.fd),
321 .out_fds_offset = -1,
322 .in_fd_count = 1,
323 .out_fd_count = 0,
324 .use_cwd_fd = false,
325 },
326 {
327 .in_fds_offset = -1,
328 .out_fds_offset = -1,
329 .in_fd_count = 0,
330 .out_fd_count = 0,
331 .use_cwd_fd = false,
332 },
333 };
334
335 struct run_as_worker_data {
336 pid_t pid; /* Worker PID. */
337 int sockpair[2];
338 char *procname;
339 };
340
341 /* Single global worker per process (for now). */
342 run_as_worker_data *global_worker;
343 /* Lock protecting the worker. */
344 pthread_mutex_t worker_lock = PTHREAD_MUTEX_INITIALIZER;
345 } /* namespace */
346
347 #ifdef VALGRIND
348 static int use_clone(void)
349 {
350 return 0;
351 }
352 #else
353 static int use_clone()
354 {
355 return !lttng_secure_getenv("LTTNG_DEBUG_NOCLONE");
356 }
357 #endif
358
359 /*
360 * Create recursively directory using the FULL path.
361 */
362 static int _mkdirat_recursive(struct run_as_data *data, struct run_as_ret *ret_value)
363 {
364 const char *path;
365 mode_t mode;
366 struct lttng_directory_handle *handle;
367
368 path = data->u.mkdir.path;
369 mode = data->u.mkdir.mode;
370
371 handle = lttng_directory_handle_create_from_dirfd(data->u.mkdir.dirfd);
372 if (!handle) {
373 ret_value->_errno = errno;
374 ret_value->_error = true;
375 ret_value->u.ret = -1;
376 goto end;
377 }
378 /* Ownership of dirfd is transferred to the handle. */
379 data->u.mkdir.dirfd = -1;
380 /* Safe to call as we have transitioned to the requested uid/gid. */
381 ret_value->u.ret = lttng_directory_handle_create_subdirectory_recursive(handle, path, mode);
382 ret_value->_errno = errno;
383 ret_value->_error = (ret_value->u.ret) != 0;
384 lttng_directory_handle_put(handle);
385 end:
386 return ret_value->u.ret;
387 }
388
389 static int _mkdirat(struct run_as_data *data, struct run_as_ret *ret_value)
390 {
391 const char *path;
392 mode_t mode;
393 struct lttng_directory_handle *handle;
394
395 path = data->u.mkdir.path;
396 mode = data->u.mkdir.mode;
397
398 handle = lttng_directory_handle_create_from_dirfd(data->u.mkdir.dirfd);
399 if (!handle) {
400 ret_value->u.ret = -1;
401 ret_value->_errno = errno;
402 ret_value->_error = true;
403 goto end;
404 }
405 /* Ownership of dirfd is transferred to the handle. */
406 data->u.mkdir.dirfd = -1;
407 /* Safe to call as we have transitioned to the requested uid/gid. */
408 ret_value->u.ret = lttng_directory_handle_create_subdirectory(handle, path, mode);
409 ret_value->_errno = errno;
410 ret_value->_error = (ret_value->u.ret) != 0;
411 lttng_directory_handle_put(handle);
412 end:
413 return ret_value->u.ret;
414 }
415
416 static int _open(struct run_as_data *data, struct run_as_ret *ret_value)
417 {
418 int fd;
419 struct lttng_directory_handle *handle;
420
421 handle = lttng_directory_handle_create_from_dirfd(data->u.open.dirfd);
422 if (!handle) {
423 ret_value->_errno = errno;
424 ret_value->_error = true;
425 ret_value->u.ret = -1;
426 goto end;
427 }
428 /* Ownership of dirfd is transferred to the handle. */
429 data->u.open.dirfd = -1;
430
431 fd = lttng_directory_handle_open_file(
432 handle, data->u.open.path, data->u.open.flags, data->u.open.mode);
433 if (fd < 0) {
434 ret_value->u.ret = -1;
435 ret_value->u.open.fd = -1;
436 } else {
437 ret_value->u.ret = 0;
438 ret_value->u.open.fd = fd;
439 }
440
441 ret_value->_errno = errno;
442 ret_value->_error = fd < 0;
443 lttng_directory_handle_put(handle);
444 end:
445 return ret_value->u.ret;
446 }
447
448 static int _unlink(struct run_as_data *data, struct run_as_ret *ret_value)
449 {
450 struct lttng_directory_handle *handle;
451
452 handle = lttng_directory_handle_create_from_dirfd(data->u.unlink.dirfd);
453 if (!handle) {
454 ret_value->u.ret = -1;
455 ret_value->_errno = errno;
456 ret_value->_error = true;
457 goto end;
458 }
459
460 /* Ownership of dirfd is transferred to the handle. */
461 data->u.unlink.dirfd = -1;
462
463 ret_value->u.ret = lttng_directory_handle_unlink_file(handle, data->u.unlink.path);
464 ret_value->_errno = errno;
465 ret_value->_error = (ret_value->u.ret) != 0;
466 lttng_directory_handle_put(handle);
467 end:
468 return ret_value->u.ret;
469 }
470
471 static int _rmdir(struct run_as_data *data, struct run_as_ret *ret_value)
472 {
473 struct lttng_directory_handle *handle;
474
475 handle = lttng_directory_handle_create_from_dirfd(data->u.rmdir.dirfd);
476 if (!handle) {
477 ret_value->u.ret = -1;
478 ret_value->_errno = errno;
479 ret_value->_error = true;
480 goto end;
481 }
482
483 /* Ownership of dirfd is transferred to the handle. */
484 data->u.rmdir.dirfd = -1;
485
486 ret_value->u.ret = lttng_directory_handle_remove_subdirectory(handle, data->u.rmdir.path);
487 ret_value->_errno = errno;
488 ret_value->_error = (ret_value->u.ret) != 0;
489 lttng_directory_handle_put(handle);
490 end:
491 return ret_value->u.ret;
492 }
493
494 static int _rmdir_recursive(struct run_as_data *data, struct run_as_ret *ret_value)
495 {
496 struct lttng_directory_handle *handle;
497
498 handle = lttng_directory_handle_create_from_dirfd(data->u.rmdir.dirfd);
499 if (!handle) {
500 ret_value->u.ret = -1;
501 ret_value->_errno = errno;
502 ret_value->_error = true;
503 goto end;
504 }
505
506 /* Ownership of dirfd is transferred to the handle. */
507 data->u.rmdir.dirfd = -1;
508
509 ret_value->u.ret = lttng_directory_handle_remove_subdirectory_recursive(
510 handle, data->u.rmdir.path, data->u.rmdir.flags);
511 ret_value->_errno = errno;
512 ret_value->_error = (ret_value->u.ret) != 0;
513 lttng_directory_handle_put(handle);
514 end:
515 return ret_value->u.ret;
516 }
517
518 static int _rename(struct run_as_data *data, struct run_as_ret *ret_value)
519 {
520 const char *old_path, *new_path;
521 struct lttng_directory_handle *old_handle = nullptr, *new_handle = nullptr;
522
523 old_path = data->u.rename.old_path;
524 new_path = data->u.rename.new_path;
525
526 old_handle = lttng_directory_handle_create_from_dirfd(data->u.rename.dirfds[0]);
527 if (!old_handle) {
528 ret_value->u.ret = -1;
529 goto end;
530 }
531 new_handle = lttng_directory_handle_create_from_dirfd(data->u.rename.dirfds[1]);
532 if (!new_handle) {
533 ret_value->u.ret = -1;
534 goto end;
535 }
536
537 /* Ownership of dirfds are transferred to the handles. */
538 data->u.rename.dirfds[0] = data->u.rename.dirfds[1] = -1;
539
540 /* Safe to call as we have transitioned to the requested uid/gid. */
541 ret_value->u.ret =
542 lttng_directory_handle_rename(old_handle, old_path, new_handle, new_path);
543 end:
544 lttng_directory_handle_put(old_handle);
545 lttng_directory_handle_put(new_handle);
546 ret_value->_errno = errno;
547 ret_value->_error = (ret_value->u.ret) != 0;
548 return ret_value->u.ret;
549 }
550
551 #ifdef HAVE_ELF_H
552 static int _extract_elf_symbol_offset(struct run_as_data *data, struct run_as_ret *ret_value)
553 {
554 int ret = 0;
555 uint64_t offset;
556
557 ret_value->_error = false;
558 ret = lttng_elf_get_symbol_offset(data->u.extract_elf_symbol_offset.fd,
559 data->u.extract_elf_symbol_offset.function,
560 &offset);
561 if (ret) {
562 DBG("Failed to extract ELF function offset");
563 ret_value->_error = true;
564 }
565 ret_value->u.extract_elf_symbol_offset.offset = offset;
566
567 return ret;
568 }
569
570 static int _extract_sdt_probe_offsets(struct run_as_data *data, struct run_as_ret *ret_value)
571 {
572 int ret = 0;
573 uint64_t *offsets = nullptr;
574 uint32_t num_offset;
575
576 ret_value->_error = false;
577
578 /* On success, this call allocates the offsets paramater. */
579 ret = lttng_elf_get_sdt_probe_offsets(data->u.extract_sdt_probe_offsets.fd,
580 data->u.extract_sdt_probe_offsets.provider_name,
581 data->u.extract_sdt_probe_offsets.probe_name,
582 &offsets,
583 &num_offset);
584
585 if (ret) {
586 DBG("Failed to extract SDT probe offsets");
587 ret_value->_error = true;
588 goto end;
589 }
590
591 if (num_offset <= 0 || num_offset > LTTNG_KERNEL_ABI_MAX_UPROBE_NUM) {
592 DBG("Wrong number of probes.");
593 ret = -1;
594 ret_value->_error = true;
595 goto free_offset;
596 }
597
598 /* Copy the content of the offsets array to the ret struct. */
599 memcpy(ret_value->u.extract_sdt_probe_offsets.offsets,
600 offsets,
601 num_offset * sizeof(uint64_t));
602
603 ret_value->u.extract_sdt_probe_offsets.num_offset = num_offset;
604
605 free_offset:
606 free(offsets);
607 end:
608 return ret;
609 }
610 #else
611 static int _extract_elf_symbol_offset(struct run_as_data *data __attribute__((unused)),
612 struct run_as_ret *ret_value __attribute__((unused)))
613 {
614 ERR("Unimplemented runas command RUN_AS_EXTRACT_ELF_SYMBOL_OFFSET");
615 return -1;
616 }
617
618 static int _extract_sdt_probe_offsets(struct run_as_data *data __attribute__((unused)),
619 struct run_as_ret *ret_value __attribute__((unused)))
620 {
621 ERR("Unimplemented runas command RUN_AS_EXTRACT_SDT_PROBE_OFFSETS");
622 return -1;
623 }
624 #endif
625
626 static int _generate_filter_bytecode(struct run_as_data *data, struct run_as_ret *ret_value)
627 {
628 int ret = 0;
629 const char *filter_expression = nullptr;
630 struct filter_parser_ctx *ctx = nullptr;
631
632 ret_value->_error = false;
633
634 filter_expression = data->u.generate_filter_bytecode.filter_expression;
635
636 if (lttng_strnlen(filter_expression, LTTNG_FILTER_MAX_LEN - 1) ==
637 LTTNG_FILTER_MAX_LEN - 1) {
638 ret_value->_error = true;
639 ret = -1;
640 goto end;
641 }
642
643 ret = filter_parser_ctx_create_from_filter_expression(filter_expression, &ctx);
644 if (ret < 0) {
645 ret_value->_error = true;
646 ret = -1;
647 goto end;
648 }
649
650 DBG("Size of bytecode generated: %u bytes.", bytecode_get_len(&ctx->bytecode->b));
651
652 /* Copy the lttng_bytecode_filter object to the return structure. */
653 memcpy(ret_value->u.generate_filter_bytecode.bytecode,
654 &ctx->bytecode->b,
655 sizeof(ctx->bytecode->b) + bytecode_get_len(&ctx->bytecode->b));
656
657 end:
658 if (ctx) {
659 filter_bytecode_free(ctx);
660 filter_ir_free(ctx);
661 filter_parser_ctx_free(ctx);
662 }
663
664 return ret;
665 }
666 static run_as_fct run_as_enum_to_fct(enum run_as_cmd cmd)
667 {
668 switch (cmd) {
669 case RUN_AS_MKDIR:
670 case RUN_AS_MKDIRAT:
671 return _mkdirat;
672 case RUN_AS_MKDIR_RECURSIVE:
673 case RUN_AS_MKDIRAT_RECURSIVE:
674 return _mkdirat_recursive;
675 case RUN_AS_OPEN:
676 case RUN_AS_OPENAT:
677 return _open;
678 case RUN_AS_UNLINK:
679 case RUN_AS_UNLINKAT:
680 return _unlink;
681 case RUN_AS_RMDIR:
682 case RUN_AS_RMDIRAT:
683 return _rmdir;
684 case RUN_AS_RMDIR_RECURSIVE:
685 case RUN_AS_RMDIRAT_RECURSIVE:
686 return _rmdir_recursive;
687 case RUN_AS_RENAME:
688 case RUN_AS_RENAMEAT:
689 return _rename;
690 case RUN_AS_EXTRACT_ELF_SYMBOL_OFFSET:
691 return _extract_elf_symbol_offset;
692 case RUN_AS_EXTRACT_SDT_PROBE_OFFSETS:
693 return _extract_sdt_probe_offsets;
694 case RUN_AS_GENERATE_FILTER_BYTECODE:
695 return _generate_filter_bytecode;
696 default:
697 ERR("Unknown command %d", (int) cmd);
698 return nullptr;
699 }
700 }
701
702 static int do_send_fds(int sock, const int *fds, unsigned int fd_count)
703 {
704 ssize_t len;
705 unsigned int i;
706
707 for (i = 0; i < fd_count; i++) {
708 if (fds[i] < 0) {
709 DBG("Attempt to send invalid file descriptor (fd = %i)", fds[i]);
710 /* Return 0 as this is not a fatal error. */
711 return 0;
712 }
713 }
714
715 len = lttcomm_send_fds_unix_sock(sock, fds, fd_count);
716 return len < 0 ? -1 : 0;
717 }
718
719 static int do_recv_fds(int sock, int *fds, unsigned int fd_count)
720 {
721 int ret = 0;
722 unsigned int i;
723 ssize_t len;
724
725 len = lttcomm_recv_fds_unix_sock(sock, fds, fd_count);
726 if (len == 0) {
727 ret = -1;
728 goto end;
729 } else if (len < 0) {
730 PERROR("Failed to receive file descriptors from socket");
731 ret = -1;
732 goto end;
733 }
734
735 for (i = 0; i < fd_count; i++) {
736 if (fds[i] < 0) {
737 ERR("Invalid file descriptor received from worker (fd = %i)", fds[i]);
738 /* Return 0 as this is not a fatal error. */
739 }
740 }
741 end:
742 return ret;
743 }
744
745 static int send_fds_to_worker(const run_as_worker_data *worker, const struct run_as_data *data)
746 {
747 int ret = 0;
748 unsigned int i;
749
750 if (COMMAND_USE_CWD_FD(data) || COMMAND_IN_FD_COUNT(data) == 0) {
751 goto end;
752 }
753
754 for (i = 0; i < COMMAND_IN_FD_COUNT(data); i++) {
755 if (COMMAND_IN_FDS(data)[i] < 0) {
756 ERR("Refusing to send invalid fd to worker (fd = %i)",
757 COMMAND_IN_FDS(data)[i]);
758 ret = -1;
759 goto end;
760 }
761 }
762
763 ret = do_send_fds(worker->sockpair[0], COMMAND_IN_FDS(data), COMMAND_IN_FD_COUNT(data));
764 if (ret < 0) {
765 PERROR("Failed to send file descriptor to run-as worker");
766 ret = -1;
767 goto end;
768 }
769 end:
770 return ret;
771 }
772
773 static int
774 send_fds_to_master(run_as_worker_data *worker, enum run_as_cmd cmd, struct run_as_ret *run_as_ret)
775 {
776 int ret = 0;
777 unsigned int i;
778
779 if (COMMAND_OUT_FD_COUNT(cmd) == 0) {
780 goto end;
781 }
782
783 ret = do_send_fds(
784 worker->sockpair[1], COMMAND_OUT_FDS(cmd, run_as_ret), COMMAND_OUT_FD_COUNT(cmd));
785 if (ret < 0) {
786 PERROR("Failed to send file descriptor to master process");
787 goto end;
788 }
789
790 for (i = 0; i < COMMAND_OUT_FD_COUNT(cmd); i++) {
791 int fd = COMMAND_OUT_FDS(cmd, run_as_ret)[i];
792 if (fd >= 0) {
793 int ret_close = close(fd);
794
795 if (ret_close < 0) {
796 PERROR("Failed to close result file descriptor (fd = %i)", fd);
797 }
798 }
799 }
800 end:
801 return ret;
802 }
803
804 static int recv_fds_from_worker(const run_as_worker_data *worker,
805 enum run_as_cmd cmd,
806 struct run_as_ret *run_as_ret)
807 {
808 int ret = 0;
809
810 if (COMMAND_OUT_FD_COUNT(cmd) == 0) {
811 goto end;
812 }
813
814 ret = do_recv_fds(
815 worker->sockpair[0], COMMAND_OUT_FDS(cmd, run_as_ret), COMMAND_OUT_FD_COUNT(cmd));
816 if (ret < 0) {
817 PERROR("Failed to receive file descriptor from run-as worker");
818 ret = -1;
819 }
820 end:
821 return ret;
822 }
823
824 static int recv_fds_from_master(run_as_worker_data *worker, struct run_as_data *data)
825 {
826 int ret = 0;
827
828 if (COMMAND_USE_CWD_FD(data)) {
829 unsigned int i;
830
831 for (i = 0; i < COMMAND_IN_FD_COUNT(data); i++) {
832 COMMAND_IN_FDS(data)[i] = AT_FDCWD;
833 }
834 goto end;
835 }
836
837 if (COMMAND_IN_FD_COUNT(data) == 0) {
838 goto end;
839 }
840
841 ret = do_recv_fds(worker->sockpair[1], COMMAND_IN_FDS(data), COMMAND_IN_FD_COUNT(data));
842 if (ret < 0) {
843 PERROR("Failed to receive file descriptors from master process");
844 ret = -1;
845 }
846 end:
847 return ret;
848 }
849
850 static int cleanup_received_fds(struct run_as_data *data)
851 {
852 int ret = 0, i;
853
854 for (i = 0; i < COMMAND_IN_FD_COUNT(data); i++) {
855 if (COMMAND_IN_FDS(data)[i] == -1) {
856 continue;
857 }
858 ret = close(COMMAND_IN_FDS(data)[i]);
859 if (ret) {
860 PERROR("Failed to close file descriptor received fd in run-as worker");
861 goto end;
862 }
863 }
864 end:
865 return ret;
866 }
867
868 static int get_user_infos_from_uid(uid_t uid, char **username, gid_t *primary_gid)
869 {
870 int ret;
871 char *buf = nullptr;
872 long raw_get_pw_buf_size;
873 size_t get_pw_buf_size;
874 struct passwd pwd;
875 struct passwd *result = nullptr;
876
877 /* Fetch the max size for the temporary buffer. */
878 errno = 0;
879 raw_get_pw_buf_size = sysconf(_SC_GETPW_R_SIZE_MAX);
880 if (raw_get_pw_buf_size < 0) {
881 if (errno != 0) {
882 PERROR("Failed to query _SC_GETPW_R_SIZE_MAX");
883 goto error;
884 }
885
886 /* Limit is indeterminate. */
887 WARN("Failed to query _SC_GETPW_R_SIZE_MAX as it is "
888 "indeterminate; falling back to default buffer size");
889 raw_get_pw_buf_size = GETPW_BUFFER_FALLBACK_SIZE;
890 }
891
892 get_pw_buf_size = (size_t) raw_get_pw_buf_size;
893
894 buf = calloc<char>(get_pw_buf_size);
895 if (buf == nullptr) {
896 PERROR("Failed to allocate buffer to get password file entries");
897 goto error;
898 }
899
900 ret = getpwuid_r(uid, &pwd, buf, get_pw_buf_size, &result);
901 if (ret < 0) {
902 PERROR("Failed to get user information for user: uid = %d", (int) uid);
903 goto error;
904 }
905
906 if (result == nullptr) {
907 ERR("Failed to find user information in password entries: uid = %d", (int) uid);
908 ret = -1;
909 goto error;
910 }
911
912 *username = strdup(result->pw_name);
913 if (*username == nullptr) {
914 PERROR("Failed to copy user name");
915 goto error;
916 }
917
918 *primary_gid = result->pw_gid;
919
920 end:
921 free(buf);
922 return ret;
923 error:
924 *username = nullptr;
925 *primary_gid = -1;
926 ret = -1;
927 goto end;
928 }
929
930 static int demote_creds(uid_t prev_uid, gid_t prev_gid, uid_t new_uid, gid_t new_gid)
931 {
932 int ret = 0;
933 gid_t primary_gid;
934 char *username = nullptr;
935
936 /* Change the group id. */
937 if (prev_gid != new_gid) {
938 ret = setegid(new_gid);
939 if (ret < 0) {
940 PERROR("Failed to set effective group id: new_gid = %d", (int) new_gid);
941 goto end;
942 }
943 }
944
945 /* Change the user id. */
946 if (prev_uid != new_uid) {
947 ret = get_user_infos_from_uid(new_uid, &username, &primary_gid);
948 if (ret < 0) {
949 goto end;
950 }
951
952 /*
953 * Initialize the supplementary group access list.
954 *
955 * This is needed to handle cases where the supplementary groups
956 * of the user the process is demoting-to would give it access
957 * to a given file/folder, but not it's primary group.
958 *
959 * e.g
960 * username: User1
961 * Primary Group: User1
962 * Secondary group: Disk, Network
963 *
964 * mkdir inside the following directory must work since User1
965 * is part of the Network group.
966 *
967 * drwxrwx--- 2 root Network 4096 Jul 23 17:17 /tmp/my_folder/
968 *
969 *
970 * The order of the following initgroups and seteuid calls is
971 * important here;
972 * Only a root process or one with CAP_SETGID capability can
973 * call the the initgroups() function. We must initialize the
974 * supplementary groups before we change the effective
975 * UID to a less-privileged user.
976 */
977 ret = initgroups(username, primary_gid);
978 if (ret < 0) {
979 PERROR("Failed to init the supplementary group access list: "
980 "username = `%s`, primary gid = %d",
981 username,
982 (int) primary_gid);
983 goto end;
984 }
985
986 ret = seteuid(new_uid);
987 if (ret < 0) {
988 PERROR("Failed to set effective user id: new_uid = %d", (int) new_uid);
989 goto end;
990 }
991 }
992 end:
993 free(username);
994 return ret;
995 }
996
997 static int promote_creds(uid_t prev_uid, gid_t prev_gid, uid_t new_uid, gid_t new_gid)
998 {
999 int ret = 0;
1000 gid_t primary_gid;
1001 char *username = nullptr;
1002
1003 /* Change the group id. */
1004 if (prev_gid != new_gid) {
1005 ret = setegid(new_gid);
1006 if (ret < 0) {
1007 PERROR("Failed to set effective group id: new_gid = %d", (int) new_gid);
1008 goto end;
1009 }
1010 }
1011
1012 /* Change the user id. */
1013 if (prev_uid != new_uid) {
1014 ret = get_user_infos_from_uid(new_uid, &username, &primary_gid);
1015 if (ret < 0) {
1016 goto end;
1017 }
1018
1019 /*
1020 * seteuid call must be done before the initgroups call because
1021 * we need to be privileged (CAP_SETGID) to call initgroups().
1022 */
1023 ret = seteuid(new_uid);
1024 if (ret < 0) {
1025 PERROR("Failed to set effective user id: new_uid = %d", (int) new_uid);
1026 goto end;
1027 }
1028
1029 /*
1030 * Initialize the supplementary group access list.
1031 *
1032 * There is a possibility the groups we set in the following
1033 * initgroups() call are not exactly the same as the ones we
1034 * had when we originally demoted. This can happen if the
1035 * /etc/group file is modified after the runas process is
1036 * forked. This is very unlikely.
1037 */
1038 ret = initgroups(username, primary_gid);
1039 if (ret < 0) {
1040 PERROR("Failed to init the supplementary group access "
1041 "list: username = `%s`, primary gid = %d",
1042 username,
1043 (int) primary_gid)
1044 goto end;
1045 }
1046 }
1047 end:
1048 free(username);
1049 return ret;
1050 }
1051
1052 /*
1053 * Return < 0 on error, 0 if OK, 1 on hangup.
1054 */
1055 static int handle_one_cmd(run_as_worker_data *worker)
1056 {
1057 int ret = 0, promote_ret;
1058 struct run_as_data data = {};
1059 ssize_t readlen, writelen;
1060 struct run_as_ret sendret = {};
1061 run_as_fct cmd;
1062 const uid_t prev_ruid = getuid();
1063 const gid_t prev_rgid = getgid();
1064
1065 /*
1066 * Stage 1: Receive run_as_data struct from the master.
1067 * The structure contains the command type and all the parameters needed for
1068 * its execution
1069 */
1070 readlen = lttcomm_recv_unix_sock(worker->sockpair[1], &data, sizeof(data));
1071 if (readlen == 0) {
1072 /* hang up */
1073 ret = 1;
1074 goto end;
1075 }
1076 if (readlen < sizeof(data)) {
1077 PERROR("lttcomm_recv_unix_sock error");
1078 ret = -1;
1079 goto end;
1080 }
1081
1082 cmd = run_as_enum_to_fct(data.cmd);
1083 if (!cmd) {
1084 ret = -1;
1085 goto end;
1086 }
1087
1088 /*
1089 * Stage 2: Receive file descriptor from master.
1090 * Some commands need a file descriptor as input so if it's needed we
1091 * receive the fd using the Unix socket.
1092 */
1093 ret = recv_fds_from_master(worker, &data);
1094 if (ret < 0) {
1095 PERROR("recv_fd_from_master error");
1096 ret = -1;
1097 goto end;
1098 }
1099
1100 ret = demote_creds(prev_ruid, prev_rgid, data.uid, data.gid);
1101 if (ret < 0) {
1102 goto write_return;
1103 }
1104
1105 /*
1106 * Also set umask to 0 for mkdir executable bit.
1107 */
1108 umask(0);
1109
1110 /*
1111 * Stage 3: Execute the command
1112 */
1113 ret = (*cmd)(&data, &sendret);
1114 if (ret < 0) {
1115 DBG("Execution of command returned an error");
1116 }
1117
1118 write_return:
1119 ret = cleanup_received_fds(&data);
1120 if (ret < 0) {
1121 ERR("Error cleaning up FD");
1122 goto promote_back;
1123 }
1124
1125 /*
1126 * Stage 4: Send run_as_ret structure to the master.
1127 * This structure contain the return value of the command and the errno.
1128 */
1129 writelen = lttcomm_send_unix_sock(worker->sockpair[1], &sendret, sizeof(sendret));
1130 if (writelen < sizeof(sendret)) {
1131 PERROR("lttcomm_send_unix_sock error");
1132 ret = -1;
1133 goto promote_back;
1134 }
1135
1136 /*
1137 * Stage 5: Send resulting file descriptors to the master.
1138 */
1139 ret = send_fds_to_master(worker, data.cmd, &sendret);
1140 if (ret < 0) {
1141 DBG("Sending FD to master returned an error");
1142 }
1143
1144 ret = 0;
1145
1146 promote_back:
1147 /* Return to previous uid/gid. */
1148 promote_ret = promote_creds(data.uid, data.gid, prev_ruid, prev_rgid);
1149 if (promote_ret < 0) {
1150 ERR("Failed to promote back to the initial credentials");
1151 }
1152
1153 end:
1154 return ret;
1155 }
1156
1157 static int run_as_worker(run_as_worker_data *worker)
1158 {
1159 int ret;
1160 ssize_t writelen;
1161 struct run_as_ret sendret;
1162 size_t proc_orig_len;
1163
1164 /*
1165 * Initialize worker. Set a different process cmdline.
1166 */
1167 proc_orig_len = strlen(worker->procname);
1168 memset(worker->procname, 0, proc_orig_len);
1169 strncpy(worker->procname, DEFAULT_RUN_AS_WORKER_NAME, proc_orig_len);
1170
1171 ret = lttng_thread_setname(DEFAULT_RUN_AS_WORKER_NAME);
1172 if (ret && ret != -ENOSYS) {
1173 /* Don't fail as this is not essential. */
1174 DBG("Failed to set pthread name attribute");
1175 }
1176
1177 memset(&sendret, 0, sizeof(sendret));
1178
1179 writelen = lttcomm_send_unix_sock(worker->sockpair[1], &sendret, sizeof(sendret));
1180 if (writelen < sizeof(sendret)) {
1181 PERROR("lttcomm_send_unix_sock error");
1182 ret = EXIT_FAILURE;
1183 goto end;
1184 }
1185
1186 for (;;) {
1187 ret = handle_one_cmd(worker);
1188 if (ret < 0) {
1189 ret = EXIT_FAILURE;
1190 goto end;
1191 } else if (ret > 0) {
1192 break;
1193 } else {
1194 continue; /* Next command. */
1195 }
1196 }
1197 ret = EXIT_SUCCESS;
1198 end:
1199 return ret;
1200 }
1201
1202 static int run_as_cmd(run_as_worker_data *worker,
1203 enum run_as_cmd cmd,
1204 struct run_as_data *data,
1205 struct run_as_ret *ret_value,
1206 uid_t uid,
1207 gid_t gid)
1208 {
1209 int ret = 0;
1210 ssize_t readlen, writelen;
1211
1212 /*
1213 * If we are non-root, we can only deal with our own uid.
1214 */
1215 if (geteuid() != 0) {
1216 if (uid != geteuid()) {
1217 ret = -1;
1218 ret_value->_errno = EPERM;
1219 ERR("Client (%d)/Server (%d) UID mismatch (and sessiond is not root)",
1220 (int) uid,
1221 (int) geteuid());
1222 goto end;
1223 }
1224 }
1225
1226 data->cmd = cmd;
1227 data->uid = uid;
1228 data->gid = gid;
1229
1230 /*
1231 * Stage 1: Send the run_as_data struct to the worker process
1232 */
1233 writelen = lttcomm_send_unix_sock(worker->sockpair[0], data, sizeof(*data));
1234 if (writelen < sizeof(*data)) {
1235 PERROR("Error writing message to run_as");
1236 ret = -1;
1237 ret_value->_errno = EIO;
1238 goto end;
1239 }
1240
1241 /*
1242 * Stage 2: Send file descriptor to the worker process if needed
1243 */
1244 ret = send_fds_to_worker(worker, data);
1245 if (ret) {
1246 PERROR("do_send_fd error");
1247 ret = -1;
1248 ret_value->_errno = EIO;
1249 goto end;
1250 }
1251
1252 /*
1253 * Stage 3: Wait for the execution of the command
1254 */
1255
1256 /*
1257 * Stage 4: Receive the run_as_ret struct containing the return value and
1258 * errno
1259 */
1260 readlen = lttcomm_recv_unix_sock(worker->sockpair[0], ret_value, sizeof(*ret_value));
1261 if (!readlen) {
1262 ERR("Run-as worker has hung-up during run_as_cmd");
1263 ret = -1;
1264 ret_value->_errno = EIO;
1265 goto end;
1266 } else if (readlen < sizeof(*ret_value)) {
1267 PERROR("Error reading response from run_as");
1268 ret = -1;
1269 ret_value->_errno = errno;
1270 goto end;
1271 }
1272
1273 if (ret_value->_error) {
1274 /* Skip stage 5 on error as there will be no fd to receive. */
1275 goto end;
1276 }
1277
1278 /*
1279 * Stage 5: Receive file descriptor if needed
1280 */
1281 ret = recv_fds_from_worker(worker, cmd, ret_value);
1282 if (ret < 0) {
1283 ERR("Error receiving fd");
1284 ret = -1;
1285 ret_value->_errno = EIO;
1286 }
1287
1288 end:
1289 return ret;
1290 }
1291
1292 /*
1293 * This is for debugging ONLY and should not be considered secure.
1294 */
1295 static int run_as_noworker(enum run_as_cmd cmd,
1296 struct run_as_data *data,
1297 struct run_as_ret *ret_value,
1298 uid_t uid __attribute__((unused)),
1299 gid_t gid __attribute__((unused)))
1300 {
1301 int ret, saved_errno;
1302 mode_t old_mask;
1303 run_as_fct fct;
1304
1305 fct = run_as_enum_to_fct(cmd);
1306 if (!fct) {
1307 errno = -ENOSYS;
1308 ret = -1;
1309 goto end;
1310 }
1311 old_mask = umask(0);
1312 ret = fct(data, ret_value);
1313 saved_errno = ret_value->_errno;
1314 umask(old_mask);
1315 errno = saved_errno;
1316 end:
1317 return ret;
1318 }
1319
1320 static int reset_sighandler()
1321 {
1322 int sig;
1323
1324 DBG("Resetting run_as worker signal handlers to default");
1325 for (sig = 1; sig <= 31; sig++) {
1326 (void) signal(sig, SIG_DFL);
1327 }
1328 return 0;
1329 }
1330
1331 static void worker_sighandler(int sig)
1332 {
1333 const char *signame;
1334
1335 /*
1336 * The worker will inherit its parent's signals since they are part of
1337 * the same process group. However, in the case of SIGINT and SIGTERM,
1338 * we want to give the worker a chance to teardown gracefully when its
1339 * parent closes the command socket.
1340 */
1341 switch (sig) {
1342 case SIGINT:
1343 signame = "SIGINT";
1344 break;
1345 case SIGTERM:
1346 signame = "SIGTERM";
1347 break;
1348 default:
1349 signame = nullptr;
1350 }
1351
1352 if (signame) {
1353 DBG("run_as worker received signal %s", signame);
1354 } else {
1355 DBG("run_as_worker received signal %d", sig);
1356 }
1357 }
1358
1359 static int set_worker_sighandlers()
1360 {
1361 int ret = 0;
1362 sigset_t sigset;
1363 struct sigaction sa;
1364
1365 if ((ret = sigemptyset(&sigset)) < 0) {
1366 PERROR("sigemptyset");
1367 goto end;
1368 }
1369
1370 sa.sa_handler = worker_sighandler;
1371 sa.sa_mask = sigset;
1372 sa.sa_flags = 0;
1373 if ((ret = sigaction(SIGINT, &sa, nullptr)) < 0) {
1374 PERROR("sigaction SIGINT");
1375 goto end;
1376 }
1377
1378 if ((ret = sigaction(SIGTERM, &sa, nullptr)) < 0) {
1379 PERROR("sigaction SIGTERM");
1380 goto end;
1381 }
1382
1383 DBG("run_as signal handler set for SIGTERM and SIGINT");
1384 end:
1385 return ret;
1386 }
1387
1388 static int run_as_create_worker_no_lock(const char *procname,
1389 post_fork_cleanup_cb clean_up_func,
1390 void *clean_up_user_data)
1391 {
1392 pid_t pid;
1393 int i, ret = 0;
1394 ssize_t readlen;
1395 struct run_as_ret recvret;
1396 run_as_worker_data *worker;
1397
1398 LTTNG_ASSERT(!global_worker);
1399 if (!use_clone()) {
1400 /*
1401 * Don't initialize a worker, all run_as tasks will be performed
1402 * in the current process.
1403 */
1404 ret = 0;
1405 goto end;
1406 }
1407 worker = zmalloc<run_as_worker_data>();
1408 if (!worker) {
1409 ret = -ENOMEM;
1410 goto end;
1411 }
1412 worker->procname = strdup(procname);
1413 if (!worker->procname) {
1414 ret = -ENOMEM;
1415 goto error_procname_alloc;
1416 }
1417 /* Create unix socket. */
1418 if (lttcomm_create_anon_unix_socketpair(worker->sockpair) < 0) {
1419 ret = -1;
1420 goto error_sock;
1421 }
1422
1423 /* Fork worker. */
1424 pid = fork();
1425 if (pid < 0) {
1426 PERROR("fork");
1427 ret = -1;
1428 goto error_fork;
1429 } else if (pid == 0) {
1430 /* Child */
1431
1432 reset_sighandler();
1433
1434 set_worker_sighandlers();
1435
1436 logger_set_thread_name("Run-as worker", true);
1437
1438 if (clean_up_func) {
1439 if (clean_up_func(clean_up_user_data) < 0) {
1440 ERR("Run-as post-fork clean-up failed, exiting.");
1441 exit(EXIT_FAILURE);
1442 }
1443 }
1444
1445 /* Just close, no shutdown. */
1446 if (close(worker->sockpair[0])) {
1447 PERROR("close");
1448 exit(EXIT_FAILURE);
1449 }
1450
1451 /*
1452 * Close all FDs aside from STDIN, STDOUT, STDERR and sockpair[1]
1453 * Sockpair[1] is used as a control channel with the master
1454 */
1455 for (i = 3; i < sysconf(_SC_OPEN_MAX); i++) {
1456 if (i != worker->sockpair[1]) {
1457 (void) close(i);
1458 }
1459 }
1460
1461 worker->sockpair[0] = -1;
1462 ret = run_as_worker(worker);
1463 if (lttcomm_close_unix_sock(worker->sockpair[1])) {
1464 PERROR("close");
1465 ret = -1;
1466 }
1467 worker->sockpair[1] = -1;
1468 free(worker->procname);
1469 free(worker);
1470 LOG(ret ? PRINT_ERR : PRINT_DBG, "run_as worker exiting (ret = %d)", ret);
1471 exit(ret ? EXIT_FAILURE : EXIT_SUCCESS);
1472 } else {
1473 /* Parent */
1474
1475 /* Just close, no shutdown. */
1476 if (close(worker->sockpair[1])) {
1477 PERROR("close");
1478 ret = -1;
1479 goto error_fork;
1480 }
1481 worker->sockpair[1] = -1;
1482 worker->pid = pid;
1483 /* Wait for worker to become ready. */
1484 readlen = lttcomm_recv_unix_sock(worker->sockpair[0], &recvret, sizeof(recvret));
1485 if (readlen < sizeof(recvret)) {
1486 ERR("readlen: %zd", readlen);
1487 PERROR("Error reading response from run_as at creation");
1488 ret = -1;
1489 goto error_fork;
1490 }
1491 global_worker = worker;
1492 }
1493 end:
1494 return ret;
1495
1496 /* Error handling. */
1497 error_fork:
1498 for (i = 0; i < 2; i++) {
1499 if (worker->sockpair[i] < 0) {
1500 continue;
1501 }
1502 if (lttcomm_close_unix_sock(worker->sockpair[i])) {
1503 PERROR("close");
1504 }
1505 worker->sockpair[i] = -1;
1506 }
1507 error_sock:
1508 free(worker->procname);
1509 error_procname_alloc:
1510 free(worker);
1511 return ret;
1512 }
1513
1514 static void run_as_destroy_worker_no_lock()
1515 {
1516 run_as_worker_data *worker = global_worker;
1517
1518 DBG("Destroying run_as worker");
1519 if (!worker) {
1520 return;
1521 }
1522 /* Close unix socket */
1523 DBG("Closing run_as worker socket");
1524 if (lttcomm_close_unix_sock(worker->sockpair[0])) {
1525 PERROR("close");
1526 }
1527 worker->sockpair[0] = -1;
1528 /* Wait for worker. */
1529 for (;;) {
1530 int status;
1531 pid_t wait_ret;
1532
1533 wait_ret = waitpid(worker->pid, &status, 0);
1534 if (wait_ret < 0) {
1535 if (errno == EINTR) {
1536 continue;
1537 }
1538 PERROR("waitpid");
1539 break;
1540 }
1541
1542 if (WIFEXITED(status)) {
1543 LOG(WEXITSTATUS(status) == 0 ? PRINT_DBG : PRINT_ERR,
1544 DEFAULT_RUN_AS_WORKER_NAME " terminated with status code %d",
1545 WEXITSTATUS(status));
1546 break;
1547 } else if (WIFSIGNALED(status)) {
1548 ERR(DEFAULT_RUN_AS_WORKER_NAME " was killed by signal %d",
1549 WTERMSIG(status));
1550 break;
1551 }
1552 }
1553 free(worker->procname);
1554 free(worker);
1555 global_worker = nullptr;
1556 }
1557
1558 static int run_as_restart_worker(run_as_worker_data *worker)
1559 {
1560 int ret = 0;
1561 char *procname = nullptr;
1562
1563 procname = worker->procname;
1564
1565 /* Close socket to run_as worker process and clean up the zombie process */
1566 run_as_destroy_worker_no_lock();
1567
1568 /* Create a new run_as worker process*/
1569 ret = run_as_create_worker_no_lock(procname, nullptr, nullptr);
1570 if (ret < 0) {
1571 ERR("Restarting the worker process failed");
1572 ret = -1;
1573 goto err;
1574 }
1575 err:
1576 return ret;
1577 }
1578
1579 static int run_as(enum run_as_cmd cmd,
1580 struct run_as_data *data,
1581 struct run_as_ret *ret_value,
1582 uid_t uid,
1583 gid_t gid)
1584 {
1585 int ret, saved_errno;
1586
1587 pthread_mutex_lock(&worker_lock);
1588 if (use_clone()) {
1589 DBG("Using run_as worker");
1590
1591 LTTNG_ASSERT(global_worker);
1592
1593 ret = run_as_cmd(global_worker, cmd, data, ret_value, uid, gid);
1594 saved_errno = ret_value->_errno;
1595
1596 /*
1597 * If the worker thread crashed the errno is set to EIO. we log
1598 * the error and start a new worker process.
1599 */
1600 if (ret == -1 && saved_errno == EIO) {
1601 DBG("Socket closed unexpectedly... "
1602 "Restarting the worker process");
1603 ret = run_as_restart_worker(global_worker);
1604 if (ret == -1) {
1605 ERR("Failed to restart worker process.");
1606 goto err;
1607 }
1608 }
1609 } else {
1610 DBG("Using run_as without worker");
1611 ret = run_as_noworker(cmd, data, ret_value, uid, gid);
1612 }
1613 err:
1614 pthread_mutex_unlock(&worker_lock);
1615 return ret;
1616 }
1617
1618 int run_as_mkdir_recursive(const char *path, mode_t mode, uid_t uid, gid_t gid)
1619 {
1620 return run_as_mkdirat_recursive(AT_FDCWD, path, mode, uid, gid);
1621 }
1622
1623 int run_as_mkdirat_recursive(int dirfd, const char *path, mode_t mode, uid_t uid, gid_t gid)
1624 {
1625 int ret;
1626 struct run_as_data data = {};
1627 struct run_as_ret run_as_ret = {};
1628
1629 DBG3("mkdirat() recursive fd = %d%s, path = %s, mode = %d, uid = %d, gid = %d",
1630 dirfd,
1631 dirfd == AT_FDCWD ? " (AT_FDCWD)" : "",
1632 path,
1633 (int) mode,
1634 (int) uid,
1635 (int) gid);
1636 ret = lttng_strncpy(data.u.mkdir.path, path, sizeof(data.u.mkdir.path));
1637 if (ret) {
1638 ERR("Failed to copy path argument of mkdirat recursive command");
1639 goto error;
1640 }
1641 data.u.mkdir.path[sizeof(data.u.mkdir.path) - 1] = '\0';
1642 data.u.mkdir.mode = mode;
1643 data.u.mkdir.dirfd = dirfd;
1644 run_as(dirfd == AT_FDCWD ? RUN_AS_MKDIR_RECURSIVE : RUN_AS_MKDIRAT_RECURSIVE,
1645 &data,
1646 &run_as_ret,
1647 uid,
1648 gid);
1649 errno = run_as_ret._errno;
1650 ret = run_as_ret.u.ret;
1651 error:
1652 return ret;
1653 }
1654
1655 int run_as_mkdir(const char *path, mode_t mode, uid_t uid, gid_t gid)
1656 {
1657 return run_as_mkdirat(AT_FDCWD, path, mode, uid, gid);
1658 }
1659
1660 int run_as_mkdirat(int dirfd, const char *path, mode_t mode, uid_t uid, gid_t gid)
1661 {
1662 int ret;
1663 struct run_as_data data = {};
1664 struct run_as_ret run_as_ret = {};
1665
1666 DBG3("mkdirat() recursive fd = %d%s, path = %s, mode = %d, uid = %d, gid = %d",
1667 dirfd,
1668 dirfd == AT_FDCWD ? " (AT_FDCWD)" : "",
1669 path,
1670 (int) mode,
1671 (int) uid,
1672 (int) gid);
1673 ret = lttng_strncpy(data.u.mkdir.path, path, sizeof(data.u.mkdir.path));
1674 if (ret) {
1675 ERR("Failed to copy path argument of mkdirat command");
1676 goto error;
1677 }
1678 data.u.mkdir.path[sizeof(data.u.mkdir.path) - 1] = '\0';
1679 data.u.mkdir.mode = mode;
1680 data.u.mkdir.dirfd = dirfd;
1681 run_as(dirfd == AT_FDCWD ? RUN_AS_MKDIR : RUN_AS_MKDIRAT, &data, &run_as_ret, uid, gid);
1682 errno = run_as_ret._errno;
1683 ret = run_as_ret.u.ret;
1684 error:
1685 return ret;
1686 }
1687
1688 int run_as_open(const char *path, int flags, mode_t mode, uid_t uid, gid_t gid)
1689 {
1690 return run_as_openat(AT_FDCWD, path, flags, mode, uid, gid);
1691 }
1692
1693 int run_as_openat(int dirfd, const char *path, int flags, mode_t mode, uid_t uid, gid_t gid)
1694 {
1695 int ret;
1696 struct run_as_data data = {};
1697 struct run_as_ret run_as_ret = {};
1698
1699 DBG3("openat() fd = %d%s, path = %s, flags = %X, mode = %d, uid %d, gid %d",
1700 dirfd,
1701 dirfd == AT_FDCWD ? " (AT_FDCWD)" : "",
1702 path,
1703 flags,
1704 (int) mode,
1705 (int) uid,
1706 (int) gid);
1707 ret = lttng_strncpy(data.u.open.path, path, sizeof(data.u.open.path));
1708 if (ret) {
1709 ERR("Failed to copy path argument of open command");
1710 goto error;
1711 }
1712 data.u.open.flags = flags;
1713 data.u.open.mode = mode;
1714 data.u.open.dirfd = dirfd;
1715 run_as(dirfd == AT_FDCWD ? RUN_AS_OPEN : RUN_AS_OPENAT, &data, &run_as_ret, uid, gid);
1716 errno = run_as_ret._errno;
1717 ret = run_as_ret.u.ret < 0 ? run_as_ret.u.ret : run_as_ret.u.open.fd;
1718 error:
1719 return ret;
1720 }
1721
1722 int run_as_unlink(const char *path, uid_t uid, gid_t gid)
1723 {
1724 return run_as_unlinkat(AT_FDCWD, path, uid, gid);
1725 }
1726
1727 int run_as_unlinkat(int dirfd, const char *path, uid_t uid, gid_t gid)
1728 {
1729 int ret;
1730 struct run_as_data data = {};
1731 struct run_as_ret run_as_ret = {};
1732
1733 DBG3("unlinkat() fd = %d%s, path = %s, uid = %d, gid = %d",
1734 dirfd,
1735 dirfd == AT_FDCWD ? " (AT_FDCWD)" : "",
1736 path,
1737 (int) uid,
1738 (int) gid);
1739 ret = lttng_strncpy(data.u.unlink.path, path, sizeof(data.u.unlink.path));
1740 if (ret) {
1741 goto error;
1742 }
1743 data.u.unlink.dirfd = dirfd;
1744 run_as(dirfd == AT_FDCWD ? RUN_AS_UNLINK : RUN_AS_UNLINKAT, &data, &run_as_ret, uid, gid);
1745 errno = run_as_ret._errno;
1746 ret = run_as_ret.u.ret;
1747 error:
1748 return ret;
1749 }
1750
1751 int run_as_rmdir(const char *path, uid_t uid, gid_t gid)
1752 {
1753 return run_as_rmdirat(AT_FDCWD, path, uid, gid);
1754 }
1755
1756 int run_as_rmdirat(int dirfd, const char *path, uid_t uid, gid_t gid)
1757 {
1758 int ret;
1759 struct run_as_data data = {};
1760 struct run_as_ret run_as_ret = {};
1761
1762 DBG3("rmdirat() fd = %d%s, path = %s, uid = %d, gid = %d",
1763 dirfd,
1764 dirfd == AT_FDCWD ? " (AT_FDCWD)" : "",
1765 path,
1766 (int) uid,
1767 (int) gid);
1768 ret = lttng_strncpy(data.u.rmdir.path, path, sizeof(data.u.rmdir.path));
1769 if (ret) {
1770 goto error;
1771 }
1772 data.u.rmdir.dirfd = dirfd;
1773 run_as(dirfd == AT_FDCWD ? RUN_AS_RMDIR : RUN_AS_RMDIRAT, &data, &run_as_ret, uid, gid);
1774 errno = run_as_ret._errno;
1775 ret = run_as_ret.u.ret;
1776 error:
1777 return ret;
1778 }
1779
1780 int run_as_rmdir_recursive(const char *path, uid_t uid, gid_t gid, int flags)
1781 {
1782 return run_as_rmdirat_recursive(AT_FDCWD, path, uid, gid, flags);
1783 }
1784
1785 int run_as_rmdirat_recursive(int dirfd, const char *path, uid_t uid, gid_t gid, int flags)
1786 {
1787 int ret;
1788 struct run_as_data data = {};
1789 struct run_as_ret run_as_ret = {};
1790
1791 DBG3("rmdirat() recursive fd = %d%s, path = %s, uid = %d, gid = %d",
1792 dirfd,
1793 dirfd == AT_FDCWD ? " (AT_FDCWD)" : "",
1794 path,
1795 (int) uid,
1796 (int) gid);
1797 ret = lttng_strncpy(data.u.rmdir.path, path, sizeof(data.u.rmdir.path));
1798 if (ret) {
1799 goto error;
1800 }
1801 data.u.rmdir.dirfd = dirfd;
1802 data.u.rmdir.flags = flags;
1803 run_as(dirfd == AT_FDCWD ? RUN_AS_RMDIR_RECURSIVE : RUN_AS_RMDIRAT_RECURSIVE,
1804 &data,
1805 &run_as_ret,
1806 uid,
1807 gid);
1808 errno = run_as_ret._errno;
1809 ret = run_as_ret.u.ret;
1810 error:
1811 return ret;
1812 }
1813
1814 int run_as_rename(const char *old_name, const char *new_name, uid_t uid, gid_t gid)
1815 {
1816 return run_as_renameat(AT_FDCWD, old_name, AT_FDCWD, new_name, uid, gid);
1817 }
1818
1819 int run_as_renameat(int old_dirfd,
1820 const char *old_name,
1821 int new_dirfd,
1822 const char *new_name,
1823 uid_t uid,
1824 gid_t gid)
1825 {
1826 int ret;
1827 struct run_as_data data = {};
1828 struct run_as_ret run_as_ret = {};
1829
1830 DBG3("renameat() old_dirfd = %d%s, old_name = %s, new_dirfd = %d%s, new_name = %s, uid = %d, gid = %d",
1831 old_dirfd,
1832 old_dirfd == AT_FDCWD ? " (AT_FDCWD)" : "",
1833 old_name,
1834 new_dirfd,
1835 new_dirfd == AT_FDCWD ? " (AT_FDCWD)" : "",
1836 new_name,
1837 (int) uid,
1838 (int) gid);
1839 ret = lttng_strncpy(data.u.rename.old_path, old_name, sizeof(data.u.rename.old_path));
1840 if (ret) {
1841 goto error;
1842 }
1843 ret = lttng_strncpy(data.u.rename.new_path, new_name, sizeof(data.u.rename.new_path));
1844 if (ret) {
1845 goto error;
1846 }
1847
1848 data.u.rename.dirfds[0] = old_dirfd;
1849 data.u.rename.dirfds[1] = new_dirfd;
1850 run_as(old_dirfd == AT_FDCWD && new_dirfd == AT_FDCWD ? RUN_AS_RENAME : RUN_AS_RENAMEAT,
1851 &data,
1852 &run_as_ret,
1853 uid,
1854 gid);
1855 errno = run_as_ret._errno;
1856 ret = run_as_ret.u.ret;
1857 error:
1858 return ret;
1859 }
1860
1861 int run_as_extract_elf_symbol_offset(
1862 int fd, const char *function, uid_t uid, gid_t gid, uint64_t *offset)
1863 {
1864 int ret;
1865 struct run_as_data data = {};
1866 struct run_as_ret run_as_ret = {};
1867
1868 DBG3("extract_elf_symbol_offset() on fd=%d and function=%s "
1869 "with for uid %d and gid %d",
1870 fd,
1871 function,
1872 (int) uid,
1873 (int) gid);
1874
1875 data.u.extract_elf_symbol_offset.fd = fd;
1876
1877 strncpy(data.u.extract_elf_symbol_offset.function, function, LTTNG_SYMBOL_NAME_LEN - 1);
1878 data.u.extract_elf_symbol_offset.function[LTTNG_SYMBOL_NAME_LEN - 1] = '\0';
1879 ret = lttng_strncpy(data.u.extract_elf_symbol_offset.function,
1880 function,
1881 sizeof(data.u.extract_elf_symbol_offset.function));
1882 if (ret) {
1883 goto error;
1884 }
1885
1886 run_as(RUN_AS_EXTRACT_ELF_SYMBOL_OFFSET, &data, &run_as_ret, uid, gid);
1887 errno = run_as_ret._errno;
1888 if (run_as_ret._error) {
1889 ret = -1;
1890 goto error;
1891 }
1892
1893 *offset = run_as_ret.u.extract_elf_symbol_offset.offset;
1894 error:
1895 return ret;
1896 }
1897
1898 int run_as_extract_sdt_probe_offsets(int fd,
1899 const char *provider_name,
1900 const char *probe_name,
1901 uid_t uid,
1902 gid_t gid,
1903 uint64_t **offsets,
1904 uint32_t *num_offset)
1905 {
1906 int ret;
1907 struct run_as_data data = {};
1908 struct run_as_ret run_as_ret = {};
1909
1910 DBG3("extract_sdt_probe_offsets() on fd=%d, probe_name=%s and "
1911 "provider_name=%s with for uid %d and gid %d",
1912 fd,
1913 probe_name,
1914 provider_name,
1915 (int) uid,
1916 (int) gid);
1917
1918 data.u.extract_sdt_probe_offsets.fd = fd;
1919
1920 ret = lttng_strncpy(data.u.extract_sdt_probe_offsets.probe_name,
1921 probe_name,
1922 sizeof(data.u.extract_sdt_probe_offsets.probe_name));
1923 if (ret) {
1924 goto error;
1925 }
1926 ret = lttng_strncpy(data.u.extract_sdt_probe_offsets.provider_name,
1927 provider_name,
1928 sizeof(data.u.extract_sdt_probe_offsets.provider_name));
1929 if (ret) {
1930 goto error;
1931 }
1932
1933 run_as(RUN_AS_EXTRACT_SDT_PROBE_OFFSETS, &data, &run_as_ret, uid, gid);
1934 errno = run_as_ret._errno;
1935 if (run_as_ret._error) {
1936 ret = -1;
1937 goto error;
1938 }
1939
1940 *num_offset = run_as_ret.u.extract_sdt_probe_offsets.num_offset;
1941 *offsets = calloc<uint64_t>(*num_offset);
1942 if (!*offsets) {
1943 ret = -ENOMEM;
1944 goto error;
1945 }
1946
1947 memcpy(*offsets,
1948 run_as_ret.u.extract_sdt_probe_offsets.offsets,
1949 *num_offset * sizeof(uint64_t));
1950 error:
1951 return ret;
1952 }
1953
1954 int run_as_generate_filter_bytecode(const char *filter_expression,
1955 const struct lttng_credentials *creds,
1956 struct lttng_bytecode **bytecode)
1957 {
1958 int ret;
1959 struct run_as_data data = {};
1960 struct run_as_ret run_as_ret = {};
1961 const struct lttng_bytecode *view_bytecode = nullptr;
1962 struct lttng_bytecode *local_bytecode = nullptr;
1963 const uid_t uid = lttng_credentials_get_uid(creds);
1964 const gid_t gid = lttng_credentials_get_gid(creds);
1965
1966 DBG3("generate_filter_bytecode() from expression=\"%s\" for uid %d and gid %d",
1967 filter_expression,
1968 (int) uid,
1969 (int) gid);
1970
1971 ret = lttng_strncpy(data.u.generate_filter_bytecode.filter_expression,
1972 filter_expression,
1973 sizeof(data.u.generate_filter_bytecode.filter_expression));
1974 if (ret) {
1975 goto error;
1976 }
1977
1978 run_as(RUN_AS_GENERATE_FILTER_BYTECODE, &data, &run_as_ret, uid, gid);
1979 errno = run_as_ret._errno;
1980 if (run_as_ret._error) {
1981 ret = -1;
1982 goto error;
1983 }
1984
1985 view_bytecode =
1986 (const struct lttng_bytecode *) run_as_ret.u.generate_filter_bytecode.bytecode;
1987
1988 local_bytecode = calloc<lttng_bytecode>(view_bytecode->len);
1989 if (!local_bytecode) {
1990 ret = -ENOMEM;
1991 goto error;
1992 }
1993
1994 memcpy(local_bytecode,
1995 run_as_ret.u.generate_filter_bytecode.bytecode,
1996 sizeof(*local_bytecode) + view_bytecode->len);
1997 *bytecode = local_bytecode;
1998 error:
1999 return ret;
2000 }
2001
2002 int run_as_create_worker(const char *procname,
2003 post_fork_cleanup_cb clean_up_func,
2004 void *clean_up_user_data)
2005 {
2006 int ret;
2007
2008 pthread_mutex_lock(&worker_lock);
2009 ret = run_as_create_worker_no_lock(procname, clean_up_func, clean_up_user_data);
2010 pthread_mutex_unlock(&worker_lock);
2011 return ret;
2012 }
2013
2014 void run_as_destroy_worker()
2015 {
2016 pthread_mutex_lock(&worker_lock);
2017 run_as_destroy_worker_no_lock();
2018 pthread_mutex_unlock(&worker_lock);
2019 }
This page took 0.121109 seconds and 4 git commands to generate.