1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 
3 #include <errno.h>
4 #include <fcntl.h>
5 #include <sys/mman.h>
6 
7 #include "alloc-util.h"
8 #include "build.h"
9 #include "env-file.h"
10 #include "env-util.h"
11 #include "fd-util.h"
12 #include "fileio.h"
13 #include "hostname-util.h"
14 #include "log.h"
15 #include "macro.h"
16 #include "parse-util.h"
17 #include "stat-util.h"
18 #include "string-util.h"
19 #include "util.h"
20 #include "virt.h"
21 
22 int saved_argc = 0;
23 char **saved_argv = NULL;
24 static int saved_in_initrd = -1;
25 
kexec_loaded(void)26 bool kexec_loaded(void) {
27        _cleanup_free_ char *s = NULL;
28 
29        if (read_one_line_file("/sys/kernel/kexec_loaded", &s) < 0)
30                return false;
31 
32        return s[0] == '1';
33 }
34 
prot_from_flags(int flags)35 int prot_from_flags(int flags) {
36 
37         switch (flags & O_ACCMODE) {
38 
39         case O_RDONLY:
40                 return PROT_READ;
41 
42         case O_WRONLY:
43                 return PROT_WRITE;
44 
45         case O_RDWR:
46                 return PROT_READ|PROT_WRITE;
47 
48         default:
49                 return -EINVAL;
50         }
51 }
52 
in_initrd(void)53 bool in_initrd(void) {
54         int r;
55         const char *e;
56         bool lenient = false;
57 
58         if (saved_in_initrd >= 0)
59                 return saved_in_initrd;
60 
61         /* We have two checks here:
62          *
63          * 1. the flag file /etc/initrd-release must exist
64          * 2. the root file system must be a memory file system
65          *
66          * The second check is extra paranoia, since misdetecting an
67          * initrd can have bad consequences due the initrd
68          * emptying when transititioning to the main systemd.
69          *
70          * If env var $SYSTEMD_IN_INITRD is not set or set to "auto",
71          * both checks are used. If it's set to "lenient", only check
72          * 1 is used. If set to a boolean value, then the boolean
73          * value is returned.
74          */
75 
76         e = secure_getenv("SYSTEMD_IN_INITRD");
77         if (e) {
78                 if (streq(e, "lenient"))
79                         lenient = true;
80                 else if (!streq(e, "auto")) {
81                         r = parse_boolean(e);
82                         if (r >= 0) {
83                                 saved_in_initrd = r > 0;
84                                 return saved_in_initrd;
85                         }
86                         log_debug_errno(r, "Failed to parse $SYSTEMD_IN_INITRD, ignoring: %m");
87                 }
88         }
89 
90         if (!lenient) {
91                 r = path_is_temporary_fs("/");
92                 if (r < 0)
93                         log_debug_errno(r, "Couldn't determine if / is a temporary file system: %m");
94 
95                 saved_in_initrd = r > 0;
96         }
97 
98         r = access("/etc/initrd-release", F_OK);
99         if (r >= 0) {
100                 if (saved_in_initrd == 0)
101                         log_debug("/etc/initrd-release exists, but it's not an initrd.");
102                 else
103                         saved_in_initrd = 1;
104         } else {
105                 if (errno != ENOENT)
106                         log_debug_errno(errno, "Failed to test if /etc/initrd-release exists: %m");
107                 saved_in_initrd = 0;
108         }
109 
110         return saved_in_initrd;
111 }
112 
in_initrd_force(bool value)113 void in_initrd_force(bool value) {
114         saved_in_initrd = value;
115 }
116 
container_get_leader(const char * machine,pid_t * pid)117 int container_get_leader(const char *machine, pid_t *pid) {
118         _cleanup_free_ char *s = NULL, *class = NULL;
119         const char *p;
120         pid_t leader;
121         int r;
122 
123         assert(machine);
124         assert(pid);
125 
126         if (streq(machine, ".host")) {
127                 *pid = 1;
128                 return 0;
129         }
130 
131         if (!hostname_is_valid(machine, 0))
132                 return -EINVAL;
133 
134         p = strjoina("/run/systemd/machines/", machine);
135         r = parse_env_file(NULL, p,
136                            "LEADER", &s,
137                            "CLASS", &class);
138         if (r == -ENOENT)
139                 return -EHOSTDOWN;
140         if (r < 0)
141                 return r;
142         if (!s)
143                 return -EIO;
144 
145         if (!streq_ptr(class, "container"))
146                 return -EIO;
147 
148         r = parse_pid(s, &leader);
149         if (r < 0)
150                 return r;
151         if (leader <= 1)
152                 return -EIO;
153 
154         *pid = leader;
155         return 0;
156 }
157 
version(void)158 int version(void) {
159         printf("systemd " STRINGIFY(PROJECT_VERSION) " (" GIT_VERSION ")\n%s\n",
160                systemd_features);
161         return 0;
162 }
163 
164 /* Turn off core dumps but only if we're running outside of a container. */
disable_coredumps(void)165 void disable_coredumps(void) {
166         int r;
167 
168         if (detect_container() > 0)
169                 return;
170 
171         r = write_string_file("/proc/sys/kernel/core_pattern", "|/bin/false", WRITE_STRING_FILE_DISABLE_BUFFER);
172         if (r < 0)
173                 log_debug_errno(r, "Failed to turn off coredumps, ignoring: %m");
174 }
175