systemd 版本 246
Debian Bullseye
内核 5.9.0-1-amd64
我不知道这个是什么时候引入的。该指令在 systemd 版本 241 中尚不存在。
当没有创建席位时,用户无权注销/关机,pulseaudio 无法启动,(某些)设备无法访问,甚至可能还有其他情况。
systemd-logind 让我头疼不已。不仅一次就发现了问题,而且 systemd 每次更新似乎都会产生新的问题。
安装 Debian Bullseye 后,我无法再次为我的会话分配座位。这次的罪魁祸首是ProtectHostname=yes在 systemd-logind.service 中。注释掉此行,或者ProtectHostname=no解决了问题。后者是默认设置。
我的问题不仅仅是如何解决这个问题。随着这个新版本的 systemd,systemd-logind.service 又添加了 10-20 行。我想了解并找到这些错误,而不是通过反复试验注释掉指令。
我在 journalctl、syslog、auth.log 和 .xsession-errors 中搜索了字符串“hostname”,但未发现任何与 hostname 相关的错误。这使得理解、调试或解决问题变得非常困难。
这systemd 手册页提到了 ProtectHostname 指令,但没有解释为什么使用/需要它、它对会话有什么影响,以及为什么在使用网络身份验证(NIS)时它不起作用。
那么,问题是:这里发生了什么以及为什么?
为了完整性,以下是 systemd-logind.service 和 nssswitch.conf 的内容
# SPDX-License-Identifier: LGPL-2.1+
#
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
[Unit]
Description=User Login Management
Documentation=man:systemd-logind.service(8) man:logind.conf(5)
Documentation=https://www.freedesktop.org/wiki/Software/systemd/logind
Documentation=https://www.freedesktop.org/wiki/Software/systemd/multiseat
Wants=user.slice [email protected]
After=nss-user-lookup.target user.slice [email protected]
ConditionPathExists=/lib/systemd/system/dbus.service
# Ask for the dbus socket.
Wants=dbus.socket
After=dbus.socket
[Service]
BusName=org.freedesktop.login1
CapabilityBoundingSet=CAP_SYS_ADMIN CAP_MAC_ADMIN CAP_AUDIT_CONTROL CAP_CHOWN CAP_DAC_READ_SEARCH CAP_DAC_OVERRIDE CAP_FOWNER CAP_SYS_TTY_CONFIG CAP_LINUX_IMMUTABLE
DeviceAllow=block-* r
DeviceAllow=char-/dev/console rw
DeviceAllow=char-drm rw
DeviceAllow=char-input rw
DeviceAllow=char-tty rw
DeviceAllow=char-vcs rw
# Make sure the DeviceAllow= lines above can work correctly when referenceing char-drm
ExecStart=/lib/systemd/systemd-logind
FileDescriptorStoreMax=512
#IPAddressDeny=
IPAddressAllow=192.168.110.0/24
LockPersonality=yes
MemoryDenyWriteExecute=yes
NoNewPrivileges=yes
PrivateTmp=yes
ProtectClock=yes
ProtectControlGroups=yes
ProtectHome=yes
ProtectHostname=no
ProtectKernelModules=yes
ProtectKernelLogs=yes
ProtectSystem=strict
ReadWritePaths=/etc /run
Restart=always
RestartSec=0
RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6
RestrictNamespaces=yes
RestrictRealtime=yes
RestrictSUIDSGID=yes
RuntimeDirectory=systemd/sessions systemd/seats systemd/users systemd/inhibit systemd/shutdown
RuntimeDirectoryPreserve=yes
StateDirectory=systemd/linger
SystemCallArchitectures=native
SystemCallErrorNumber=EPERM
SystemCallFilter=@system-service
WatchdogSec=3min
# Increase the default a bit in order to allow many simultaneous logins since
# we keep one fd open per session.
LimitNOFILE=524288
# /etc/nsswitch.conf
#
# Example configuration of GNU Name Service Switch functionality.
# If you have the `glibc-doc-reference' and `info' packages installed, try:
# `info libc "Name Service Switch"' for information about this file.
passwd: files systemd nis
group: files systemd nis
shadow: files
gshadow: files
hosts: files mdns4_minimal [NOTFOUND=return] dns nis
networks: files
protocols: db files
services: db files
ethers: db files
rpc: db files
netgroup: nis
答案1
“ProtectHostname=”创建一个新的UTS 命名空间,类似于 PrivateNetwork= 创建新的网络命名空间和 PrivateTmp= 创建新的挂载命名空间。(其目标是防止该进程更改系统的主机名,这在理论上可能导致与主机名绑定的“sudo”策略或 LDAP 授权检查等的安全问题。)
“UTS 命名空间”涵盖由uname() 调用in struct utsname
– 这包括一些只读数据(内核版本);主机名(显然);和 NIS 域名。(不太清楚为什么 NIS 域名存储在内核空间中,但在 Linux 上确实如此。)
因此如果你的启动过程如下:logind 已启动前如果 NIS 客户端启动并且设置了默认域名,则 logind 的私有 UTS 命名空间仍将具有包含空 NIS 域名的“struct utsname”的旧副本。当 logind 尝试通过 libnss_nis 解析用户名时,后者将放弃,因为未设置域名。
# strace -v -e uname ypdomainname
uname({sysname="Linux", nodename="ember", release="5.4.70-1-lts",
version="#1 SMP Wed, 07 Oct 2020 23:54:51 +0000", machine="x86_64",
domainname="example.com"}) = 0
example.com
+++ exited with 0 +++
# nsenter --target $(pidof systemd-logind) --uts \
strace -v -e uname ypdomainname
uname({sysname="Linux", nodename="ember", release="5.4.70-1-lts",
version="#1 SMP Wed, 07 Oct 2020 23:54:51 +0000", machine="x86_64",
domainname="(none)"}) = 0
Local domain name not set
+++ exited with 1 +++
一种解决方法是确保您的 NIS 服务在 nss-user-lookup.target 之前启动,因为 systemd-logind 已经声明了在此目标之后的排序 - 表明用户查找可用正是此 .target 的目的:
# ypbind.service
[Unit]
Wants=nss-user-lookup.target
Before=nss-user-lookup.target
另一种方法是通过 设置 NIS 域名/etc/sysctl.d
,该方法比大多数服务处理得更早:
kernel.domainname = example.com