Fix: leak of sessiond configuration on launch of run-as worker
[lttng-tools.git] / src / common / runas.c
1 /*
2 * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
3 * Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
4 *
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.
8 *
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
12 * more details.
13 *
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.
17 */
18
19 #define _LGPL_SOURCE
20 #include <errno.h>
21 #include <limits.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <sys/wait.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <unistd.h>
29 #include <fcntl.h>
30 #include <sched.h>
31 #include <signal.h>
32 #include <assert.h>
33 #include <signal.h>
34
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>
43
44 #include <lttng/constant.h>
45
46 #include "runas.h"
47
48 struct run_as_data;
49 struct run_as_ret;
50 typedef int (*run_as_fct)(struct run_as_data *data, struct run_as_ret *ret_value);
51
52 struct run_as_mkdir_data {
53 char path[PATH_MAX];
54 mode_t mode;
55 };
56
57 struct run_as_open_data {
58 char path[PATH_MAX];
59 int flags;
60 mode_t mode;
61 };
62
63 struct run_as_unlink_data {
64 char path[PATH_MAX];
65 };
66
67 struct run_as_rmdir_recursive_data {
68 char path[PATH_MAX];
69 };
70
71 struct run_as_extract_elf_symbol_offset_data {
72 char function[LTTNG_SYMBOL_NAME_LEN];
73 };
74
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];
78 };
79
80 struct run_as_mkdir_ret {
81 int ret;
82 };
83
84 struct run_as_open_ret {
85 int ret;
86 };
87
88 struct run_as_unlink_ret {
89 int ret;
90 };
91
92 struct run_as_rmdir_recursive_ret {
93 int ret;
94 };
95
96 struct run_as_extract_elf_symbol_offset_ret {
97 uint64_t offset;
98 };
99
100 struct run_as_extract_sdt_probe_offsets_ret {
101 uint32_t num_offset;
102 uint64_t offsets[LTTNG_KERNEL_MAX_UPROBE_NUM];
103 };
104
105 enum run_as_cmd {
106 RUN_AS_MKDIR,
107 RUN_AS_OPEN,
108 RUN_AS_UNLINK,
109 RUN_AS_RMDIR_RECURSIVE,
110 RUN_AS_MKDIR_RECURSIVE,
111 RUN_AS_EXTRACT_ELF_SYMBOL_OFFSET,
112 RUN_AS_EXTRACT_SDT_PROBE_OFFSETS,
113 };
114
115 struct run_as_data {
116 enum run_as_cmd cmd;
117 int fd;
118 union {
119 struct run_as_mkdir_data mkdir;
120 struct run_as_open_data open;
121 struct run_as_unlink_data unlink;
122 struct run_as_rmdir_recursive_data rmdir_recursive;
123 struct run_as_extract_elf_symbol_offset_data extract_elf_symbol_offset;
124 struct run_as_extract_sdt_probe_offsets_data extract_sdt_probe_offsets;
125 } u;
126 uid_t uid;
127 gid_t gid;
128 };
129
130 /*
131 * The run_as_ret structure holds the returned value and status of the command.
132 *
133 * The `u` union field holds the return value of the command; in most cases it
134 * represents the success or the failure of the command. In more complex
135 * commands, it holds a computed value.
136 *
137 * The _errno field is the errno recorded after the execution of the command.
138 *
139 * The _error fields is used the signify that return status of the command. For
140 * simple commands returning `int` the _error field will be the same as the
141 * ret_int field. In complex commands, it signify the success or failure of the
142 * command.
143 *
144 */
145 struct run_as_ret {
146 int fd;
147 union {
148 struct run_as_mkdir_ret mkdir;
149 struct run_as_open_ret open;
150 struct run_as_unlink_ret unlink;
151 struct run_as_rmdir_recursive_ret rmdir_recursive;
152 struct run_as_extract_elf_symbol_offset_ret extract_elf_symbol_offset;
153 struct run_as_extract_sdt_probe_offsets_ret extract_sdt_probe_offsets;
154 } u;
155 int _errno;
156 bool _error;
157 };
158
159 struct run_as_worker {
160 pid_t pid; /* Worker PID. */
161 int sockpair[2];
162 char *procname;
163 };
164
165 /* Single global worker per process (for now). */
166 static struct run_as_worker *global_worker;
167 /* Lock protecting the worker. */
168 static pthread_mutex_t worker_lock = PTHREAD_MUTEX_INITIALIZER;
169
170 #ifdef VALGRIND
171 static
172 int use_clone(void)
173 {
174 return 0;
175 }
176 #else
177 static
178 int use_clone(void)
179 {
180 return !lttng_secure_getenv("LTTNG_DEBUG_NOCLONE");
181 }
182 #endif
183
184 LTTNG_HIDDEN
185 int _utils_mkdir_recursive_unsafe(const char *path, mode_t mode);
186
187 /*
188 * Create recursively directory using the FULL path.
189 */
190 static
191 int _mkdir_recursive(struct run_as_data *data, struct run_as_ret *ret_value)
192 {
193 const char *path;
194 mode_t mode;
195
196 path = data->u.mkdir.path;
197 mode = data->u.mkdir.mode;
198
199 /* Safe to call as we have transitioned to the requested uid/gid. */
200 ret_value->u.mkdir.ret = _utils_mkdir_recursive_unsafe(path, mode);
201 ret_value->_errno = errno;
202 ret_value->_error = (ret_value->u.mkdir.ret) ? true : false;
203 return ret_value->u.mkdir.ret;
204 }
205
206 static
207 int _mkdir(struct run_as_data *data, struct run_as_ret *ret_value)
208 {
209 ret_value->u.mkdir.ret = mkdir(data->u.mkdir.path, data->u.mkdir.mode);
210 ret_value->_errno = errno;
211 ret_value->_error = (ret_value->u.mkdir.ret) ? true : false;
212 return ret_value->u.mkdir.ret;
213 }
214
215 static
216 int _open(struct run_as_data *data, struct run_as_ret *ret_value)
217 {
218 ret_value->u.open.ret = open(data->u.open.path, data->u.open.flags, data->u.open.mode);
219 ret_value->fd = ret_value->u.open.ret;
220 ret_value->_errno = errno;
221 ret_value->_error = ret_value->u.open.ret < 0;
222 return ret_value->u.open.ret;
223 }
224
225 static
226 int _unlink(struct run_as_data *data, struct run_as_ret *ret_value)
227 {
228 ret_value->u.unlink.ret = unlink(data->u.unlink.path);
229 ret_value->_errno = errno;
230 ret_value->_error = (ret_value->u.unlink.ret) ? true : false;
231 return ret_value->u.unlink.ret;
232 }
233
234 static
235 int _rmdir_recursive(struct run_as_data *data, struct run_as_ret *ret_value)
236 {
237 ret_value->u.rmdir_recursive.ret = utils_recursive_rmdir(data->u.rmdir_recursive.path);
238 ret_value->_errno = errno;
239 ret_value->_error = (ret_value->u.rmdir_recursive.ret) ? true : false;
240 return ret_value->u.rmdir_recursive.ret;
241 }
242
243 #ifdef HAVE_ELF_H
244 static
245 int _extract_elf_symbol_offset(struct run_as_data *data,
246 struct run_as_ret *ret_value)
247 {
248 int ret = 0;
249 ret_value->_error = false;
250
251 ret = lttng_elf_get_symbol_offset(data->fd,
252 data->u.extract_elf_symbol_offset.function,
253 &ret_value->u.extract_elf_symbol_offset.offset);
254 if (ret) {
255 DBG("Failed to extract ELF function offset");
256 ret_value->_error = true;
257 }
258
259 return ret;
260 }
261
262 static
263 int _extract_sdt_probe_offsets(struct run_as_data *data,
264 struct run_as_ret *ret_value)
265 {
266 int ret = 0;
267 uint64_t *offsets = NULL;
268 uint32_t num_offset;
269
270 ret_value->_error = false;
271
272 /* On success, this call allocates the offsets paramater. */
273 ret = lttng_elf_get_sdt_probe_offsets(data->fd,
274 data->u.extract_sdt_probe_offsets.provider_name,
275 data->u.extract_sdt_probe_offsets.probe_name,
276 &offsets, &num_offset);
277
278 if (ret) {
279 DBG("Failed to extract SDT probe offsets");
280 ret_value->_error = true;
281 goto end;
282 }
283
284 if (num_offset <= 0 || num_offset > LTTNG_KERNEL_MAX_UPROBE_NUM) {
285 DBG("Wrong number of probes.");
286 ret = -1;
287 ret_value->_error = true;
288 goto free_offset;
289 }
290
291 /* Copy the content of the offsets array to the ret struct. */
292 memcpy(ret_value->u.extract_sdt_probe_offsets.offsets,
293 offsets, num_offset * sizeof(uint64_t));
294
295 ret_value->u.extract_sdt_probe_offsets.num_offset = num_offset;
296
297 free_offset:
298 free(offsets);
299 end:
300 return ret;
301 }
302 #else
303 static
304 int _extract_elf_symbol_offset(struct run_as_data *data,
305 struct run_as_ret *ret_value)
306 {
307 ERR("Unimplemented runas command RUN_AS_EXTRACT_ELF_SYMBOL_OFFSET");
308 return -1;
309 }
310
311 static
312 int _extract_sdt_probe_offsets(struct run_as_data *data,
313 struct run_as_ret *ret_value)
314 {
315 ERR("Unimplemented runas command RUN_AS_EXTRACT_SDT_PROBE_OFFSETS");
316 return -1;
317 }
318 #endif
319
320 static
321 run_as_fct run_as_enum_to_fct(enum run_as_cmd cmd)
322 {
323 switch (cmd) {
324 case RUN_AS_MKDIR:
325 return _mkdir;
326 case RUN_AS_OPEN:
327 return _open;
328 case RUN_AS_UNLINK:
329 return _unlink;
330 case RUN_AS_RMDIR_RECURSIVE:
331 return _rmdir_recursive;
332 case RUN_AS_MKDIR_RECURSIVE:
333 return _mkdir_recursive;
334 case RUN_AS_EXTRACT_ELF_SYMBOL_OFFSET:
335 return _extract_elf_symbol_offset;
336 case RUN_AS_EXTRACT_SDT_PROBE_OFFSETS:
337 return _extract_sdt_probe_offsets;
338 default:
339 ERR("Unknown command %d", (int) cmd);
340 return NULL;
341 }
342 }
343
344 static
345 int do_send_fd(int sock, int fd)
346 {
347 ssize_t len;
348
349 if (fd < 0) {
350 ERR("Attempt to send invalid file descriptor to master (fd = %i)", fd);
351 /* Return 0 as this is not a fatal error. */
352 return 0;
353 }
354
355 len = lttcomm_send_fds_unix_sock(sock, &fd, 1);
356 if (len < 0) {
357 PERROR("lttcomm_send_fds_unix_sock");
358 return -1;
359 }
360 return 0;
361 }
362
363 static
364 int do_recv_fd(int sock, int *fd)
365 {
366 ssize_t len;
367
368 len = lttcomm_recv_fds_unix_sock(sock, fd, 1);
369
370 if (!len) {
371 return -1;
372 } else if (len < 0) {
373 PERROR("lttcomm_recv_fds_unix_sock");
374 return -1;
375 }
376 if (*fd < 0) {
377 ERR("Invalid file descriptor received from worker (fd = %i)", *fd);
378 /* Return 0 as this is not a fatal error. */
379 return 0;
380 }
381
382 return 0;
383 }
384
385 static
386 int send_fd_to_worker(struct run_as_worker *worker, enum run_as_cmd cmd, int fd)
387 {
388 int ret = 0;
389
390 switch (cmd) {
391 case RUN_AS_EXTRACT_ELF_SYMBOL_OFFSET:
392 case RUN_AS_EXTRACT_SDT_PROBE_OFFSETS:
393 break;
394 default:
395 return 0;
396 }
397
398 if (fd < 0) {
399 ERR("Refusing to send invalid fd to worker (fd = %i)", fd);
400 return -1;
401 }
402
403 ret = do_send_fd(worker->sockpair[0], fd);
404 if (ret < 0) {
405 PERROR("do_send_fd");
406 ret = -1;
407 }
408
409 return ret;
410 }
411
412 static
413 int send_fd_to_master(struct run_as_worker *worker, enum run_as_cmd cmd, int fd)
414 {
415 int ret = 0, ret_close = 0;
416
417 switch (cmd) {
418 case RUN_AS_OPEN:
419 break;
420 default:
421 return 0;
422 }
423
424 if (fd < 0) {
425 DBG("Not sending file descriptor to master as it is invalid (fd = %i)", fd);
426 return 0;
427 }
428 ret = do_send_fd(worker->sockpair[1], fd);
429 if (ret < 0) {
430 PERROR("do_send_fd error");
431 ret = -1;
432 }
433
434 ret_close = close(fd);
435 if (ret_close < 0) {
436 PERROR("close");
437 }
438
439 return ret;
440 }
441
442 static
443 int recv_fd_from_worker(struct run_as_worker *worker, enum run_as_cmd cmd, int *fd)
444 {
445 int ret = 0;
446
447 switch (cmd) {
448 case RUN_AS_OPEN:
449 break;
450 default:
451 return 0;
452 }
453
454 ret = do_recv_fd(worker->sockpair[0], fd);
455 if (ret < 0) {
456 PERROR("do_recv_fd error");
457 ret = -1;
458 }
459
460 return ret;
461 }
462
463 static
464 int recv_fd_from_master(struct run_as_worker *worker, enum run_as_cmd cmd, int *fd)
465 {
466 int ret = 0;
467
468 switch (cmd) {
469 case RUN_AS_EXTRACT_ELF_SYMBOL_OFFSET:
470 case RUN_AS_EXTRACT_SDT_PROBE_OFFSETS:
471 break;
472 default:
473 return 0;
474 }
475
476 ret = do_recv_fd(worker->sockpair[1], fd);
477 if (ret < 0) {
478 PERROR("do_recv_fd error");
479 ret = -1;
480 }
481
482 return ret;
483 }
484
485 static
486 int cleanup_received_fd(enum run_as_cmd cmd, int fd)
487 {
488 int ret = 0;
489
490 switch (cmd) {
491 case RUN_AS_EXTRACT_ELF_SYMBOL_OFFSET:
492 case RUN_AS_EXTRACT_SDT_PROBE_OFFSETS:
493 break;
494 default:
495 return 0;
496 }
497
498 if (fd < 0) {
499 return 0;
500 }
501 ret = close(fd);
502 if (ret < 0) {
503 PERROR("close error");
504 ret = -1;
505 }
506
507 return ret;
508 }
509
510 /*
511 * Return < 0 on error, 0 if OK, 1 on hangup.
512 */
513 static
514 int handle_one_cmd(struct run_as_worker *worker)
515 {
516 int ret = 0;
517 struct run_as_data data;
518 ssize_t readlen, writelen;
519 struct run_as_ret sendret;
520 run_as_fct cmd;
521 uid_t prev_euid;
522
523 memset(&sendret, 0, sizeof(sendret));
524 sendret.fd = -1;
525
526 /*
527 * Stage 1: Receive run_as_data struct from the master.
528 * The structure contains the command type and all the parameters needed for
529 * its execution
530 */
531 readlen = lttcomm_recv_unix_sock(worker->sockpair[1], &data,
532 sizeof(data));
533 if (readlen == 0) {
534 /* hang up */
535 ret = 1;
536 goto end;
537 }
538 if (readlen < sizeof(data)) {
539 PERROR("lttcomm_recv_unix_sock error");
540 ret = -1;
541 goto end;
542 }
543
544 cmd = run_as_enum_to_fct(data.cmd);
545 if (!cmd) {
546 ret = -1;
547 goto end;
548 }
549
550 /*
551 * Stage 2: Receive file descriptor from master.
552 * Some commands need a file descriptor as input so if it's needed we
553 * receive the fd using the Unix socket.
554 */
555 ret = recv_fd_from_master(worker, data.cmd, &data.fd);
556 if (ret < 0) {
557 PERROR("recv_fd_from_master error");
558 ret = -1;
559 goto end;
560 }
561
562 prev_euid = getuid();
563 if (data.gid != getegid()) {
564 ret = setegid(data.gid);
565 if (ret < 0) {
566 sendret._error = true;
567 sendret._errno = errno;
568 PERROR("setegid");
569 goto write_return;
570 }
571 }
572 if (data.uid != prev_euid) {
573 ret = seteuid(data.uid);
574 if (ret < 0) {
575 sendret._error = true;
576 sendret._errno = errno;
577 PERROR("seteuid");
578 goto write_return;
579 }
580 }
581
582 /*
583 * Also set umask to 0 for mkdir executable bit.
584 */
585 umask(0);
586
587 /*
588 * Stage 3: Execute the command
589 */
590 ret = (*cmd)(&data, &sendret);
591 if (ret < 0) {
592 DBG("Execution of command returned an error");
593 }
594
595 write_return:
596 ret = cleanup_received_fd(data.cmd, data.fd);
597 if (ret < 0) {
598 ERR("Error cleaning up FD");
599 goto end;
600 }
601
602 /*
603 * Stage 4: Send run_as_ret structure to the master.
604 * This structure contain the return value of the command and the errno.
605 */
606 writelen = lttcomm_send_unix_sock(worker->sockpair[1], &sendret,
607 sizeof(sendret));
608 if (writelen < sizeof(sendret)) {
609 PERROR("lttcomm_send_unix_sock error");
610 ret = -1;
611 goto end;
612 }
613
614 /*
615 * Stage 5: Send file descriptor to the master
616 * Some commands return a file descriptor so if it's needed we pass it back
617 * to the master using the Unix socket.
618 */
619 ret = send_fd_to_master(worker, data.cmd, sendret.fd);
620 if (ret < 0) {
621 DBG("Sending FD to master returned an error");
622 goto end;
623 }
624
625 if (seteuid(prev_euid) < 0) {
626 PERROR("seteuid");
627 ret = -1;
628 goto end;
629 }
630 ret = 0;
631 end:
632 return ret;
633 }
634
635 static
636 int run_as_worker(struct run_as_worker *worker)
637 {
638 int ret;
639 ssize_t writelen;
640 struct run_as_ret sendret;
641 size_t proc_orig_len;
642
643 /*
644 * Initialize worker. Set a different process cmdline.
645 */
646 proc_orig_len = strlen(worker->procname);
647 memset(worker->procname, 0, proc_orig_len);
648 strncpy(worker->procname, DEFAULT_RUN_AS_WORKER_NAME, proc_orig_len);
649
650 ret = lttng_prctl(PR_SET_NAME,
651 (unsigned long) DEFAULT_RUN_AS_WORKER_NAME, 0, 0, 0);
652 if (ret && ret != -ENOSYS) {
653 /* Don't fail as this is not essential. */
654 PERROR("prctl PR_SET_NAME");
655 }
656
657 memset(&sendret, 0, sizeof(sendret));
658
659 writelen = lttcomm_send_unix_sock(worker->sockpair[1], &sendret,
660 sizeof(sendret));
661 if (writelen < sizeof(sendret)) {
662 PERROR("lttcomm_send_unix_sock error");
663 ret = EXIT_FAILURE;
664 goto end;
665 }
666
667 for (;;) {
668 ret = handle_one_cmd(worker);
669 if (ret < 0) {
670 ret = EXIT_FAILURE;
671 goto end;
672 } else if (ret > 0) {
673 break;
674 } else {
675 continue; /* Next command. */
676 }
677 }
678 ret = EXIT_SUCCESS;
679 end:
680 return ret;
681 }
682
683 static
684 int run_as_cmd(struct run_as_worker *worker,
685 enum run_as_cmd cmd,
686 struct run_as_data *data,
687 struct run_as_ret *ret_value,
688 uid_t uid, gid_t gid)
689 {
690 int ret = 0;
691 ssize_t readlen, writelen;
692
693 /*
694 * If we are non-root, we can only deal with our own uid.
695 */
696 if (geteuid() != 0) {
697 if (uid != geteuid()) {
698 ret = -1;
699 ret_value->_errno = EPERM;
700 ERR("Client (%d)/Server (%d) UID mismatch (and sessiond is not root)",
701 (int) uid, (int) geteuid());
702 goto end;
703 }
704 }
705
706 data->cmd = cmd;
707 data->uid = uid;
708 data->gid = gid;
709
710 /*
711 * Stage 1: Send the run_as_data struct to the worker process
712 */
713 writelen = lttcomm_send_unix_sock(worker->sockpair[0], data,
714 sizeof(*data));
715 if (writelen < sizeof(*data)) {
716 PERROR("Error writing message to run_as");
717 ret = -1;
718 ret_value->_errno = EIO;
719 goto end;
720 }
721
722 /*
723 * Stage 2: Send file descriptor to the worker process if needed
724 */
725 ret = send_fd_to_worker(worker, data->cmd, data->fd);
726 if (ret) {
727 PERROR("do_send_fd error");
728 ret = -1;
729 ret_value->_errno = EIO;
730 goto end;
731 }
732
733 /*
734 * Stage 3: Wait for the execution of the command
735 */
736
737 /*
738 * Stage 4: Receive the run_as_ret struct containing the return value and
739 * errno
740 */
741 readlen = lttcomm_recv_unix_sock(worker->sockpair[0], ret_value,
742 sizeof(*ret_value));
743 if (!readlen) {
744 ERR("Run-as worker has hung-up during run_as_cmd");
745 ret = -1;
746 ret_value->_errno = EIO;
747 goto end;
748 } else if (readlen < sizeof(*ret_value)) {
749 PERROR("Error reading response from run_as");
750 ret = -1;
751 ret_value->_errno = errno;
752 goto end;
753 }
754
755 if (ret_value->_error) {
756 /* Skip stage 5 on error as there will be no fd to receive. */
757 goto end;
758 }
759
760 /*
761 * Stage 5: Receive file descriptor if needed
762 */
763 ret = recv_fd_from_worker(worker, data->cmd, &ret_value->fd);
764 if (ret < 0) {
765 ERR("Error receiving fd");
766 ret = -1;
767 ret_value->_errno = EIO;
768 }
769
770 end:
771 return ret;
772 }
773
774 /*
775 * This is for debugging ONLY and should not be considered secure.
776 */
777 static
778 int run_as_noworker(enum run_as_cmd cmd,
779 struct run_as_data *data, struct run_as_ret *ret_value,
780 uid_t uid, gid_t gid)
781 {
782 int ret, saved_errno;
783 mode_t old_mask;
784 run_as_fct fct;
785
786 fct = run_as_enum_to_fct(cmd);
787 if (!fct) {
788 errno = -ENOSYS;
789 ret = -1;
790 goto end;
791 }
792 old_mask = umask(0);
793 ret = fct(data, ret_value);
794 saved_errno = ret_value->_errno;
795 umask(old_mask);
796 errno = saved_errno;
797 end:
798 return ret;
799 }
800
801 static
802 int reset_sighandler(void)
803 {
804 int sig;
805
806 DBG("Resetting run_as worker signal handlers to default");
807 for (sig = 1; sig <= 31; sig++) {
808 (void) signal(sig, SIG_DFL);
809 }
810 return 0;
811 }
812
813 static
814 void worker_sighandler(int sig)
815 {
816 const char *signame;
817
818 /*
819 * The worker will inherit its parent's signals since they are part of
820 * the same process group. However, in the case of SIGINT and SIGTERM,
821 * we want to give the worker a chance to teardown gracefully when its
822 * parent closes the command socket.
823 */
824 switch (sig) {
825 case SIGINT:
826 signame = "SIGINT";
827 break;
828 case SIGTERM:
829 signame = "SIGTERM";
830 break;
831 default:
832 signame = NULL;
833 }
834
835 if (signame) {
836 DBG("run_as worker received signal %s", signame);
837 } else {
838 DBG("run_as_worker received signal %d", sig);
839 }
840 }
841
842 static
843 int set_worker_sighandlers(void)
844 {
845 int ret = 0;
846 sigset_t sigset;
847 struct sigaction sa;
848
849 if ((ret = sigemptyset(&sigset)) < 0) {
850 PERROR("sigemptyset");
851 goto end;
852 }
853
854 sa.sa_handler = worker_sighandler;
855 sa.sa_mask = sigset;
856 sa.sa_flags = 0;
857 if ((ret = sigaction(SIGINT, &sa, NULL)) < 0) {
858 PERROR("sigaction SIGINT");
859 goto end;
860 }
861
862 if ((ret = sigaction(SIGTERM, &sa, NULL)) < 0) {
863 PERROR("sigaction SIGTERM");
864 goto end;
865 }
866
867 DBG("run_as signal handler set for SIGTERM and SIGINT");
868 end:
869 return ret;
870 }
871
872 static
873 int run_as_create_worker_no_lock(const char *procname,
874 post_fork_cleanup_cb clean_up_func,
875 void *clean_up_user_data)
876 {
877 pid_t pid;
878 int i, ret = 0;
879 ssize_t readlen;
880 struct run_as_ret recvret;
881 struct run_as_worker *worker;
882
883 assert(!global_worker);
884 if (!use_clone()) {
885 /*
886 * Don't initialize a worker, all run_as tasks will be performed
887 * in the current process.
888 */
889 ret = 0;
890 goto end;
891 }
892 worker = zmalloc(sizeof(*worker));
893 if (!worker) {
894 ret = -ENOMEM;
895 goto end;
896 }
897 worker->procname = strdup(procname);
898 if (!worker->procname) {
899 ret = -ENOMEM;
900 goto error_procname_alloc;
901 }
902 /* Create unix socket. */
903 if (lttcomm_create_anon_unix_socketpair(worker->sockpair) < 0) {
904 ret = -1;
905 goto error_sock;
906 }
907
908 /* Fork worker. */
909 pid = fork();
910 if (pid < 0) {
911 PERROR("fork");
912 ret = -1;
913 goto error_fork;
914 } else if (pid == 0) {
915 /* Child */
916
917 reset_sighandler();
918
919 set_worker_sighandlers();
920 if (clean_up_func) {
921 if (clean_up_func(clean_up_user_data) < 0) {
922 ERR("Run-as post-fork clean-up failed, exiting.");
923 exit(EXIT_FAILURE);
924 }
925 }
926
927 /* Just close, no shutdown. */
928 if (close(worker->sockpair[0])) {
929 PERROR("close");
930 exit(EXIT_FAILURE);
931 }
932
933 /*
934 * Close all FDs aside from STDIN, STDOUT, STDERR and sockpair[1]
935 * Sockpair[1] is used as a control channel with the master
936 */
937 for (i = 3; i < sysconf(_SC_OPEN_MAX); i++) {
938 if (i != worker->sockpair[1]) {
939 (void) close(i);
940 }
941 }
942
943 worker->sockpair[0] = -1;
944 ret = run_as_worker(worker);
945 if (lttcomm_close_unix_sock(worker->sockpair[1])) {
946 PERROR("close");
947 ret = -1;
948 }
949 worker->sockpair[1] = -1;
950 free(worker->procname);
951 free(worker);
952 LOG(ret ? PRINT_ERR : PRINT_DBG, "run_as worker exiting (ret = %d)", ret);
953 exit(ret ? EXIT_FAILURE : EXIT_SUCCESS);
954 } else {
955 /* Parent */
956
957 /* Just close, no shutdown. */
958 if (close(worker->sockpair[1])) {
959 PERROR("close");
960 ret = -1;
961 goto error_fork;
962 }
963 worker->sockpair[1] = -1;
964 worker->pid = pid;
965 /* Wait for worker to become ready. */
966 readlen = lttcomm_recv_unix_sock(worker->sockpair[0],
967 &recvret, sizeof(recvret));
968 if (readlen < sizeof(recvret)) {
969 ERR("readlen: %zd", readlen);
970 PERROR("Error reading response from run_as at creation");
971 ret = -1;
972 goto error_fork;
973 }
974 global_worker = worker;
975 }
976 end:
977 return ret;
978
979 /* Error handling. */
980 error_fork:
981 for (i = 0; i < 2; i++) {
982 if (worker->sockpair[i] < 0) {
983 continue;
984 }
985 if (lttcomm_close_unix_sock(worker->sockpair[i])) {
986 PERROR("close");
987 }
988 worker->sockpair[i] = -1;
989 }
990 error_sock:
991 free(worker->procname);
992 error_procname_alloc:
993 free(worker);
994 return ret;
995 }
996
997 static
998 int run_as_restart_worker(struct run_as_worker *worker)
999 {
1000 int ret = 0;
1001 char *procname = NULL;
1002
1003 procname = worker->procname;
1004
1005 /* Close socket to run_as worker process and clean up the zombie process */
1006 run_as_destroy_worker();
1007
1008 /* Create a new run_as worker process*/
1009 ret = run_as_create_worker_no_lock(procname, NULL, NULL);
1010 if (ret < 0 ) {
1011 ERR("Restarting the worker process failed");
1012 ret = -1;
1013 goto err;
1014 }
1015 err:
1016 return ret;
1017 }
1018
1019 static
1020 int run_as(enum run_as_cmd cmd, struct run_as_data *data,
1021 struct run_as_ret *ret_value, uid_t uid, gid_t gid)
1022 {
1023 int ret, saved_errno;
1024
1025 pthread_mutex_lock(&worker_lock);
1026 if (use_clone()) {
1027 DBG("Using run_as worker");
1028
1029 assert(global_worker);
1030
1031 ret = run_as_cmd(global_worker, cmd, data, ret_value, uid, gid);
1032 saved_errno = ret_value->_errno;
1033
1034 /*
1035 * If the worker thread crashed the errno is set to EIO. we log
1036 * the error and start a new worker process.
1037 */
1038 if (ret == -1 && saved_errno == EIO) {
1039 DBG("Socket closed unexpectedly... "
1040 "Restarting the worker process");
1041 ret = run_as_restart_worker(global_worker);
1042 if (ret == -1) {
1043 ERR("Failed to restart worker process.");
1044 goto err;
1045 }
1046 }
1047 } else {
1048 DBG("Using run_as without worker");
1049 ret = run_as_noworker(cmd, data, ret_value, uid, gid);
1050 }
1051 err:
1052 pthread_mutex_unlock(&worker_lock);
1053 return ret;
1054 }
1055
1056 LTTNG_HIDDEN
1057 int run_as_mkdir_recursive(const char *path, mode_t mode, uid_t uid, gid_t gid)
1058 {
1059 struct run_as_data data;
1060 struct run_as_ret ret;
1061
1062 memset(&data, 0, sizeof(data));
1063 memset(&ret, 0, sizeof(ret));
1064 DBG3("mkdir() recursive %s with mode %d for uid %d and gid %d",
1065 path, (int) mode, (int) uid, (int) gid);
1066 strncpy(data.u.mkdir.path, path, PATH_MAX - 1);
1067 data.u.mkdir.path[PATH_MAX - 1] = '\0';
1068 data.u.mkdir.mode = mode;
1069
1070 run_as(RUN_AS_MKDIR_RECURSIVE, &data, &ret, uid, gid);
1071 errno = ret._errno;
1072 return ret.u.mkdir.ret;
1073 }
1074
1075 LTTNG_HIDDEN
1076 int run_as_mkdir(const char *path, mode_t mode, uid_t uid, gid_t gid)
1077 {
1078 struct run_as_data data;
1079 struct run_as_ret ret;
1080
1081 memset(&data, 0, sizeof(data));
1082 memset(&ret, 0, sizeof(ret));
1083
1084 DBG3("mkdir() %s with mode %d for uid %d and gid %d",
1085 path, (int) mode, (int) uid, (int) gid);
1086 strncpy(data.u.mkdir.path, path, PATH_MAX - 1);
1087 data.u.mkdir.path[PATH_MAX - 1] = '\0';
1088 data.u.mkdir.mode = mode;
1089 run_as(RUN_AS_MKDIR, &data, &ret, uid, gid);
1090 errno = ret._errno;
1091 return ret.u.mkdir.ret;
1092 }
1093
1094 LTTNG_HIDDEN
1095 int run_as_open(const char *path, int flags, mode_t mode, uid_t uid, gid_t gid)
1096 {
1097 struct run_as_data data;
1098 struct run_as_ret ret;
1099
1100 memset(&data, 0, sizeof(data));
1101 memset(&ret, 0, sizeof(ret));
1102
1103 DBG3("open() %s with flags %X mode %d for uid %d and gid %d",
1104 path, flags, (int) mode, (int) uid, (int) gid);
1105 strncpy(data.u.open.path, path, PATH_MAX - 1);
1106 data.u.open.path[PATH_MAX - 1] = '\0';
1107 data.u.open.flags = flags;
1108 data.u.open.mode = mode;
1109 run_as(RUN_AS_OPEN, &data, &ret, uid, gid);
1110 errno = ret._errno;
1111 ret.u.open.ret = ret.fd;
1112 return ret.u.open.ret;
1113 }
1114
1115 LTTNG_HIDDEN
1116 int run_as_unlink(const char *path, uid_t uid, gid_t gid)
1117 {
1118 struct run_as_data data;
1119 struct run_as_ret ret;
1120
1121 memset(&data, 0, sizeof(data));
1122 memset(&ret, 0, sizeof(ret));
1123
1124 DBG3("unlink() %s with for uid %d and gid %d",
1125 path, (int) uid, (int) gid);
1126 strncpy(data.u.unlink.path, path, PATH_MAX - 1);
1127 data.u.unlink.path[PATH_MAX - 1] = '\0';
1128 run_as(RUN_AS_UNLINK, &data, &ret, uid, gid);
1129 errno = ret._errno;
1130 return ret.u.unlink.ret;
1131 }
1132
1133 LTTNG_HIDDEN
1134 int run_as_rmdir_recursive(const char *path, uid_t uid, gid_t gid)
1135 {
1136 struct run_as_data data;
1137 struct run_as_ret ret;
1138
1139 memset(&data, 0, sizeof(data));
1140 memset(&ret, 0, sizeof(ret));
1141
1142 DBG3("rmdir_recursive() %s with for uid %d and gid %d",
1143 path, (int) uid, (int) gid);
1144 strncpy(data.u.rmdir_recursive.path, path, PATH_MAX - 1);
1145 data.u.rmdir_recursive.path[PATH_MAX - 1] = '\0';
1146 run_as(RUN_AS_RMDIR_RECURSIVE, &data, &ret, uid, gid);
1147 errno = ret._errno;
1148 return ret.u.rmdir_recursive.ret;
1149 }
1150
1151 LTTNG_HIDDEN
1152 int run_as_extract_elf_symbol_offset(int fd, const char* function,
1153 uid_t uid, gid_t gid, uint64_t *offset)
1154 {
1155 struct run_as_data data;
1156 struct run_as_ret ret;
1157
1158 memset(&data, 0, sizeof(data));
1159 memset(&ret, 0, sizeof(ret));
1160
1161 DBG3("extract_elf_symbol_offset() on fd=%d and function=%s "
1162 "with for uid %d and gid %d", fd, function, (int) uid, (int) gid);
1163
1164 data.fd = fd;
1165
1166 strncpy(data.u.extract_elf_symbol_offset.function, function, LTTNG_SYMBOL_NAME_LEN - 1);
1167
1168 data.u.extract_elf_symbol_offset.function[LTTNG_SYMBOL_NAME_LEN - 1] = '\0';
1169
1170 run_as(RUN_AS_EXTRACT_ELF_SYMBOL_OFFSET, &data, &ret, uid, gid);
1171
1172 errno = ret._errno;
1173
1174 if (ret._error) {
1175 return -1;
1176 }
1177
1178 *offset = ret.u.extract_elf_symbol_offset.offset;
1179 return 0;
1180 }
1181
1182 LTTNG_HIDDEN
1183 int run_as_extract_sdt_probe_offsets(int fd, const char* provider_name,
1184 const char* probe_name, uid_t uid, gid_t gid,
1185 uint64_t **offsets, uint32_t *num_offset)
1186 {
1187 struct run_as_data data;
1188 struct run_as_ret ret;
1189
1190 memset(&data, 0, sizeof(data));
1191 memset(&ret, 0, sizeof(ret));
1192
1193 DBG3("extract_sdt_probe_offsets() on fd=%d, probe_name=%s and "
1194 "provider_name=%s with for uid %d and gid %d", fd, probe_name,
1195 provider_name, (int) uid, (int) gid);
1196
1197 data.fd = fd;
1198
1199 strncpy(data.u.extract_sdt_probe_offsets.probe_name, probe_name, LTTNG_SYMBOL_NAME_LEN - 1);
1200 strncpy(data.u.extract_sdt_probe_offsets.provider_name, provider_name, LTTNG_SYMBOL_NAME_LEN - 1);
1201
1202 data.u.extract_sdt_probe_offsets.probe_name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0';
1203 data.u.extract_sdt_probe_offsets.provider_name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0';
1204
1205 run_as(RUN_AS_EXTRACT_SDT_PROBE_OFFSETS, &data, &ret, uid, gid);
1206
1207 errno = ret._errno;
1208
1209 if (ret._error) {
1210 return -1;
1211 }
1212
1213 *num_offset = ret.u.extract_sdt_probe_offsets.num_offset;
1214
1215 *offsets = zmalloc(*num_offset * sizeof(uint64_t));
1216 if (!*offsets) {
1217 return -ENOMEM;
1218 }
1219
1220 memcpy(*offsets, ret.u.extract_sdt_probe_offsets.offsets, *num_offset * sizeof(uint64_t));
1221 return 0;
1222 }
1223
1224 LTTNG_HIDDEN
1225 int run_as_create_worker(const char *procname,
1226 post_fork_cleanup_cb clean_up_func,
1227 void *clean_up_user_data)
1228 {
1229 int ret;
1230
1231 pthread_mutex_lock(&worker_lock);
1232 ret = run_as_create_worker_no_lock(procname, clean_up_func,
1233 clean_up_user_data);
1234 pthread_mutex_unlock(&worker_lock);
1235 return ret;
1236 }
1237
1238 LTTNG_HIDDEN
1239 void run_as_destroy_worker(void)
1240 {
1241 struct run_as_worker *worker = global_worker;
1242
1243 DBG("Destroying run_as worker");
1244 pthread_mutex_lock(&worker_lock);
1245 if (!worker) {
1246 goto end;
1247 }
1248 /* Close unix socket */
1249 DBG("Closing run_as worker socket");
1250 if (lttcomm_close_unix_sock(worker->sockpair[0])) {
1251 PERROR("close");
1252 }
1253 worker->sockpair[0] = -1;
1254 /* Wait for worker. */
1255 for (;;) {
1256 int status;
1257 pid_t wait_ret;
1258
1259 wait_ret = waitpid(worker->pid, &status, 0);
1260 if (wait_ret < 0) {
1261 if (errno == EINTR) {
1262 continue;
1263 }
1264 PERROR("waitpid");
1265 break;
1266 }
1267
1268 if (WIFEXITED(status)) {
1269 LOG(WEXITSTATUS(status) == 0 ? PRINT_DBG : PRINT_ERR,
1270 DEFAULT_RUN_AS_WORKER_NAME " terminated with status code %d",
1271 WEXITSTATUS(status));
1272 break;
1273 } else if (WIFSIGNALED(status)) {
1274 ERR(DEFAULT_RUN_AS_WORKER_NAME " was killed by signal %d",
1275 WTERMSIG(status));
1276 break;
1277 }
1278 }
1279 free(worker->procname);
1280 free(worker);
1281 global_worker = NULL;
1282 end:
1283 pthread_mutex_unlock(&worker_lock);
1284 }
This page took 0.089066 seconds and 4 git commands to generate.