summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/dbus-execute.c4
-rw-r--r--src/core/device.c19
-rw-r--r--src/core/execute.c37
-rw-r--r--src/core/killall.c21
-rw-r--r--src/core/load-fragment.c11
-rw-r--r--src/core/main.c9
-rw-r--r--src/core/manager.c2
-rw-r--r--src/core/service.c2
-rw-r--r--src/core/transaction.c27
9 files changed, 74 insertions, 58 deletions
diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c
index c2238c8c43..eae0808f9e 100644
--- a/src/core/dbus-execute.c
+++ b/src/core/dbus-execute.c
@@ -141,7 +141,7 @@ static int property_get_nice(
else {
errno = 0;
n = getpriority(PRIO_PROCESS, 0);
- if (errno != 0)
+ if (errno > 0)
n = 0;
}
@@ -1382,7 +1382,7 @@ int bus_exec_context_set_transient_property(
dirs = &c->read_write_dirs;
else if (streq(name, "ReadOnlyDirectories"))
dirs = &c->read_only_dirs;
- else if (streq(name, "InaccessibleDirectories"))
+ else /* "InaccessibleDirectories" */
dirs = &c->inaccessible_dirs;
if (strv_length(l) == 0) {
diff --git a/src/core/device.c b/src/core/device.c
index 56ed947089..807547c87f 100644
--- a/src/core/device.c
+++ b/src/core/device.c
@@ -315,12 +315,19 @@ static int device_setup_unit(Manager *m, struct udev_device *dev, const char *pa
u = manager_get_unit(m, e);
- if (u &&
- sysfs &&
- DEVICE(u)->sysfs &&
- !path_equal(DEVICE(u)->sysfs, sysfs)) {
- log_unit_debug(u, "Device %s appeared twice with different sysfs paths %s and %s", e, DEVICE(u)->sysfs, sysfs);
- return -EEXIST;
+ /* The device unit can still be present even if the device was
+ * unplugged: a mount unit can reference it hence preventing
+ * the GC to have garbaged it. That's desired since the device
+ * unit may have a dependency on the mount unit which was
+ * added during the loading of the later. */
+ if (u && DEVICE(u)->state == DEVICE_PLUGGED) {
+ /* This unit is in plugged state: we're sure it's
+ * attached to a device. */
+ if (!path_equal(DEVICE(u)->sysfs, sysfs)) {
+ log_unit_error(u, "Dev %s appeared twice with different sysfs paths %s and %s",
+ e, DEVICE(u)->sysfs, sysfs);
+ return -EEXIST;
+ }
}
if (!u) {
diff --git a/src/core/execute.c b/src/core/execute.c
index ac91568b63..b9de2617a9 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -814,8 +814,7 @@ static int setup_pam(
_cleanup_(barrier_destroy) Barrier barrier = BARRIER_NULL;
pam_handle_t *handle = NULL;
sigset_t old_ss;
- int pam_code = PAM_SUCCESS;
- int err = 0;
+ int pam_code = PAM_SUCCESS, r;
char **e = NULL;
bool close_session = false;
pid_t pam_pid = 0, parent_pid;
@@ -832,8 +831,8 @@ static int setup_pam(
* daemon. We do things this way to ensure that the main PID
* of the daemon is the one we initially fork()ed. */
- err = barrier_create(&barrier);
- if (err < 0)
+ r = barrier_create(&barrier);
+ if (r < 0)
goto fail;
if (log_get_max_level() < LOG_DEBUG)
@@ -875,12 +874,13 @@ static int setup_pam(
parent_pid = getpid();
pam_pid = fork();
- if (pam_pid < 0)
+ if (pam_pid < 0) {
+ r = -errno;
goto fail;
+ }
if (pam_pid == 0) {
- int sig;
- int r = EXIT_PAM;
+ int sig, ret = EXIT_PAM;
/* The child's job is to reset the PAM session on
* termination */
@@ -945,11 +945,11 @@ static int setup_pam(
goto child_finish;
}
- r = 0;
+ ret = 0;
child_finish:
pam_end(handle, pam_code | flags);
- _exit(r);
+ _exit(ret);
}
barrier_set_role(&barrier, BARRIER_PARENT);
@@ -978,10 +978,9 @@ static int setup_pam(
fail:
if (pam_code != PAM_SUCCESS) {
log_error("PAM failed: %s", pam_strerror(handle, pam_code));
- err = -EPERM; /* PAM errors do not map to errno */
- } else {
- err = log_error_errno(err < 0 ? err : errno, "PAM failed: %m");
- }
+ r = -EPERM; /* PAM errors do not map to errno */
+ } else
+ log_error_errno(r, "PAM failed: %m");
if (handle) {
if (close_session)
@@ -991,15 +990,9 @@ fail:
}
strv_free(e);
-
closelog();
- if (pam_pid > 1) {
- kill(pam_pid, SIGTERM);
- kill(pam_pid, SIGCONT);
- }
-
- return err;
+ return r;
}
#endif
@@ -2319,7 +2312,7 @@ int exec_context_load_environment(Unit *unit, const ExecContext *c, char ***l) {
continue;
strv_free(r);
- return errno ? -errno : -EINVAL;
+ return errno > 0 ? -errno : -EINVAL;
}
count = pglob.gl_pathc;
if (count == 0) {
@@ -2683,7 +2676,7 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) {
fputc('\n', f);
}
- if (c->syscall_errno != 0)
+ if (c->syscall_errno > 0)
fprintf(f,
"%sSystemCallErrorNumber: %s\n",
prefix, strna(errno_to_name(c->syscall_errno)));
diff --git a/src/core/killall.c b/src/core/killall.c
index 77f145b4d1..d0c7c89670 100644
--- a/src/core/killall.c
+++ b/src/core/killall.c
@@ -37,7 +37,7 @@
#define TIMEOUT_USEC (10 * USEC_PER_SEC)
-static bool ignore_proc(pid_t pid) {
+static bool ignore_proc(pid_t pid, bool warn_rootfs) {
_cleanup_fclose_ FILE *f = NULL;
char c;
const char *p;
@@ -72,7 +72,22 @@ static bool ignore_proc(pid_t pid) {
* spree.
*
* http://www.freedesktop.org/wiki/Software/systemd/RootStorageDaemons */
- if (count == 1 && c == '@')
+ if (c == '@' && warn_rootfs) {
+ _cleanup_free_ char *comm = NULL;
+
+ r = pid_from_same_root_fs(pid);
+ if (r < 0)
+ return true;
+
+ get_process_comm(pid, &comm);
+
+ if (r)
+ log_notice("Process " PID_FMT " (%s) has been been marked to be excluded from killing. It is "
+ "running from the root file system, and thus likely to block re-mounting of the "
+ "root file system to read-only. Please consider moving it into an initrd file "
+ "system instead.", pid, strna(comm));
+ return true;
+ } else if (c == '@')
return true;
return false;
@@ -171,7 +186,7 @@ static int killall(int sig, Set *pids, bool send_sighup) {
if (parse_pid(d->d_name, &pid) < 0)
continue;
- if (ignore_proc(pid))
+ if (ignore_proc(pid, sig == SIGKILL && !in_initrd()))
continue;
if (sig == SIGKILL) {
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
index d3880b4e3c..903e6f0cf6 100644
--- a/src/core/load-fragment.c
+++ b/src/core/load-fragment.c
@@ -575,7 +575,9 @@ int config_parse_exec(
void *data,
void *userdata) {
+ _cleanup_free_ char *cmd = NULL;
ExecCommand **e = data;
+ Unit *u = userdata;
const char *p;
bool semicolon;
int r;
@@ -584,6 +586,7 @@ int config_parse_exec(
assert(lvalue);
assert(rvalue);
assert(e);
+ assert(u);
e += ltype;
rvalue += strspn(rvalue, WHITESPACE);
@@ -594,7 +597,13 @@ int config_parse_exec(
return 0;
}
- p = rvalue;
+ r = unit_full_printf(u, rvalue, &cmd);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers on %s, ignoring: %m", rvalue);
+ return 0;
+ }
+
+ p = cmd;
do {
_cleanup_free_ char *path = NULL, *firstword = NULL;
bool separate_argv0 = false, ignore = false;
diff --git a/src/core/main.c b/src/core/main.c
index 2f9094f03a..27ba6af031 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -1968,6 +1968,15 @@ finish:
(void) clearenv();
assert(i <= args_size);
+
+ /*
+ * We want valgrind to print its memory usage summary before reexecution.
+ * Valgrind won't do this is on its own on exec(), but it will do it on exit().
+ * Hence, to ensure we get a summary here, fork() off a child, let it exit() cleanly,
+ * so that it prints the summary, and wait() for it in the parent, before proceeding into the exec().
+ */
+ valgrind_summary_hack();
+
(void) execv(args[0], (char* const*) args);
}
diff --git a/src/core/manager.c b/src/core/manager.c
index 39e3cbbfe1..a83a8b013a 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -233,7 +233,7 @@ static int have_ask_password(void) {
errno = 0;
de = readdir(dir);
- if (!de && errno != 0)
+ if (!de && errno > 0)
return -errno;
if (!de)
return false;
diff --git a/src/core/service.c b/src/core/service.c
index c5b689a35c..ae84cccbc8 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -3201,7 +3201,7 @@ int service_set_socket_fd(Service *s, int fd, Socket *sock, bool selinux_context
if (s->state != SERVICE_DEAD)
return -EAGAIN;
- if (getpeername_pretty(fd, &peer) >= 0) {
+ if (getpeername_pretty(fd, true, &peer) >= 0) {
if (UNIT(s)->description) {
_cleanup_free_ char *a;
diff --git a/src/core/transaction.c b/src/core/transaction.c
index bc85cef266..8b0ed74643 100644
--- a/src/core/transaction.c
+++ b/src/core/transaction.c
@@ -27,6 +27,7 @@
#include "bus-error.h"
#include "terminal-util.h"
#include "transaction.h"
+#include "dbus-unit.h"
static void transaction_unlink_job(Transaction *tr, Job *j, bool delete_dependencies);
@@ -860,30 +861,12 @@ int transaction_add_job_and_dependencies(
if (!IN_SET(unit->load_state, UNIT_LOADED, UNIT_ERROR, UNIT_NOT_FOUND, UNIT_MASKED))
return sd_bus_error_setf(e, BUS_ERROR_LOAD_FAILED, "Unit %s is not loaded properly.", unit->id);
- if (type != JOB_STOP && unit->load_state == UNIT_ERROR) {
- if (unit->load_error == -ENOENT || unit->manager->test_run)
- return sd_bus_error_setf(e, BUS_ERROR_LOAD_FAILED,
- "Unit %s failed to load: %s.",
- unit->id,
- strerror(-unit->load_error));
- else
- return sd_bus_error_setf(e, BUS_ERROR_LOAD_FAILED,
- "Unit %s failed to load: %s. "
- "See system logs and 'systemctl status %s' for details.",
- unit->id,
- strerror(-unit->load_error),
- unit->id);
+ if (type != JOB_STOP) {
+ r = bus_unit_check_load_state(unit, e);
+ if (r < 0)
+ return r;
}
- if (type != JOB_STOP && unit->load_state == UNIT_NOT_FOUND)
- return sd_bus_error_setf(e, BUS_ERROR_LOAD_FAILED,
- "Unit %s failed to load: %s.",
- unit->id, strerror(-unit->load_error));
-
- if (type != JOB_STOP && unit->load_state == UNIT_MASKED)
- return sd_bus_error_setf(e, BUS_ERROR_UNIT_MASKED,
- "Unit %s is masked.", unit->id);
-
if (!unit_job_is_applicable(unit, type))
return sd_bus_error_setf(e, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE,
"Job type %s is not applicable for unit %s.",