]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/util.c
util-lib: move running_in_chroot() into virt.[ch]
[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 <glob.h>
27 #include <grp.h>
28 #include <langinfo.h>
29 #include <libintl.h>
30 #include <limits.h>
31 #include <linux/magic.h>
32 #include <linux/oom.h>
33 #include <linux/sched.h>
34 #include <locale.h>
35 #include <poll.h>
36 #include <pwd.h>
37 #include <sched.h>
38 #include <signal.h>
39 #include <stdarg.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <sys/file.h>
44 #include <sys/ioctl.h>
45 #include <sys/mman.h>
46 #include <sys/mount.h>
47 #include <sys/personality.h>
48 #include <sys/prctl.h>
49 #include <sys/stat.h>
50 #include <sys/statvfs.h>
51 #include <sys/time.h>
52 #include <sys/types.h>
53 #include <sys/utsname.h>
54 #include <sys/vfs.h>
55 #include <sys/wait.h>
56 #include <syslog.h>
57 #include <unistd.h>
58
59 /* When we include libgen.h because we need dirname() we immediately
60 * undefine basename() since libgen.h defines it as a macro to the
61 * POSIX version which is really broken. We prefer GNU basename(). */
62 #include <libgen.h>
63 #undef basename
64
65 #ifdef HAVE_SYS_AUXV_H
66 #include <sys/auxv.h>
67 #endif
68
69 /* We include linux/fs.h as last of the system headers, as it
70 * otherwise conflicts with sys/mount.h. Yay, Linux is great! */
71 #include <linux/fs.h>
72
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 bool fstype_is_network(const char *fstype) {
129 static const char table[] =
130 "afs\0"
131 "cifs\0"
132 "smbfs\0"
133 "sshfs\0"
134 "ncpfs\0"
135 "ncp\0"
136 "nfs\0"
137 "nfs4\0"
138 "gfs\0"
139 "gfs2\0"
140 "glusterfs\0";
141
142 const char *x;
143
144 x = startswith(fstype, "fuse.");
145 if (x)
146 fstype = x;
147
148 return nulstr_contains(table, fstype);
149 }
150
151 void rename_process(const char name[8]) {
152 assert(name);
153
154 /* This is a like a poor man's setproctitle(). It changes the
155 * comm field, argv[0], and also the glibc's internally used
156 * name of the process. For the first one a limit of 16 chars
157 * applies, to the second one usually one of 10 (i.e. length
158 * of "/sbin/init"), to the third one one of 7 (i.e. length of
159 * "systemd"). If you pass a longer string it will be
160 * truncated */
161
162 prctl(PR_SET_NAME, name);
163
164 if (program_invocation_name)
165 strncpy(program_invocation_name, name, strlen(program_invocation_name));
166
167 if (saved_argc > 0) {
168 int i;
169
170 if (saved_argv[0])
171 strncpy(saved_argv[0], name, strlen(saved_argv[0]));
172
173 for (i = 1; i < saved_argc; i++) {
174 if (!saved_argv[i])
175 break;
176
177 memzero(saved_argv[i], strlen(saved_argv[i]));
178 }
179 }
180 }
181
182 noreturn void freeze(void) {
183
184 /* Make sure nobody waits for us on a socket anymore */
185 close_all_fds(NULL, 0);
186
187 sync();
188
189 for (;;)
190 pause();
191 }
192
193 static int do_execute(char **directories, usec_t timeout, char *argv[]) {
194 _cleanup_hashmap_free_free_ Hashmap *pids = NULL;
195 _cleanup_set_free_free_ Set *seen = NULL;
196 char **directory;
197
198 /* We fork this all off from a child process so that we can
199 * somewhat cleanly make use of SIGALRM to set a time limit */
200
201 (void) reset_all_signal_handlers();
202 (void) reset_signal_mask();
203
204 assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0);
205
206 pids = hashmap_new(NULL);
207 if (!pids)
208 return log_oom();
209
210 seen = set_new(&string_hash_ops);
211 if (!seen)
212 return log_oom();
213
214 STRV_FOREACH(directory, directories) {
215 _cleanup_closedir_ DIR *d;
216 struct dirent *de;
217
218 d = opendir(*directory);
219 if (!d) {
220 if (errno == ENOENT)
221 continue;
222
223 return log_error_errno(errno, "Failed to open directory %s: %m", *directory);
224 }
225
226 FOREACH_DIRENT(de, d, break) {
227 _cleanup_free_ char *path = NULL;
228 pid_t pid;
229 int r;
230
231 if (!dirent_is_file(de))
232 continue;
233
234 if (set_contains(seen, de->d_name)) {
235 log_debug("%1$s/%2$s skipped (%2$s was already seen).", *directory, de->d_name);
236 continue;
237 }
238
239 r = set_put_strdup(seen, de->d_name);
240 if (r < 0)
241 return log_oom();
242
243 path = strjoin(*directory, "/", de->d_name, NULL);
244 if (!path)
245 return log_oom();
246
247 if (null_or_empty_path(path)) {
248 log_debug("%s is empty (a mask).", path);
249 continue;
250 }
251
252 pid = fork();
253 if (pid < 0) {
254 log_error_errno(errno, "Failed to fork: %m");
255 continue;
256 } else if (pid == 0) {
257 char *_argv[2];
258
259 assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0);
260
261 if (!argv) {
262 _argv[0] = path;
263 _argv[1] = NULL;
264 argv = _argv;
265 } else
266 argv[0] = path;
267
268 execv(path, argv);
269 return log_error_errno(errno, "Failed to execute %s: %m", path);
270 }
271
272 log_debug("Spawned %s as " PID_FMT ".", path, pid);
273
274 r = hashmap_put(pids, UINT_TO_PTR(pid), path);
275 if (r < 0)
276 return log_oom();
277 path = NULL;
278 }
279 }
280
281 /* Abort execution of this process after the timout. We simply
282 * rely on SIGALRM as default action terminating the process,
283 * and turn on alarm(). */
284
285 if (timeout != USEC_INFINITY)
286 alarm((timeout + USEC_PER_SEC - 1) / USEC_PER_SEC);
287
288 while (!hashmap_isempty(pids)) {
289 _cleanup_free_ char *path = NULL;
290 pid_t pid;
291
292 pid = PTR_TO_UINT(hashmap_first_key(pids));
293 assert(pid > 0);
294
295 path = hashmap_remove(pids, UINT_TO_PTR(pid));
296 assert(path);
297
298 wait_for_terminate_and_warn(path, pid, true);
299 }
300
301 return 0;
302 }
303
304 void execute_directories(const char* const* directories, usec_t timeout, char *argv[]) {
305 pid_t executor_pid;
306 int r;
307 char *name;
308 char **dirs = (char**) directories;
309
310 assert(!strv_isempty(dirs));
311
312 name = basename(dirs[0]);
313 assert(!isempty(name));
314
315 /* Executes all binaries in the directories in parallel and waits
316 * for them to finish. Optionally a timeout is applied. If a file
317 * with the same name exists in more than one directory, the
318 * earliest one wins. */
319
320 executor_pid = fork();
321 if (executor_pid < 0) {
322 log_error_errno(errno, "Failed to fork: %m");
323 return;
324
325 } else if (executor_pid == 0) {
326 r = do_execute(dirs, timeout, argv);
327 _exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
328 }
329
330 wait_for_terminate_and_warn(name, executor_pid, true);
331 }
332
333 bool plymouth_running(void) {
334 return access("/run/plymouth/pid", F_OK) >= 0;
335 }
336
337 bool display_is_local(const char *display) {
338 assert(display);
339
340 return
341 display[0] == ':' &&
342 display[1] >= '0' &&
343 display[1] <= '9';
344 }
345
346 int socket_from_display(const char *display, char **path) {
347 size_t k;
348 char *f, *c;
349
350 assert(display);
351 assert(path);
352
353 if (!display_is_local(display))
354 return -EINVAL;
355
356 k = strspn(display+1, "0123456789");
357
358 f = new(char, strlen("/tmp/.X11-unix/X") + k + 1);
359 if (!f)
360 return -ENOMEM;
361
362 c = stpcpy(f, "/tmp/.X11-unix/X");
363 memcpy(c, display+1, k);
364 c[k] = 0;
365
366 *path = f;
367
368 return 0;
369 }
370
371 int glob_exists(const char *path) {
372 _cleanup_globfree_ glob_t g = {};
373 int k;
374
375 assert(path);
376
377 errno = 0;
378 k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
379
380 if (k == GLOB_NOMATCH)
381 return 0;
382 else if (k == GLOB_NOSPACE)
383 return -ENOMEM;
384 else if (k == 0)
385 return !strv_isempty(g.gl_pathv);
386 else
387 return errno ? -errno : -EIO;
388 }
389
390 int glob_extend(char ***strv, const char *path) {
391 _cleanup_globfree_ glob_t g = {};
392 int k;
393 char **p;
394
395 errno = 0;
396 k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
397
398 if (k == GLOB_NOMATCH)
399 return -ENOENT;
400 else if (k == GLOB_NOSPACE)
401 return -ENOMEM;
402 else if (k != 0 || strv_isempty(g.gl_pathv))
403 return errno ? -errno : -EIO;
404
405 STRV_FOREACH(p, g.gl_pathv) {
406 k = strv_extend(strv, *p);
407 if (k < 0)
408 break;
409 }
410
411 return k;
412 }
413
414 int block_get_whole_disk(dev_t d, dev_t *ret) {
415 char *p, *s;
416 int r;
417 unsigned n, m;
418
419 assert(ret);
420
421 /* If it has a queue this is good enough for us */
422 if (asprintf(&p, "/sys/dev/block/%u:%u/queue", major(d), minor(d)) < 0)
423 return -ENOMEM;
424
425 r = access(p, F_OK);
426 free(p);
427
428 if (r >= 0) {
429 *ret = d;
430 return 0;
431 }
432
433 /* If it is a partition find the originating device */
434 if (asprintf(&p, "/sys/dev/block/%u:%u/partition", major(d), minor(d)) < 0)
435 return -ENOMEM;
436
437 r = access(p, F_OK);
438 free(p);
439
440 if (r < 0)
441 return -ENOENT;
442
443 /* Get parent dev_t */
444 if (asprintf(&p, "/sys/dev/block/%u:%u/../dev", major(d), minor(d)) < 0)
445 return -ENOMEM;
446
447 r = read_one_line_file(p, &s);
448 free(p);
449
450 if (r < 0)
451 return r;
452
453 r = sscanf(s, "%u:%u", &m, &n);
454 free(s);
455
456 if (r != 2)
457 return -EINVAL;
458
459 /* Only return this if it is really good enough for us. */
460 if (asprintf(&p, "/sys/dev/block/%u:%u/queue", m, n) < 0)
461 return -ENOMEM;
462
463 r = access(p, F_OK);
464 free(p);
465
466 if (r >= 0) {
467 *ret = makedev(m, n);
468 return 0;
469 }
470
471 return -ENOENT;
472 }
473
474 static const char *const ioprio_class_table[] = {
475 [IOPRIO_CLASS_NONE] = "none",
476 [IOPRIO_CLASS_RT] = "realtime",
477 [IOPRIO_CLASS_BE] = "best-effort",
478 [IOPRIO_CLASS_IDLE] = "idle"
479 };
480
481 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ioprio_class, int, INT_MAX);
482
483 static const char *const sigchld_code_table[] = {
484 [CLD_EXITED] = "exited",
485 [CLD_KILLED] = "killed",
486 [CLD_DUMPED] = "dumped",
487 [CLD_TRAPPED] = "trapped",
488 [CLD_STOPPED] = "stopped",
489 [CLD_CONTINUED] = "continued",
490 };
491
492 DEFINE_STRING_TABLE_LOOKUP(sigchld_code, int);
493
494 static const char *const log_facility_unshifted_table[LOG_NFACILITIES] = {
495 [LOG_FAC(LOG_KERN)] = "kern",
496 [LOG_FAC(LOG_USER)] = "user",
497 [LOG_FAC(LOG_MAIL)] = "mail",
498 [LOG_FAC(LOG_DAEMON)] = "daemon",
499 [LOG_FAC(LOG_AUTH)] = "auth",
500 [LOG_FAC(LOG_SYSLOG)] = "syslog",
501 [LOG_FAC(LOG_LPR)] = "lpr",
502 [LOG_FAC(LOG_NEWS)] = "news",
503 [LOG_FAC(LOG_UUCP)] = "uucp",
504 [LOG_FAC(LOG_CRON)] = "cron",
505 [LOG_FAC(LOG_AUTHPRIV)] = "authpriv",
506 [LOG_FAC(LOG_FTP)] = "ftp",
507 [LOG_FAC(LOG_LOCAL0)] = "local0",
508 [LOG_FAC(LOG_LOCAL1)] = "local1",
509 [LOG_FAC(LOG_LOCAL2)] = "local2",
510 [LOG_FAC(LOG_LOCAL3)] = "local3",
511 [LOG_FAC(LOG_LOCAL4)] = "local4",
512 [LOG_FAC(LOG_LOCAL5)] = "local5",
513 [LOG_FAC(LOG_LOCAL6)] = "local6",
514 [LOG_FAC(LOG_LOCAL7)] = "local7"
515 };
516
517 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_facility_unshifted, int, LOG_FAC(~0));
518
519 bool log_facility_unshifted_is_valid(int facility) {
520 return facility >= 0 && facility <= LOG_FAC(~0);
521 }
522
523 static const char *const log_level_table[] = {
524 [LOG_EMERG] = "emerg",
525 [LOG_ALERT] = "alert",
526 [LOG_CRIT] = "crit",
527 [LOG_ERR] = "err",
528 [LOG_WARNING] = "warning",
529 [LOG_NOTICE] = "notice",
530 [LOG_INFO] = "info",
531 [LOG_DEBUG] = "debug"
532 };
533
534 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_level, int, LOG_DEBUG);
535
536 bool log_level_is_valid(int level) {
537 return level >= 0 && level <= LOG_DEBUG;
538 }
539
540 static const char* const sched_policy_table[] = {
541 [SCHED_OTHER] = "other",
542 [SCHED_BATCH] = "batch",
543 [SCHED_IDLE] = "idle",
544 [SCHED_FIFO] = "fifo",
545 [SCHED_RR] = "rr"
546 };
547
548 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(sched_policy, int, INT_MAX);
549
550 bool kexec_loaded(void) {
551 bool loaded = false;
552 char *s;
553
554 if (read_one_line_file("/sys/kernel/kexec_loaded", &s) >= 0) {
555 if (s[0] == '1')
556 loaded = true;
557 free(s);
558 }
559 return loaded;
560 }
561
562 int prot_from_flags(int flags) {
563
564 switch (flags & O_ACCMODE) {
565
566 case O_RDONLY:
567 return PROT_READ;
568
569 case O_WRONLY:
570 return PROT_WRITE;
571
572 case O_RDWR:
573 return PROT_READ|PROT_WRITE;
574
575 default:
576 return -EINVAL;
577 }
578 }
579
580 void* memdup(const void *p, size_t l) {
581 void *r;
582
583 assert(p);
584
585 r = malloc(l);
586 if (!r)
587 return NULL;
588
589 memcpy(r, p, l);
590 return r;
591 }
592
593 int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...) {
594 bool stdout_is_tty, stderr_is_tty;
595 pid_t parent_pid, agent_pid;
596 sigset_t ss, saved_ss;
597 unsigned n, i;
598 va_list ap;
599 char **l;
600
601 assert(pid);
602 assert(path);
603
604 /* Spawns a temporary TTY agent, making sure it goes away when
605 * we go away */
606
607 parent_pid = getpid();
608
609 /* First we temporarily block all signals, so that the new
610 * child has them blocked initially. This way, we can be sure
611 * that SIGTERMs are not lost we might send to the agent. */
612 assert_se(sigfillset(&ss) >= 0);
613 assert_se(sigprocmask(SIG_SETMASK, &ss, &saved_ss) >= 0);
614
615 agent_pid = fork();
616 if (agent_pid < 0) {
617 assert_se(sigprocmask(SIG_SETMASK, &saved_ss, NULL) >= 0);
618 return -errno;
619 }
620
621 if (agent_pid != 0) {
622 assert_se(sigprocmask(SIG_SETMASK, &saved_ss, NULL) >= 0);
623 *pid = agent_pid;
624 return 0;
625 }
626
627 /* In the child:
628 *
629 * Make sure the agent goes away when the parent dies */
630 if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
631 _exit(EXIT_FAILURE);
632
633 /* Make sure we actually can kill the agent, if we need to, in
634 * case somebody invoked us from a shell script that trapped
635 * SIGTERM or so... */
636 (void) reset_all_signal_handlers();
637 (void) reset_signal_mask();
638
639 /* Check whether our parent died before we were able
640 * to set the death signal and unblock the signals */
641 if (getppid() != parent_pid)
642 _exit(EXIT_SUCCESS);
643
644 /* Don't leak fds to the agent */
645 close_all_fds(except, n_except);
646
647 stdout_is_tty = isatty(STDOUT_FILENO);
648 stderr_is_tty = isatty(STDERR_FILENO);
649
650 if (!stdout_is_tty || !stderr_is_tty) {
651 int fd;
652
653 /* Detach from stdout/stderr. and reopen
654 * /dev/tty for them. This is important to
655 * ensure that when systemctl is started via
656 * popen() or a similar call that expects to
657 * read EOF we actually do generate EOF and
658 * not delay this indefinitely by because we
659 * keep an unused copy of stdin around. */
660 fd = open("/dev/tty", O_WRONLY);
661 if (fd < 0) {
662 log_error_errno(errno, "Failed to open /dev/tty: %m");
663 _exit(EXIT_FAILURE);
664 }
665
666 if (!stdout_is_tty)
667 dup2(fd, STDOUT_FILENO);
668
669 if (!stderr_is_tty)
670 dup2(fd, STDERR_FILENO);
671
672 if (fd > 2)
673 close(fd);
674 }
675
676 /* Count arguments */
677 va_start(ap, path);
678 for (n = 0; va_arg(ap, char*); n++)
679 ;
680 va_end(ap);
681
682 /* Allocate strv */
683 l = alloca(sizeof(char *) * (n + 1));
684
685 /* Fill in arguments */
686 va_start(ap, path);
687 for (i = 0; i <= n; i++)
688 l[i] = va_arg(ap, char*);
689 va_end(ap);
690
691 execv(path, l);
692 _exit(EXIT_FAILURE);
693 }
694
695 bool http_etag_is_valid(const char *etag) {
696 if (isempty(etag))
697 return false;
698
699 if (!endswith(etag, "\""))
700 return false;
701
702 if (!startswith(etag, "\"") && !startswith(etag, "W/\""))
703 return false;
704
705 return true;
706 }
707
708 bool http_url_is_valid(const char *url) {
709 const char *p;
710
711 if (isempty(url))
712 return false;
713
714 p = startswith(url, "http://");
715 if (!p)
716 p = startswith(url, "https://");
717 if (!p)
718 return false;
719
720 if (isempty(p))
721 return false;
722
723 return ascii_is_valid(p);
724 }
725
726 bool documentation_url_is_valid(const char *url) {
727 const char *p;
728
729 if (isempty(url))
730 return false;
731
732 if (http_url_is_valid(url))
733 return true;
734
735 p = startswith(url, "file:/");
736 if (!p)
737 p = startswith(url, "info:");
738 if (!p)
739 p = startswith(url, "man:");
740
741 if (isempty(p))
742 return false;
743
744 return ascii_is_valid(p);
745 }
746
747 bool in_initrd(void) {
748 static int saved = -1;
749 struct statfs s;
750
751 if (saved >= 0)
752 return saved;
753
754 /* We make two checks here:
755 *
756 * 1. the flag file /etc/initrd-release must exist
757 * 2. the root file system must be a memory file system
758 *
759 * The second check is extra paranoia, since misdetecting an
760 * initrd can have bad bad consequences due the initrd
761 * emptying when transititioning to the main systemd.
762 */
763
764 saved = access("/etc/initrd-release", F_OK) >= 0 &&
765 statfs("/", &s) >= 0 &&
766 is_temporary_fs(&s);
767
768 return saved;
769 }
770
771 /* hey glibc, APIs with callbacks without a user pointer are so useless */
772 void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size,
773 int (*compar) (const void *, const void *, void *), void *arg) {
774 size_t l, u, idx;
775 const void *p;
776 int comparison;
777
778 l = 0;
779 u = nmemb;
780 while (l < u) {
781 idx = (l + u) / 2;
782 p = (void *)(((const char *) base) + (idx * size));
783 comparison = compar(key, p, arg);
784 if (comparison < 0)
785 u = idx;
786 else if (comparison > 0)
787 l = idx + 1;
788 else
789 return (void *)p;
790 }
791 return NULL;
792 }
793
794 int on_ac_power(void) {
795 bool found_offline = false, found_online = false;
796 _cleanup_closedir_ DIR *d = NULL;
797
798 d = opendir("/sys/class/power_supply");
799 if (!d)
800 return errno == ENOENT ? true : -errno;
801
802 for (;;) {
803 struct dirent *de;
804 _cleanup_close_ int fd = -1, device = -1;
805 char contents[6];
806 ssize_t n;
807
808 errno = 0;
809 de = readdir(d);
810 if (!de && errno != 0)
811 return -errno;
812
813 if (!de)
814 break;
815
816 if (hidden_file(de->d_name))
817 continue;
818
819 device = openat(dirfd(d), de->d_name, O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_NOCTTY);
820 if (device < 0) {
821 if (errno == ENOENT || errno == ENOTDIR)
822 continue;
823
824 return -errno;
825 }
826
827 fd = openat(device, "type", O_RDONLY|O_CLOEXEC|O_NOCTTY);
828 if (fd < 0) {
829 if (errno == ENOENT)
830 continue;
831
832 return -errno;
833 }
834
835 n = read(fd, contents, sizeof(contents));
836 if (n < 0)
837 return -errno;
838
839 if (n != 6 || memcmp(contents, "Mains\n", 6))
840 continue;
841
842 safe_close(fd);
843 fd = openat(device, "online", O_RDONLY|O_CLOEXEC|O_NOCTTY);
844 if (fd < 0) {
845 if (errno == ENOENT)
846 continue;
847
848 return -errno;
849 }
850
851 n = read(fd, contents, sizeof(contents));
852 if (n < 0)
853 return -errno;
854
855 if (n != 2 || contents[1] != '\n')
856 return -EIO;
857
858 if (contents[0] == '1') {
859 found_online = true;
860 break;
861 } else if (contents[0] == '0')
862 found_offline = true;
863 else
864 return -EIO;
865 }
866
867 return found_online || !found_offline;
868 }
869
870 void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size) {
871 size_t a, newalloc;
872 void *q;
873
874 assert(p);
875 assert(allocated);
876
877 if (*allocated >= need)
878 return *p;
879
880 newalloc = MAX(need * 2, 64u / size);
881 a = newalloc * size;
882
883 /* check for overflows */
884 if (a < size * need)
885 return NULL;
886
887 q = realloc(*p, a);
888 if (!q)
889 return NULL;
890
891 *p = q;
892 *allocated = newalloc;
893 return q;
894 }
895
896 void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size) {
897 size_t prev;
898 uint8_t *q;
899
900 assert(p);
901 assert(allocated);
902
903 prev = *allocated;
904
905 q = greedy_realloc(p, allocated, need, size);
906 if (!q)
907 return NULL;
908
909 if (*allocated > prev)
910 memzero(q + prev * size, (*allocated - prev) * size);
911
912 return q;
913 }
914
915 bool id128_is_valid(const char *s) {
916 size_t i, l;
917
918 l = strlen(s);
919 if (l == 32) {
920
921 /* Simple formatted 128bit hex string */
922
923 for (i = 0; i < l; i++) {
924 char c = s[i];
925
926 if (!(c >= '0' && c <= '9') &&
927 !(c >= 'a' && c <= 'z') &&
928 !(c >= 'A' && c <= 'Z'))
929 return false;
930 }
931
932 } else if (l == 36) {
933
934 /* Formatted UUID */
935
936 for (i = 0; i < l; i++) {
937 char c = s[i];
938
939 if ((i == 8 || i == 13 || i == 18 || i == 23)) {
940 if (c != '-')
941 return false;
942 } else {
943 if (!(c >= '0' && c <= '9') &&
944 !(c >= 'a' && c <= 'z') &&
945 !(c >= 'A' && c <= 'Z'))
946 return false;
947 }
948 }
949
950 } else
951 return false;
952
953 return true;
954 }
955
956 int container_get_leader(const char *machine, pid_t *pid) {
957 _cleanup_free_ char *s = NULL, *class = NULL;
958 const char *p;
959 pid_t leader;
960 int r;
961
962 assert(machine);
963 assert(pid);
964
965 if (!machine_name_is_valid(machine))
966 return -EINVAL;
967
968 p = strjoina("/run/systemd/machines/", machine);
969 r = parse_env_file(p, NEWLINE, "LEADER", &s, "CLASS", &class, NULL);
970 if (r == -ENOENT)
971 return -EHOSTDOWN;
972 if (r < 0)
973 return r;
974 if (!s)
975 return -EIO;
976
977 if (!streq_ptr(class, "container"))
978 return -EIO;
979
980 r = parse_pid(s, &leader);
981 if (r < 0)
982 return r;
983 if (leader <= 1)
984 return -EIO;
985
986 *pid = leader;
987 return 0;
988 }
989
990 int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *userns_fd, int *root_fd) {
991 _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, netnsfd = -1, usernsfd = -1;
992 int rfd = -1;
993
994 assert(pid >= 0);
995
996 if (mntns_fd) {
997 const char *mntns;
998
999 mntns = procfs_file_alloca(pid, "ns/mnt");
1000 mntnsfd = open(mntns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
1001 if (mntnsfd < 0)
1002 return -errno;
1003 }
1004
1005 if (pidns_fd) {
1006 const char *pidns;
1007
1008 pidns = procfs_file_alloca(pid, "ns/pid");
1009 pidnsfd = open(pidns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
1010 if (pidnsfd < 0)
1011 return -errno;
1012 }
1013
1014 if (netns_fd) {
1015 const char *netns;
1016
1017 netns = procfs_file_alloca(pid, "ns/net");
1018 netnsfd = open(netns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
1019 if (netnsfd < 0)
1020 return -errno;
1021 }
1022
1023 if (userns_fd) {
1024 const char *userns;
1025
1026 userns = procfs_file_alloca(pid, "ns/user");
1027 usernsfd = open(userns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
1028 if (usernsfd < 0 && errno != ENOENT)
1029 return -errno;
1030 }
1031
1032 if (root_fd) {
1033 const char *root;
1034
1035 root = procfs_file_alloca(pid, "root");
1036 rfd = open(root, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
1037 if (rfd < 0)
1038 return -errno;
1039 }
1040
1041 if (pidns_fd)
1042 *pidns_fd = pidnsfd;
1043
1044 if (mntns_fd)
1045 *mntns_fd = mntnsfd;
1046
1047 if (netns_fd)
1048 *netns_fd = netnsfd;
1049
1050 if (userns_fd)
1051 *userns_fd = usernsfd;
1052
1053 if (root_fd)
1054 *root_fd = rfd;
1055
1056 pidnsfd = mntnsfd = netnsfd = usernsfd = -1;
1057
1058 return 0;
1059 }
1060
1061 int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd) {
1062 if (userns_fd >= 0) {
1063 /* Can't setns to your own userns, since then you could
1064 * escalate from non-root to root in your own namespace, so
1065 * check if namespaces equal before attempting to enter. */
1066 _cleanup_free_ char *userns_fd_path = NULL;
1067 int r;
1068 if (asprintf(&userns_fd_path, "/proc/self/fd/%d", userns_fd) < 0)
1069 return -ENOMEM;
1070
1071 r = files_same(userns_fd_path, "/proc/self/ns/user");
1072 if (r < 0)
1073 return r;
1074 if (r)
1075 userns_fd = -1;
1076 }
1077
1078 if (pidns_fd >= 0)
1079 if (setns(pidns_fd, CLONE_NEWPID) < 0)
1080 return -errno;
1081
1082 if (mntns_fd >= 0)
1083 if (setns(mntns_fd, CLONE_NEWNS) < 0)
1084 return -errno;
1085
1086 if (netns_fd >= 0)
1087 if (setns(netns_fd, CLONE_NEWNET) < 0)
1088 return -errno;
1089
1090 if (userns_fd >= 0)
1091 if (setns(userns_fd, CLONE_NEWUSER) < 0)
1092 return -errno;
1093
1094 if (root_fd >= 0) {
1095 if (fchdir(root_fd) < 0)
1096 return -errno;
1097
1098 if (chroot(".") < 0)
1099 return -errno;
1100 }
1101
1102 return reset_uid_gid();
1103 }
1104
1105 unsigned long personality_from_string(const char *p) {
1106
1107 /* Parse a personality specifier. We introduce our own
1108 * identifiers that indicate specific ABIs, rather than just
1109 * hints regarding the register size, since we want to keep
1110 * things open for multiple locally supported ABIs for the
1111 * same register size. We try to reuse the ABI identifiers
1112 * used by libseccomp. */
1113
1114 #if defined(__x86_64__)
1115
1116 if (streq(p, "x86"))
1117 return PER_LINUX32;
1118
1119 if (streq(p, "x86-64"))
1120 return PER_LINUX;
1121
1122 #elif defined(__i386__)
1123
1124 if (streq(p, "x86"))
1125 return PER_LINUX;
1126
1127 #elif defined(__s390x__)
1128
1129 if (streq(p, "s390"))
1130 return PER_LINUX32;
1131
1132 if (streq(p, "s390x"))
1133 return PER_LINUX;
1134
1135 #elif defined(__s390__)
1136
1137 if (streq(p, "s390"))
1138 return PER_LINUX;
1139 #endif
1140
1141 return PERSONALITY_INVALID;
1142 }
1143
1144 const char* personality_to_string(unsigned long p) {
1145
1146 #if defined(__x86_64__)
1147
1148 if (p == PER_LINUX32)
1149 return "x86";
1150
1151 if (p == PER_LINUX)
1152 return "x86-64";
1153
1154 #elif defined(__i386__)
1155
1156 if (p == PER_LINUX)
1157 return "x86";
1158
1159 #elif defined(__s390x__)
1160
1161 if (p == PER_LINUX)
1162 return "s390x";
1163
1164 if (p == PER_LINUX32)
1165 return "s390";
1166
1167 #elif defined(__s390__)
1168
1169 if (p == PER_LINUX)
1170 return "s390";
1171
1172 #endif
1173
1174 return NULL;
1175 }
1176
1177 uint64_t physical_memory(void) {
1178 long mem;
1179
1180 /* We return this as uint64_t in case we are running as 32bit
1181 * process on a 64bit kernel with huge amounts of memory */
1182
1183 mem = sysconf(_SC_PHYS_PAGES);
1184 assert(mem > 0);
1185
1186 return (uint64_t) mem * (uint64_t) page_size();
1187 }
1188
1189 int update_reboot_param_file(const char *param) {
1190 int r = 0;
1191
1192 if (param) {
1193 r = write_string_file(REBOOT_PARAM_FILE, param, WRITE_STRING_FILE_CREATE);
1194 if (r < 0)
1195 return log_error_errno(r, "Failed to write reboot param to "REBOOT_PARAM_FILE": %m");
1196 } else
1197 (void) unlink(REBOOT_PARAM_FILE);
1198
1199 return 0;
1200 }
1201
1202 int syslog_parse_priority(const char **p, int *priority, bool with_facility) {
1203 int a = 0, b = 0, c = 0;
1204 int k;
1205
1206 assert(p);
1207 assert(*p);
1208 assert(priority);
1209
1210 if ((*p)[0] != '<')
1211 return 0;
1212
1213 if (!strchr(*p, '>'))
1214 return 0;
1215
1216 if ((*p)[2] == '>') {
1217 c = undecchar((*p)[1]);
1218 k = 3;
1219 } else if ((*p)[3] == '>') {
1220 b = undecchar((*p)[1]);
1221 c = undecchar((*p)[2]);
1222 k = 4;
1223 } else if ((*p)[4] == '>') {
1224 a = undecchar((*p)[1]);
1225 b = undecchar((*p)[2]);
1226 c = undecchar((*p)[3]);
1227 k = 5;
1228 } else
1229 return 0;
1230
1231 if (a < 0 || b < 0 || c < 0 ||
1232 (!with_facility && (a || b || c > 7)))
1233 return 0;
1234
1235 if (with_facility)
1236 *priority = a*100 + b*10 + c;
1237 else
1238 *priority = (*priority & LOG_FACMASK) | c;
1239
1240 *p += k;
1241 return 1;
1242 }
1243
1244 int version(void) {
1245 puts(PACKAGE_STRING "\n"
1246 SYSTEMD_FEATURES);
1247 return 0;
1248 }
1249
1250 bool fdname_is_valid(const char *s) {
1251 const char *p;
1252
1253 /* Validates a name for $LISTEN_FDNAMES. We basically allow
1254 * everything ASCII that's not a control character. Also, as
1255 * special exception the ":" character is not allowed, as we
1256 * use that as field separator in $LISTEN_FDNAMES.
1257 *
1258 * Note that the empty string is explicitly allowed
1259 * here. However, we limit the length of the names to 255
1260 * characters. */
1261
1262 if (!s)
1263 return false;
1264
1265 for (p = s; *p; p++) {
1266 if (*p < ' ')
1267 return false;
1268 if (*p >= 127)
1269 return false;
1270 if (*p == ':')
1271 return false;
1272 }
1273
1274 return p - s < 256;
1275 }
1276
1277 bool oom_score_adjust_is_valid(int oa) {
1278 return oa >= OOM_SCORE_ADJ_MIN && oa <= OOM_SCORE_ADJ_MAX;
1279 }