Ubuntu 26 root shutdown时被拒
原创
沈沉舟
沈沉舟
青衣十三楼飞花堂
2026年7月28日 00:00
北京
在小说阅读器读本章
去阅读
创建: 2026-07-24 16:35
链接: https://scz.617.cn/unix/202607241635.txt
Q:
Ubuntu 26,以root身份shutdown时,提示被拒
# shutdown -P now
Operation inhibited by \"scz\" (PID 3423 \"gnome-session-s\", user scz), reason is \"user session inhibited\". User scz is logged in on tty2. Please retry operation after closing inhibitors and logging out other users. 'systemd-inhibit' can be used to list active inhibitors. Alternatively, ignore inhibitors and users with 'systemctl poweroff -i'.
这是什么情况?
A:
精确复现方案,在X用scz登录,开Terminal,执行
python3
此时root已无法shutdown,出现前述提示。一定在X的Terminal中执行python3进行测试,在SSH Shell中执行python3,无此效果。
Ubuntu 26中init是到systemd的符号链接,shutdown是到systemctl的符号链接。
$ readlink -f $(which init)
/usr/lib/systemd/systemd
$ readlink -f $(which shutdown)
/usr/bin/systemctl
这种系统\"init 0\"不对应关机。\"shutdown -P\"实际执行\"systemctl poweroff\"。systemctl通过systemd、systemd-logind完成关机、重启等操作,这套机制遵循一种名为\"Inhibitor Locks\"的东西,参看:
https://systemd.io/INHIBITOR_LOCKS
普通进程可通过D-Bus向systemd-logind注册指定类型的inhibitor,比如说,我正在升级,请勿关机。之后的\"systemctl poweroff\"会通过systemd询问systemd-logind,发现有个shutdown inhibitor,systemd将拒绝关机。
可用如下命令查看当前注册生效中的inhibitor
systemd-inhibit --list
systemd-inhibit --no-pager --no-legend --list
或者更底层、更直接的命令
gdbus call \\
--system \\
--dest org.freedesktop.login1 \\
--object-path /org/freedesktop/login1 \\
--method org.freedesktop.login1.Manager.ListInhibitors
可用systemd-inhibit注册shutdown inhibitor,同时执行一个长期驻留的子进程,在子进程存活期间,inhibitor对应的fd(文件句柄)不会自动关闭,inhibitor不会自动注销。比如
systemd-inhibit \\
--what=shutdown \\
--who=\"any\" \\
--why=\"some\" \\
--mode=block \\
bash
bash可换成\"pauseme sleep 0\"之类的,只要子进程能长期驻留即可。上述操作对系统有潜在影响,普通用户执行时要求输入root密码。
如果遭遇root shutdown被拒,提示信息中已给出解决方案之一
systemctl poweroff -i
\"-i\"是忽略inhibitor的意思。但这样过于简单粗暴,更好的解决之道是,找出那个注册了shutdown inhibitor的进程,正常结束它,再关机。
D:
D-Bus是个较大的攻击面,但我从未研究过,这次稍微多做点实验。
gdbus introspect \\
--system \\
--dest org.freedesktop.login1 \\
--object-path /org/freedesktop/login1
上述命令向systemd-logind查询「你这个D-Bus服务提供哪些接口」,部分输出如下
interface org.freedesktop.login1.Manager {
methods:
...
ListSessions(out a(susso) sessions);
ListSessionsEx(out a(sussussbto) sessions);
ListUsers(out a(uso) users);
...
ListInhibitors(out a(ssssuu) inhibitors);
...
LockSessions();
UnlockSessions();
...
PowerOff(in b interactive);
...
Reboot(in b interactive);
gdbus可直接调用这些API。
gdbus call \\
--system \\
--dest org.freedesktop.login1 \\
--object-path /org/freedesktop/login1 \\
--method org.freedesktop.login1.Manager.LockSessions
在SSH Shell中以root身份执行LockSessions,将在主控台产生锁屏的效果,简单类比成Windows cmd中执行:
rundll32.exe user32.dll,LockWorkStation
针对LockSessions,可用gdbus取消锁屏:
gdbus call \\
--system \\
--dest org.freedesktop.login1 \\
--object-path /org/freedesktop/login1 \\
--method org.freedesktop.login1.Manager.UnlockSessions
若在主控台交互式取消锁屏,需输入密码,gdbus取消锁屏则不需要,有趣。不过,若主控台处于登录界面,UnlockSessions无法取消录登界面。
gdbus call \\
--system \\
--dest org.freedesktop.login1 \\
--object-path /org/freedesktop/login1 \\
--method org.freedesktop.login1.Manager.ListSessions
可通过D-Bus关机,以root身份执行:
gdbus call \\
--system \\
--dest org.freedesktop.login1 \\
--object-path /org/freedesktop/login1 \\
--method org.freedesktop.login1.Manager.PowerOff \\
true
对于root,无论PowerOff的参数是false还是true,均不会交互式授权,因为已经是root。对于普通用户,上述命令过于底层,无法进入交互式授权环节,因为这是由其他组件配合提供的,gdbus无此能力,只会报错:
Error: GDBus.Error:org.freedesktop.DBus.Error.InteractiveAuthorizationRequired: Access denied as the requested operation requires interactive authentication. However, interactive authentication has not been enabled by the calling program.
可监控D-Bus消息,比如
dbus-monitor --system --monitor \\
type=method_call,interface=org.freedesktop.login1.Manager,member=Inhibit
在X Terminal中执行python3,在dbus-monitor中将看到
method call ... path=/org/freedesktop/login1; interface=org.freedesktop.login1.Manager; member=Inhibit
string \"shutdown\"
string \"scz\"
string \"user session inhibited\"
string \"block\"
在root shell中执行
gdbus call \\
--system \\
--dest org.freedesktop.login1 \\
--object-path /org/freedesktop/login1 \\
--method org.freedesktop.login1.Manager.Inhibit \\
shutdown \\
any \\
some \\
block
在dbus-monitor中将看到
method call ...
string \"shutdown\"
string \"any\"
string \"some\"
string \"block\"
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。









评论