You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GDM用户DBus Daemon调用Polkit认证报错的解决方法

问题分析与解决方案

错误原因

你遇到的NotAuthorized错误核心原因有两个:

  1. 代码中Polkit动作ID拼写错误(写成了org.gnome.GdmSettings.,多了末尾的点,与policy文件中的org.gnome.GdmSettings.SetAllowedUID不匹配)。
  2. GDM用户并非Polkit可信调用者:Polkit仅允许root用户或动作所有者,对其他身份的Subject调用带POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION标志的验证,而GDM用户不在可信范围内,因此触发权限限制。

推荐实现方案:DBus与Polkit集成

利用DBus内置的Polkit授权机制,让DBus自动处理验证流程(包括密码弹窗),无需守护进程手动调用Polkit API,这是更符合规范的实现方式。

1. 创建DBus系统配置文件

在/usr/share/dbus-1/system.d/下新建org.gnome.GdmSettings.conf,内容如下:

<!DOCTYPE busconfig PUBLIC
 "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
 "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
  <!-- 允许GDM用户拥有该DBus服务 -->
  <policy user="gdm">
    <allow own="org.gnome.GdmSettings"/>
  </policy>
  <!-- 默认策略配置 -->
  <policy context="default">
    <allow send_destination="org.gnome.GdmSettings"/>
    <!-- 指定SetAllowedUID方法需要Polkit授权 -->
    <allow send_interface="org.gnome.GdmSettings" send_member="SetAllowedUID">
      <annotate key="org.freedesktop.DBus.Auth.PolicyKit.Action" value="org.gnome.GdmSettings.SetAllowedUID"/>
    </allow>
  </policy>
</busconfig>

该配置会让DBus自动拦截对SetAllowedUID方法的调用,触发Polkit验证流程,验证通过后才会将请求转发给守护进程。

2. 简化守护进程代码

移除原有的Polkit调用逻辑,专注处理业务即可:

// 直接处理SetAllowedUID方法的业务逻辑
static void handle_set_allowed_uid(GDBusConnection *connection,
                                   const gchar *sender,
                                   const gchar *object_path,
                                   const gchar *interface_name,
                                   const gchar *method_name,
                                   GVariant *parameters,
                                   GDBusMethodInvocation *invocation) {
    // 在这里实现修改允许UID的业务逻辑
    set_timeout();
    g_dbus_method_invocation_return_value(invocation, g_variant_new("()"));
}

3. 确认Policy文件配置

你的org.gnome.GdmSettings.SetAllowedUID.policy文件配置正确,只需确保动作ID与DBus配置一致即可:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE policyconfig PUBLIC
"-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
"http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd">

<policyconfig>
  <vendor>The GNOME Project</vendor>
  <vendor_url>http://www.gnome.org/</vendor_url>

  <action id="org.gnome.GdmSettings.SetAllowedUID">
    <description>Manage Gdm Settings</description>
    <message>Authentication is required to change GDM data</message>
    <defaults>
      <allow_any>no</allow_any>
      <allow_inactive>no</allow_inactive>
      <allow_active>auth_admin_keep</allow_active>
    </defaults>
  </action>
</policyconfig>

4. 优化DBus Service文件

移除dbus-launch,直接启动守护进程(若需会话总线,可在守护进程内部初始化或通过环境变量配置):

[Unit]
Description=GNOME Display Manager Settings

[D-BUS Service]
Name=org.gnome.GdmSettings
Exec=/usr/bin/your-daemon-executable
User=gdm

备选方案:手动Polkit验证(不推荐)

若必须在守护进程中手动处理验证,需移除用户交互标志,改为异步调用,并让客户端自行触发授权:

static void auth_check_ready(PolkitAuthority *authority, GAsyncResult *res, gpointer user_data) {
    GDBusMethodInvocation *invocation = G_DBUS_METHOD_INVOCATION(user_data);
    g_autoptr(PolkitAuthorizationResult) result = NULL;
    GError *error = NULL;

    result = polkit_authority_check_authorization_finish(authority, res, &error);
    if (error != NULL) {
        g_dbus_method_invocation_return_error(invocation, G_IO_ERROR, G_IO_ERROR_FAILED, "%s", error->message);
        g_clear_error(&error);
        return;
    }

    if (polkit_authorization_result_get_is_authorized(result)) {
        set_timeout();
        g_dbus_method_invocation_return_value(invocation, g_variant_new("()"));
    } else {
        g_dbus_method_invocation_return_error(invocation, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED, "Not authorized");
    }
}

// 在方法处理函数中调用
static void handle_set_allowed_uid(...) {
    g_autoptr(PolkitAuthority) authority = polkit_authority_get_sync(NULL, NULL);
    g_autoptr(PolkitSubject) sender = polkit_system_bus_name_new(g_dbus_method_invocation_get_sender(invocation));

    polkit_authority_check_authorization(
        authority,
        sender,
        "org.gnome.GdmSettings.SetAllowedUID",
        NULL,
        0, // 禁止用户交互
        NULL,
        auth_check_ready,
        invocation
    );
}

此方式不会自动弹出密码框,需要客户端通过pkexec或Polkit客户端API自行完成授权。

内容的提问来源于stack exchange,提问作者Rastersoft

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 05:55:07