Luca Boccassi
2026-02-24 11:50:01 +00:00
committed by GitHub
4 changed files with 64 additions and 55 deletions

8
NEWS
View File

@@ -64,6 +64,14 @@ CHANGES WITH 260 in spe:
directory or not, we make use of it unconditionally and have dropped
support for the old way using protofiles.
* The org.systemd.login1.Manager D-Bus interface has a minor API break.
The `CanPowerOff()`, `CanReboot()`, `CanSuspend()`, etc. family of
methods have introduced new return values which may break downstream
consumers, such as desktop environments. The new return values more
precisely communicate the status of inhibitors. This allows desktops
to differentiate between system administrator policy and
temporary restrictions imposed by inhibitors.
New system interfaces and components:
* The os-release(3) gained a new field FANCY_NAME= that is similar

View File

@@ -276,7 +276,6 @@ node /org/freedesktop/login1 {
readonly t RuntimeDirectoryInodesMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t InhibitorsMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t NCurrentInhibitors = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t SessionsMax = ...;
@@ -711,12 +710,19 @@ node /org/freedesktop/login1 {
<function>CanRebootParameter()</function>, <function>CanRebootToFirmwareSetup()</function>,
<function>CanRebootToBootLoaderMenu()</function>, and <function>CanRebootToBootLoaderEntry()</function>
test whether the system supports the respective operation and whether the calling user is allowed to
execute it. Returns one of <literal>na</literal>, <literal>yes</literal>, <literal>no</literal>, and
<literal>challenge</literal>. If <literal>na</literal> is returned, the operation is not available because
hardware, kernel, or drivers do not support it. If <literal>yes</literal> is returned, the operation is
supported and the user may execute the operation without further authentication. If <literal>no</literal>
is returned, the operation is available but the user is not allowed to execute the operation. If
<literal>challenge</literal> is returned, the operation is available but only after authorization.</para>
execute it. Returns one of <literal>na</literal>, <literal>yes</literal>, <literal>no</literal>,
<literal>challenge</literal>, and <literal>inhibited</literal>. If <literal>na</literal> is returned,
the operation is not available because hardware, kernel, or drivers do not support it. If <literal>yes</literal>
is returned, the operation is supported and the user may execute the operation without further authentication.
If <literal>no</literal> is returned, the operation is available but the user is not allowed to execute
the operation. If <literal>challenge</literal> is returned, the operation is available but only after
authorization. If <literal>inhibited</literal> is returned, the operation is normally available without
authorization but is currently inhibited. The operation is available only if inhibitors are ignored and
after authorization. If <literal>inhibitor-blocked</literal> is returned, the operation is normally
available without authorization but is currently inhibited. While the inhibitor remains active, the user
is not allowed to execute the operation. <literal>challenge-inhibitor-blocked</literal> is similar:
the operation is normally available after authorization but a held inhibitor disallows the user from
executing the operation.</para>
<para><function>ScheduleShutdown()</function> schedules a shutdown operation <varname>type</varname> at
time <varname>usec</varname> in microseconds since the UNIX epoch. Alternatively, if

View File

@@ -2927,7 +2927,6 @@ static int method_can_shutdown_or_sleep(
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
bool multiple_sessions, challenge, blocked, check_unit_state = true;
const HandleActionData *a;
const char *result = NULL;
uid_t uid;
int r;
@@ -2984,12 +2983,27 @@ static int method_can_shutdown_or_sleep(
if (r < 0)
return r;
if (!streq(load_state, "loaded")) {
result = "no";
goto finish;
}
if (!streq(load_state, "loaded"))
return sd_bus_reply_method_return(message, "s", "no");
}
const char *result;
r = bus_test_polkit(
message,
a->polkit_action,
/* details= */ NULL,
/* good_user= */ UID_INVALID,
&challenge,
error);
if (r < 0)
return r;
if (r > 0)
result = "yes";
else if (challenge)
result = "challenge";
else
result = "no";
if (multiple_sessions) {
r = bus_test_polkit(
message,
@@ -3001,12 +3015,13 @@ static int method_can_shutdown_or_sleep(
if (r < 0)
return r;
if (r > 0)
result = "yes";
else if (challenge)
result = "challenge";
else
result = "no";
if (r == 0) {
if (challenge) {
if (streq(result, "yes")) /* Avoid upgrading no -> challenge */
result = "challenge";
} else
result = "no";
}
}
if (blocked) {
@@ -3020,39 +3035,21 @@ static int method_can_shutdown_or_sleep(
if (r < 0)
return r;
if (r > 0) {
if (!result)
result = "yes";
} else if (challenge) {
if (!result || streq(result, "yes"))
result = "challenge";
} else
result = "no";
if (r == 0) {
if (challenge) {
if (streq(result, "yes"))
result = "inhibited";
/* If result is already "challenge" or "no", the held inhibitor has no effect */
} else {
if (streq(result, "yes"))
result = "inhibitor-blocked";
else if (streq(result, "challenge"))
result = "challenge-inhibitor-blocked";
/* If the result is already "no", the held inhibitor has no effect */
}
}
}
if (!multiple_sessions && !blocked) {
/* If neither inhibit nor multiple sessions
* apply then just check the normal policy */
r = bus_test_polkit(
message,
a->polkit_action,
/* details= */ NULL,
/* good_user= */ UID_INVALID,
&challenge,
error);
if (r < 0)
return r;
if (r > 0)
result = "yes";
else if (challenge)
result = "challenge";
else
result = "no";
}
finish:
return sd_bus_reply_method_return(message, "s", result);
}
@@ -3963,7 +3960,7 @@ static const sd_bus_vtable manager_vtable[] = {
SD_BUS_PROPERTY("RuntimeDirectorySize", "t", NULL, offsetof(Manager, runtime_dir_size), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("RuntimeDirectoryInodesMax", "t", NULL, offsetof(Manager, runtime_dir_inodes), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("InhibitorsMax", "t", NULL, offsetof(Manager, inhibitors_max), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("NCurrentInhibitors", "t", property_get_hashmap_size, offsetof(Manager, inhibitors), 0),
SD_BUS_PROPERTY("NCurrentInhibitors", "t", property_get_hashmap_size, offsetof(Manager, inhibitors), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("SessionsMax", "t", NULL, offsetof(Manager, sessions_max), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("NCurrentSessions", "t", property_get_hashmap_size, offsetof(Manager, sessions), 0),
SD_BUS_PROPERTY("UserTasksMax", "t", property_get_compat_user_tasks_max, 0, SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),

View File

@@ -148,13 +148,11 @@ static int inhibitor_save(Inhibitor *i) {
}
static int bus_manager_send_inhibited_change(Inhibitor *i) {
const char *property;
assert(i);
property = IN_SET(i->mode, INHIBIT_BLOCK, INHIBIT_BLOCK_WEAK) ? "BlockInhibited" : "DelayInhibited";
return manager_send_changed(i->manager, property);
return manager_send_changed(i->manager,
i->mode == INHIBIT_DELAY ? "DelayInhibited" : "BlockInhibited",
"NCurrentInhibitors");
}
int inhibitor_start(Inhibitor *i) {