diff options
author | Lennart Poettering <lennart@poettering.net> | 2020-04-30 11:59:30 +0200 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2020-04-30 18:36:05 +0200 |
commit | 9dcd43b14927fe6f9182a252213dbf182d9d8e01 (patch) | |
tree | 28b24ea0c30a289557dc465e95b1ac4b00a4c0af /src/notify/notify.c | |
parent | 484f4e5b2d62e885998fa3c09ed4d58b6c38f987 (diff) | |
download | systemd-9dcd43b14927fe6f9182a252213dbf182d9d8e01.tar.gz |
notify: beef up --pid= logic
Prompted by the discussions on #15547.
Diffstat (limited to 'src/notify/notify.c')
-rw-r--r-- | src/notify/notify.c | 55 |
1 files changed, 49 insertions, 6 deletions
diff --git a/src/notify/notify.c b/src/notify/notify.c index a76f337695..6c2dedd53f 100644 --- a/src/notify/notify.c +++ b/src/notify/notify.c @@ -54,6 +54,26 @@ static int help(void) { return 0; } +static pid_t manager_pid(void) { + const char *e; + pid_t pid; + int r; + + /* If we run as a service managed by systemd --user the $MANAGERPID environment variable points to + * the service manager's PID. */ + e = getenv("MANAGERPID"); + if (!e) + return 0; + + r = parse_pid(e, &pid); + if (r < 0) { + log_warning_errno(r, "$MANAGERPID is set to an invalid PID, ignoring: %s", e); + return 0; + } + + return pid; +} + static int parse_argv(int argc, char *argv[]) { enum { @@ -96,13 +116,24 @@ static int parse_argv(int argc, char *argv[]) { break; case ARG_PID: + if (isempty(optarg) || streq(optarg, "auto")) { + arg_pid = getppid(); - if (optarg) { - if (parse_pid(optarg, &arg_pid) < 0) - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), - "Failed to parse PID %s.", optarg); - } else + if (arg_pid <= 1 || + arg_pid == manager_pid()) /* Don't send from PID 1 or the service + * manager's PID (which might be distinct from + * 1, if we are a --user instance), that'd just + * be confusing for the service manager */ + arg_pid = getpid(); + } else if (streq(optarg, "parent")) arg_pid = getppid(); + else if (streq(optarg, "self")) + arg_pid = getpid(); + else { + r = parse_pid(optarg, &arg_pid); + if (r < 0) + return log_error_errno(r, "Failed to parse PID %s.", optarg); + } break; @@ -151,6 +182,7 @@ static int run(int argc, char* argv[]) { _cleanup_strv_free_ char **final_env = NULL; char* our_env[4]; unsigned i = 0; + pid_t source_pid; int r; log_show_color(true); @@ -207,7 +239,18 @@ static int run(int argc, char* argv[]) { setreuid(arg_uid, (uid_t) -1) < 0) return log_error_errno(errno, "Failed to change UID: %m"); - r = sd_pid_notify(arg_pid ? arg_pid : getppid(), false, n); + if (arg_pid > 0) + source_pid = arg_pid; + else { + /* Pretend the message originates from our parent, given that we are typically called from a + * shell script, i.e. we are not the main process of a service but only a child of it. */ + source_pid = getppid(); + if (source_pid <= 1 || + source_pid == manager_pid()) /* safety check: don't claim we'd send anything from PID 1 + * or the service manager itself */ + source_pid = 0; + } + r = sd_pid_notify(source_pid, false, n); if (r < 0) return log_error_errno(r, "Failed to notify init system: %m"); if (r == 0) |