systemd-logind ProtectHostname=yes 可防止在 LXDE 中使用 NIS 时创建席位

systemd-logind ProtectHostname=yes 可防止在 LXDE 中使用 NIS 时创建席位

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

相关内容