Skip to content

feat(daemon): integrate deepin-security-loader trust mechanism - #258

Merged
max-lvs merged 1 commit into
linuxdeepin:develop/eaglefrom
wangrong1069:pr0911-3
Sep 11, 2026
Merged

max-lvs merged 1 commit into
linuxdeepin:develop/eaglefrom
wangrong1069:pr0911-3

Conversation

@wangrong1069

@wangrong1069 wangrong1069 commented Sep 11, 2026 •

Copy link
Copy Markdown
Contributor

Add trust_client for process whitelist negotiation with deepin-security-loader, switch to RelayEventListener, and launch daemon via loader with forking service type and PID file tracking.

集成 deepin-security-loader 进程信任机制,新增 trust_client 进行 白名单协商;切换到 RelayEventListener;daemon 通过 loader 启动,
service 改为 forking 模式并使用 PID 文件跟踪;日志切换到 syslog
避免 loader 关闭 stdout 后丢失;fs_event 字段统一为 path,rename 跟踪改用 unordered_map;新增 trust_client 单元测试框架。

Log: 集成 deepin-security-loader 信任机制并重构事件处理
PMS: BUG-370779
Influence: daemon 现在通过 deepin-security-loader 启动并进行进程白名单 协商,事件监听切换为中继模式,日志改用 syslog,影响 daemon 启动流程、
事件处理和日志输出方式。

Summary by Sourcery

Integrate deepin-security-loader trust enforcement and relay-based event handling into the daemon lifecycle.

New Features:

  • Add process trust negotiation with deepin-security-loader through a dedicated trust client.
  • Switch daemon event consumption to a relay listener with server restart detection.

Bug Fixes:

  • Preserve daemon logging when the security loader closes standard output and error streams.
  • Improve rename event pairing and handling for concurrent filesystem events.

Enhancements:

  • Standardize filesystem event metadata around a single path field and add mount-device information.
  • Track the daemon PID for systemd-managed forking startup.

Build:

  • Install the daemon under the loader-managed deepin libexec directory and add optional test targets.

Deployment:

  • Update the systemd service to launch through deepin-security-loader with forking semantics and PID-file tracking.

Tests:

  • Add unit tests covering trust-client argument parsing and trust negotiation responses and failure cases.

Add trust_client for process whitelist negotiation with
deepin-security-loader, switch to RelayEventListener, and launch
daemon via loader with forking service type and PID file tracking.

集成 deepin-security-loader 进程信任机制,新增 trust_client 进行
白名单协商;切换到 RelayEventListener;daemon 通过 loader 启动,
service 改为 forking 模式并使用 PID 文件跟踪;日志切换到 syslog
避免 loader 关闭 stdout 后丢失;fs_event 字段统一为 path,rename
跟踪改用 unordered_map;新增 trust_client 单元测试框架。

Log: 集成 deepin-security-loader 信任机制并重构事件处理
PMS: BUG-370779
Influence: daemon 现在通过 deepin-security-loader 启动并进行进程白名单
协商,事件监听切换为中继模式,日志改用 syslog,影响 daemon 启动流程、
事件处理和日志输出方式。
@sourcery-ai

sourcery-ai Bot commented Sep 11, 2026

Copy link
Copy Markdown

Reviewer's Guide

The daemon is reworked for deepin-security-loader integration: startup now negotiates process trust over injected file descriptors, filesystem events arrive through a relay listener, event data and rename correlation are refactored, and systemd deployment/logging are updated for loader-managed forking execution with opt-in protocol tests.

Sequence diagram for loader trust negotiation and daemon startup

sequenceDiagram
    participant Loader as deepin-security-loader
    participant Daemon as deepin-anything-daemon
    participant DBus as SystemBus

    Loader->>Daemon: exec with --fd1 and --fd2
    Daemon->>Daemon: write_pid_file()
    Daemon->>DBus: g_bus_get_sync()
    Daemon->>Daemon: parse_trust_fds()
    Daemon->>Loader: JSON trust request via request_fd
    Daemon->>Daemon: read_balanced_json()
    Loader-->>Daemon: JSON response via response_fd
    Daemon->>Daemon: request_dbus_trust()
    alt Result is true
        Daemon->>Daemon: start relay event listener
    else Result is false or request fails
        Daemon-->>Loader: exit APP_QUIT_CODE
    end
Loading

Sequence diagram for relay event delivery and server restart handling

sequenceDiagram
    participant Server as deepin-anything-server
    participant Relay as RelayEventListener
    participant Handler as default_event_handler
    participant DBus as SystemBus

    Relay->>Server: event_relay_receiver_new()
    Relay->>Server: event_relay_receiver_get_fd()
    Relay->>Relay: relay_event_listener_start()
    Server-->>Relay: filesystem events over relay channel
    Relay->>Relay: event_relay_receiver_receive()
    Relay->>Handler: callback(user_data, fs_event)
    Handler->>Handler: convert_fs_event()
    Handler->>Handler: filter_event()
    alt relay connection lost
        Relay->>DBus: get_bus_name_owner()
        DBus-->>Relay: current unique bus owner
        Relay->>Relay: on_restart_check()
        Relay-->>Handler: quit_callback(user_data)
    end
Loading

Flow diagram for filesystem event conversion and rename correlation

flowchart TD
    A[fs_event received] --> B{Mount or unmount?}
    B -- Yes --> C[mount_info_update]
    B -- No --> D{Rename-from event?}
    D -- Yes --> E[Store path in rename_from_ by cookie]
    D -- No --> F{Rename-to event?}
    F -- Yes --> G{Matching cookie found?}
    G -- Yes --> H[Build source and destination paths]
    G -- No --> I[Ignore unmatched rename-to event]
    F -- No --> J[Build event from event.path]
    H --> K[filter_event]
    J --> K
    K --> L{Under lower filesystem mount?}
    L -- Yes --> M[Drop event]
    L -- No --> N[Process filesystem event]
Loading

File-Level Changes

Change Details Files
Integrate deepin-security-loader process trust negotiation into daemon startup.
  • Parse loader-injected --fd1/--fd2 descriptors.
  • Connect to the system bus and exchange JSON trust requests/replies.
  • Reject startup when trust negotiation fails while preserving a non-loader fallback path.
src/daemon/include/core/trust_client.h
src/daemon/src/core/trust_client.cpp
src/daemon/src/main.cpp
Replace direct event listening with a D-Bus relay listener and restart detection.
  • Receive serialized filesystem events through EventRelayReceiver and a GLib main-context thread.
  • Track server bus-owner changes and request daemon shutdown after relay disconnect or failed restart detection.
  • Update the existing listener’s GLib source setup to use explicit GSource objects.
src/daemon/include/core/relay_event_listener.h
src/daemon/src/core/relay_event_listener.cpp
src/daemon/src/core/event_listener.cpp
src/daemon/src/main.cpp
Refactor filesystem event representation and event conversion/rename handling.
  • Replace src/dst fields with a unified path plus sequence and device metadata.
  • Resolve mount roots and filter lower-fs events during conversion.
  • Correlate rename pairs by cookie using an unordered map instead of single pending-event state.
src/daemon/include/common/fs_event.h
src/daemon/include/core/default_event_handler.h
src/daemon/src/core/default_event_handler.cpp
Adapt daemon deployment and logging for loader-managed forking startup.
  • Install the daemon under libexec/deepin.
  • Write a per-user runtime PID file for systemd Type=forking tracking.
  • Route spdlog output to syslog so logs remain available after loader closes standard streams.
src/daemon/CMakeLists.txt
src/daemon/deepin-anything-daemon.service
src/daemon/src/main.cpp
Add an opt-in trust-client unit-test target and protocol coverage.
  • Exclude test sources from the daemon binary.
  • Build tests under ENABLE_TESTING with CTest and GLib g_test.
  • Exercise descriptor parsing, request construction, grants/denials, malformed responses, EOF, and JSON strings containing braces.
src/daemon/CMakeLists.txt
src/daemon/tests/CMakeLists.txt
src/daemon/tests/test_trust_client.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 found 3 issues

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="src/daemon/src/core/relay_event_listener.cpp" line_range="164-165" />
<code_context>
+        fs_event evt;
+        memset(&evt, 0, sizeof(evt));
+
+        EventReceiveResult result = event_relay_receiver_receive(
+            listener->receiver, &evt, sizeof(evt));
+
+        switch (result) {
</code_context>
<issue_to_address>
**issue (bug_risk):** The relay listener receives a `dispatch_event_t` wire record directly into the expanded `fs_event` structure, but the structures have different layouts: the relay payload contains action, cookie, and path, while `fs_event` inserts `seq`, `major`, and `minor` before `path`. Consequently the client reads part of the path as device metadata and reads the path from the wrong offset, so events are corrupted or discarded.

**Triggers:** When the daemon receives any event through the relay channel.

**Suggested fix:** Receive into `dispatch_event_t` and explicitly map its action, cookie, and path into `fs_event`, or make the relay wire format match `fs_event` exactly.
</issue_to_address>

### Comment 2
<location path="src/daemon/src/core/relay_event_listener.cpp" line_range="209" />
<code_context>
+    }
+
+    listener->loop = g_main_loop_new(listener->context, FALSE);
+    g_main_context_push_thread_default(listener->context);
+
+    int sock_fd = -1;
</code_context>
<issue_to_address>
**issue (bug_risk):** The return value of `g_main_loop_new` is not checked before `g_main_loop_run(listener->loop)`. If loop allocation fails, the listener still installs sources and later calls `g_main_loop_run` with a null loop, causing a crash instead of reporting startup failure.

**Triggers:** When GLib cannot allocate the listener main loop.

**Suggested fix:** Check `listener->loop` immediately after creation, signal startup failure, and clean up the context without starting the loop.
</issue_to_address>

### Comment 3
<location path="src/daemon/src/main.cpp" line_range="80-82" />
<code_context>
+        return false;
+    }
+
+    pid_file.write(QByteArray::number(QCoreApplication::applicationPid()));
+    pid_file.close();
+    spdlog::info("PID file written: {}", pid_path.toStdString());
+    return true;
+}
</code_context>
<issue_to_address>
**issue (bug_risk):** The PID file write result is ignored, so the service continues even when the PID file cannot be created or written. With `Type=forking` and `PIDFile=`, systemd then cannot reliably identify the daemon and can leave startup tracking or stop/restart behavior broken.

**Triggers:** When `$XDG_RUNTIME_DIR` is missing or the PID file cannot be opened or written.

**Suggested fix:** Treat failure to create or write the PID file as a startup error, and verify the `QFile::write` return value before proceeding.
</issue_to_address>

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

Comment thread src/daemon/src/core/relay_event_listener.cpp
Comment thread src/daemon/src/core/relay_event_listener.cpp
Comment thread src/daemon/src/main.cpp
@deepin-ci-robot

Copy link
Copy Markdown

deepin pr auto review

🤖 AI 代码审查报告

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

Pass


📊 总体评价

项目 结果
审查结论 代码审查通过
评分详情 总体评分 72 分,大于 70 分通过阈值。本次 PR 集成 deepin-security-loader 信任机制,整体实现合理,但存在 rename_from_ 映射未清理和 RENAME_TO 缺失匹配时的未初始化问题,需修复后更加完善。

🔍 详细分析

1. 语法逻辑 ❌

评价: 需改进 ❌ 不通过

潜在问题:

  1. src/daemon/src/core/default_event_handler.cpp:280 - convert_fs_event() 中 rename_from_.erase() 条件检查 event->act == ACT_RENAME_FILE/FOLDER,但输入事件 act 永远不是这些值,导致映射条目永不清除(内存泄漏)
  2. src/daemon/src/core/default_event_handler.cpp:265 - convert_fs_event() RENAME_TO 分支 cookie 未匹配时 event_with_full_path->act 未初始化,后续 act_names[event.act] 可能越界
  3. src/daemon/src/core/event_listener.cpp:137 - on_fd_readable() 中 g_slice_new 分配的 fs_event 新增字段 seq/major/minor 未赋值,convert_fs_event 中 makedev 使用垃圾值

建议: 1.修复 erase 条件:将 event->act 改为 event_with_full_path->act,或在 RENAME_TO 匹配成功后立即 erase
2.RENAME_TO 未匹配时添加 else 分支,设置默认 act 并返回 true 跳过处理
3.event_listener.cpp 中使用 g_slice_new0 替代 g_slice_new,或显式初始化新字段


2. 代码质量 ✅

评价: 良好 ✅ 通过

潜在问题:

  1. src/daemon/src/core/relay_event_listener.cpp:1 - 与 event_listener.cpp 存在大量代码重复(signal_startup、notify_quit、start_restart_check 等函数模式几乎相同)

建议: 考虑提取公共逻辑到独立工具模块或基类中,减少重复代码维护成本


3. 代码性能 ✅

评价: 良好 ✅ 通过

潜在问题:

  1. src/daemon/src/core/trust_client.cpp:176 - read_balanced_json() 逐字节读取 fd,最多 4096 次系统调用,应使用缓冲区批量读取

建议: 1.read_balanced_json 使用缓冲区批量读取(如 char buf[256]),减少系统调用次数
2.修复 erase 逻辑后此问题自然消除


4. 代码安全 🔒

评价: 优秀 ✅ 通过

🔐 发现 1 个安全漏洞

安全漏洞详情:

  1. 🟢 参数校验不足 (src/daemon/src/core/trust_client.cpp - parse_trust_fds): parse_trust_fds() 对 --fd1/--fd2 参数仅校验非负,未校验 fd 上限(如 FD_SETSIZE 或系统最大 fd)。虽然 daemon 由 deepin-security-loader 启动而非直接用户调用,风险较低,但缺少防御性校验可能导致异常 fd 值传入 write/read 时产生不可预期行为 ——非常重要

建议: 在 parse_trust_fds 中添加 fd 上限校验(如 fd < 0 || fd > 1024),防止异常 fd 值导致不可预期行为


💡 改进建议代码示例

// 修复1: rename_from_ 映射清理 - default_event_handler.cpp
// 将 erase 条件从检查 event->act 改为检查 event_with_full_path->act
if (event_with_full_path->act == ACT_RENAME_FILE ||
    event_with_full_path->act == ACT_RENAME_FOLDER) {
    rename_from_.erase(event->cookie);
}

// 修复2: RENAME_TO 未匹配时处理 - default_event_handler.cpp
case ACT_RENAME_TO_FILE:
case ACT_RENAME_TO_FOLDER:
    if (auto search = rename_from_.find(event->cookie);
        search != rename_from_.end()) {
        event_with_full_path->act = event->act == ACT_RENAME_TO_FILE
            ? ACT_RENAME_FILE : ACT_RENAME_FOLDER;
        event_with_full_path->dst = event->path;
        event_with_full_path->src = rename_from_[event->cookie];
    } else {
        // 未找到匹配的 RENAME_FROM,跳过此事件
        spdlog::warn("RENAME_TO without matching FROM, cookie: {}", event->cookie);
        return true;
    }
    break;

// 修复3: event_listener.cpp 使用 g_slice_new0 零初始化
fs_event *evt = g_slice_new0(fs_event);  // 替代 g_slice_new

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

@deepin-ci-robot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: max-lvs, wangrong1069

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

@wangrong1069

Copy link
Copy Markdown
Contributor Author

/merge

@max-lvs
max-lvs merged commit 4f2e57a into linuxdeepin:develop/eagle Sep 11, 2026
17 checks passed
@wangrong1069
wangrong1069 deleted the pr0911-3 branch September 11, 2026 10:07
@deepin-bot

deepin-bot Bot commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

This pr cannot be merged! (status: unknown)

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