Skip to content

refactor(accounts): disable UnionID password setting due to security check race condition#1045

Merged
ComixHe merged 1 commit intolinuxdeepin:masterfrom
ComixHe:master
Mar 5, 2026
Merged

refactor(accounts): disable UnionID password setting due to security check race condition#1045
ComixHe merged 1 commit intolinuxdeepin:masterfrom
ComixHe:master

Conversation

@ComixHe
Copy link
Contributor

@ComixHe ComixHe commented Mar 4, 2026

The newCaller() function uses /proc//exe to verify the caller is running a trusted binary, but this check has a race condition and can be faked by the caller. Since there is no quick fix and this feature is not currently needed, temporarily disable the UnionID password setting functionality.

Pms: BUG-349987

Summary by Sourcery

Temporarily disable setting passwords via UnionID due to an insecure caller verification mechanism and document the executable-path-based caller check as problematic.

Bug Fixes:

  • Prevent potential exploitation of the UnionID-based password setting flow by bypassing an unreliable caller security check.

Enhancements:

  • Mark the executable-path-based caller identification logic with a FIXME comment to highlight the need for a safer approach.

@sourcery-ai
Copy link

sourcery-ai bot commented Mar 4, 2026

Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

This PR temporarily disables the UnionID-based password setting path due to a race-condition vulnerability in caller verification, and documents the underlying issue in the caller identification logic.

Sequence diagram for updated SetPassword UnionID handling

sequenceDiagram
    participant Client
    participant DbusSender as Dbus_Sender
    participant User as User_SetPassword

    Client->>User: SetPassword(sender, password)
    User->>User: check if password is empty
    alt password_is_empty
        Note over User: UnionID-based password setting<br/>path is temporarily disabled
        User-->>Client: return nil (no password change)
    else password_is_non_empty
        User->>User: checkAuth(sender, false, "")
        alt auth_success
            User->>User: setPasswordWithProvidedPassword
            User-->>Client: return nil
        else auth_failure
            User-->>Client: return dbus.Error
        end
    end
Loading

File-Level Changes

Change Details Files
Bypass UnionID-based password setting when an empty password is supplied to SetPassword.
  • Change SetPassword to immediately return success when the provided password string is empty instead of delegating to the UnionID-based password setting helper
  • Remove the call to the UnionID password setting helper and its associated error handling path in SetPassword
accounts1/user_ifc.go
Document the security concern with using the executable path for caller identification in newCaller.
  • Add a FIXME comment noting that relying on the executable path to identify the caller is unsafe and should be avoided
accounts1/user_chpwd_union_id.go

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

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey - I've left some high level feedback:

  • Silently returning nil when password == "" changes behavior in a way that might be hard to detect; consider returning a specific error or at least logging that UnionID-based password setting is disabled so callers can react appropriately.
  • Since the newCaller executable-path check is known to be unsafe and marked FIXME, it may be safer to short-circuit callers that rely on it (or guard it behind a feature flag) to avoid accidental future reuse while the race condition remains unresolved.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Silently returning nil when `password == ""` changes behavior in a way that might be hard to detect; consider returning a specific error or at least logging that UnionID-based password setting is disabled so callers can react appropriately.
- Since the `newCaller` executable-path check is known to be unsafe and marked FIXME, it may be safer to short-circuit callers that rely on it (or guard it behind a feature flag) to avoid accidental future reuse while the race condition remains unresolved.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@ComixHe ComixHe requested a review from fly602 March 4, 2026 09:46
fly602
fly602 previously approved these changes Mar 5, 2026
…check race condition

The newCaller() function uses /proc/<pid>/exe to verify the caller is running
a trusted binary, but this check has a race condition and can be faked by the
caller. Since there is no quick fix and this feature is not currently needed,
temporarily disable the UnionID password setting functionality.

Pms: BUG-349987
Signed-off-by: ComixHe <heyuming@deepin.org>
@deepin-ci-robot
Copy link

deepin pr auto review

经过对提供的 Git diff 的审查,这段代码主要涉及了 DBus 服务端的调用者验证逻辑修改。以下是针对语法逻辑、代码质量、代码性能和代码安全的详细审查意见及改进建议:

1. 代码逻辑与安全性审查

主要问题:安全验证被移除

user_chpwd_union_id.go 文件中,代码注释掉了通过可执行文件路径 (proc.Exe()) 来验证调用者身份的逻辑,并将 app 字段硬编码为 "unknown"。随后在 user_ifc.go 中,当 SetPassword 接收到空密码(即 UnionID 设置密码的触发条件)时,直接返回 nil,完全移除了 setPwdWithUnionID 的调用。

  • 风险分析:这是一个严重的安全隐患。
    • 原逻辑:只允许特定的受信任进程(控制中心、锁屏、登录界面)触发 UnionID 密码设置。这是一种防御性编程,防止恶意程序通过 DBus 接口重置用户密码。
    • 修改后:任何能够连接到 DBus System Bus 并调用该方法的进程,只要传入空字符串作为密码,都能绕过验证。虽然注释中写了 FIXME,但在没有替代验证机制的情况下移除现有机制,会极大地降低系统安全性。

改进建议

  • 必须恢复或替代验证机制:不能仅仅注释掉代码而不提供替代方案。
  • 使用更安全的验证方式:正如 FIXME 所说,依赖可执行文件路径并不完全安全(路径可能被伪造或改变)。建议使用 Linux Security Modules (LSM),如 AppArmorSELinux 的上下文来验证调用者,或者检查调用者的 UID/GID 以及进程的 Capabilities
  • 代码完整性:如果 setPwdWithUnionID 函数不再被使用,应该在代码库中彻底删除该函数及其相关依赖,以保持代码整洁。

2. 代码质量审查

  • 注释与 FIXME
    • FIXME 注释表明开发者知道当前的修改(硬编码 "unknown")是不完美的。但在代码合并前,应该有明确的计划或 Issue 跟踪这个 FIXME,而不是让代码长期处于这种“已知不安全”的状态。
  • 版权年份更新
    • user_ifc.go 中的版权年份从 2022 更新到了 2026。通常版权年份更新至当前年份即可,更新到未来的年份(2026)虽然不违法,但不符合常规操作,建议修改为当前年份(如 2023 或 2024)。

3. 代码性能审查

  • 性能影响
    • 移除了 proc.Exe() 的调用,这在性能上是一个微小的提升(因为读取 /proc/<pid>/exe 涉及系统调用)。但鉴于这是安全验证的关键步骤,这种性能提升得不偿失。
  • 逻辑简化
    • user_ifc.go 中,if password == "" 块内的逻辑被简化为直接 return nil。这消除了函数调用开销,但同样,这是以牺牲功能和安全为代价的。

4. 具体修改建议代码

为了修复上述安全问题,建议不要直接注释掉验证逻辑,而是采用基于 PID 的安全检查(例如检查 PID 是否属于特定的系统用户或具有特定安全标签)。以下是一个基于现有代码结构的改进示例,假设我们决定暂时保留路径检查但增强错误处理,或者建议引入更严格的检查:

建议方案 A(如果必须移除路径检查,应至少保留 UID 检查作为临时防线):

// accounts1/user_chpwd_union_id.go

// ... 获取 proc ...

// 注释掉路径检查,但建议增加 UID 检查
// var app string
// switch exe { ... }

// 新增:检查调用者是否为 root 或特定系统用户
uid, err := proc.Uid()
if err != nil {
    err = fmt.Errorf("get sender uid error: %v", err)
    return
}

// 假设只有 root (uid 0) 或特定系统用户有权调用
// 这比完全不做检查要好,但不如 LSM 安全
if uid != 0 {
    err = fmt.Errorf("set password with Union ID called by uid %d, permission denied", uid)
    return
}

// ... 后续逻辑 ...

ret = &caller{
    // ...
    // 暂时标记为 system 或 root,而不是 unknown
    app: "system", 
    // ...
}

建议方案 B(针对 user_ifc.go 的逻辑恢复):

// accounts1/user_ifc.go

func (u *User) SetPassword(sender dbus.Sender, password string) *dbus.Error {
    // ... 前置检查 ...

    // set password from UnionID
    if password == "" {
        // 即使 newCaller 做了放宽,这里也应确保逻辑完整
        // 如果 setPwdWithUnionID 确实不再需要,请删除该函数定义
        // 否则应该保留调用,除非有明确的业务逻辑变更说明
        logger.Warning("SetPassword with empty password called, triggering UnionID flow")
        err := u.setPwdWithUnionID(sender)
        if err != nil {
            return dbusutil.ToError(err)
        }
        return nil
    }

    // ... 正常密码设置逻辑 ...
}

总结

这段代码修改目前处于不安全且逻辑不完整的状态。

  1. 拒绝当前 Diff:在未补充替代安全验证机制之前,不应合并此代码。
  2. 修复安全漏洞:必须重新引入对调用者的身份验证。
  3. 清理代码:如果 setPwdWithUnionID 确实废弃,请删除相关代码;如果是临时禁用,请添加详细的 Jira/Issue 链接说明原因和恢复计划。
  4. 修正版权年份:将 2026 改为当前年份。

@deepin-ci-robot
Copy link

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: ComixHe, 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

@ComixHe ComixHe merged commit 1bbd70b into linuxdeepin:master Mar 5, 2026
16 of 18 checks passed
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.

3 participants