summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2017-01-14 19:48:04 -0500
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2017-01-14 21:29:27 -0500
commit6b3d378331fe714c7bf2263eaa9a8b33fc878e7c (patch)
tree5fca867e0b2cda62c2dc4f1a9a4bd78ab345b158 /src/core
parentab8864ebc3ac01288729b44f0d5f18fff37defb5 (diff)
parentbafbac4e85a5eefd4b57a5cd0eb61885fb60edc9 (diff)
Merge pull request #4879 from poettering/systemd
Diffstat (limited to 'src/core')
-rw-r--r--src/core/dbus-manager.c34
-rw-r--r--src/core/job.c2
-rw-r--r--src/core/main.c125
-rw-r--r--src/core/mount-setup.c24
4 files changed, 110 insertions, 75 deletions
diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
index 9af49dd1bc..9876251438 100644
--- a/src/core/dbus-manager.c
+++ b/src/core/dbus-manager.c
@@ -35,6 +35,7 @@
#include "fd-util.h"
#include "fileio.h"
#include "format-util.h"
+#include "fs-util.h"
#include "install.h"
#include "log.h"
#include "path-util.h"
@@ -1484,25 +1485,36 @@ static int method_switch_root(sd_bus_message *message, void *userdata, sd_bus_er
if (r < 0)
return r;
- if (path_equal(root, "/") || !path_is_absolute(root))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid switch root path %s", root);
+ if (isempty(root))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "New root directory may not be the empty string.");
+ if (!path_is_absolute(root))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "New root path '%s' is not absolute.", root);
+ if (path_equal(root, "/"))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "New root directory cannot be the old root directory.");
/* Safety check */
if (isempty(init)) {
- if (!path_is_os_tree(root))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified switch root path %s does not seem to be an OS tree. os-release file is missing.", root);
+ r = path_is_os_tree(root);
+ if (r < 0)
+ return sd_bus_error_set_errnof(error, r, "Failed to determine whether root path '%s' contains an OS tree: %m", root);
+ if (r == 0)
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified switch root path '%s' does not seem to be an OS tree. os-release file is missing.", root);
} else {
- _cleanup_free_ char *p = NULL;
+ _cleanup_free_ char *chased = NULL;
if (!path_is_absolute(init))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid init path %s", init);
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path to init binary '%s' not absolute.", init);
- p = strappend(root, init);
- if (!p)
- return -ENOMEM;
+ r = chase_symlinks(init, root, CHASE_PREFIX_ROOT, &chased);
+ if (r < 0)
+ return sd_bus_error_set_errnof(error, r, "Could not resolve init executable %s: %m", init);
+
+ if (laccess(chased, X_OK) < 0) {
+ if (errno == EACCES)
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Init binary %s is not executable.", init);
- if (access(p, X_OK) < 0)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified init binary %s does not exist.", p);
+ return sd_bus_error_set_errnof(error, r, "Could not check whether init binary %s is executable: %m", init);
+ }
}
rt = strdup(root);
diff --git a/src/core/job.c b/src/core/job.c
index 2ba4c78096..f7c4c59c32 100644
--- a/src/core/job.c
+++ b/src/core/job.c
@@ -645,7 +645,7 @@ _pure_ static const char *job_get_status_message_format(Unit *u, JobType t, JobR
[JOB_DEPENDENCY] = "Dependency failed for %s.",
[JOB_ASSERT] = "Assertion failed for %s.",
[JOB_UNSUPPORTED] = "Starting of %s not supported.",
- [JOB_COLLECTED] = "Unecessary job for %s was removed.",
+ [JOB_COLLECTED] = "Unnecessary job for %s was removed.",
};
static const char *const generic_finished_stop_job[_JOB_RESULT_MAX] = {
[JOB_DONE] = "Stopped %s.",
diff --git a/src/core/main.c b/src/core/main.c
index 02992c7324..56a81ab94a 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -49,6 +49,7 @@
#include "cpu-set-util.h"
#include "dbus-manager.h"
#include "def.h"
+#include "emergency-action.h"
#include "env-util.h"
#include "fd-util.h"
#include "fdset.h"
@@ -90,7 +91,6 @@
#include "user-util.h"
#include "virt.h"
#include "watchdog.h"
-#include "emergency-action.h"
static enum {
ACTION_RUN,
@@ -337,60 +337,73 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
assert(key);
- if (streq(key, "systemd.unit") && value) {
-
- if (!in_initrd())
- return free_and_strdup(&arg_default_unit, value);
+ if (STR_IN_SET(key, "systemd.unit", "rd.systemd.unit")) {
- } else if (streq(key, "rd.systemd.unit") && value) {
+ if (proc_cmdline_value_missing(key, value))
+ return 0;
- if (in_initrd())
- return free_and_strdup(&arg_default_unit, value);
+ if (!unit_name_is_valid(value, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE))
+ log_warning("Unit name specified on %s= is not valid, ignoring: %s", key, value);
+ else if (in_initrd() == !!startswith(key, "rd.")) {
+ if (free_and_strdup(&arg_default_unit, value) < 0)
+ return log_oom();
+ }
- } else if (streq(key, "systemd.dump_core") && value) {
+ } else if (proc_cmdline_key_streq(key, "systemd.dump_core")) {
- r = parse_boolean(value);
+ r = value ? parse_boolean(value) : true;
if (r < 0)
log_warning("Failed to parse dump core switch %s. Ignoring.", value);
else
arg_dump_core = r;
- } else if (streq(key, "systemd.crash_chvt") && value) {
+ } else if (proc_cmdline_key_streq(key, "systemd.crash_chvt")) {
- if (parse_crash_chvt(value) < 0)
+ if (!value)
+ arg_crash_chvt = 0; /* turn on */
+ else if (parse_crash_chvt(value) < 0)
log_warning("Failed to parse crash chvt switch %s. Ignoring.", value);
- } else if (streq(key, "systemd.crash_shell") && value) {
+ } else if (proc_cmdline_key_streq(key, "systemd.crash_shell")) {
- r = parse_boolean(value);
+ r = value ? parse_boolean(value) : true;
if (r < 0)
log_warning("Failed to parse crash shell switch %s. Ignoring.", value);
else
arg_crash_shell = r;
- } else if (streq(key, "systemd.crash_reboot") && value) {
+ } else if (proc_cmdline_key_streq(key, "systemd.crash_reboot")) {
- r = parse_boolean(value);
+ r = value ? parse_boolean(value) : true;
if (r < 0)
log_warning("Failed to parse crash reboot switch %s. Ignoring.", value);
else
arg_crash_reboot = r;
- } else if (streq(key, "systemd.confirm_spawn") && value) {
-
- arg_confirm_spawn = mfree(arg_confirm_spawn);
+ } else if (proc_cmdline_key_streq(key, "systemd.confirm_spawn")) {
+ char *s;
- r = parse_confirm_spawn(value, &arg_confirm_spawn);
+ r = parse_confirm_spawn(value, &s);
if (r < 0)
log_warning_errno(r, "Failed to parse confirm_spawn switch %s. Ignoring.", value);
+ else {
+ free(arg_confirm_spawn);
+ arg_confirm_spawn = s;
+ }
- } else if (streq(key, "systemd.show_status") && value) {
+ } else if (proc_cmdline_key_streq(key, "systemd.show_status")) {
- r = parse_show_status(value, &arg_show_status);
- if (r < 0)
- log_warning("Failed to parse show status switch %s. Ignoring.", value);
+ if (value) {
+ r = parse_show_status(value, &arg_show_status);
+ if (r < 0)
+ log_warning("Failed to parse show status switch %s. Ignoring.", value);
+ } else
+ arg_show_status = SHOW_STATUS_YES;
+
+ } else if (proc_cmdline_key_streq(key, "systemd.default_standard_output")) {
- } else if (streq(key, "systemd.default_standard_output") && value) {
+ if (proc_cmdline_value_missing(key, value))
+ return 0;
r = exec_output_from_string(value);
if (r < 0)
@@ -398,7 +411,10 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
else
arg_default_std_output = r;
- } else if (streq(key, "systemd.default_standard_error") && value) {
+ } else if (proc_cmdline_key_streq(key, "systemd.default_standard_error")) {
+
+ if (proc_cmdline_value_missing(key, value))
+ return 0;
r = exec_output_from_string(value);
if (r < 0)
@@ -406,24 +422,42 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
else
arg_default_std_error = r;
- } else if (streq(key, "systemd.setenv") && value) {
+ } else if (streq(key, "systemd.setenv")) {
+
+ if (proc_cmdline_value_missing(key, value))
+ return 0;
if (env_assignment_is_valid(value)) {
char **env;
env = strv_env_set(arg_default_environment, value);
- if (env)
- arg_default_environment = env;
- else
- log_warning_errno(ENOMEM, "Setting environment variable '%s' failed, ignoring: %m", value);
+ if (!env)
+ return log_oom();
+
+ arg_default_environment = env;
} else
log_warning("Environment variable name '%s' is not valid. Ignoring.", value);
- } else if (streq(key, "systemd.machine_id") && value) {
+ } else if (proc_cmdline_key_streq(key, "systemd.machine_id")) {
+
+ if (proc_cmdline_value_missing(key, value))
+ return 0;
+
+ r = set_machine_id(value);
+ if (r < 0)
+ log_warning("MachineID '%s' is not valid. Ignoring.", value);
+
+ } else if (proc_cmdline_key_streq(key, "systemd.default_timeout_start_sec")) {
+
+ if (proc_cmdline_value_missing(key, value))
+ return 0;
+
+ r = parse_sec(value, &arg_default_timeout_start_usec);
+ if (r < 0)
+ log_warning_errno(r, "Failed to parse default start timeout: %s, ignoring.", value);
- r = set_machine_id(value);
- if (r < 0)
- log_warning("MachineID '%s' is not valid. Ignoring.", value);
+ if (arg_default_timeout_start_usec <= 0)
+ arg_default_timeout_start_usec = USEC_INFINITY;
} else if (streq(key, "quiet") && !value) {
@@ -445,15 +479,6 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
target = runlevel_to_target(key);
if (target)
return free_and_strdup(&arg_default_unit, target);
-
- } else if (streq(key, "systemd.default_timeout_start_sec") && value) {
-
- r = parse_sec(value, &arg_default_timeout_start_usec);
- if (r < 0)
- log_warning_errno(r, "Failed to parse default start timeout: %s, ignoring.", value);
-
- if (arg_default_timeout_start_usec <= 0)
- arg_default_timeout_start_usec = USEC_INFINITY;
}
return 0;
@@ -1341,10 +1366,9 @@ static int fixup_environment(void) {
* However if TERM was configured through the kernel
* command line then leave it alone. */
- r = get_proc_cmdline_key("TERM=", &term);
+ r = proc_cmdline_get_key("TERM", 0, &term);
if (r < 0)
return r;
-
if (r == 0) {
term = strdup(default_term_for_tty("/dev/console"));
if (!term)
@@ -1411,7 +1435,7 @@ int main(int argc, char *argv[]) {
called 'systemd'. That is confusing, hence let's call us
systemd right-away. */
program_invocation_short_name = systemd;
- prctl(PR_SET_NAME, systemd);
+ (void) prctl(PR_SET_NAME, systemd);
saved_argv = argv;
saved_argc = argc;
@@ -1435,9 +1459,10 @@ int main(int argc, char *argv[]) {
if (!skip_setup) {
r = mount_setup_early();
if (r < 0) {
- error_message = "Failed to early mount API filesystems";
+ error_message = "Failed to mount early API filesystems";
goto finish;
}
+
dual_timestamp_get(&security_start_timestamp);
if (mac_selinux_setup(&loaded_policy) < 0) {
error_message = "Failed to load SELinux policy";
@@ -1513,7 +1538,7 @@ int main(int argc, char *argv[]) {
log_close_console(); /* force reopen of /dev/console */
log_open();
- /* For the later on, see above... */
+ /* For later on, see above... */
log_set_target(LOG_TARGET_JOURNAL);
/* clear the kernel timestamp,
@@ -1590,7 +1615,7 @@ int main(int argc, char *argv[]) {
}
if (arg_system) {
- r = parse_proc_cmdline(parse_proc_cmdline_item, NULL, false);
+ r = proc_cmdline_parse(parse_proc_cmdline_item, NULL, 0);
if (r < 0)
log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m");
}
diff --git a/src/core/mount-setup.c b/src/core/mount-setup.c
index 6338067d7e..9c2bf3a0ef 100644
--- a/src/core/mount-setup.c
+++ b/src/core/mount-setup.c
@@ -360,7 +360,6 @@ int mount_setup(bool loaded_policy) {
int r = 0;
r = mount_points_setup(ELEMENTSOF(mount_table), loaded_policy);
-
if (r < 0)
return r;
@@ -391,25 +390,24 @@ int mount_setup(bool loaded_policy) {
* udevd. */
dev_setup(NULL, UID_INVALID, GID_INVALID);
- /* Mark the root directory as shared in regards to mount
- * propagation. The kernel defaults to "private", but we think
- * it makes more sense to have a default of "shared" so that
- * nspawn and the container tools work out of the box. If
- * specific setups need other settings they can reset the
- * propagation mode to private if needed. */
+ /* Mark the root directory as shared in regards to mount propagation. The kernel defaults to "private", but we
+ * think it makes more sense to have a default of "shared" so that nspawn and the container tools work out of
+ * the box. If specific setups need other settings they can reset the propagation mode to private if
+ * needed. Note that we set this only when we are invoked directly by the kernel. If we are invoked by a
+ * container manager we assume the container manager knows what it is doing (for example, because it set up
+ * some directories with different propagation modes). */
if (detect_container() <= 0)
if (mount(NULL, "/", NULL, MS_REC|MS_SHARED, NULL) < 0)
log_warning_errno(errno, "Failed to set up the root directory for shared mount propagation: %m");
- /* Create a few directories we always want around, Note that
- * sd_booted() checks for /run/systemd/system, so this mkdir
- * really needs to stay for good, otherwise software that
- * copied sd-daemon.c into their sources will misdetect
- * systemd. */
+ /* Create a few directories we always want around, Note that sd_booted() checks for /run/systemd/system, so
+ * this mkdir really needs to stay for good, otherwise software that copied sd-daemon.c into their sources will
+ * misdetect systemd. */
(void) mkdir_label("/run/systemd", 0755);
(void) mkdir_label("/run/systemd/system", 0755);
- (void) mkdir_label("/run/systemd/inaccessible", 0000);
+
/* Set up inaccessible items */
+ (void) mkdir_label("/run/systemd/inaccessible", 0000);
(void) mknod("/run/systemd/inaccessible/reg", S_IFREG | 0000, 0);
(void) mkdir_label("/run/systemd/inaccessible/dir", 0000);
(void) mknod("/run/systemd/inaccessible/chr", S_IFCHR | 0000, makedev(0, 0));