Skip to content

迁移配置至 dconfig - #109

Merged
Groveer merged 3 commits into
linuxdeepin:masterfrom
glyvut:master
Oct 21, 2026
Merged

Groveer merged 3 commits into
linuxdeepin:masterfrom
glyvut:master

Conversation

@glyvut

@glyvut glyvut commented Aug 27, 2026 •

Copy link
Copy Markdown
Contributor

Summary by Sourcery

将 DDM 的配置和会话管理迁移到 DConfig 及 greeter 协作模型。

New Features:

  • 迁移 DDM 配置至 DConfig,并安装对应的配置 schema。
  • 通过登录协议传递会话目录,最近会话等

Enhancements:

  • 重构守护进程配置、会话发现及用户会话启动流程,并移除旧的配置文件与状态文件机制。
  • 更新架构说明、命令行帮助和相关手册以反映新的配置与会话管理方式。

Build:

  • 增加 Dtk6 DConfig 构建依赖及配置代码生成与 schema 安装。

CI:

  • 更新 Arch Linux 构建环境以安装 dtk6core。

Documentation:

  • 更新架构和配置文档,说明 DConfig 配置及由 greeter 管理会话选择和最近会话。

Chores:

  • 移除旧的配置读取、状态配置和 ddm-state.conf 手册内容,并整理 daemon 与 common 的代码归属。

@github-actions

github-actions Bot commented Aug 27, 2026 •

Copy link
Copy Markdown

TAG Bot

TAG: 0.4.1
EXISTED: no
DISTRIBUTION: unstable

@sourcery-ai

sourcery-ai Bot commented Aug 27, 2026 •

Copy link
Copy Markdown

Reviewer's Guide

Migrates DDM from legacy configuration and daemon-managed login state to the shared DConfig schema, with asynchronous daemon initialization, greeter-owned session selection/history, and explicit propagation of session settings to a configuration-free PAM helper; build, packaging, and documentation are updated accordingly.

Sequence diagram for DConfig initialization and greeter session selection

sequenceDiagram
    participant DConfig
    participant Daemon
    participant Greeter
    participant Session

    Daemon->>DConfig: DdmConfig::create()
    DConfig-->>Daemon: configInitializeSucceed
    Daemon->>Greeter: SessionDirs(waylandSessionDir, x11SessionDir)
    Greeter->>Daemon: Login(user, password, absoluteSessionPath)
    Daemon->>Session: Session(sessionPath)
    Session-->>Daemon: validated session
Loading

Sequence diagram for configuration propagation to the PAM helper

sequenceDiagram
    participant Daemon
    participant Helper
    participant PAM
    participant UserSession

    Daemon->>Helper: openSession(env, cookie, display, tty, type, command, sessionCommand, sessionLogFile, namespaces)
    Helper->>PAM: authenticate and open_session
    PAM-->>Helper: session opened
    Helper->>UserSession: setSessionCommand(sessionCommand)
    Helper->>UserSession: setSessionLogFile(sessionLogFile)
    Helper->>UserSession: setNamespaces(namespaces)
    UserSession->>UserSession: start(command, type, cookie)
Loading

File-Level Changes

Change Details Files
Replace legacy file/state configuration with asynchronously initialized DConfig owned by the daemon.
  • Add the shared org.deepin.dde.ddm schema and generated configuration class.
  • Initialize configuration before starting seat management and migrate daemon consumers to generated accessors.
  • Remove legacy readers, state persistence, reload behavior, and obsolete state manual page.
CMakeLists.txt
data/CMakeLists.txt
data/dconfig/org.deepin.dde.ddm.json.in
data/man/CMakeLists.txt
data/man/ddm-state.conf.rst.in
data/man/ddm.conf.rst.in
src/common/ConfigReader.cpp
src/common/ConfigReader.h
src/common/Configuration.h
src/common/Configuration.cpp
src/daemon/Configuration.cpp
src/daemon/Configuration.h
src/daemon/DaemonApp.cpp
src/daemon/DaemonApp.h
src/daemon/Display.cpp
src/daemon/PowerManager.cpp
src/daemon/SeatManager.cpp
src/daemon/XorgDisplayServer.cpp
Move session discovery and remembered login selection from DDM to the greeter.
  • Send configured Wayland and X11 session directories during greeter connection.
  • Change Login messages to carry an absolute desktop-file path and validate it against configured directories.
  • Stop persisting last user/session state in the daemon; autologin accepts absolute session paths.
src/common/Messages.h
src/common/SocketWriter.cpp
src/common/SocketWriter.h
src/daemon/Session.cpp
src/daemon/Session.h
src/daemon/SocketServer.cpp
docs/ARCHITECTURE.md
data/man/ddm.conf.rst.in
data/man/ddm.rst.in
Keep the PAM session helper configuration-free by passing all session runtime settings from the daemon.
  • Pass session command, log file, and namespace settings in the helper request.
  • Store and use those values in UserSession instead of reading configuration.
  • Remove daemon-only configuration and session dependencies from the common/helper path.
src/daemon/Auth.cpp
src/daemon/UserSession.cpp
src/daemon/UserSession.h
src/helper/HelperApp.cpp
src/helper/HelperApp.h
src/helper/CMakeLists.txt
src/common/CMakeLists.txt
Update build, packaging, licensing metadata, and documentation for the DConfig architecture.
  • Add Dtk6Core/Dtk6Tools dependencies and schema generation/installation.
  • Update Arch CI and Debian build dependencies.
  • Revise architecture/configuration documentation and file ownership metadata.
.github/workflows/ddm-archlinux-build.yml
debian/control
REUSE.toml
docs/ARCHITECTURE.md
services/ddm-tmpfiles.conf.in
src/daemon/CMakeLists.txt
src/common/LogindDBusTypes.cpp
src/common/LogindDBusTypes.h
src/common/MessageHandler.h

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/common/Configuration.cpp" line_range="37" />
<code_context>
-        auto it = m_entries.find(name);
-        if (it != m_entries.end())
-            return it.value();
-        return nullptr;
-    }
-
</code_context>
<issue_to_address>
**issue (bug_risk):** When either DConfig instance cannot be created, `createConfig` returns `nullptr`, but `initConfiguration` leaves the corresponding global null and the daemon later dereferences it through calls such as `mainConfig->autologinUser()`, causing a startup or first-request crash.

**Triggers:** When the dconfig daemon is unavailable or configuration creation fails.

**Suggested fix:** Treat initialization failure as fatal with a clear error and exit, or keep the daemon disabled until both configuration pointers are valid.
</issue_to_address>

### Comment 2
<location path="src/common/Configuration.cpp" line_range="48" />
<code_context>
+                return nullptr;
+
+            if (config->isInitializeSucceeded())
+                return config;
+
+            QEventLoop loop;
</code_context>
<issue_to_address>
**issue (bug_risk):** After `configInitializeFailed` or the five-second timeout, `createConfig` still returns the uninitialized configuration object instead of reporting failure, so callers read and write an object whose DConfig state was never initialized.

**Triggers:** When asynchronous DConfig initialization fails or does not complete within five seconds.

**Suggested fix:** Track whether initialization succeeded and return `nullptr` or otherwise fail initialization when the failure signal or timeout ends the event loop.

```suggestion
            return config->isInitializeSucceeded() ? config : nullptr;
```
</issue_to_address>

### Comment 3
<location path="src/daemon/DaemonApp.cpp" line_range="123-124" />
<code_context>
         std::cout << "Usage: ddm [options]\n"
                   << "Options: \n"
-                  << "  --example-config    Print the complete current configuration to stdout" << std::endl;
+                  << "  --test-mode    Start daemon in test mode" << std::endl;

         return EXIT_FAILURE;
</code_context>
<issue_to_address>
**issue (bug_risk):** The help text advertises `--test-mode`, but `main` only checks `--help` and never parses or applies `--test-mode`; invoking it starts the normal daemon rather than test mode.

**Triggers:** When an operator or test invokes ddm with `--test-mode`.

**Suggested fix:** Implement the test-mode branch before constructing the normal daemon, or remove the option from the help output.

```suggestion
                  << "Options: \n";
```
</issue_to_address>

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.

Comment thread src/common/Configuration.cpp Outdated
Comment thread src/common/Configuration.cpp Outdated
Comment thread src/daemon/DaemonApp.cpp Outdated
@glyvut
glyvut marked this pull request as draft August 27, 2026 06:26
@glyvut
glyvut marked this pull request as ready for review August 27, 2026 08:17

@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 1 issue

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

## Individual Comments

### Comment 1
<location path="src/common/ConfigReader.cpp" line_range="2" />
<code_context>
 /*
- * INI Configuration parser classes
+ * INI Configuration parser classes (DConfig backed)
  * Copyright (C) 2014 Martin Bříza <mbriza@redhat.com>
  *
</code_context>
<issue_to_address>
**nitpick:** The file header still describes these classes as an INI configuration parser even though the implementation no longer reads or writes INI files and instead uses DConfig. This misleads maintainers about the storage backend and the behavior of ConfigBase.

**Suggested fix:** Update the header comments in both files to describe the DConfig-backed configuration wrapper.
</issue_to_address>

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.

Comment thread src/common/ConfigReader.cpp Outdated
@glyvut
glyvut force-pushed the master branch 2 times, most recently from c6ba540 to 3de45e4 Compare August 27, 2026 08:39
@glyvut
glyvut marked this pull request as draft August 27, 2026 08:50
@glyvut
glyvut marked this pull request as ready for review August 27, 2026 08:52

@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 2 issues

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

## Individual Comments

### Comment 1
<location path="CMakeLists.txt" line_range="120-124" />
<code_context>
-set(CONFIG_FILE                 "${CMAKE_INSTALL_FULL_SYSCONFDIR}/ddm.conf"        CACHE PATH      "Path of the ddm config file")
</code_context>
<issue_to_address>
**issue:** The CMake cache variables `CONFIG_FILE`, `CONFIG_DIR`, and `SYSTEM_CONFIG_DIR` are removed while the man-page templates still reference them during configuration. The generated `ddm(1)`, `ddm.conf(5)`, and `ddm-state.conf(5)` documentation therefore contains empty configuration paths instead of describing the DConfig storage locations.

**Triggers:** When `BUILD_MAN_PAGES` is enabled.

**Suggested fix:** Update the man-page templates and their configure inputs to document the DConfig schema and state locations, or retain suitable path variables for the generated documentation.
</issue_to_address>

### Comment 2
<location path="src/common/ConfigReader.cpp" line_range="92-100" />
<code_context>
+            return key;
+        }
+
+        DTK_CORE_NAMESPACE::DConfig *dconfigFor(const QString &appId, const QString &name) {
+            static QHash<QString, DTK_CORE_NAMESPACE::DConfig *> s_configs;
+            const QString cacheKey = appId + QLatin1Char('/') + name;
+            auto it = s_configs.constFind(cacheKey);
+            if (it != s_configs.constEnd())
+                return it.value();
+            auto *config = DTK_CORE_NAMESPACE::DConfig::create(appId, name, QString(), nullptr);
+            s_configs.insert(cacheKey, config);
+            return config;
+        }
+
</code_context>
<issue_to_address>
**nitpick (bug_risk):** Every DConfig object created by `dconfigFor` is allocated with a null parent and retained in a process-global `QHash` without any ownership or cleanup. Each distinct app/name pair permanently leaks its DConfig object for the lifetime of the process.

**Triggers:** When additional distinct DConfig configurations are requested in a long-running process.

**Suggested fix:** Give the objects an owning Qt parent or store them in an owning smart pointer/container and release them during shutdown.
</issue_to_address>

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.

Comment thread CMakeLists.txt
Comment thread src/common/ConfigReader.cpp Outdated
@deepin-bot

deepin-bot Bot commented Oct 10, 2026

Copy link
Copy Markdown

TAG Bot

New tag: 0.4.0
DISTRIBUTION: unstable
Suggest: synchronizing this PR through rebase #115

@glyvut
glyvut force-pushed the master branch 2 times, most recently from 637b4c5 to ad2fdeb Compare October 12, 2026 08:51
@wineee
wineee requested a balanced review from Copilot October 12, 2026 09:48

Copilot AI 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.

🟡 Changes recommended

Global writable autologin settings, missing legacy-value migration, and DConfig packaging/interface defects must be addressed. / 必须解决全局可写自动登录、旧配置迁移缺失及 DConfig 打包接口问题。

7 open findings
What changed in this PR

Migrates DDM configuration and session state from INI files to DConfig. / 将 DDM 配置和会话状态从 INI 迁移至 DConfig。

Changes:

  • Adds DConfig-backed loading, saving, and schemas. / 新增 DConfig 读写及 schema。
  • Updates build dependencies, packaging, and version to 0.4.1. / 更新构建依赖、打包及版本。
  • Revises configuration documentation. / 更新配置文档。
File Description
CMakeLists.txt Adds DTK/DConfig setup and version bump. / 添加 DTK/DConfig 配置并升级版本。
.github/​workflows/​ddm-archlinux-build.yml Adds Arch DTK dependency. / 添加 Arch DTK 依赖。
debian/​changelog Records release changes. / 记录发行变更。
debian/​control Adds Debian DTK dependencies. / 添加 Debian DTK 依赖。
services/​ddm-tmpfiles.conf.in Removes obsolete state-file note. / 移除过时状态文件说明。
src/​common/​CMakeLists.txt Links DTK Core. / 链接 DTK Core。
src/​common/​Constants.h.in Removes INI path constants. / 移除 INI 路径常量。
src/​common/​Configuration.h Defines DConfig resources. / 定义 DConfig 资源。
src/​common/​ConfigReader.cpp Replaces INI persistence with DConfig. / 使用 DConfig 替代 INI 持久化。
src/​daemon/​DaemonApp.cpp Reloads configuration after application creation. / 应用创建后重新加载配置。
data/​CMakeLists.txt Installs DConfig schemas. / 安装 DConfig schema。
data/​dconfig/​org.deepin.dde.ddm.json.in Defines main configuration schema. / 定义主配置 schema。
data/​dconfig/​org.deepin.dde.ddm.state.json Defines state schema. / 定义状态 schema。
data/​man/​ddm.rst.in Documents DConfig files. / 说明 DConfig 文件。
data/​man/​ddm.conf.rst.in Documents migrated settings. / 说明迁移后的配置项。
data/​man/​ddm-state.conf.rst.in Documents state resource. / 说明状态资源。

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread data/dconfig/org.deepin.dde.ddm.json.in Outdated
Comment thread src/common/ConfigReader.cpp Outdated
Comment thread CMakeLists.txt Outdated
Comment thread data/dconfig/org.deepin.dde.ddm.json.in Outdated
Comment thread src/common/CMakeLists.txt Outdated
Comment thread data/dconfig/org.deepin.dde.ddm.json.in
Comment thread data/dconfig/org.deepin.dde.ddm.state.json Outdated
@glyvut
glyvut marked this pull request as draft October 13, 2026 00:49
@glyvut
glyvut marked this pull request as ready for review October 13, 2026 13:10

@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 4 issues

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

## Individual Comments

### Comment 1
<location path="src/common/Configuration.h" line_range="83" />
<code_context>
     );

-    Config(StateConfig, []()->QString{auto tmp = getpwnam("ddm"); return tmp ? QString::fromLocal8Bit(tmp->pw_dir) : QStringLiteral(STATE_DIR);}().append(QStringLiteral("/state.conf")), QString(), QString(),
+    Config(StateConfig, _S(DDM_DCONFIG_APP_ID ".state"), _S(DDM_DCONFIG_APP_ID), QString(),
         Section(Last,
             Entry(Session,         QString,     QString(),                                      _S("Name of the session for the last logged-in user.\n"
</code_context>
<issue_to_address>
**Writable session state runs attacker code**

When a local user sets `lastSession` to a desktop file they control and DDM uses the remembered session for configured autologin, `stateConfig.Last.Session` is accepted from DConfig and passed to `Session::setTo()`, where an absolute path bypasses the configured session directories; DDM parses that file's `Exec` entry and launches it during passwordless autologin, running the attacker's command as the autologin user.

Restrict writes to the state key and reject session paths that do not resolve to files inside the configured, trusted session directories.
</issue_to_address>

### Comment 2
<location path="CMakeLists.txt" line_range="87" />
<code_context>
 qt_standard_project_setup(REQUIRES 6.6)

+# DTK (DConfig)
+find_package(Dtk6 REQUIRED COMPONENTS Core)
+
 # Uninstall target
</code_context>
<issue_to_address>
**Nix package fails to configure**

When the Nix package is built, `find_package(Dtk6 REQUIRED COMPONENTS Core)` cannot find Dtk6 in the Nix build environment, so CMake configuration fails before the package can build.

Add the Nix package providing Dtk6 Core to `nix/default.nix` build inputs.
</issue_to_address>

### Comment 3
<location path="src/common/ConfigReader.cpp" line_range="247" />
<code_context>
+            if (e->matchesDefault())
+                config->reset(key);
+            else
+                config->setValue(key, stringToVariant(config, key, e->value()));
         };

</code_context>
<issue_to_address>
**Most settings stay read-only**

When an administrator tries to change a non-autologin setting through DConfig, the main schema marks those settings as read-only, so DConfig rejects the updates and administrators cannot configure settings that were writable through the previous INI files.

Mark the non-autologin settings that administrators are meant to configure as writable in the schema.
</issue_to_address>

### Comment 4
<location path="src/common/ConfigReader.cpp" line_range="105-114" />
<code_context>
+            return config.data();
+        }
+
+        QString variantToString(const QVariant &value) {
+            if (value.typeId() == QMetaType::QStringList)
+                return value.toStringList().join(QLatin1Char(','));
+            if (value.typeId() == QMetaType::QVariantList) {
+                QStringList stringList;
+                const auto list = value.toList();
+                for (const QVariant &item : list)
+                    stringList << item.toString();
+                return stringList.join(QLatin1Char(','));
+            }
+            return value.toString();
+        }
</code_context>
<issue_to_address>
**Comma-containing paths are split**

When a DConfig list element, such as a namespace path, contains a comma, `variantToString` joins DConfig list elements with commas, and `ConfigEntry::setValue` splits that string on commas, so a single path containing a comma becomes multiple paths. `UserSession::childModifier` then fails to open a namespace path and aborts session startup.

Preserve list elements directly when loading DConfig arrays instead of serializing and reparsing them as comma-separated text.
</issue_to_address>

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

Comment thread src/common/Configuration.h Outdated
Comment thread CMakeLists.txt Outdated
Comment thread src/common/ConfigReader.cpp Outdated
Comment thread src/common/ConfigReader.cpp Outdated
Comment thread debian/changelog Outdated
Comment thread src/common/ConfigReader.cpp Outdated
@glyvut
glyvut marked this pull request as draft October 19, 2026 06:19
@glyvut
glyvut force-pushed the master branch 3 times, most recently from 0fa68b6 to ebe8ccc Compare October 19, 2026 06:54
@glyvut
glyvut force-pushed the master branch 11 times, most recently from 1fc1ea9 to fd2985e Compare October 20, 2026 02:59
@glyvut
glyvut marked this pull request as ready for review October 20, 2026 03:01

@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 1 issue

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

## Individual Comments

### Comment 1
<location path="CMakeLists.txt" line_range="87" />
<code_context>
 qt_standard_project_setup(REQUIRES 6.6)

+# DTK (DConfig)
+find_package(Dtk6 REQUIRED COMPONENTS Core Tools)
+
 # Uninstall target
</code_context>
<issue_to_address>
**Nix builds lack DTK dependencies**

When DDM is built through `nix/default.nix`, `find_package(Dtk6 REQUIRED COMPONENTS Core Tools)` fails during CMake configuration in the Nix derivation because neither its `buildInputs` nor `nativeBuildInputs` includes DTK6. Nix builds of DDM therefore cannot configure.

Add the DTK6 Core and Tools packages to the Nix derivation’s appropriate inputs.
</issue_to_address>

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

Comment thread CMakeLists.txt
Comment thread data/dconfig/org.deepin.dde.ddm.json.in Outdated
Comment thread data/dconfig/org.deepin.dde.ddm.json.in Outdated
Comment thread src/daemon/Session.cpp
@glyvut
glyvut force-pushed the master branch 2 times, most recently from 8266fab to 6838e30 Compare October 20, 2026 05:10
wineee
wineee previously approved these changes Oct 20, 2026
Session, LogindDBusTypes and MessageHandler are used by the ddm daemon
only. Keeping them in the shared library made the session helper link
against daemon-only code, and SocketWriter exposed Session even though
it never writes one.

将 Session、LogindDBusTypes 与 MessageHandler 移到 daemon:它们只被 ddm
使用,留在共享库里会让 session helper 链接 daemon 专用代码;同时去掉
SocketWriter 中从未使用的 Session 序列化。

Log: libddm-common 不再包含 daemon 专用实现
PMS: BUG-294419
Influence: 无行为变化,libddm-common 导出的头文件减少;需重新构建依赖它的模块。
Replace the INI configuration with the generated DConfig schema
org.deepin.dde.ddm. The daemon waits for the asynchronous configuration
before starting the seat manager, and passes the session command, log
file and namespaces to ddm-helper through openSession instead of
creating a DConfig object before pam_open_session() forks.

用生成的 DConfig schema 替代 INI 配置。daemon 等待异步配置就绪后再
启动 seat manager;会话命令、日志文件与命名空间改由 openSession 传给
ddm-helper,避免在 pam_open_session() fork 前创建 DConfig。

DDM also owns the session directories and the last login: it sends
SessionDirs and LastLogin to the greeter, records lastUser/lastSession on
successful login, and falls back to lastSession when autologinSession is
empty. The installed schema is the reference for keys and defaults;
--example-config is removed and DTK6 is now required.

会话目录与上次登录也归 DDM:向 greeter 下发 SessionDirs 与 LastLogin,
登录成功后记录 lastUser/lastSession,autologinSession 为空时回退到
lastSession。schema 即配置参考,删除 --example-config,构建新增 DTK6
依赖。

Log: DDM 配置迁移到 DConfig,并接管会话目录与上次登录状态
PMS: BUG-294419
Influence: 不再读取 /etc/ddm.conf;需安装 DSG schema;新增
  SessionDirs/LastLogin 消息,Login 改为传 desktop 文件绝对路径,需与
  treeland 同步升级;删除 state.conf、RememberLastUser、
  RememberLastSession 与 --example-config。
Describe the DConfig schema as the configuration reference and document
the SessionDirs/LastLogin messages and the desktop file path in Login.
Drop the obsolete ddm.conf(5) page; ddm(1) now covers the schema,
dde-dconfig usage and the DDM-owned last login state.

以 schema 作为配置参考,补充 SessionDirs/LastLogin 消息与 Login 的
desktop 文件路径;删除 ddm.conf(5),并在 ddm(1) 中说明 schema、
dde-dconfig 用法及 DDM 维护的上次登录状态。

Log: 文档与 DConfig 配置及新的登录流程保持一致
PMS: BUG-294419
Influence: 删除 ddm.conf(5),配置项以 schema 为准。
@deepin-ci-robot

Copy link
Copy Markdown

deepin pr auto review

🤖 AI 代码审查报告

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

Pass


📊 总体评价

项目 结果
审查结论 代码审查通过
评分详情 本次提交将 ddm 配置系统从 INI 文件(ConfigReader)迁移至 DConfig 框架,重构彻底且逻辑清晰。移除了旧的 INI 解析器,通过 DTK6 生成的 DdmConfig 类访问配置,采用异步初始化确保配置就绪后再启动座席管理器。四维度均未发现问题,无安全漏洞。

🔍 详细分析

1. 语法逻辑 ✅

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

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

建议: ['建议在 recordLastLogin() 方法注释中说明:相比旧版本,RememberLastUser/RememberLastSession 选项已被移除,现在始终记录最后登录用户和会话。']


2. 代码质量 ✅

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

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

建议: []


3. 代码性能 ✅

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

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

建议: []


4. 代码安全 🔒

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

🔐 发现 0 个安全漏洞

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

建议: []


💡 改进建议代码示例

本次提交无需修复,代码质量良好。以下是一个可选的改进建议——在 recordLastLogin() 方法中添加注释说明行为变化: /**
 * Remember the user and optionally the session of a successful
 * login. ddm owns this state and hands it to the greeter.
 *
 * Note: Unlike the previous INI-based configuration, this always
 * records the last user and session. The RememberLastUser and
 * RememberLastSession options have been removed in the DConfig
 * migration; if selective recording is needed again, it should
 * be added as a DConfig option.
 */
void Display::recordLastLogin(const QString &user, const Session *session) {
    mainConfig()->setLastUser(user);
    if (session)
        mainConfig()->setLastSession(session->fileName());
}

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

@deepin-wm

Copy link
Copy Markdown

评审意见

把配置集中到 DConfig、把会话发现与"上次登录"下放给 greeter,方向是对的。但建议先不要合并:第 1 条是权限模型降级,第 2、3 条会让 daemon 在异常情况下静默失效。行号取自 head 7d7e302。

P0 · 任意本地用户可改写 root 执行的配置

data/dconfig/org.deepin.dde.ddm.json.in 里所有 key 都是 permissions: readwrite(visibility: private 只是文档语义,不是访问控制)。其中这些值由 ddm 以 root 直接执行:

  • haltCommand / rebootCommand(src/daemon/PowerManager.cpp:92,98)
  • x11ServerPath、x11SessionCommand、x11DisplayCommand、x11DisplayStopCommand、singleSessionCommand、waylandSessionCommand(经 helper 执行)
  • usersDefaultPath、namespaces、x11SessionDirs/waylandSessionDirs、autologinUser/autologinSession

而 dde-dconfig 侧没有任何跨 uid 授权:

  • DSGConfigServer::acquireManagerV2(uid, ...)(dde-app-services dconfig-center/dde-dconfig-daemon/dconfigserver.cpp:261)直接采用调用者传入的 uid,不校验调用者是否等于该 uid;
  • DSGConfigConn::setValue(同仓 dconfigconn.cpp:113)也不校验调用者;
  • org.desktopspec.ConfigManager.conf 对 default context 放行了 org.desktopspec.ConfigManager.Manager 的所有方法。

结论:普通用户可以 dde-dconfig -u 0 set -a org.deepin.dde.ddm ... -k haltCommand -v "<任意命令>",下次关机时以 root 执行;同理改 autologinUser 可以免密进入任意账号。旧 /etc/ddm.conf 是 root-only 文件,这次迁移实际上把 root 命令的执行入口变成了用户可写的 DConfig。

建议:特权 key 在 schema 中设 permissions: readonly,管理员配置走 root 拥有的 override(或保留一个 root-only 配置文件),lastUser/lastSession 这类 ddm 自己写的状态留在 DConfig 即可;同时把 dde-dconfig 的跨 uid 写入问题报给 dde-app-services。这条不解决,上面"autologinUser 全局可写"的评论就不该被当作已处理。

P1 · 初始化失败或无响应时,daemon 仍然带着空配置跑起来

src/daemon/Configuration.cpp:37-48:configInitializeFailed 也调用 setReady(),于是 onConfigurationsReady() 照常 m_seatManager->initialize()。生成的 DdmConfig 在初始化失败时 getter 返回的是未写入的缓存值(全空),后果是:

  • SocketServer.cpp:159-166 给 greeter 下发空 LastLogin/SessionDirs → 会话列表为空 → 任何人都登录不进去,而且界面上没有任何错误提示;
  • mainConfig()->haltCommand() 为空时,PowerManager.cpp:92 的 splitCommand("") 得到空列表再 takeFirst(),是空列表越界(debug 断言 / release UB)。

反过来,DConfig 一直不回复(dde-dconfig-daemon 卡住)时没有超时,seat manager 永不启动 —— 黑屏且无日志。

建议:初始化失败时 qCritical + exit(EXIT_FAILURE)(systemd 会重启并留日志),或至少加一个 5~10s 看门狗并在失败时明确拒绝启动 greeter;顺手给 powerOff()/reboot() 的空命令加保护。

P1 · 报文格式变了,但没有版本协商,包版本也没动

Login 从 Session(quint32 type + QString name) 改成绝对路径 QString,并新增 SessionDirs/LastLogin。版本号保持 0.4.0,于是:

  • treeland 侧仍是 find_package(DDM 0.2.0)(src/CMakeLists.txt:15)、libddm-dev (>= 0.4.0)、Recommends: ddm (>= 0.4.0);
  • ddm 侧 Depends: treeland(无版本约束)。

新 ddm + 旧 treeland greeter(或反过来)不会报错,只会表现为"登录没反应 / 会话列表为空",并且 QDataStream 会读错位。建议在 Connect 里带一个协议版本(或复用 Capabilities 加位),不匹配时明确拒绝并打日志;同时把 treeland 的 find_package(DDM ...) 和 debian 依赖提到新版本。

另外:Session/Configuration 头从 DDM::Common 移除、SocketWriter::operator<<(Session) 删除,但 SOVERSION 仍是 0(libddm-common.so.0 不变),其它 consumer 会在运行期缺符号。请确认没有其它 consumer,或升 SOVERSION。

P2 · 小问题

  • src/daemon/Session.cpp:312:if (!mainConfig()) return; 静默返回,建议加一行 qWarning(如果 wineee 在 Session.cpp:318 的 "else warn" 指的是这块的失败分支,一并处理)。
  • src/daemon/Display.cpp:257-311:login() 在 startUserSession() 校验会话之前就完成了 PAM 认证,非法会话也会消耗一次密码校验。现在会话路径由 greeter 传入,先 session.isValid() 快速失败并 loginFailed 更合适。
  • schema x11CursorTheme/x11CursorSize 默认空串(wineee 在 38/49 行提的):XorgDisplayServer.cpp:78 无条件 env.insert("XCURSOR_THEME", ""),而 size 有空判断、theme 没有;要么 theme 也判空,要么给合理默认值。
  • wineee 还有 3 条未关闭的 thread(org.deepin.dde.ddm.json.in:38、:49、Session.cpp:318),合并前需要逐条回应。

已核对没问题的部分

Wants/After=dde-dconfig-daemon.service 是对的(它是 system bus 上的 system service,User=deepin-daemon,D-Bus policy 允许 root);debian/ddm.install 的 usr/share/* 能带上 schema;REUSE.toml 的 data/** 覆盖了新 JSON;data 在 src 之前 add_subdirectory,dtk_add_config_to_cpp 的输入在 configure 阶段已存在;data()/Session::setTo 对 greeter 传入的绝对路径有目录校验,lastSession 作为 autologin 回退也因此是安全的。

@glyvut

glyvut commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor Author

P0 · 任意本地用户可改写 root 执行的配置

完全不成立,只要 flag 无 user-public 即无权限

P1 · 初始化失败或无响应时,daemon 仍然带着空配置跑起来

完全不成立,初始化失败回落的是默认配置

P1 · 报文格式变了,但没有版本协商,包版本也没动

包版本之后变动,treeland 与 DDM 同步升级

@deepin-ci-robot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: glyvut, Groveer

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

@Groveer
Groveer merged commit c8414fd into linuxdeepin:master Oct 21, 2026
8 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.

6 participants