dbus: mirror legacy runlevel edge cases in Manager1.SetRunlevel

The bus method called sm_runlevel() unconditionally.  In runlevel 0
and 6 that aborts an in-flight shutdown, which INIT_CMD_RUNLVL
refuses with a warning, and during bootstrap it switches immediately
where the legacy path defers via cfglevel to the end of runlevel S.

Port both.  A bad runlevel argument still returns InvalidArgs, where
the legacy protocol acks silently: a typed interface rejects garbage.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
Joachim Wiberg committed 2026-08-16 22:03:37 +02:00
1 parent 8114508bbb
commit b53c7e6879
4 files changed
+29 -23

No files matched your search

+3 -20
View File
@@ -233,6 +233,7 @@ static void bypass_shutdown(void *unused)
do_shutdown(halt);
}
/*
* Handle switch_root API command.
* Parses data: "newroot\0newinit\0"
@@ -370,8 +371,8 @@ static void api_cb(uev_t *w, void *arg, int events)
{
static svc_t *iter = NULL;
struct init_request rq;
int sd, lvl;
svc_t *svc;
int sd;
(void)arg;
@@ -446,14 +447,6 @@ static void api_cb(uev_t *w, void *arg, int events)
switch (rq.cmd) {
case INIT_CMD_RUNLVL:
/* Allow changing cfglevel in runlevel S */
if (IS_RESERVED_RUNLEVEL(runlevel)) {
if (runlevel != INIT_LEVEL) {
warnx("Cannot abort runlevel 6/0.");
break;
}
}
switch (rq.runlevel) {
case 's':
case 'S':
@@ -462,17 +455,7 @@ static void api_cb(uev_t *w, void *arg, int events)
case '0'...'9':
dbg("Setting new runlevel %c", rq.runlevel);
lvl = rq.runlevel - '0';
if (lvl == 0)
halt = SHUT_OFF;
if (lvl == 6)
halt = SHUT_REBOOT;
/* User requested change in next runlevel */
if (runlevel == INIT_LEVEL)
cfglevel = lvl;
else
sm_runlevel(lvl);
sm_request_runlevel(rq.runlevel - '0');
break;
default:
+1 -3
View File
@@ -454,9 +454,7 @@ static int manager_set_runlevel(link_call_t *call, void *userdata)
"org.freedesktop.DBus.Error.InvalidArgs",
"runlevel must be 0-9 (excluding internal levels)");
if (lvl == 0) halt = SHUT_OFF;
if (lvl == 6) halt = SHUT_REBOOT;
sm_runlevel((int)lvl);
sm_request_runlevel((int)lvl);
(void)link_call_reply(call);
return 0;
+24
View File
@@ -94,6 +94,30 @@ static void shutdown_wdt_cb(uev_t *w, void *arg, int events)
do_shutdown(halt);
}
/*
* User-requested runlevel change, shared by the legacy API and the
* D-Bus SetRunlevel method. Refused in runlevel 0/6, deferred via
* cfglevel during bootstrap.
*/
void sm_request_runlevel(int lvl)
{
if (IS_RESERVED_RUNLEVEL(runlevel) && runlevel != INIT_LEVEL) {
warnx("Cannot abort runlevel 6/0.");
return;
}
if (lvl == 0)
halt = SHUT_OFF;
if (lvl == 6)
halt = SHUT_REBOOT;
/* Runlevel S: user requested change in next runlevel */
if (runlevel == INIT_LEVEL)
cfglevel = lvl;
else
sm_runlevel(lvl);
}
/*
* Console input callback - handles Ctrl-C during bootstrap wait
*/
+1
View File
@@ -35,6 +35,7 @@ void sm_step (void);
int sm_in_reload (void);
void sm_reload (void);
void sm_runlevel (int newlevel);
void sm_request_runlevel(int lvl);
#endif /* FINIT_SM_H_ */