Skip to content

feat: sessionFieldOverrides for override Exec key in a given session - #379

Merged
BLumia merged 1 commit into
linuxdeepin:masterfrom
BLumia:feat-session-overrides
Aug 13, 2026
Merged

feat: sessionFieldOverrides for override Exec key in a given session#379
BLumia merged 1 commit into
linuxdeepin:masterfrom
BLumia:feat-session-overrides

Conversation

@BLumia

@BLumia BLumia commented Aug 6, 2026

Copy link
Copy Markdown
Member

新增 DConfig 配置项,允许为指定会话(例如wayland)覆盖指定desktop文件中
的Exec/TryExec字段的值.

配置格式大致为

/usr/share/dsg/configs/overrides/org.deepin.dde.application-manager/org.deepin.dde.am.appoverride/x11/example.app-id/90-override.json

{
    "magic": "dsg.config.override",
    "version": "1.0",
    "contents": {
        "Exec": {
            "value": "notify-send 'test am override'"
        }
    }
}

配置好后使用这个命令验证配置项是否正确:dde-dconfig get -a org.deepin.dde.application-manager -r org.deepin.dde.am.appoverride -s /x11/example.app-id -k Exec

实际场景为解决部分应用程序默认Exec字段的参数会无法在treeland下表现良
好的问题.

Log:

Summary by Sourcery

Introduce session-aware configuration to override desktop file Exec/TryExec and environment fields per session and integrate it into application filtering and autostart handling.

Enhancements:

  • Add SessionOverrideConfig and SessionType utilities wired into ApplicationManager to load DConfig-based sessionFieldOverrides and trigger application list reloads on config changes.
  • Apply session-specific Exec and environment overrides when processing compatibility for application launches, including support for action-specific groups and placeholder substitution in Exec values.
  • Extend application visibility and autostart checks to consider session-level TryExec overrides, including a force-show behavior for empty overrides.

Tests:

  • Add unit tests covering session override config parsing, value/env lookup, Exec placeholder resolution, TryExec override behavior, and session type detection.

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

Sorry @BLumia, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@BLumia
BLumia requested a review from ComixHe August 6, 2026 12:34
@sourcery-ai

sourcery-ai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Reviewer's Guide

Adds a DConfig-driven, session-specific override mechanism for desktop file Exec/TryExec and environment variables, wires it through application creation/autostart checks, and introduces supporting SessionOverrideConfig and SessionType helpers with unit tests.

Sequence diagram for Exec and Env resolution with session overrides

sequenceDiagram
    participant AMS as ApplicationManager1Service
    participant AS as ApplicationService
    participant CM as CompatibilityManager
    participant SOC as SessionOverrideConfig

    AMS->>AS: createApplicationService(...)
    AMS->>AMS: getSessionOverrideConfig()
    AMS->>AS: shouldBeShown(entry, desktopId, sessionConfig)

    AS->>CM: getCompatibilityManager()
    AS->>AS: processCompatibility(action, options, execStr)
    Note over AS: originalExec = execStr
    AS->>CM: getExec(desktopId)
    AS->>AS: apply compatibility Exec/env

    AS->>AMS: parent().getSessionOverrideConfig()
    AS->>SOC: getValue(desktopId, groupKey, DesktopEntryExec)
    alt Exec override exists
        AS->>SOC: resolveExecValue(overrideExec, originalExec)
        AS->>AS: execStr = resolvedExec
    end

    AS->>SOC: getEnv(desktopId, groupKey)
    alt Env overrides not empty
        AS->>AS: merge Env into options[EnvKey]
    end
Loading

File-Level Changes

Change Details Files
Introduce SessionOverrideConfig and SessionType utilities to load and represent per-session overrides from DConfig.
  • Add SessionOverrideConfig class that reads org.deepin.dde.application-manager.sessionFieldOverrides via DConfig, parses JSON into per-desktop override maps, exposes getValue/getEnv/hasOverride helpers, and emits configChanged when updated.
  • Implement parseSessionConfig to select the block matching the current session (wayland/x11) and build a QHash of desktopId -> QJsonObject, logging and skipping invalid data.
  • Implement resolveExecValue helper to substitute the !AM_FULL! placeholder with the original Exec string.
  • Add SessionType enum and currentSessionType() helper that infers Wayland/X11/Unknown from process environment variables.
src/sessionoverrideconfig.h
src/sessionoverrideconfig.cpp
src/sessiontype.h
src/sessiontype.cpp
Apply session-specific Exec and environment overrides when launching applications.
  • Capture the original Exec string before compatibility processing so it can be used for !AM_FULL! substitution.
  • Fetch the SessionOverrideConfig from ApplicationManager1Service and, if present, apply per-session Exec overrides for the relevant Desktop Entry or Desktop Action group, resolving !AM_FULL! against the original Exec.
  • Merge session-level Env overrides into the existing options env list, appending to any existing Env entries.
  • Log applied session overrides for Exec and Env for debugging.
src/dbus/applicationservice.cpp
src/dbus/applicationservice.h
Apply session-specific TryExec overrides consistently in visibility/autostart checks.
  • Extend ApplicationFilter::tryExecCheck to accept desktopId and an optional SessionOverrideConfig pointer, and first check for a TryExec override in DConfig.
  • Treat an empty overridden TryExec as force-show; for non-empty values, resolve absolute paths via QFileInfo and relative names via QStandardPaths::findExecutable to decide visibility.
  • Propagate the new tryExecCheck signature through ApplicationService::shouldBeShown, the autostart helper parseAutostartDesktopFile, ApplicationManager1Service::updateAutostartStatus, and dde-autostart main, always passing desktopId and sessionConfig where available.
src/applicationchecker.h
src/applicationchecker.cpp
src/dbus/applicationservice.cpp
src/dbus/applicationservice.h
src/dbus/applicationmanager1service.cpp
src/dbus/applicationmanager1service.h
apps/dde-autostart/src/main.cpp
Wire SessionOverrideConfig into ApplicationManager1Service lifecycle and configuration constants.
  • Instantiate SessionOverrideConfig in ApplicationManager1Service::initService, store it as a unique_ptr member, and expose it via getSessionOverrideConfig().
  • Connect the SessionOverrideConfig::configChanged signal to trigger doReloadApplications so overrides take effect without restart.
  • Introduce the SessionFieldOverrides DConfig key constant and register it in the org.deepin.dde.application-manager DConfig schema JSON.
src/dbus/applicationmanager1service.cpp
src/dbus/applicationmanager1service.h
src/constant.h
misc/dsg/configs/dde-application-manager/org.deepin.dde.application-manager.json
Add unit tests covering session override parsing, lookup, and TryExec integration.
  • Create tests that verify parseSessionConfig selects the correct session block, ignores empty/invalid JSON, and skips invalid desktop entries.
  • Test getValue, getEnv, and hasOverride for existing/missing apps, groups, and fields, including Env array handling.
  • Validate resolveExecValue behavior for multiple !AM_FULL! placements and cases without placeholders.
  • Exercise ApplicationFilter::tryExecCheck with overrides for valid, invalid, and empty TryExec values, plus fallback behavior when no override is present, and basic currentSessionType detection.
tests/ut_sessionoverrideconfig.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

@BLumia
BLumia force-pushed the feat-session-overrides branch from c0c75c0 to ea88ef1 Compare August 11, 2026 11:47
Comment thread misc/dsg/configs/dde-application-manager/org.deepin.dde.am.appoverride.json Outdated
Comment thread src/sessionoverrideconfig.cpp Outdated
@BLumia
BLumia force-pushed the feat-session-overrides branch 2 times, most recently from d189844 to f7468cd Compare August 11, 2026 13:11
ComixHe
ComixHe previously approved these changes Aug 12, 2026
@BLumia
BLumia force-pushed the feat-session-overrides branch 2 times, most recently from c49bc93 to 4ca5876 Compare August 13, 2026 05:05
@BLumia
BLumia requested a review from zccrs August 13, 2026 05:07
ComixHe
ComixHe previously approved these changes Aug 13, 2026
@BLumia

BLumia commented Aug 13, 2026

Copy link
Copy Markdown
Member Author

备注:

安全漏洞1(中危):路径遍历 在 SessionOverrideConfig::configFor 中,subpath 由 desktopId 直接拼接而成(u"/"_s % desktopId % m_subpathPrefix)。如果 desktopId 包含 ../ 或以 / 开头,可能导致 DConfig 读取非预期的配置文件,从而覆盖非目标应用的配置或导致程序异常。

desktopid 不允许包含 / 字符,这个场景不会发生。

新增 DConfig 配置项,允许为指定会话(例如wayland)覆盖指定desktop文件中
的Exec/TryExec/Icon字段的值.

实际场景为解决部分应用程序默认Exec字段的参数会无法在treeland下表现良
好的问题.Icon字段则为允许应用(低频率)动态更新图标所用

Log:
@deepin-ci-robot

Copy link
Copy Markdown

deepin pr auto review

★ 总体评分:60分

■ 【总体评价】

代码实现了基于会话类型的动态配置覆盖功能,但因存在路径遍历安全漏洞导致评分受限
逻辑正确且质量良好,但安全维度存在中危漏洞,触发安全优先原则强制降分

■ 【详细分析】

  • 1.语法逻辑(基本正确)✓

SessionOverrideConfiggetValueconfigFor方法使用了const修饰但内部通过const_cast修改mutable成员,虽语法合法但属于冗余操作。整体控制流、空指针检查及std::optional使用无误。
潜在问题:configFor函数中不必要地使用了const_cast<SessionOverrideConfig*>(this),由于m_configs等已声明为mutable,直接调用即可。
建议:移除configFor中的const_cast,直接使用this->m_configs进行操作。

  • 2.代码质量(良好)✓

代码结构清晰,职责划分合理。新增的SessionOverrideConfig类封装了DConfig的读取与缓存逻辑,使用现代C++特性如std::optionalQStringView。单元测试覆盖了核心逻辑与边界条件。
潜在问题:getValue方法在缓存未命中时,存在与updateOverride相似的直接读取config->Exec()等字段的重复逻辑。
建议:可考虑在ensureLoadedconfigFor中同步强制刷新一次m_overrides,消除getValue末尾的兜底读取代码,保持单一数据源。

  • 3.代码性能(存在性能问题)✕

doReloadApplications中调用m_sessionOverrideConfig->preload(m_applicationList.keys()),会为系统内所有已安装应用同步创建DConfig实例并尝试连接后端。
潜在问题:系统应用数量通常达数百个,在主线程或启动阶段批量实例化大量DConfig对象并建立IPC连接,可能导致明显的启动延迟或瞬间CPU与IO峰值。
建议:将全量预加载改为懒加载,仅在shouldBeShownprocessCompatibility实际被调用时按需触发ensureLoaded;若必须预加载,应将其放入低优先级线程池或分批异步处理。

  • 4.代码安全(存在 1 个安全漏洞)✕

漏洞对比统计:新增漏洞 1 个,减少漏洞 0 个,持平 0 个
总体风险描述,在SessionOverrideConfig::configFor中直接拼接desktopId构造DConfig子路径,若desktopId包含路径遍历字符,可能越权访问或篡改其他应用的配置项。

  • 安全漏洞1(中危):路径遍历 在 SessionOverrideConfig::configFor 中,输入源为DesktopFile::desktopId(),若恶意构造的desktop文件其ID包含../(如../../etc/evil),拼接生成的subpath(/../../etc/evil/wayland)可能逃逸预期目录,导致读取或监听非预期的DConfig节点,引发配置信息泄露或异常覆盖 ——非常重要

  • 建议:在configFor函数入口处对desktopId进行严格校验,禁止包含/../等路径分隔符与遍历字符,仅允许合法的桌面应用ID格式(如org.example.app);可使用正则表达式^[a-zA-Z0-9.-]+$进行过滤。

■ 【改进建议代码示例】

// src/sessionoverrideconfig.cpp
#include <QRegularExpression>

ApplicationOverrideConfig *SessionOverrideConfig::configFor(const QString &desktopId) const
{
    if (m_subpathPrefix.isEmpty())
        return nullptr;

    // 安全检查:防止路径遍历攻击
    static const QRegularExpression validIdRegex("^[a-zA-Z0-9._-]+$");
    if (!validIdRegex.match(desktopId).hasMatch()) {
        qCWarning(logSessionOverride) << "Invalid desktopId detected, possible path traversal:" << desktopId;
        return nullptr;
    }

    auto it = m_configs.find(desktopId);
    if (it != m_configs.end())
        return it->second.get();

    const auto subpath = u"/"_s % desktopId % m_subpathPrefix;
    // 移除不必要的 const_cast,直接使用 mutable 成员
    auto config = ApplicationOverrideConfig::create(fromStaticRaw(ApplicationServiceID),
                                                     subpath,
                                                     this);
    if (!config) {
        qCWarning(logSessionOverride) << "Failed to create DConfig for subpath:" << subpath;
        return nullptr;
    }

    qCInfo(logSessionOverride) << "Creating DConfig for" << desktopId << "subpath:" << subpath;

    QObject::connect(config, &ApplicationOverrideConfig::valueChanged,
                     this, [this, desktopId](const QString &key) {
        if (key == u"Exec"_s || key == u"TryExec"_s || key == u"Icon"_s) {
            qCInfo(logSessionOverride) << "Override changed for" << desktopId << "key:" << key;
            this->updateOverride(desktopId);
            emit this->overrideChanged(desktopId, key);
            emit this->configChanged();
        }
    });

    QObject::connect(config, &ApplicationOverrideConfig::configInitializeSucceed,
                     this, [this, desktopId, config](DTK_CORE_NAMESPACE::DConfig *) {
        qCInfo(logSessionOverride) << "Override config initialized for" << desktopId;
        this->updateOverride(desktopId);
    });

    QObject::connect(config, &ApplicationOverrideConfig::configInitializeFailed,
                     this, [this, desktopId]() {
        qCWarning(logSessionOverride) << "Override config initialization failed for" << desktopId;
    });

    m_configs[desktopId] = std::unique_ptr<ApplicationOverrideConfig>(config);
    return config;
}

@deepin-ci-robot

Copy link
Copy Markdown

@BLumia: The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
github-pr-review-ci cb7b7fd link true /test github-pr-review-ci

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. I understand the commands that are listed here.

@deepin-ci-robot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: BLumia, ComixHe

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

@BLumia
BLumia merged commit 61ad6de into linuxdeepin:master Aug 13, 2026
14 of 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.

4 participants