Skip to content

fix(power): read procfs credentials before checking EOF - #197

Merged
deepin-bot[bot] merged 1 commit into
linuxdeepin:masterfrom
fly602:fix/power-caller-proc-credentials
Oct 15, 2026
Merged

deepin-bot[bot] merged 1 commit into
linuxdeepin:masterfrom
fly602:fix/power-caller-proc-credentials

Conversation

@fly602

@fly602 fly602 commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

fix: read procfs credentials before checking EOF

  1. Read the first line before testing for EOF, instead of relying on
    QFile::atEnd(); procfs reports size 0, so atEnd() is already true
    before the first read.
  2. Normalize whitespace so the tab separated Gid field parses too, and
    ignore non numeric fields so gid 0 cannot be matched by a gap.
  3. Use the same read loop in readParentPid(), which backs the descendant
    check performed when a caller registers itself.

Log: Restore passwordless caller registration for the power service

Influence:

  1. Upgrade dde-services and log in again: /run/dde-services/
    power_allow_callers.json should now exist and list the session bus
    unique name.
  2. User journal should no longer log "invalid caller :1.x" for
    dde-session at login.
  3. Hibernate from one logged in user, resume, switch to the other user:
    no administrator password dialog should be left behind.
  4. Switch the power mode from control center in an active session and
    confirm no polkit prompt appears.

fix: 修正 procfs 凭据读取,恢复免密授权注册

  1. 改为先读取一行再判断结束,不再依赖 QFile::atEnd():procfs 文件
    大小为 0,首次读取前 atEnd() 已为真。
  2. 归一化空白字符,使制表符分隔的 Gid 字段可解析;忽略非数字字段,
    避免空字段被当作 gid 0 匹配。
  3. readParentPid() 采用同样的读取方式,它是调用方注册时判断进程
    父子关系的基础。

Log: 恢复电源服务调用方的免密注册

Influence:

  1. 升级 dde-services 后重新登录,/run/dde-services/
    power_allow_callers.json 应生成并包含会话的系统总线唯一名。
  2. 登录阶段用户日志中不再出现 dde-session 的
    "invalid caller :1.x"。
  3. 在一个用户会话中休眠,唤醒后切到另一个用户,确认不再残留管理员
    密码认证弹窗。
  4. 活动会话中通过控制中心切换电源模式,确认无 polkit 弹窗。

PMS: BUG-379055

Summary by Sourcery

Restore passwordless power-service authorization by making procfs credential and process ancestry checks reliable.

Bug Fixes:

  • Restore power service caller registration by correctly reading credentials and parent-process data from procfs files.
  • Prevent non-numeric procfs fields from being interpreted as group ID 0.

Enhancements:

  • Normalize procfs credential whitespace so tab-separated group fields are parsed reliably.

@sourcery-ai

sourcery-ai Bot commented Oct 15, 2026

Copy link
Copy Markdown
Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Fix power-system caller authorization on procfs by reading credential data before EOF checks, normalizing Gid/Groups whitespace, and validating numeric gids; this restores legitimate loader authorization and prevents unnecessary polkit prompts.

Sequence diagram for power caller authorization via procfs

sequenceDiagram
    participant Loader as deepin-security-loader
    participant Power as power-system
    participant Procfs as procfs_status
    participant Policy as CallerPolicy

    Loader->>Power: SetAllowCaller()
    Power->>Procfs: processHasGroup()
    Procfs-->>Power: Gid/Groups match
    Power->>Procfs: readParentPid()
    Procfs-->>Power: PPid
    Power->>Policy: addAllowedCaller()
    Policy-->>Power: caller authorized
Loading

Flow diagram for procfs credential parsing

flowchart TD
    A[Open /proc/<pid>/status] --> B[Read first line]
    B --> C{Data is empty?}
    C -- Yes --> D[Return false]
    C -- No --> E{Gid or Groups line?}
    E -- No --> B
    E -- Yes --> F[Normalize whitespace]
    F --> G[Parse numeric fields]
    G --> H{Matching gid found?}
    H -- Yes --> I[Return true]
    H -- No --> B
Loading

File-Level Changes

Change Details Files
Replace procfs EOF-driven iteration with read-first loops so credential and parent-process parsing works with procfs files that report a zero size.
  • Read each line before evaluating termination, allowing the first procfs line to be processed.
  • Apply the same iteration fix to group membership and parent PID parsing.
src/plugin-qt/power/system/powermanager.cpp
Make group parsing robust across procfs whitespace and reject malformed numeric fields.
  • Normalize tabs and spaces after the Gid/Groups separator before splitting values.
  • Require successful numeric conversion before comparing a parsed value with the requested gid.
src/plugin-qt/power/system/powermanager.cpp

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

@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.

Hey - I've reviewed your changes and they look great!


Sourcery is free for open source - if you like our reviews please consider sharing them ✨

@fly602
fly602 force-pushed the fix/power-caller-proc-credentials branch from b2eb63e to d232dd6 Compare October 15, 2026 11:22
1. Read the first line before testing for EOF, instead of relying on
   QFile::atEnd(); procfs reports size 0, so atEnd() is already true
   before the first read.
2. Normalize whitespace so the tab separated Gid field parses too, and
   ignore non numeric fields so gid 0 cannot be matched by a gap.
3. Use the same read loop in readParentPid(), which backs the descendant
   check performed when a caller registers itself.

Log: Restore passwordless caller registration for the power service

Influence:
1. Upgrade dde-services and log in again: /run/dde-services/
   power_allow_callers.json should now exist and list the session bus
   unique name.
2. User journal should no longer log "invalid caller :1.x" for
   dde-session at login.
3. Hibernate from one logged in user, resume, switch to the other user:
   no administrator password dialog should be left behind.
4. Switch the power mode from control center in an active session and
   confirm no polkit prompt appears.

fix: 修正 procfs 凭据读取,恢复免密授权注册

1. 改为先读取一行再判断结束,不再依赖 QFile::atEnd():procfs 文件
   大小为 0,首次读取前 atEnd() 已为真。
2. 归一化空白字符,使制表符分隔的 Gid 字段可解析;忽略非数字字段,
   避免空字段被当作 gid 0 匹配。
3. readParentPid() 采用同样的读取方式,它是调用方注册时判断进程
   父子关系的基础。

Log: 恢复电源服务调用方的免密注册

Influence:
1. 升级 dde-services 后重新登录,/run/dde-services/
   power_allow_callers.json 应生成并包含会话的系统总线唯一名。
2. 登录阶段用户日志中不再出现 dde-session 的
   "invalid caller :1.x"。
3. 在一个用户会话中休眠,唤醒后切到另一个用户,确认不再残留管理员
   密码认证弹窗。
4. 活动会话中通过控制中心切换电源模式,确认无 polkit 弹窗。

PMS: BUG-379055
@fly602
fly602 force-pushed the fix/power-caller-proc-credentials branch from d232dd6 to 36e6044 Compare October 15, 2026 11:31
@deepin-ci-robot

Copy link
Copy Markdown

deepin pr auto review

🤖 AI 代码审查报告

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

Pass


📊 总体评价

项目 结果
审查结论 代码审查通过
评分详情 总体评分 98 分,大于 70 分通过阈值,代码质量符合要求。本次修改正确修复了 procfs 凭据读取问题,逻辑清晰,无安全漏洞。

🔍 详细分析

1. 语法逻辑 ✅

评价: 优秀 ✅ 通过

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

建议: 语法正确,逻辑清晰。for 循环模式 (QByteArray data = file.readLine(); !data.isEmpty(); data = file.readLine()) 正确处理了 procfs 文件大小为 0 的情况。toUInt(&ok) 的 ok 标志检查正确防止了非数字字符串的误匹配。simplified() 正确归一化了空白字符。边界条件处理完善:空文件时循环不执行返回 false,无匹配行时循环耗尽返回 false。


2. 代码质量 ✅

评价: 优秀 ✅ 通过

潜在问题:

  1. src/plugin-qt/power/system/powermanager.cpp:103 - readParentPid() 函数缺少与 processHasGroup() 类似的 procfs 行为说明注释,建议添加注释提高可维护性

建议: 代码结构清晰,注释完整。建议在 readParentPid() 函数中添加与 processHasGroup() 相同的 procfs 行为说明注释,提高代码可维护性。两个函数的读取循环模式一致,可考虑未来提取为公共辅助函数。


3. 代码性能 ✅

评价: 优秀 ✅ 通过

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

建议: 性能良好,资源使用合理。修改后将 QString::fromLatin1() 转换延迟到匹配行才执行,避免了非匹配行的 unnecessary 字符串转换。QByteArray::startsWith() 比 QString::startsWith(QLatin1String()) 更高效。无不必要的内存分配。


4. 代码安全 🔒

评价: 优秀 ✅ 通过

🔐 发现 0 个安全漏洞

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

建议: 漏洞对比统计:新增漏洞 0 个,减少漏洞 0 个,持平 0 个。存在0个安全漏洞。本次修改实际上是安全增强:toUInt(&ok) 的 ok 标志检查防止了非数字字段被转换为 0 后误匹配 gid 0(root 组),避免了潜在的权限提升风险。无硬编码凭据,无注入风险,无敏感信息泄露。


💡 改进建议代码示例

// 建议在 readParentPid() 中添加注释,与 processHasGroup() 保持一致
static bool readParentPid(uint pid, uint &parent)
{
    QFile file(QString::fromLatin1("/proc/%1/status").arg(pid));
    if (!file.open(QIODevice::ReadOnly))
        return false;

    // procfs reports size zero, so atEnd() is true even before the first read.
    for (QByteArray data = file.readLine(); !data.isEmpty(); data = file.readLine()) {
        if (!data.startsWith("PPid:"))
            continue;
        const QString line = QString::fromLatin1(data);
        bool ok = false;
        parent = line.section(QLatin1Char(':'), 1).trimmed().toUInt(&ok);
        return ok;
    }
    return false;
}

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

@deepin-ci-robot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: fly602, mhduiy

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

@fly602

fly602 commented Oct 15, 2026

Copy link
Copy Markdown
Contributor Author

/forcemerge

@deepin-bot

deepin-bot Bot commented Oct 15, 2026

Copy link
Copy Markdown

This pr force merged! (status: blocked)

@deepin-bot
deepin-bot Bot merged commit 2bbce32 into linuxdeepin:master Oct 15, 2026
6 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