Skip to content

fix(security): enforce fail-closed auth and validate path inputs - #967

Merged
deepin-bot[bot] merged 2 commits into
linuxdeepin:masterfrom
add-uos:fix-security-auth-fail-closed-and-input-validation
Nov 11, 2026
Merged

deepin-bot[bot] merged 2 commits into
linuxdeepin:masterfrom
add-uos:fix-security-auth-fail-closed-and-input-validation

Conversation

@add-uos

@add-uos add-uos commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor

安全修复 Summary

修复 deepin-devicemanager D-Bus 接口(deepin-devicecontrol)的四个安全问题(对应内部安全报告 0007/0009):

1. 鉴权 fail-open(根因,P0)

getUserAuthorPasswd() 中 serviceUid() 查询失败时,QDBusReply::value() 返回默认值 0(root),未认证调用被误判为 root 直接放行。攻击者用 NO_REPLY 发送调用后立即断开连接,即可在 GetConnectionUnixUser 返回 NameHasNoOwner 时绕过 polkit。

修复:查询失败时 fail-closed 拒绝。

2. delDeb 路径穿越(P0)

delDeb(debname) 直接拼接 DB_PATH/driver/<debname> 后递归删除,无组件名校验,../../../../var/lib/xxx 可穿越删除任意 root 目录/文件。

修复:与 backupDebFd 一致使用 FdUtil::isValidComponentName 白名单校验。

3. setWakeupMachine 路径穿越(P1)

wakeupPath() 拼接 "/sys" + syspath 后写 "enabled"/"disabled",syspath 含 .. 时可覆写任意 root 文件前 7 字节。

修复:拒绝含 .. 的 syspath,并校验解析后的文件路径必须位于 /sys 之下。

4. enablePrinter 栈越界读(P1)

construct_uri() 在缓冲区恰好填满时不写 NUL,ippAddString() 内部 strlen() 越界读。999 字符 printer name 触发 ASan stack-buffer-overflow READ of size 1025 @ controlinterface.cpp:185,daemon 崩溃。

修复:缓冲区填满时截断并保证 NUL 终止。

附带

qdelDirectory() 递归删除时清理空子目录,使备份目录树完整删除(原实现残留空目录骨架)。

自测

测试 修复前 修复后
竞态鉴权绕过(发送+断连 ×15+20×10) 第 1 次尝试即放行,victim 文件被覆写 全部拒绝(NameHasNoOwner → fail-closed),victim 完好
delDeb 路径穿越(root) 删光 root-owned 文件(含嵌套) 穿越被拒;合法组件名正常删除(含顶层目录)
setWakeupMachine 穿越覆写(root) root 文件前 7 字节被覆写 穿越被拒,文件完好
enablePrinter 999×'a'(ASan 构建) stack-buffer-overflow READ of size 1025,daemon 崩溃 正常执行返回 true,无 ASan 报错,daemon 存活

测试环境:私有 D-Bus(未触碰系统 bus);非 root(uid 24129)与非特权 userns root 两种身份;Release(DISABLE_POLKIT=false)与 ASan 双构建。

影响范围

仅加固 deepin-devicecontrol 的鉴权与输入校验逻辑,正常授权流程(合法 root 调用、polkit 认证)行为不变。

Summary by Sourcery

Harden deepin-devicecontrol authorization and path handling against security bypasses, arbitrary file deletion or modification, and malformed printer input.

Bug Fixes:

  • Make authorization fail closed when the caller UID cannot be resolved, preventing unauthenticated D-Bus requests from being treated as root.
  • Prevent path traversal in Debian package deletion and wakeup-device paths.
  • Ensure printer URI buffers are always NUL-terminated to prevent out-of-bounds reads.

Enhancements:

  • Remove empty nested directories during recursive backup cleanup.

Tests:

  • Update control-interface and wakeup utility tests to cover NUL termination and canonical path validation.

- Reject D-Bus calls when resolving the sender UID fails instead of
  treating the default value 0 as root (authorization fail-open)
- Validate debname with the component-name whitelist in delDeb to
  block path traversal that deleted arbitrary directories as root
- Reject '..' in syspath and verify the resolved wakeup file stays
  under /sys to prevent overwriting arbitrary root-owned files
- Always NUL-terminate the URI built by construct_uri to fix a stack
  out-of-bounds read (ASan: READ of size 1025) in ippAddString
- Remove now-empty subdirectories in qdelDirectory so the backup
  directory tree is fully deleted

修复安全问题:发送方UID查询失败时拒绝调用(原实现将默认值0误判为root
导致鉴权可被竞态绕过);delDeb增加组件名白名单校验防止路径穿越删除任意
目录;wakeup路径校验防止覆写任意root文件;construct_uri保证NUL终止修
复栈越界读;qdelDirectory清理空子目录。

Log: 修复鉴权fail-open、路径穿越删除/覆写及URI栈越界读等安全问题
Influence: 加固 deepin-devicecontrol D-Bus 接口鉴权与输入校验,正常功能不受影响。
@sourcery-ai

sourcery-ai Bot commented Nov 10, 2026

Copy link
Copy Markdown

Sorry @add-uos, you've used your own review budget of 250,000 diff characters for the last 7 days.

You can request another review in 20 hours and 56 minutes by commenting @sourcery-ai review. Upgrade to get a review now.

@sourcery-ai

sourcery-ai Bot commented Nov 10, 2026 •

Copy link
Copy Markdown

Reviewer's Guide

Implementation

Reject D-Bus calls when the sender UID lookup fails, so an invalid reply cannot default to UID 0 and bypass authorization.

  • deepin-devicemanager-server/deepin-devicecontrol/src/controlinterface.cpp L91-99

Ensure printer URI construction NUL-terminates a full buffer, preventing downstream reads past its end.

  • deepin-devicemanager-server/deepin-devicecontrol/src/controlinterface.cpp L672-678

Validate package names before deletion and remove emptied child directories so valid backup trees are fully deleted.

  • deepin-devicemanager-server/deepin-devicecontrol/src/drivercontrol/drivermanager.cpp L748-750, L761-765

Reject traversal in wakeup paths and require the resolved target to remain under /sys before allowing use of that path.

  • deepin-devicemanager-server/deepin-devicecontrol/src/wakecontrol/wakeuputils.cpp L14, L89-93, L102-107

Tests

Update URI overflow tests to assert that exactly full buffers are truncated and NUL-terminated.

  • deepin-devicemanager-server/tests/control-ut/ut_controlinterface.cpp L893-898, L909-914

Stub canonical path resolution in wakeup-device tests so their mocked existing /sys files pass the new containment check.

  • deepin-devicemanager-server/tests/src/WakeControl/ut_wakeuputils.cpp L447-453 (+5 small edits)

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

对齐 PR linuxdeepin#967 安全修复后的实际行为,更新 6 个固化旧缺陷行为的用例:
1. ConstructUri_BaseOverflow_TruncatesBase / ConstructUri_ValueOverflow_StopsAtBufferEnd:
   construct_uri 恰好填满缓冲区时现在截去末尾 1 字符并强制 NUL 终止(ut-t25
   越界读缺陷已修复),更新断言从"恰好填满不写 NUL"改为"截断并 NUL 终止";
2. WakeupUtilsTest 4 个 updateWakeupDeviceInfo 用例:wakeupPath 新增
   canonicalFilePath 兜底校验后,QFile::exists 打桩为 true 但 QFileInfo 未打桩,
   假路径 canonical 解析返回空串被误判为逃逸 /sys 导致 writeWakeupFile 不再被
   调用;补充 QFileInfo::canonicalFilePath 打桩模拟真实存在的 /sys 文件。

Align 6 test cases with the actual behavior after the security fixes in
PR linuxdeepin#967: construct_uri now truncates one char and force-terminates with
NUL when the buffer is exactly full (ut-t25 OOB-read fixed); wakeupPath
now validates the canonical path stays under /sys, so the 4
updateWakeupDeviceInfo cases stub QFileInfo::canonicalFilePath to
simulate a real /sys file.

Log: 更新单元测试以对齐 PR linuxdeepin#967 安全修复后的正确行为
Influence: 仅测试代码,不影响功能逻辑
@add-uos

add-uos commented Nov 10, 2026

Copy link
Copy Markdown
Contributor Author

本地全量单测验证(3281 客户端用例 + 830 服务端/control 用例)发现本 PR 会导致 6 个用例失败,均为测试固化了修复前的旧(缺陷)行为,已在 bcfa5cc 更新测试对齐:

control-test(2 个)

  • ConstructUri_BaseOverflow_TruncatesBase / ConstructUri_ValueOverflow_StopsAtBufferEnd:construct_uri 恰好填满缓冲区时现在截去末尾 1 字符并强制 NUL 终止(ut-t25 越界读缺陷已修复),断言从"恰好填满不写 NUL"更新为"截断并 NUL 终止"

server-test / WakeupUtilsTest(4 个)

  • updateWakeupDeviceInfo_{uidMatch_dbWakeupTrue, md5Uid, ps2Keyboard, md5UidWithDeviceLink}_*:wakeupPath 新增 canonicalFilePath 兜底校验后,测试中 QFile::exists 打桩为 true 但 QFileInfo 未打桩,假路径 canonical 解析返回空串会被误判为"逃逸出 /sys";补充 QFileInfo::canonicalFilePath 打桩模拟真实存在的 /sys 文件

更新后本地实测:control-test 73/73、WakeupUtilsTest 49/49 全部通过。

@deepin-ci-robot

Copy link
Copy Markdown

deepin pr auto review

🤖 AI 代码审查报告

总体评分: 100 分 (通过阈值: 70分)

Pass


📊 总体评价

项目 结果
审查结论 代码审查通过
评分详情 本次提交是一个安全加固修复,修复了4个安全问题(权限绕过、缓冲区未终止读取、2处路径穿越),代码逻辑正确、注释详尽、测试同步更新,未引入新的安全漏洞。OCR 指出的 '..' 子串检查范围过宽属于轻微改进建议,不影响安全性(fail-closed 行为保证安全)。

🔍 详细分析

1. 语法逻辑 ✅

评价: 语法正确,逻辑清晰 ✅ 通过

潜在问题:
✅ 未发现明显问题

建议: ["construct_uri() 中 buflen==0 时 else 分支会执行 buffer[-1]='\0' 越界写,建议在函数入口增加 buflen>0 前置检查,虽然当前无调用方传 0,但防御性编程更安全。"]


2. 代码质量 ✅

评价: 代码结构清晰,注释完整 ✅ 通过

潜在问题:
✅ 未发现明显问题

建议: ["考虑将 syspath.contains('..') 替换为 QDir::cleanPath(syspath) 规范化后检查是否仍以 '/' 开头且不含 '..',或移除子串检查仅依赖 canonicalFilePath() 兜底校验。"]


3. 代码性能 ✅

评价: 性能良好,资源使用合理 ✅ 通过

潜在问题:
✅ 未发现明显问题

建议: []


4. 代码安全 🔒

评价: 存在0个安全漏洞 ✅ 通过

🔐 发现 0 个安全漏洞

安全漏洞详情:
✅ 未发现安全漏洞

建议: ['建议在 construct_uri() 入口增加 buflen > 0 的断言或前置检查,彻底消除 buflen==0 时的理论越界写。']


💡 改进建议代码示例

// construct_uri 入口增加 buflen 防御性检查
void ControlInterface::construct_uri(char *buffer, size_t buflen, const char *base, const char *value)
{
    if (!buffer || buflen == 0) {
        return; // 防御性检查:空缓冲区或零长度直接返回
    }
    // ... 原有逻辑 ...
}

// wakeupPath 改进:用 QDir::cleanPath 替代 contains("..") 子串检查
bool WakeupUtils::wakeupPath(const QString &syspath, QString &wakeuppath)
{
    qCDebug(appLog) << "Finding wakeup path for syspath:" << syspath;
    // 规范化路径,消除冗余的 "." 和 ".."
    const QString cleaned = QDir::cleanPath(syspath);
    if (cleaned.contains(QLatin1String(".."))) {
        qCWarning(appLog) << "Invalid syspath contains '..':" << syspath;
        return false;
    }
    // ... 原有逻辑 ...
}

本报告由 AI 代码审查工具自动生成

@deepin-ci-robot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: add-uos, lzwind

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

@add-uos

add-uos commented Nov 11, 2026

Copy link
Copy Markdown
Contributor Author

/forcemerge

@deepin-bot
deepin-bot Bot merged commit 63ef909 into linuxdeepin:master Nov 11, 2026
16 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