]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/util.c
Merge pull request #1880 from fsateler/sysctl-doc
[thirdparty/systemd.git] / src / basic / util.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <ctype.h>
23 #include <dirent.h>
24 #include <errno.h>
25 #include <fcntl.h>
26 #include <grp.h>
27 #include <langinfo.h>
28 #include <libintl.h>
29 #include <limits.h>
30 #include <linux/magic.h>
31 #include <linux/oom.h>
32 #include <linux/sched.h>
33 #include <locale.h>
34 #include <poll.h>
35 #include <pwd.h>
36 #include <sched.h>
37 #include <signal.h>
38 #include <stdarg.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <sys/file.h>
43 #include <sys/ioctl.h>
44 #include <sys/mman.h>
45 #include <sys/mount.h>
46 #include <sys/personality.h>
47 #include <sys/prctl.h>
48 #include <sys/stat.h>
49 #include <sys/statvfs.h>
50 #include <sys/time.h>
51 #include <sys/types.h>
52 #include <sys/utsname.h>
53 #include <sys/vfs.h>
54 #include <sys/wait.h>
55 #include <syslog.h>
56 #include <unistd.h>
57
58 /* When we include libgen.h because we need dirname() we immediately
59 * undefine basename() since libgen.h defines it as a macro to the
60 * POSIX version which is really broken. We prefer GNU basename(). */
61 #include <libgen.h>
62 #undef basename
63
64 #ifdef HAVE_SYS_AUXV_H
65 #include <sys/auxv.h>
66 #endif
67
68 /* We include linux/fs.h as last of the system headers, as it
69 * otherwise conflicts with sys/mount.h. Yay, Linux is great! */
70 #include <linux/fs.h>
71
72 #include "alloc-util.h"
73 #include "build.h"
74 #include "def.h"
75 #include "device-nodes.h"
76 #include "env-util.h"
77 #include "escape.h"
78 #include "exit-status.h"
79 #include "fd-util.h"
80 #include "fileio.h"
81 #include "formats-util.h"
82 #include "gunicode.h"
83 #include "hashmap.h"
84 #include "hostname-util.h"
85 #include "ioprio.h"
86 #include "log.h"
87 #include "macro.h"
88 #include "missing.h"
89 #include "mkdir.h"
90 #include "hexdecoct.h"
91 #include "parse-util.h"
92 #include "path-util.h"
93 #include "process-util.h"
94 #include "random-util.h"
95 #include "signal-util.h"
96 #include "sparse-endian.h"
97 #include "string-table.h"
98 #include "string-util.h"
99 #include "strv.h"
100 #include "terminal-util.h"
101 #include "user-util.h"
102 #include "utf8.h"
103 #include "util.h"
104 #include "virt.h"
105 #include "dirent-util.h"
106 #include "stat-util.h"
107
108 /* Put this test here for a lack of better place */
109 assert_cc(EAGAIN == EWOULDBLOCK);
110
111 int saved_argc = 0;
112 char **saved_argv = NULL;
113
114 size_t page_size(void) {
115 static thread_local size_t pgsz = 0;
116 long r;
117
118 if (_likely_(pgsz > 0))
119 return pgsz;
120
121 r = sysconf(_SC_PAGESIZE);
122 assert(r > 0);
123
124 pgsz = (size_t) r;
125 return pgsz;
126 }
127
128 static int do_execute(char **directories, usec_t timeout, char *argv[]) {
129 _cleanup_hashmap_free_free_ Hashmap *pids = NULL;
130 _cleanup_set_free_free_ Set *seen = NULL;
131 char **directory;
132
133 /* We fork this all off from a child process so that we can
134 * somewhat cleanly make use of SIGALRM to set a time limit */
135
136 (void) reset_all_signal_handlers();
137 (void) reset_signal_mask();
138
139 assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0);
140
141 pids = hashmap_new(NULL);
142 if (!pids)
143 return log_oom();
144
145 seen = set_new(&string_hash_ops);
146 if (!seen)
147 return log_oom();
148
149 STRV_FOREACH(directory, directories) {
150 _cleanup_closedir_ DIR *d;
151 struct dirent *de;
152
153 d = opendir(*directory);
154 if (!d) {
155 if (errno == ENOENT)
156 continue;
157
158 return log_error_errno(errno, "Failed to open directory %s: %m", *directory);
159 }
160
161 FOREACH_DIRENT(de, d, break) {
162 _cleanup_free_ char *path = NULL;
163 pid_t pid;
164 int r;
165
166 if (!dirent_is_file(de))
167 continue;
168
169 if (set_contains(seen, de->d_name)) {
170 log_debug("%1$s/%2$s skipped (%2$s was already seen).", *directory, de->d_name);
171 continue;
172 }
173
174 r = set_put_strdup(seen, de->d_name);
175 if (r < 0)
176 return log_oom();
177
178 path = strjoin(*directory, "/", de->d_name, NULL);
179 if (!path)
180 return log_oom();
181
182 if (null_or_empty_path(path)) {
183 log_debug("%s is empty (a mask).", path);
184 continue;
185 }
186
187 pid = fork();
188 if (pid < 0) {
189 log_error_errno(errno, "Failed to fork: %m");
190 continue;
191 } else if (pid == 0) {
192 char *_argv[2];
193
194 assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0);
195
196 if (!argv) {
197 _argv[0] = path;
198 _argv[1] = NULL;
199 argv = _argv;
200 } else
201 argv[0] = path;
202
203 execv(path, argv);
204 return log_error_errno(errno, "Failed to execute %s: %m", path);
205 }
206
207 log_debug("Spawned %s as " PID_FMT ".", path, pid);
208
209 r = hashmap_put(pids, UINT_TO_PTR(pid), path);
210 if (r < 0)
211 return log_oom();
212 path = NULL;
213 }
214 }
215
216 /* Abort execution of this process after the timout. We simply
217 * rely on SIGALRM as default action terminating the process,
218 * and turn on alarm(). */
219
220 if (timeout != USEC_INFINITY)
221 alarm((timeout + USEC_PER_SEC - 1) / USEC_PER_SEC);
222
223 while (!hashmap_isempty(pids)) {
224 _cleanup_free_ char *path = NULL;
225 pid_t pid;
226
227 pid = PTR_TO_UINT(hashmap_first_key(pids));
228 assert(pid > 0);
229
230 path = hashmap_remove(pids, UINT_TO_PTR(pid));
231 assert(path);
232
233 wait_for_terminate_and_warn(path, pid, true);
234 }
235
236 return 0;
237 }
238
239 void execute_directories(const char* const* directories, usec_t timeout, char *argv[]) {
240 pid_t executor_pid;
241 int r;
242 char *name;
243 char **dirs = (char**) directories;
244
245 assert(!strv_isempty(dirs));
246
247 name = basename(dirs[0]);
248 assert(!isempty(name));
249
250 /* Executes all binaries in the directories in parallel and waits
251 * for them to finish. Optionally a timeout is applied. If a file
252 * with the same name exists in more than one directory, the
253 * earliest one wins. */
254
255 executor_pid = fork();
256 if (executor_pid < 0) {
257 log_error_errno(errno, "Failed to fork: %m");
258 return;
259
260 } else if (executor_pid == 0) {
261 r = do_execute(dirs, timeout, argv);
262 _exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
263 }
264
265 wait_for_terminate_and_warn(name, executor_pid, true);
266 }
267
268 bool plymouth_running(void) {
269 return access("/run/plymouth/pid", F_OK) >= 0;
270 }
271
272 bool display_is_local(const char *display) {
273 assert(display);
274
275 return
276 display[0] == ':' &&
277 display[1] >= '0' &&
278 display[1] <= '9';
279 }
280
281 int socket_from_display(const char *display, char **path) {
282 size_t k;
283 char *f, *c;
284
285 assert(display);
286 assert(path);
287
288 if (!display_is_local(display))
289 return -EINVAL;
290
291 k = strspn(display+1, "0123456789");
292
293 f = new(char, strlen("/tmp/.X11-unix/X") + k + 1);
294 if (!f)
295 return -ENOMEM;
296
297 c = stpcpy(f, "/tmp/.X11-unix/X");
298 memcpy(c, display+1, k);
299 c[k] = 0;
300
301 *path = f;
302
303 return 0;
304 }
305
306 int block_get_whole_disk(dev_t d, dev_t *ret) {
307 char *p, *s;
308 int r;
309 unsigned n, m;
310
311 assert(ret);
312
313 /* If it has a queue this is good enough for us */
314 if (asprintf(&p, "/sys/dev/block/%u:%u/queue", major(d), minor(d)) < 0)
315 return -ENOMEM;
316
317 r = access(p, F_OK);
318 free(p);
319
320 if (r >= 0) {
321 *ret = d;
322 return 0;
323 }
324
325 /* If it is a partition find the originating device */
326 if (asprintf(&p, "/sys/dev/block/%u:%u/partition", major(d), minor(d)) < 0)
327 return -ENOMEM;
328
329 r = access(p, F_OK);
330 free(p);
331
332 if (r < 0)
333 return -ENOENT;
334
335 /* Get parent dev_t */
336 if (asprintf(&p, "/sys/dev/block/%u:%u/../dev", major(d), minor(d)) < 0)
337 return -ENOMEM;
338
339 r = read_one_line_file(p, &s);
340 free(p);
341
342 if (r < 0)
343 return r;
344
345 r = sscanf(s, "%u:%u", &m, &n);
346 free(s);
347
348 if (r != 2)
349 return -EINVAL;
350
351 /* Only return this if it is really good enough for us. */
352 if (asprintf(&p, "/sys/dev/block/%u:%u/queue", m, n) < 0)
353 return -ENOMEM;
354
355 r = access(p, F_OK);
356 free(p);
357
358 if (r >= 0) {
359 *ret = makedev(m, n);
360 return 0;
361 }
362
363 return -ENOENT;
364 }
365
366 bool kexec_loaded(void) {
367 bool loaded = false;
368 char *s;
369
370 if (read_one_line_file("/sys/kernel/kexec_loaded", &s) >= 0) {
371 if (s[0] == '1')
372 loaded = true;
373 free(s);
374 }
375 return loaded;
376 }
377
378 int prot_from_flags(int flags) {
379
380 switch (flags & O_ACCMODE) {
381
382 case O_RDONLY:
383 return PROT_READ;
384
385 case O_WRONLY:
386 return PROT_WRITE;
387
388 case O_RDWR:
389 return PROT_READ|PROT_WRITE;
390
391 default:
392 return -EINVAL;
393 }
394 }
395
396 int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...) {
397 bool stdout_is_tty, stderr_is_tty;
398 pid_t parent_pid, agent_pid;
399 sigset_t ss, saved_ss;
400 unsigned n, i;
401 va_list ap;
402 char **l;
403
404 assert(pid);
405 assert(path);
406
407 /* Spawns a temporary TTY agent, making sure it goes away when
408 * we go away */
409
410 parent_pid = getpid();
411
412 /* First we temporarily block all signals, so that the new
413 * child has them blocked initially. This way, we can be sure
414 * that SIGTERMs are not lost we might send to the agent. */
415 assert_se(sigfillset(&ss) >= 0);
416 assert_se(sigprocmask(SIG_SETMASK, &ss, &saved_ss) >= 0);
417
418 agent_pid = fork();
419 if (agent_pid < 0) {
420 assert_se(sigprocmask(SIG_SETMASK, &saved_ss, NULL) >= 0);
421 return -errno;
422 }
423
424 if (agent_pid != 0) {
425 assert_se(sigprocmask(SIG_SETMASK, &saved_ss, NULL) >= 0);
426 *pid = agent_pid;
427 return 0;
428 }
429
430 /* In the child:
431 *
432 * Make sure the agent goes away when the parent dies */
433 if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
434 _exit(EXIT_FAILURE);
435
436 /* Make sure we actually can kill the agent, if we need to, in
437 * case somebody invoked us from a shell script that trapped
438 * SIGTERM or so... */
439 (void) reset_all_signal_handlers();
440 (void) reset_signal_mask();
441
442 /* Check whether our parent died before we were able
443 * to set the death signal and unblock the signals */
444 if (getppid() != parent_pid)
445 _exit(EXIT_SUCCESS);
446
447 /* Don't leak fds to the agent */
448 close_all_fds(except, n_except);
449
450 stdout_is_tty = isatty(STDOUT_FILENO);
451 stderr_is_tty = isatty(STDERR_FILENO);
452
453 if (!stdout_is_tty || !stderr_is_tty) {
454 int fd;
455
456 /* Detach from stdout/stderr. and reopen
457 * /dev/tty for them. This is important to
458 * ensure that when systemctl is started via
459 * popen() or a similar call that expects to
460 * read EOF we actually do generate EOF and
461 * not delay this indefinitely by because we
462 * keep an unused copy of stdin around. */
463 fd = open("/dev/tty", O_WRONLY);
464 if (fd < 0) {
465 log_error_errno(errno, "Failed to open /dev/tty: %m");
466 _exit(EXIT_FAILURE);
467 }
468
469 if (!stdout_is_tty)
470 dup2(fd, STDOUT_FILENO);
471
472 if (!stderr_is_tty)
473 dup2(fd, STDERR_FILENO);
474
475 if (fd > 2)
476 close(fd);
477 }
478
479 /* Count arguments */
480 va_start(ap, path);
481 for (n = 0; va_arg(ap, char*); n++)
482 ;
483 va_end(ap);
484
485 /* Allocate strv */
486 l = alloca(sizeof(char *) * (n + 1));
487
488 /* Fill in arguments */
489 va_start(ap, path);
490 for (i = 0; i <= n; i++)
491 l[i] = va_arg(ap, char*);
492 va_end(ap);
493
494 execv(path, l);
495 _exit(EXIT_FAILURE);
496 }
497
498 bool in_initrd(void) {
499 static int saved = -1;
500 struct statfs s;
501
502 if (saved >= 0)
503 return saved;
504
505 /* We make two checks here:
506 *
507 * 1. the flag file /etc/initrd-release must exist
508 * 2. the root file system must be a memory file system
509 *
510 * The second check is extra paranoia, since misdetecting an
511 * initrd can have bad bad consequences due the initrd
512 * emptying when transititioning to the main systemd.
513 */
514
515 saved = access("/etc/initrd-release", F_OK) >= 0 &&
516 statfs("/", &s) >= 0 &&
517 is_temporary_fs(&s);
518
519 return saved;
520 }
521
522 /* hey glibc, APIs with callbacks without a user pointer are so useless */
523 void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size,
524 int (*compar) (const void *, const void *, void *), void *arg) {
525 size_t l, u, idx;
526 const void *p;
527 int comparison;
528
529 l = 0;
530 u = nmemb;
531 while (l < u) {
532 idx = (l + u) / 2;
533 p = (void *)(((const char *) base) + (idx * size));
534 comparison = compar(key, p, arg);
535 if (comparison < 0)
536 u = idx;
537 else if (comparison > 0)
538 l = idx + 1;
539 else
540 return (void *)p;
541 }
542 return NULL;
543 }
544
545 int on_ac_power(void) {
546 bool found_offline = false, found_online = false;
547 _cleanup_closedir_ DIR *d = NULL;
548
549 d = opendir("/sys/class/power_supply");
550 if (!d)
551 return errno == ENOENT ? true : -errno;
552
553 for (;;) {
554 struct dirent *de;
555 _cleanup_close_ int fd = -1, device = -1;
556 char contents[6];
557 ssize_t n;
558
559 errno = 0;
560 de = readdir(d);
561 if (!de && errno != 0)
562 return -errno;
563
564 if (!de)
565 break;
566
567 if (hidden_file(de->d_name))
568 continue;
569
570 device = openat(dirfd(d), de->d_name, O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_NOCTTY);
571 if (device < 0) {
572 if (errno == ENOENT || errno == ENOTDIR)
573 continue;
574
575 return -errno;
576 }
577
578 fd = openat(device, "type", O_RDONLY|O_CLOEXEC|O_NOCTTY);
579 if (fd < 0) {
580 if (errno == ENOENT)
581 continue;
582
583 return -errno;
584 }
585
586 n = read(fd, contents, sizeof(contents));
587 if (n < 0)
588 return -errno;
589
590 if (n != 6 || memcmp(contents, "Mains\n", 6))
591 continue;
592
593 safe_close(fd);
594 fd = openat(device, "online", O_RDONLY|O_CLOEXEC|O_NOCTTY);
595 if (fd < 0) {
596 if (errno == ENOENT)
597 continue;
598
599 return -errno;
600 }
601
602 n = read(fd, contents, sizeof(contents));
603 if (n < 0)
604 return -errno;
605
606 if (n != 2 || contents[1] != '\n')
607 return -EIO;
608
609 if (contents[0] == '1') {
610 found_online = true;
611 break;
612 } else if (contents[0] == '0')
613 found_offline = true;
614 else
615 return -EIO;
616 }
617
618 return found_online || !found_offline;
619 }
620
621 bool id128_is_valid(const char *s) {
622 size_t i, l;
623
624 l = strlen(s);
625 if (l == 32) {
626
627 /* Simple formatted 128bit hex string */
628
629 for (i = 0; i < l; i++) {
630 char c = s[i];
631
632 if (!(c >= '0' && c <= '9') &&
633 !(c >= 'a' && c <= 'z') &&
634 !(c >= 'A' && c <= 'Z'))
635 return false;
636 }
637
638 } else if (l == 36) {
639
640 /* Formatted UUID */
641
642 for (i = 0; i < l; i++) {
643 char c = s[i];
644
645 if ((i == 8 || i == 13 || i == 18 || i == 23)) {
646 if (c != '-')
647 return false;
648 } else {
649 if (!(c >= '0' && c <= '9') &&
650 !(c >= 'a' && c <= 'z') &&
651 !(c >= 'A' && c <= 'Z'))
652 return false;
653 }
654 }
655
656 } else
657 return false;
658
659 return true;
660 }
661
662 int container_get_leader(const char *machine, pid_t *pid) {
663 _cleanup_free_ char *s = NULL, *class = NULL;
664 const char *p;
665 pid_t leader;
666 int r;
667
668 assert(machine);
669 assert(pid);
670
671 if (!machine_name_is_valid(machine))
672 return -EINVAL;
673
674 p = strjoina("/run/systemd/machines/", machine);
675 r = parse_env_file(p, NEWLINE, "LEADER", &s, "CLASS", &class, NULL);
676 if (r == -ENOENT)
677 return -EHOSTDOWN;
678 if (r < 0)
679 return r;
680 if (!s)
681 return -EIO;
682
683 if (!streq_ptr(class, "container"))
684 return -EIO;
685
686 r = parse_pid(s, &leader);
687 if (r < 0)
688 return r;
689 if (leader <= 1)
690 return -EIO;
691
692 *pid = leader;
693 return 0;
694 }
695
696 int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *userns_fd, int *root_fd) {
697 _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, netnsfd = -1, usernsfd = -1;
698 int rfd = -1;
699
700 assert(pid >= 0);
701
702 if (mntns_fd) {
703 const char *mntns;
704
705 mntns = procfs_file_alloca(pid, "ns/mnt");
706 mntnsfd = open(mntns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
707 if (mntnsfd < 0)
708 return -errno;
709 }
710
711 if (pidns_fd) {
712 const char *pidns;
713
714 pidns = procfs_file_alloca(pid, "ns/pid");
715 pidnsfd = open(pidns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
716 if (pidnsfd < 0)
717 return -errno;
718 }
719
720 if (netns_fd) {
721 const char *netns;
722
723 netns = procfs_file_alloca(pid, "ns/net");
724 netnsfd = open(netns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
725 if (netnsfd < 0)
726 return -errno;
727 }
728
729 if (userns_fd) {
730 const char *userns;
731
732 userns = procfs_file_alloca(pid, "ns/user");
733 usernsfd = open(userns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
734 if (usernsfd < 0 && errno != ENOENT)
735 return -errno;
736 }
737
738 if (root_fd) {
739 const char *root;
740
741 root = procfs_file_alloca(pid, "root");
742 rfd = open(root, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
743 if (rfd < 0)
744 return -errno;
745 }
746
747 if (pidns_fd)
748 *pidns_fd = pidnsfd;
749
750 if (mntns_fd)
751 *mntns_fd = mntnsfd;
752
753 if (netns_fd)
754 *netns_fd = netnsfd;
755
756 if (userns_fd)
757 *userns_fd = usernsfd;
758
759 if (root_fd)
760 *root_fd = rfd;
761
762 pidnsfd = mntnsfd = netnsfd = usernsfd = -1;
763
764 return 0;
765 }
766
767 int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd) {
768 if (userns_fd >= 0) {
769 /* Can't setns to your own userns, since then you could
770 * escalate from non-root to root in your own namespace, so
771 * check if namespaces equal before attempting to enter. */
772 _cleanup_free_ char *userns_fd_path = NULL;
773 int r;
774 if (asprintf(&userns_fd_path, "/proc/self/fd/%d", userns_fd) < 0)
775 return -ENOMEM;
776
777 r = files_same(userns_fd_path, "/proc/self/ns/user");
778 if (r < 0)
779 return r;
780 if (r)
781 userns_fd = -1;
782 }
783
784 if (pidns_fd >= 0)
785 if (setns(pidns_fd, CLONE_NEWPID) < 0)
786 return -errno;
787
788 if (mntns_fd >= 0)
789 if (setns(mntns_fd, CLONE_NEWNS) < 0)
790 return -errno;
791
792 if (netns_fd >= 0)
793 if (setns(netns_fd, CLONE_NEWNET) < 0)
794 return -errno;
795
796 if (userns_fd >= 0)
797 if (setns(userns_fd, CLONE_NEWUSER) < 0)
798 return -errno;
799
800 if (root_fd >= 0) {
801 if (fchdir(root_fd) < 0)
802 return -errno;
803
804 if (chroot(".") < 0)
805 return -errno;
806 }
807
808 return reset_uid_gid();
809 }
810
811 uint64_t physical_memory(void) {
812 long mem;
813
814 /* We return this as uint64_t in case we are running as 32bit
815 * process on a 64bit kernel with huge amounts of memory */
816
817 mem = sysconf(_SC_PHYS_PAGES);
818 assert(mem > 0);
819
820 return (uint64_t) mem * (uint64_t) page_size();
821 }
822
823 int update_reboot_param_file(const char *param) {
824 int r = 0;
825
826 if (param) {
827 r = write_string_file(REBOOT_PARAM_FILE, param, WRITE_STRING_FILE_CREATE);
828 if (r < 0)
829 return log_error_errno(r, "Failed to write reboot param to "REBOOT_PARAM_FILE": %m");
830 } else
831 (void) unlink(REBOOT_PARAM_FILE);
832
833 return 0;
834 }
835
836 int version(void) {
837 puts(PACKAGE_STRING "\n"
838 SYSTEMD_FEATURES);
839 return 0;
840 }