static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exit_type, service_exit_type, ServiceExitType);
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, service_result, ServiceResult);
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_restart, service_restart, ServiceRestart);
-static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_notify_access, notify_access, NotifyAccess);
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_emergency_action, emergency_action, EmergencyAction);
+static BUS_DEFINE_PROPERTY_GET2(property_get_notify_access, "s", Service, service_get_notify_access, notify_access_to_string);
static BUS_DEFINE_PROPERTY_GET(property_get_timeout_abort_usec, "t", Service, service_timeout_abort_usec);
static BUS_DEFINE_PROPERTY_GET(property_get_watchdog_usec, "t", Service, service_get_watchdog_usec);
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_timeout_failure_mode, service_timeout_failure_mode, ServiceTimeoutFailureMode);
SD_BUS_PROPERTY("ExitType", "s", property_get_exit_type, offsetof(Service, exit_type), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Restart", "s", property_get_restart, offsetof(Service, restart), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("PIDFile", "s", NULL, offsetof(Service, pid_file), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("NotifyAccess", "s", property_get_notify_access, offsetof(Service, notify_access), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("NotifyAccess", "s", property_get_notify_access, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("RestartUSec", "t", bus_property_get_usec, offsetof(Service, restart_usec), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("TimeoutStartUSec", "t", bus_property_get_usec, offsetof(Service, timeout_start_usec), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("TimeoutStopUSec", "t", bus_property_get_usec, offsetof(Service, timeout_stop_usec), SD_BUS_VTABLE_PROPERTY_CONST),
s->exec_context.keyring_mode = MANAGER_IS_SYSTEM(u->manager) ?
EXEC_KEYRING_PRIVATE : EXEC_KEYRING_INHERIT;
+ s->notify_access_override = _NOTIFY_ACCESS_INVALID;
+
s->watchdog_original_usec = USEC_INFINITY;
s->oom_policy = _OOM_POLICY_INVALID;
s->socket_peer = socket_peer_unref(s->socket_peer);
}
+static void service_override_notify_access(Service *s, NotifyAccess notify_access_override) {
+ assert(s);
+
+ s->notify_access_override = notify_access_override;
+
+ log_unit_debug(UNIT(s), "notify_access=%s", notify_access_to_string(s->notify_access));
+ log_unit_debug(UNIT(s), "notify_access_override=%s", notify_access_to_string(s->notify_access_override));
+}
+
static void service_stop_watchdog(Service *s) {
assert(s);
prefix, yes_no(s->guess_main_pid),
prefix, service_type_to_string(s->type),
prefix, service_restart_to_string(s->restart),
- prefix, notify_access_to_string(s->notify_access),
+ prefix, notify_access_to_string(service_get_notify_access(s)),
prefix, notify_state_to_string(s->notify_state),
prefix, oom_policy_to_string(s->oom_policy),
prefix, signal_to_string(s->reload_signal));
if (flags & EXEC_IS_CONTROL)
/* A control process */
- return IN_SET(s->notify_access, NOTIFY_EXEC, NOTIFY_ALL);
+ return IN_SET(service_get_notify_access(s), NOTIFY_EXEC, NOTIFY_ALL);
/* We only spawn main processes and control processes, so any
* process that is not a control process is a main process */
- return s->notify_access != NOTIFY_NONE;
+ return service_get_notify_access(s) != NOTIFY_NONE;
}
static Service *service_get_triggering_service(Service *s) {
/* The next restart might not be a manual stop, hence reset the flag indicating manual stops */
s->forbid_restart = false;
+ /* Reset NotifyAccess override */
+ s->notify_access_override = _NOTIFY_ACCESS_INVALID;
+
/* We want fresh tmpdirs in case service is started again immediately */
s->exec_runtime = exec_runtime_unref(s->exec_runtime, true);
s->n_restarts ++;
s->flush_n_restarts = false;
+ s->notify_access_override = _NOTIFY_ACCESS_INVALID;
+
log_unit_struct(UNIT(s), LOG_INFO,
"MESSAGE_ID=" SD_MESSAGE_UNIT_RESTART_SCHEDULED_STR,
LOG_UNIT_INVOCATION_ID(UNIT(s)),
s->status_text = mfree(s->status_text);
s->status_errno = 0;
+ s->notify_access_override = _NOTIFY_ACCESS_INVALID;
s->notify_state = NOTIFY_UNKNOWN;
s->watchdog_original_usec = s->watchdog_usec;
}
}
+ if (s->notify_access_override >= 0)
+ (void) serialize_item(f, "notify-access-override", notify_access_to_string(s->notify_access_override));
+
(void) serialize_dual_timestamp(f, "watchdog-timestamp", &s->watchdog_timestamp);
(void) serialize_bool(f, "forbid-restart", s->forbid_restart);
deserialize_dual_timestamp(value, &s->main_exec_status.start_timestamp);
else if (streq(key, "main-exec-status-exit"))
deserialize_dual_timestamp(value, &s->main_exec_status.exit_timestamp);
- else if (streq(key, "watchdog-timestamp"))
+ else if (streq(key, "notify-access-override")) {
+ NotifyAccess notify_access;
+
+ notify_access = notify_access_from_string(value);
+ if (notify_access < 0)
+ log_unit_debug(u, "Failed to parse notify-access-override value: %s", value);
+ else
+ s->notify_access_override = notify_access;
+ } else if (streq(key, "watchdog-timestamp"))
deserialize_dual_timestamp(value, &s->watchdog_timestamp);
else if (streq(key, "forbid-restart")) {
int b;
* has been received */
if (f != SERVICE_SUCCESS)
service_enter_signal(s, SERVICE_STOP_SIGTERM, f);
- else if (!s->remain_after_exit || s->notify_access == NOTIFY_MAIN)
+ else if (!s->remain_after_exit || service_get_notify_access(s) == NOTIFY_MAIN)
/* The service has never been and will never be active */
service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_PROTOCOL);
break;
static bool service_notify_message_authorized(Service *s, pid_t pid, FDSet *fds) {
assert(s);
- if (s->notify_access == NOTIFY_NONE) {
+ NotifyAccess notify_access = service_get_notify_access(s);
+
+ if (notify_access == NOTIFY_NONE) {
log_unit_warning(UNIT(s), "Got notification message from PID "PID_FMT", but reception is disabled.", pid);
return false;
}
- if (s->notify_access == NOTIFY_MAIN && pid != s->main_pid) {
+ if (notify_access == NOTIFY_MAIN && pid != s->main_pid) {
if (s->main_pid != 0)
log_unit_warning(UNIT(s), "Got notification message from PID "PID_FMT", but reception only permitted for main PID "PID_FMT, pid, s->main_pid);
else
return false;
}
- if (s->notify_access == NOTIFY_EXEC && pid != s->main_pid && pid != s->control_pid) {
+ if (notify_access == NOTIFY_EXEC && pid != s->main_pid && pid != s->control_pid) {
if (s->main_pid != 0 && s->control_pid != 0)
log_unit_warning(UNIT(s), "Got notification message from PID "PID_FMT", but reception only permitted for main PID "PID_FMT" and control PID "PID_FMT,
pid, s->main_pid, s->control_pid);
assert(u);
assert(ucred);
- if (!service_notify_message_authorized(SERVICE(u), ucred->pid, fds))
+ if (!service_notify_message_authorized(s, ucred->pid, fds))
return;
if (DEBUG_LOGGING) {
}
}
+ /* Interpret NOTIFYACCESS= */
+ e = strv_find_startswith(tags, "NOTIFYACCESS=");
+ if (e) {
+ NotifyAccess notify_access;
+
+ notify_access = notify_access_from_string(e);
+ if (notify_access < 0)
+ log_unit_warning_errno(u, notify_access,
+ "Failed to parse NOTIFYACCESS= field value '%s' in notification message, ignoring: %m", e);
+
+ /* We don't need to check whether the new access mode is more strict than what is
+ * already in use, since only the privileged process is allowed to change it
+ * in the first place. */
+ if (service_get_notify_access(s) != notify_access) {
+ service_override_notify_access(s, notify_access);
+ notify_dbus = true;
+ }
+ }
+
/* Interpret ERRNO= */
e = strv_find_startswith(tags, "ERRNO=");
if (e) {