refactor: add polkit authorization to PM#1666
Conversation
There was a problem hiding this comment.
Code Review
This pull request refactors the authentication and interaction model of the Linglong Package Manager. It replaces the previous client-side authorization logic with server-side Polkit checks for privileged operations such as installation, uninstallation, updates, and configuration changes. Additionally, the interaction signals and methods have been moved from the global PackageManager interface to individual Task objects. Feedback for this PR focuses on several critical areas: a potential deadlock issue where QEventLoop is used within a std::thread without a dispatcher, the risk of freezing the service's main thread due to synchronous Polkit authorization calls, and suggestions for improving code safety and organization through better DBus argument validation and namespace management.
| public: | ||
| PolkitAuthority() = delete; | ||
|
|
||
| static utils::error::Result<bool> checkAuthorization(const std::string &actionId, |
| { | ||
| LINGLONG_TRACE("check polkit authorization"); | ||
|
|
||
| static std::once_flag flag; |
There was a problem hiding this comment.
- 这里是单线程,没必要用once_flag
- qtbus相关的要不统一放到ll-cli的main.cpp里,那里已经有
qDBusRegisterMetaType<QDBusObjectPath>();了。
| auto PackageManager::Update(const QVariantMap ¶meters) noexcept -> QVariantMap | ||
| { | ||
| // Polkit authorization check | ||
| if (calledFromDBus()) { |
|
我还遇到了一个问题,如果长时间不确定授权,超时之后cli会因为json反序列化缺少字段而崩溃 |
f42d7c4 to
3e02a56
Compare
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request refactors the Linglong Package Manager's authorization and interaction model. It moves Polkit-based permission checks from the CLI to the daemon, allowing for more secure and fine-grained access control, and introduces a peer-to-peer DBus mode. Additionally, interaction signals and methods have been moved from the PackageManager interface to the Task interface to better associate user prompts with specific operations. Review feedback focused on ensuring that DBus connections are correctly passed to internal implementation methods in peer mode to allow task exposure, adding safety checks for null pointers when deserializing interaction replies, and improving the robustness of the task confirmation event loop by handling external cancellations.
3e02a56 to
be3f231
Compare
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request refactors the permission and authentication model of the Linglong package manager. It replaces the old client-side authorization checks with daemon-side asynchronous Polkit authorization, defining fine-grained Polkit actions for operations like install, update, uninstall, prune, and configuration changes. Additionally, the user interaction flow (RequestInteraction/ReplyInteraction) has been moved from the package manager interface to individual tasks.
Our review identified a critical issue in PackageTask::waitConfirm where a deserialized object is dereferenced without a null check, which could lead to a daemon crash. There is also a thread-safety concern regarding signal-slot connections and QEventLoop::exit across different threads; passing the event loop as a context object to connect is recommended to ensure safe execution.
be3f231 to
975e01d
Compare
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request refactors the permission control mechanism of the package manager by delegating authorization checks to Polkit instead of using custom DBus permissions. It introduces a new PolkitAuthority helper class to perform asynchronous authorization checks, modifies the DBus interface and system policies, and updates task interaction logic to handle caller disconnections. The review feedback highlights critical issues in PackageTask::waitConfirm regarding incorrect service names for local peer signals and thread-safety violations when exiting the event loop from a different thread, as well as a recommendation to avoid declaring Qt metatypes for structs defined in anonymous namespaces.
| struct PolkitSubject | ||
| { | ||
| QString kind; | ||
| QVariantMap details; | ||
| }; | ||
|
|
||
| struct PolkitResult | ||
| { | ||
| bool isAuthorized = false; | ||
| bool isChallenge = false; | ||
| QMap<QString, QString> details; | ||
| }; |
There was a problem hiding this comment.
Declaring metatypes for types defined in an anonymous namespace is generally discouraged in Qt because anonymous namespace types have internal linkage and their names are not globally unique or stable across translation units. This can lead to duplicate registration or compilation issues.
Consider defining PolkitSubject and PolkitResult inside the linglong::service namespace (or a private sub-namespace like linglong::service::detail) and declaring their metatypes there.
| msg.service().toStdString(), | ||
| [this, parameters, msg, conn](utils::error::Result<void> authResult) { | ||
| if (!authResult) { | ||
| conn.send( |
There was a problem hiding this comment.
connection的send返回值都没检查,false代表发送失败,下同
975e01d to
d99962f
Compare
There was a problem hiding this comment.
Pull request overview
This PR adds polkit-based authorization checks to the PackageManager D-Bus service for privileged operations and refactors the user-interaction flow so that interaction requests/replies are handled by per-task (Task1) objects rather than the PackageManager itself.
Changes:
- Introduce
PolkitAuthorityand gate Install/InstallFromFile/Uninstall/Update/Prune/SetConfiguration behind polkit authorization. - Move interaction APIs/signals from
PackageManager1toTask1(task emitsRequestInteraction, client replies viaTask1.ReplyInteraction). - Relax D-Bus daemon policy to allow access to the service, relying on service-side polkit checks for permission enforcement.
Reviewed changes
Copilot reviewed 17 out of 17 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| misc/share/polkit-1/actions/org.deepin.linglong.PackageManager1.policy | Defines new per-operation polkit action IDs and defaults. |
| misc/share/dbus-1/system.d/org.deepin.linglong.PackageManager1.conf | Opens D-Bus access broadly, expecting polkit enforcement in-service. |
| libs/utils/src/linglong/utils/error/error.h | Adds ErrorCode::PermissionDenied for authorization failures. |
| libs/linglong/src/linglong/package_manager/uab_installation.cpp | Switches upgrade confirmation from PM-level interaction to task-level waitConfirm(). |
| libs/linglong/src/linglong/package_manager/ref_installation.cpp | Same interaction refactor as UAB path. |
| libs/linglong/src/linglong/package_manager/polkit_authority.h | Declares async polkit authorization helper. |
| libs/linglong/src/linglong/package_manager/polkit_authority.cpp | Implements polkit CheckAuthorization call over system bus. |
| libs/linglong/src/linglong/package_manager/package_task.h | Adds caller context + interaction request/reply API on tasks. |
| libs/linglong/src/linglong/package_manager/package_task.cpp | Implements interaction waiting, timeout handling, and caller-disconnect handling. |
| libs/linglong/src/linglong/package_manager/package_manager.h | Refactors privileged methods, adds SetConfiguration, and threads caller context through task creation. |
| libs/linglong/src/linglong/package_manager/package_manager.cpp | Adds polkit gating and async reply handling around privileged operations. |
| libs/linglong/src/linglong/cli/cli.h | Updates CLI interfaces to match interaction refactor. |
| libs/linglong/src/linglong/cli/cli.cpp | Connects to Task1 interaction signal, replies via Task1 method, adjusts error handling and timeouts. |
| libs/linglong/CMakeLists.txt | Adds new polkit authority sources to build. |
| apps/ll-package-manager/src/main.cpp | Passes peer-mode flag into PM initialization. |
| api/dbus/org.deepin.linglong.Task1.xml | Adds ReplyInteraction method + RequestInteraction signal to Task1 interface. |
| api/dbus/org.deepin.linglong.PackageManager1.xml | Removes PM-level interaction API, adds SetConfiguration, updates Configuration property access. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| #include <optional> | ||
| #include <thread> | ||
|
|
||
| using namespace std::chrono_literals; |
| return LINGLONG_ERR("failed to initialize package manager signals", ret.error()); | ||
| } | ||
|
|
||
| this->pkgMan->setTimeout(INT_MAX); |
| if (!m_peerMode) { | ||
| auto msg = message(); | ||
| auto conn = connection(); | ||
| setDelayedReply(true); | ||
|
|
||
| CallerContext ctx{ conn, msg }; | ||
|
|
||
| checkPolkitAuthorizationAsync( | ||
| "org.deepin.linglong.PackageManager1.install", | ||
| msg.service().toStdString(), | ||
| [this, parameters, ctx](utils::error::Result<void> authResult) { | ||
| if (!authResult) { | ||
| ctx.connection.send(ctx.message.createErrorReply( | ||
| QDBusError::AccessDenied, | ||
| QString::fromStdString(authResult.error().message()))); | ||
| return; | ||
| } | ||
|
|
||
| auto result = installImpl(parameters, ctx); | ||
| ctx.connection.send(ctx.message.createReply(result)); | ||
| }); | ||
| return {}; | ||
| } | ||
|
|
||
| return installImpl(parameters, CallerContext{ connection(), message() }); |
| ctx.connection.send(ctx.message.createErrorReply( | ||
| QDBusError::AccessDenied, | ||
| QString::fromStdString(authResult.error().message()))); |
| case utils::error::ErrorCode::PermissionDenied: | ||
| this->printer.printMessage(_("Permission denied, authentication is required")); | ||
| break; |
| <action id="org.deepin.linglong.PackageManager1.prune"> | ||
| <description>Prune package cache</description> | ||
| <message>Authentication is required to prune package cache</message> | ||
| <defaults> | ||
| <allow_any>auth_admin</allow_any> | ||
| <allow_inactive>auth_admin</allow_inactive> | ||
| <allow_active>auth_admin</allow_active> | ||
| </defaults> | ||
| <annotate key="org.freedesktop.policykit.owner">unix-user:@LINGLONG_USERNAME@</annotate> | ||
| </action> | ||
|
|
||
| <action id="org.deepin.linglong.PackageManager1.set-configuration"> | ||
| <description>Modify package manager configuration</description> | ||
| <message>Authentication is required to modify package manager configuration</message> | ||
| <defaults> | ||
| <allow_any>auth_admin</allow_any> | ||
| <allow_inactive>auth_admin</allow_inactive> | ||
| <allow_active>auth_admin</allow_active> | ||
| </defaults> |
| bool PackageTask::waitConfirm( | ||
| api::types::v1::InteractionMessageType msgType, | ||
| const api::types::v1::PackageManager1RequestInteractionAdditionalMessage &additionalMessage, | ||
| std::chrono::milliseconds timeout) noexcept | ||
| { | ||
| Q_EMIT RequestInteraction(static_cast<int>(msgType), | ||
| common::serialize::toQVariantMap(additionalMessage)); | ||
| QEventLoop loop; |
d99962f to
3c979e4
Compare
Add PolkitAuthority helper class to check authorization before Install, InstallFromFile, Uninstall, Update, Prune and SetConfiguration operations. Move interaction interface from PM to Task and add timeout. Signed-off-by: reddevillg <reddevillg@gmail.com>
3c979e4 to
f91ae8b
Compare
deepin pr auto review本次代码审查主要针对将权限校验从前端CLI转移到后端Daemon、引入Polkit异步鉴权机制、以及将交互信号从PackageManager下沉到Task对象的重大重构。 整体来看,这次重构的方向非常正确,将鉴权逻辑下沉到服务端大大提高了安全性,避免了客户端绕过的风险,同时任务级别的交互信号设计也更加合理。但代码中存在一些严重的并发逻辑隐患、资源泄漏风险以及架构设计问题,需要重点关注和修改。 以下是详细的审查意见: 1. 严重逻辑/并发问题1.1
1.2
1.3
2. 资源泄漏2.1
3. 架构与代码质量3.1 Polkit 鉴权逻辑的代码冗余
3.2
3.3
4. 安全性4.1 DBus 配置过度放宽
4.2 Polkit 策略的
5. 性能5.1
总结本次提交的核心风险在于异步回调中对象生命周期的管理以及事件循环阻塞期间的信号时序与取消逻辑。强烈建议:
|
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: ComixHe, reddevillg The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
Add PolkitAuthority helper class to check authorization before Install, InstallFromFile, Uninstall, Update, Prune and SetConfiguration operations.
Move interaction interface from PM to Task.