Skip to content

Fix security - #1199

Open
fly602 wants to merge 8 commits into
linuxdeepin:masterfrom
fly602:fix-security
Open

Fix security#1199
fly602 wants to merge 8 commits into
linuxdeepin:masterfrom
fly602:fix-security

Conversation

@fly602

@fly602 fly602 commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Summary by Sourcery

Integrate deepin-security-loader into system daemons and hardware-control services to enforce caller-based authorization while preserving existing Polkit fallback.

New Features:

  • Introduce a securityloader allow-caller registry with persistent state and process-ancestry validation for D-Bus callers.
  • Add security-loader handshake support to session and system daemons and langselector for secure startup under deepin-security-loader.
  • Expose SetAllowCaller D-Bus methods for Daemon1, Power1, InputDevices1, AirplaneMode1, and related components to register authorized callers dynamically.
  • Add security-loader integration in touchpad, power, airplane mode, and idle/screen state controls to gate hardware actions on registered callers with Polkit fallback when not loader-launched.

Bug Fixes:

  • Harden hardware and power control paths by rejecting unauthorized D-Bus callers rather than relying solely on global Polkit rules.

Enhancements:

  • Update D-Bus policies to restrict SetAllowCaller usage to root or the deepin-daemon group while denying it for unprivileged callers.
  • Refine RPM and build scripts to depend on deepin-security-loader, add hardware-control policy translations, and install loader wrappers for session-daemon and langselector without breaking libexec layout.
  • Add comprehensive unit tests for securityloader allow-caller registry, process group and ancestry checks, and security-loader handshake argument parsing and I/O validation.
  • Persist and restore authorized callers across daemon lifetimes with bus-ID scoping to avoid leaking authorizations across system bus restarts.

Build:

  • Extend policy translation targets to include new hardware-control polkit policy.
  • Adjust Makefile install paths to place dde-session-daemon and langselector binaries under /usr/libexec/deepin with loader wrapper scripts in the original daemon lib directory.

Tests:

  • Add tests covering allow-caller authorization logic, persistence, removal, concurrent registration, and process-ancestry validation.
  • Add tests validating security-loader handshake argument parsing, descriptor validation, and response size limits.

Chores:

  • Declare deepin-security-loader as a package dependency in RPM and wire system units to the new loader-aware binary layout.

@deepin-ci-robot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: fly602

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @fly602, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@sourcery-ai

sourcery-ai Bot commented Aug 11, 2026

Copy link
Copy Markdown

Reviewer's Guide

Integrates deepin-security-loader into multiple daemons and hardware-control paths, introducing an allow-caller registry that enforces DBus caller authorization per scope with a Polkit fallback, wiring it through airplane mode, power, system-daemon, input devices, and langselector, plus packaging and DBus policy updates to run certain binaries via loader wrappers.

File-Level Changes

Change Details Files
Introduce securityloader allow-caller registry and handshake mechanism for security-loader integration.
  • Add AllowCallerRegistry type that persists authorized DBus unique names per scope and validates registrars based on uid, groups, and process ancestry.
  • Implement Authorize logic returning AuthOK/AuthDenied/AuthNotEnabled based on registry state and caller uid.
  • Implement Handshake helper that parses injected --fd1/--fd2 arguments, exchanges JSON over pipes with deepin-security-loader, and registers the process unique name for specified destinations.
  • Add comprehensive unit tests for allow-caller registry logic, process ancestry helpers, persistence, and handshake argument/IO validation.
securityloader/allowcaller.go
securityloader/allowcaller_test.go
securityloader/handshake.go
securityloader/handshake_test.go
Wire allow-caller authorization into airplane mode, power management, system-daemon power interface, and input devices touchpad control with Polkit fallback when not loader-started.
  • Extend Manager/Daemon/InputDevices/Touchpad structs with AllowCallerRegistry references and initialize registry from system-daemon main.
  • Add SetAllowCaller DBus methods on Daemon1, Power1, AirplaneMode1, and InputDevices1 to register allowed callers per scope via the registry.
  • Update Enable/EnableWifi/EnableBluetooth, SetIdleState/SetScreenState, SetTlpMode, and SetTouchpadEnable to first consult AllowCallerRegistry, deny on AuthDenied, and fallback to existing Polkit-based authorization when AuthNotEnabled.
  • Introduce checkDaemonAuth, checkPowerAuth, and checkTouchpadAuth helpers using Polkit Authority for fine-grained actions when loader is not in use.
system/airplane_mode1/manager.go
system/airplane_mode1/exported_methods_auto.go
bin/dde-system-daemon/power.go
system/inputdevices1/touchpad.go
system/inputdevices1/inputdevices.go
system/inputdevices1/inputdevices_ifc.go
system/inputdevices1/exported_methods_auto.go
system/power1/manager.go
system/power1/manager_ifc.go
system/power1/exported_methods_auto.go
bin/dde-system-daemon/exported_methods_auto.go
bin/dde-system-daemon/main.go
Integrate security-loader startup for session-daemon and langselector and extend langselector with per-user destination registration.
  • Modify dde-session-daemon main to perform securityloader.Handshake with a set of DDE system destinations and refuse startup on fatal handshake error when loaded by loader.
  • Add securityloader.DoSecurityLoader invocation in langselector main and provide langselector-specific Destinations including LocaleHelper1, Lastore1, and the current Accounts1.User path resolved via DBus.
  • Add langselector1/securityloader.go with helper to build loader destination list and resolve the current user’s accounts path.
  • Install loader-wrapper scripts for dde-session-daemon and langselector to run them via deepin-security-loader while keeping binaries under libexec.
bin/dde-session-daemon/main.go
bin/langselector/main.go
langselector1/securityloader.go
misc/scripts/dde-session-daemon-loader-wrapper
misc/scripts/langselector-loader-wrapper
Update DBus policy configs to restrict SetAllowCaller calls to root/deepin-daemon group and deny them for default context, ensuring only privileged components can register allowed callers.
  • Extend org.deepin.dde.AirplaneMode1.conf and org.deepin.dde.InputDevices1.conf to allow SetAllowCaller only for root and deepin-daemon group and explicitly deny it in default policy.
  • Update org.deepin.dde.Daemon1.conf and org.deepin.dde.Power1.conf to add deepin-daemon group policies allowing SetAllowCaller and deny this member for default context.
  • Ensure only the owning service and privileged group can call SetAllowCaller while all other methods remain broadly callable as before.
misc/conf/org.deepin.dde.AirplaneMode1.conf
misc/conf/org.deepin.dde.InputDevices1.conf
misc/conf/org.deepin.dde.Daemon1.conf
misc/conf/org.deepin.dde.Power1.conf
Adjust build, packaging, and systemd wiring to add hardware-control polkit policy, depend on deepin-security-loader, and route specific daemons through libexec/deepin wrappers.
  • Extend Makefile POLICIES list with hardware-control and ensure ts conversion and install steps copy dde-session-daemon and langselector into libexec/deepin with loader wrappers installed into lib/deepin-daemon.
  • Update RPM spec to require deepin-security-loader and to tweak Makefile lib vs libexec substitutions while preserving security-loader-target paths.
  • Modify dde-lockservice systemd unit ExecStart to reference both the existing libexecdir path and a deepin-specific libexec/dde path (line-wrapped).
  • Add hardware-control polkit policy template file and Debian packaging stubs/overrides for the new securities (files listed but content not shown in diff).
Makefile
rpm/dde-daemon.spec
misc/conf/org.deepin.dde.Power1.conf
misc/polkit-action/org.deepin.dde.hardware-control.policy.in
systemd/lockservice.service
debian/control
debian/dde-daemon.lintian-overrides
misc/polkit-action/org.deepin.dde.airplane.policy
misc/polkit-action/org.deepin.dde.power.policy

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@fly602
fly602 force-pushed the fix-security branch 2 times, most recently from 0bb9d87 to e02c924 Compare August 11, 2026 09:21
fly602 added 6 commits August 11, 2026 17:35
1. 新增 securityloader 模块,实现与 deepin-security-loader 的文件描述符
通信握手机制,解析并清理注入的启动参数
2. 将 dde-session-daemon 二进制文件安装路径从 /usr/lib/deepin-daemon 迁
移至 /usr/libexec/deepin/,原路径替换为 loader-wrapper 脚本以实现安全
加载
3. 在 dde-system-daemon 和 system/power 模块中引入 AllowCallerRegistry,
新增 SetAllowCaller DBus 方法用于动态注册受信任的调用方唯一名称
4. 对 SetIdleState、SetScreenState 和 SetTlpMode 等敏感接口增加权限校
验,拦截非 root 且未在 AllowCallerRegistry 中注册的 DBus 调用
5. 实现 AllowCallerRegistry 状态的 JSON 持久化,通过比对系统总线 BusID
防止跨重启周期的无效授权,并监听 NameOwnerChanged 信号自动清理断开连接的
调用方
6. 更新 DBus 策略配置,严格限制 SetAllowCaller 方法仅允许 root 用户和
deepin-daemon 组调用,并在 default 策略中显式拒绝
7. 在 debian 和 rpm 打包规则中新增 deepin-security-loader 依赖,并添加相
关单元测试

Influence:
1. 验证 dde-session-daemon 能否通过 wrapper 脚本正常启动,并确认启动日志
中无 security-loader handshake failed 错误
2. 测试 dde-session-daemon 正常启动后

Task: https://pms.uniontech.com/task-view-393313.html
1. 在 InputDevices 和 Touchpad 模块中集成 securityloader 的 AllowCaller
机制以增强安全性
2. 为 SetTouchpadEnable 接口增加 DBus Sender 权限校验防止恶意调用
3. 新增并导出 SetAllowCaller 接口供受信任的系统服务进行调用者身份注册
4. 更新 DBus 策略配置限制仅 root 和 deepin-daemon 组可调用
SetAllowCaller 并在默认策略中拒绝其他未授权访问
5. 在 session-daemon 启动阶段注册 InputDevices 的安全作用域

Task: https://pms.uniontech.com/task-view-393313.html
1. 移除飞行模式模块中原有的基于 polkit 的同步鉴权逻辑及相关的依赖
2. 引入并集成 securityloader 的 AllowCallerRegistry 白名单鉴权机制,增加
AirplaneModeScope 常量定义
3. 导出 SetAllowCaller 接口,并在 dde-session-daemon 中添加该接口的 DBus
配置以完成权限注册
4. 修改 DBus 策略配置文件,严格限制 SetAllowCaller 方法仅允许 root 用户
和 deepin-daemon 组访问,并在默认策略中增加拒绝规则
5. 修改 Enable、EnableWifi、EnableBluetooth 三个核心方法的权限校验方式,
由原来的 polkit 交互式鉴权改为统一白名单校验,并补充鉴权失败时的日志记录

Task: https://pms.uniontech.com/task-view-393313.html
dde-session-daemon 启动时将 org.deepin.dde.Lastore1.Manager 加入
security-loader 握手目标,使当前进程的 system bus unique name 通过
lastore-daemon 的 SetAllowCaller 注册为受信任调用者。

lastore Agent 调用 RegisterAgent 和 UnRegisterAgent 时复用该 system bus
连接,从而走 allow-caller 鉴权,避免弹出 polkit 交互认证框。

Log: 为 lastore Agent 注册适配 security-loader

Influence: lastore Agent 注册、注销及更新通知功能

Task: https://pms.uniontech.com/task-view-393313.html
1. 在 securityloader.go 的 defaultDestList 中新增了 LocaleHelper 的 D-Bus
配置项
2. 包含其 DbusName、DbusPath 和 DbusInterface 的具体定义
3. 此改动是为了将 LocaleHelper 服务纳入安全握手机制的白名单中,确保系统语
言选择器能够正常与 LocaleHelper 进行安全通信,避免因权限校验导致的 D-Bus
调用失败

历史相关:迁移 v20 中 langselector securityloader 完整握手机制
(含 cfd01e630 控制中心切换语言弹鉴权窗、e29680ba3 修复切换语言不生效
两笔历史提交),D-Bus 接口名适配 v25 风格:
- com.deepin.api.LocaleHelper -> org.deepin.dde.LocaleHelper1
- com.deepin.daemon.Accounts -> org.deepin.dde.Accounts1
- com.deepin.lastore -> org.deepin.dde.Lastore1

Influence:
1. 测试系统语言或区域设置的切换功能是否正常生效
2. 验证语言选择器与LocaleHelper之间的D-Bus通信是否畅通无阻
3. 检查系统日志中是否还存在与LocaleHelper相关的D-Bus权限拒绝或安全握手失
败的报错
4. 回归测试语言选择器的其他基础功能,确保新增配置未对原有服务通信造成
干扰
Log: 切换语言仅允许dde-session-daemon调用

Task: https://pms.uniontech.com/task-view-393313.html
当服务未通过 deepin-security-loader 启动时,AllowCaller 白名单未启用,
SetTouchpadEnable、SetTlpMode、SetIdleState、SetScreenState 等接口
回退到 polkit 认证提权,保证非安全加载场景下功能可用。

新增 polkit 策略 org.deepin.dde.hardware-control:
- org.deepin.dde.inputdevices.set-touchpad: 触控板开关
- org.deepin.dde.daemon.set-idle-state: 设置空闲状态
- org.deepin.dde.daemon.set-screen-state: 设置屏幕状态

SetTlpMode 复用已有 org.deepin.dde.power.doAction 策略。

Task: https://pms.uniontech.com/task-view-393313.html
1. 为 dde-system-daemon 配置 /run/dde-daemon 运行目录及状态保留,
   使 AllowCaller 状态在 ProtectSystem=strict 下可写
2. 将 dde-session-daemon 用户服务改为 forking 模式,由 systemd
   接管 security-loader 启动的真实进程,并等待 D-Bus 名称就绪
3. wrapper 检查 loader 及 CAP_SETGID,不可用时直接启动真实进程,
   由原有 polkit 鉴权路径回退

Influence:
1. 验证 dde-system-daemon 启动及重启后 /run/dde-daemon 权限正确,
   AllowCaller 状态可写入和恢复
2. 验证 dde-session-daemon 通过 security-loader 启动后服务保持 active,
   MainPID 指向真实进程且 D-Bus 名称正常就绪
3. 验证 Daemon1、Lastore1、InputDevices1 和 AirplaneMode1 的调用方
   注册成功,日志中无 read-only file system 错误
4. 验证 loader 缺失或 CAP_SETGID 不可用时可直接启动,并使用原有
   polkit 鉴权路径
5. 验证服务停止、异常退出和自动重启时无残留进程

Task: https://pms.uniontech.com/task-view-393313.html
1. Fall back to Polkit whenever a non-root caller is not registered.
2. Fail closed when caller identity or registry checks cannot be resolved.
3. Reject operations when Polkit returns false without an explicit error.
4. Guard registry lookups with locks and extend authorization unit tests.

Log: Restore Polkit fallback for valid unregistered callers

Influence:
1. Verify registered callers can access protected methods without Polkit.
2. Verify unregistered callers require successful Polkit authorization.
3. Verify UID lookup and Polkit denial failures block protected operations.

fix: 修正 security-loader 鉴权回退逻辑

1. 未注册的非 root 调用方统一回退到 Polkit 鉴权。
2. 调用方身份或注册表鉴权异常时保持失败关闭。
3. Polkit 返回未授权且无错误时显式拒绝敏感操作。
4. 在读锁内查询注册状态,并补充鉴权相关单元测试。

Log: 恢复合法未注册调用方的 Polkit 鉴权回退

Influence:
1. 验证已注册调用方无需 Polkit 即可访问受保护接口。
2. 验证未注册调用方仅在 Polkit 鉴权成功后可执行操作。
3. 验证 UID 查询失败和 Polkit 拒绝时不会执行受保护操作。

PMS: TASK-393313
@deepin-ci-robot

Copy link
Copy Markdown

deepin pr auto review

★ 总体评分:60分

■ 【总体评价】

代码引入了安全加载器机制以优化鉴权流程,但存在方法签名不一致导致功能失效的严重逻辑错误
逻辑缺陷导致核心功能受损,且存在潜在权限绕过风险,扣分较多

■ 【详细分析】

  • 1.语法逻辑(存在严重错误)✕

system/power1/manager.goSetTlpMode 方法签名增加了 sender dbus.Sender 参数,但对应的 system/power1/exported_methods_auto.go 未同步更新导出方法定义,将导致 D-Bus 反射调用时参数不匹配,方法无法正常导出或调用失败。langselector1/securityloader.goDoSecurityLoader 函数调用了 securityloader.Handshake 但未将返回的 cleanedArgs 赋值回 os.Args,导致 --fd1--fd2 参数残留,可能影响后续参数解析。
潜在问题:SetTlpMode 功能完全失效;langselector 启动参数污染
建议:同步更新 exported_methods_auto.goSetTlpMode 的定义;在 DoSecurityLoader 中使用 os.Args = cleanedArgs 更新参数

  • 2.代码质量(一般)✕

bin/dde-system-daemon/power.gosystem/inputdevices1/touchpad.gosystem/power1/manager_ifc.go 中存在高度重复的 checkDaemonAuthcheckTouchpadAuthcheckPowerAuth 函数,仅 actionId 不同,违反 DRY 原则。langselector1/securityloader.gosecurityloader/handshake.go 文件末尾缺少换行符。
潜在问题:代码维护成本增加,容易在修改时遗漏
建议:将鉴权函数抽象为通用方法,如 checkAuth(sysBusName, actionId string);在文件末尾补充换行符

  • 3.代码性能(存在性能问题)✕

securityloader/allowcaller.goAllowCallerRegistry.saveLocked 方法在持有写锁 mu 的情况下执行文件 I/O 操作(序列化、创建临时文件、写入、重命名),这会阻塞所有 Authorize 鉴权请求。虽然保证了数据一致性,但在高频调用场景下可能成为性能瓶颈。
建议:考虑异步持久化机制,或缩小锁的粒度,仅在修改内存数据结构时持锁,持久化操作在锁外执行

  • 4.代码安全(存在 1 个安全漏洞)✕

漏洞对比统计:新增漏洞 1 个,减少漏洞 0 个,持平 0 个
引入的白名单鉴权机制存在设计风险,deepin-daemon 组成员可注册同 UID 后代进程绕过 polkit 鉴权,若组权限管理不严可能导致权限提升

  • 安全漏洞1(中危):权限绕过 在 securityloader/allowcaller.goauthorizeRegistrar 函数中,允许 deepin-daemon 组成员注册与其相同 UID 的后代进程为可信调用者,从而绕过后续的 polkit 鉴权。如果 deepin-daemon 组包含非完全可信用户,攻击者可通过此机制执行需要特权操作而无需每次弹窗授权 ——非常重要

  • 建议:严格限制 SetAllowCaller 的调用权限,仅允许 root 或特定的系统服务用户调用,或在注册时增加额外的验证机制

■ 【改进建议代码示例】

--- a/system/power1/exported_methods_auto.go
+++ b/system/power1/exported_methods_auto.go
@@ -33,6 +33,11 @@ func (v *Manager) GetExportedMethods() dbusutil.ExportedMethods {
 			Name: "RefreshMains",
 			Fn:   v.RefreshMains,
 		},
+		{
+			Name:   "SetTlpMode",
+			Fn:     v.SetTlpMode,
+			InArgs: []string{"mode"},
+		},
 		{
 			Name:   "SetAllowCaller",
 			Fn:     v.SetAllowCaller,
diff --git a/langselector1/securityloader.go b/langselector1/securityloader.go
index ceca6d74d..000000000
--- a/langselector1/securityloader.go
+++ b/langselector1/securityloader.go
@@ -21,7 +21,8 @@ func DoSecurityLoader(args []string) {
 	// 构建 destList,包括 lastore 和 accounts
 	destList := buildDestList()
 
-	_, loaded, err := securityloader.Handshake(args, destList)
+	cleanedArgs, loaded, err := securityloader.Handshake(args, destList)
+	os.Args = cleanedArgs
 	if err != nil {
 		if loaded {
 			logger.Warning("security loader handshake failed:", err)
@@ -91,4 +92,4 @@ func getCurrentUserAccountsPath() (string, error) {
 	}
 
 	return userPath, nil
-}
\ No newline at end of file
+}
diff --git a/bin/dde-system-daemon/power.go b/bin/dde-system-daemon/power.go
index 528697af6..5ee16805a 100644
--- a/bin/dde-system-daemon/power.go
+++ b/bin/dde-system-daemon/power.go
@@ -209,6 +209,7 @@ func (d *Daemon) SetScreenState(sender dbus.Sender, state bool) *dbus.Error {
 	return dbusutil.ToError(d.setState(d.idleScreenStatePath, state))
 }
 
+// checkAuth 通用 polkit 鉴权函数
 func checkAuth(sysBusName, actionId string) (bool, error) {
 	systemBus, err := dbus.SystemBus()
 	if err != nil {

@deepin-ci-robot

Copy link
Copy Markdown

@fly602: The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
github-pr-review-ci 921f3a7 link true /test github-pr-review-ci

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. I understand the commands that are listed here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants