1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
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.
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.
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/>.
30 #include <linux/magic.h>
31 #include <linux/oom.h>
32 #include <linux/sched.h>
43 #include <sys/ioctl.h>
45 #include <sys/mount.h>
46 #include <sys/personality.h>
47 #include <sys/prctl.h>
49 #include <sys/statvfs.h>
51 #include <sys/types.h>
52 #include <sys/utsname.h>
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(). */
64 #ifdef HAVE_SYS_AUXV_H
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! */
72 #include "alloc-util.h"
75 #include "device-nodes.h"
78 #include "exit-status.h"
81 #include "formats-util.h"
84 #include "hostname-util.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"
100 #include "terminal-util.h"
101 #include "user-util.h"
105 #include "dirent-util.h"
106 #include "stat-util.h"
108 /* Put this test here for a lack of better place */
109 assert_cc(EAGAIN
== EWOULDBLOCK
);
112 char **saved_argv
= NULL
;
114 size_t page_size(void) {
115 static thread_local
size_t pgsz
= 0;
118 if (_likely_(pgsz
> 0))
121 r
= sysconf(_SC_PAGESIZE
);
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
;
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 */
136 (void) reset_all_signal_handlers();
137 (void) reset_signal_mask();
139 assert_se(prctl(PR_SET_PDEATHSIG
, SIGTERM
) == 0);
141 pids
= hashmap_new(NULL
);
145 seen
= set_new(&string_hash_ops
);
149 STRV_FOREACH(directory
, directories
) {
150 _cleanup_closedir_
DIR *d
;
153 d
= opendir(*directory
);
158 return log_error_errno(errno
, "Failed to open directory %s: %m", *directory
);
161 FOREACH_DIRENT(de
, d
, break) {
162 _cleanup_free_
char *path
= NULL
;
166 if (!dirent_is_file(de
))
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
);
174 r
= set_put_strdup(seen
, de
->d_name
);
178 path
= strjoin(*directory
, "/", de
->d_name
, NULL
);
182 if (null_or_empty_path(path
)) {
183 log_debug("%s is empty (a mask).", path
);
189 log_error_errno(errno
, "Failed to fork: %m");
191 } else if (pid
== 0) {
194 assert_se(prctl(PR_SET_PDEATHSIG
, SIGTERM
) == 0);
204 return log_error_errno(errno
, "Failed to execute %s: %m", path
);
207 log_debug("Spawned %s as " PID_FMT
".", path
, pid
);
209 r
= hashmap_put(pids
, UINT_TO_PTR(pid
), path
);
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(). */
220 if (timeout
!= USEC_INFINITY
)
221 alarm((timeout
+ USEC_PER_SEC
- 1) / USEC_PER_SEC
);
223 while (!hashmap_isempty(pids
)) {
224 _cleanup_free_
char *path
= NULL
;
227 pid
= PTR_TO_UINT(hashmap_first_key(pids
));
230 path
= hashmap_remove(pids
, UINT_TO_PTR(pid
));
233 wait_for_terminate_and_warn(path
, pid
, true);
239 void execute_directories(const char* const* directories
, usec_t timeout
, char *argv
[]) {
243 char **dirs
= (char**) directories
;
245 assert(!strv_isempty(dirs
));
247 name
= basename(dirs
[0]);
248 assert(!isempty(name
));
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. */
255 executor_pid
= fork();
256 if (executor_pid
< 0) {
257 log_error_errno(errno
, "Failed to fork: %m");
260 } else if (executor_pid
== 0) {
261 r
= do_execute(dirs
, timeout
, argv
);
262 _exit(r
< 0 ? EXIT_FAILURE
: EXIT_SUCCESS
);
265 wait_for_terminate_and_warn(name
, executor_pid
, true);
268 bool plymouth_running(void) {
269 return access("/run/plymouth/pid", F_OK
) >= 0;
272 bool display_is_local(const char *display
) {
281 int socket_from_display(const char *display
, char **path
) {
288 if (!display_is_local(display
))
291 k
= strspn(display
+1, "0123456789");
293 f
= new(char, strlen("/tmp/.X11-unix/X") + k
+ 1);
297 c
= stpcpy(f
, "/tmp/.X11-unix/X");
298 memcpy(c
, display
+1, k
);
306 int block_get_whole_disk(dev_t d
, dev_t
*ret
) {
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)
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)
335 /* Get parent dev_t */
336 if (asprintf(&p
, "/sys/dev/block/%u:%u/../dev", major(d
), minor(d
)) < 0)
339 r
= read_one_line_file(p
, &s
);
345 r
= sscanf(s
, "%u:%u", &m
, &n
);
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)
359 *ret
= makedev(m
, n
);
366 bool kexec_loaded(void) {
370 if (read_one_line_file("/sys/kernel/kexec_loaded", &s
) >= 0) {
378 int prot_from_flags(int flags
) {
380 switch (flags
& O_ACCMODE
) {
389 return PROT_READ
|PROT_WRITE
;
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
;
407 /* Spawns a temporary TTY agent, making sure it goes away when
410 parent_pid
= getpid();
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);
420 assert_se(sigprocmask(SIG_SETMASK
, &saved_ss
, NULL
) >= 0);
424 if (agent_pid
!= 0) {
425 assert_se(sigprocmask(SIG_SETMASK
, &saved_ss
, NULL
) >= 0);
432 * Make sure the agent goes away when the parent dies */
433 if (prctl(PR_SET_PDEATHSIG
, SIGTERM
) < 0)
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();
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
)
447 /* Don't leak fds to the agent */
448 close_all_fds(except
, n_except
);
450 stdout_is_tty
= isatty(STDOUT_FILENO
);
451 stderr_is_tty
= isatty(STDERR_FILENO
);
453 if (!stdout_is_tty
|| !stderr_is_tty
) {
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
);
465 log_error_errno(errno
, "Failed to open /dev/tty: %m");
470 dup2(fd
, STDOUT_FILENO
);
473 dup2(fd
, STDERR_FILENO
);
479 /* Count arguments */
481 for (n
= 0; va_arg(ap
, char*); n
++)
486 l
= alloca(sizeof(char *) * (n
+ 1));
488 /* Fill in arguments */
490 for (i
= 0; i
<= n
; i
++)
491 l
[i
] = va_arg(ap
, char*);
498 bool in_initrd(void) {
499 static int saved
= -1;
505 /* We make two checks here:
507 * 1. the flag file /etc/initrd-release must exist
508 * 2. the root file system must be a memory file system
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.
515 saved
= access("/etc/initrd-release", F_OK
) >= 0 &&
516 statfs("/", &s
) >= 0 &&
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
) {
533 p
= (void *)(((const char *) base
) + (idx
* size
));
534 comparison
= compar(key
, p
, arg
);
537 else if (comparison
> 0)
545 int on_ac_power(void) {
546 bool found_offline
= false, found_online
= false;
547 _cleanup_closedir_
DIR *d
= NULL
;
549 d
= opendir("/sys/class/power_supply");
551 return errno
== ENOENT
? true : -errno
;
555 _cleanup_close_
int fd
= -1, device
= -1;
561 if (!de
&& errno
!= 0)
567 if (hidden_file(de
->d_name
))
570 device
= openat(dirfd(d
), de
->d_name
, O_DIRECTORY
|O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
572 if (errno
== ENOENT
|| errno
== ENOTDIR
)
578 fd
= openat(device
, "type", O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
586 n
= read(fd
, contents
, sizeof(contents
));
590 if (n
!= 6 || memcmp(contents
, "Mains\n", 6))
594 fd
= openat(device
, "online", O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
602 n
= read(fd
, contents
, sizeof(contents
));
606 if (n
!= 2 || contents
[1] != '\n')
609 if (contents
[0] == '1') {
612 } else if (contents
[0] == '0')
613 found_offline
= true;
618 return found_online
|| !found_offline
;
621 bool id128_is_valid(const char *s
) {
627 /* Simple formatted 128bit hex string */
629 for (i
= 0; i
< l
; i
++) {
632 if (!(c
>= '0' && c
<= '9') &&
633 !(c
>= 'a' && c
<= 'z') &&
634 !(c
>= 'A' && c
<= 'Z'))
638 } else if (l
== 36) {
642 for (i
= 0; i
< l
; i
++) {
645 if ((i
== 8 || i
== 13 || i
== 18 || i
== 23)) {
649 if (!(c
>= '0' && c
<= '9') &&
650 !(c
>= 'a' && c
<= 'z') &&
651 !(c
>= 'A' && c
<= 'Z'))
662 int container_get_leader(const char *machine
, pid_t
*pid
) {
663 _cleanup_free_
char *s
= NULL
, *class = NULL
;
671 if (!machine_name_is_valid(machine
))
674 p
= strjoina("/run/systemd/machines/", machine
);
675 r
= parse_env_file(p
, NEWLINE
, "LEADER", &s
, "CLASS", &class, NULL
);
683 if (!streq_ptr(class, "container"))
686 r
= parse_pid(s
, &leader
);
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;
705 mntns
= procfs_file_alloca(pid
, "ns/mnt");
706 mntnsfd
= open(mntns
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
);
714 pidns
= procfs_file_alloca(pid
, "ns/pid");
715 pidnsfd
= open(pidns
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
);
723 netns
= procfs_file_alloca(pid
, "ns/net");
724 netnsfd
= open(netns
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
);
732 userns
= procfs_file_alloca(pid
, "ns/user");
733 usernsfd
= open(userns
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
);
734 if (usernsfd
< 0 && errno
!= ENOENT
)
741 root
= procfs_file_alloca(pid
, "root");
742 rfd
= open(root
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
|O_DIRECTORY
);
757 *userns_fd
= usernsfd
;
762 pidnsfd
= mntnsfd
= netnsfd
= usernsfd
= -1;
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
;
774 if (asprintf(&userns_fd_path
, "/proc/self/fd/%d", userns_fd
) < 0)
777 r
= files_same(userns_fd_path
, "/proc/self/ns/user");
785 if (setns(pidns_fd
, CLONE_NEWPID
) < 0)
789 if (setns(mntns_fd
, CLONE_NEWNS
) < 0)
793 if (setns(netns_fd
, CLONE_NEWNET
) < 0)
797 if (setns(userns_fd
, CLONE_NEWUSER
) < 0)
801 if (fchdir(root_fd
) < 0)
808 return reset_uid_gid();
811 uint64_t physical_memory(void) {
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 */
817 mem
= sysconf(_SC_PHYS_PAGES
);
820 return (uint64_t) mem
* (uint64_t) page_size();
823 int update_reboot_param_file(const char *param
) {
827 r
= write_string_file(REBOOT_PARAM_FILE
, param
, WRITE_STRING_FILE_CREATE
);
829 return log_error_errno(r
, "Failed to write reboot param to "REBOOT_PARAM_FILE
": %m");
831 (void) unlink(REBOOT_PARAM_FILE
);
837 puts(PACKAGE_STRING
"\n"