Skip to content

polkitbackend: fix a memory leak when querying NoNewPrivileges - #653

Merged
jrybar-rh merged 1 commit into
polkit-org:mainfrom
mrc0mmand:memleak-fix
Apr 27, 2026
Merged

jrybar-rh merged 1 commit into
polkit-org:mainfrom
mrc0mmand:memleak-fix

Conversation

@mrc0mmand

Copy link
Copy Markdown
Member

There's currently a memory leak when querying systemd's NoNewPrivileges property over D-Bus. Specifically, this line:

  g_variant_get (no_new_privs_result, "(v)", &no_new_privs_value);

has one "unfortunate" side-effect - the variant from the "v" specifier is actually a new reference that has to be freed by the caller, as stated in GLib's manual:

Upon encountering a v, g_variant_get() takes a pointer to a (GVariant
*) (ie: (GVariant **)). It is set to a new reference to a GVariant
instance containing the contents of the variant value. It is
appropriate to free this reference using g_variant_unref().

See: https://docs.gtk.org/glib/gvariant-format-strings.html#variants

So, every time this method was called, which can be quite often on systemd-based desktops, a small GVariant was left behind that could over time accumulate into a significant memory leak.

The memory leak can be triggered by a following D-Bus call:

busctl call org.freedesktop.PolicyKit1 /org/freedesktop/PolicyKit1/Authority \
            org.freedesktop.PolicyKit1.Authority CheckAuthorization '(sa{sv})sa{ss}us' \
            system-bus-name 1 name s :1.1 org.freedesktop.policykit.exec 0 0 ''

And with Polkit compiled with ASan (and appropriate ASan-aware systemd unit magic) a single call yields this stack trace:

Direct leak of 65 byte(s) in 1 object(s) allocated from:
    #0 0x7fa8fa4ef41f in malloc (/lib64/libasan.so.8+0xef41f) (BuildId: 80bfc4ae44fdec6ef5fecfb01e2b57d28660991c)
    #1 0x7fa8fa0944b9 in g_malloc (/lib64/libglib-2.0.so.0+0x454b9) (BuildId: dc61914957dd0fe121ad2089adaf15c832526b63)
    #2 0x7fa8fa0ea7b1 in g_variant_new_preallocated_trusted (/lib64/libglib-2.0.so.0+0x9b7b1) (BuildId: dc61914957dd0fe121ad2089adaf15c832526b63)
    #3 0x7fa8fa0db833 in g_variant_new_boolean (/lib64/libglib-2.0.so.0+0x8c833) (BuildId: dc61914957dd0fe121ad2089adaf15c832526b63)
    #4 0x7fa8fa300f4a in parse_value_from_blob.isra.0 (/lib64/libgio-2.0.so.0+0xeef4a) (BuildId: fe6e790dadb8d9bc9a597e99d3a1bca974179bf0)
    #5 0x7fa8fa3017bf in parse_value_from_blob.isra.0 (/lib64/libgio-2.0.so.0+0xef7bf) (BuildId: fe6e790dadb8d9bc9a597e99d3a1bca974179bf0)
    #6 0x7fa8fa30152c in parse_value_from_blob.isra.0 (/lib64/libgio-2.0.so.0+0xef52c) (BuildId: fe6e790dadb8d9bc9a597e99d3a1bca974179bf0)
    #7 0x7fa8fa3063b4 in g_dbus_message_new_from_blob (/lib64/libgio-2.0.so.0+0xf43b4) (BuildId: fe6e790dadb8d9bc9a597e99d3a1bca974179bf0)
    #8 0x7fa8fa3140c9 in _g_dbus_worker_do_read_cb (/lib64/libgio-2.0.so.0+0x1020c9) (BuildId: fe6e790dadb8d9bc9a597e99d3a1bca974179bf0)
    #9 0x7fa8fa29685b in g_task_return_now (/lib64/libgio-2.0.so.0+0x8485b) (BuildId: fe6e790dadb8d9bc9a597e99d3a1bca974179bf0)
    #10 0x7fa8fa296894 in complete_in_idle_cb (/lib64/libgio-2.0.so.0+0x84894) (BuildId: fe6e790dadb8d9bc9a597e99d3a1bca974179bf0)
    #11 0x7fa8fa094463 in g_idle_dispatch (/lib64/libglib-2.0.so.0+0x45463) (BuildId: dc61914957dd0fe121ad2089adaf15c832526b63)
    #12 0x7fa8fa092e83 in g_main_context_dispatch_unlocked.lto_priv.0 (/lib64/libglib-2.0.so.0+0x43e83) (BuildId: dc61914957dd0fe121ad2089adaf15c832526b63)
    #13 0x7fa8fa096f77 in g_main_context_iterate_unlocked.isra.0 (/lib64/libglib-2.0.so.0+0x47f77) (BuildId: dc61914957dd0fe121ad2089adaf15c832526b63)
    #14 0x7fa8fa097226 in g_main_loop_run (/lib64/libglib-2.0.so.0+0x48226) (BuildId: dc61914957dd0fe121ad2089adaf15c832526b63)
    #15 0x7fa8fa3096c1 in gdbus_shared_thread_func.lto_priv.0 (/lib64/libgio-2.0.so.0+0xf76c1) (BuildId: fe6e790dadb8d9bc9a597e99d3a1bca974179bf0)
    #16 0x7fa8fa0cca51 in g_thread_proxy (/lib64/libglib-2.0.so.0+0x7da51) (BuildId: dc61914957dd0fe121ad2089adaf15c832526b63)
    #17 0x7fa8fa42b606 in asan_thread_start(void*) (/lib64/libasan.so.8+0x2b606) (BuildId: 80bfc4ae44fdec6ef5fecfb01e2b57d28660991c)

SUMMARY: AddressSanitizer: 65 byte(s) leaked in 1 allocation(s).

The fix is simple - just unref the GVariant once we're done with it.

Also, fix a typo in the variable name (no_new_privis_value -> no_new_privs_value).

Follow-up for a23d9ce.


/cc @bluca

There's currently a memory leak when querying systemd's NoNewPrivileges
property over D-Bus. Specifically, this line:

  g_variant_get (no_new_privs_result, "(v)", &no_new_privs_value);

has one "unfortunate" side-effect - the variant from the "v" specifier
is actually a new reference that has to be freed by the caller, as
stated in GLib's manual:

  Upon encountering a v, g_variant_get() takes a pointer to a (GVariant
  *) (ie: (GVariant **)). It is set to a new reference to a GVariant
  instance containing the contents of the variant value. It is
  appropriate to free this reference using g_variant_unref().

See: https://docs.gtk.org/glib/gvariant-format-strings.html#variants

So, every time this method was called, which can be quite often on
systemd-based desktops, a small GVariant was left behind that could
over time accumulate into a significant memory leak.

The memory leak can be triggered by a following D-Bus call:

busctl call org.freedesktop.PolicyKit1 /org/freedesktop/PolicyKit1/Authority \
            org.freedesktop.PolicyKit1.Authority CheckAuthorization '(sa{sv})sa{ss}us' \
            system-bus-name 1 name s :1.1 org.freedesktop.policykit.exec 0 0 ''

And with Polkit compiled with ASan (and appropriate ASan-aware systemd
unit magic) a single call yields this stack trace:

Direct leak of 65 byte(s) in 1 object(s) allocated from:
    #0 0x7fa8fa4ef41f in malloc (/lib64/libasan.so.8+0xef41f) (BuildId: 80bfc4ae44fdec6ef5fecfb01e2b57d28660991c)
    #1 0x7fa8fa0944b9 in g_malloc (/lib64/libglib-2.0.so.0+0x454b9) (BuildId: dc61914957dd0fe121ad2089adaf15c832526b63)
    #2 0x7fa8fa0ea7b1 in g_variant_new_preallocated_trusted (/lib64/libglib-2.0.so.0+0x9b7b1) (BuildId: dc61914957dd0fe121ad2089adaf15c832526b63)
    #3 0x7fa8fa0db833 in g_variant_new_boolean (/lib64/libglib-2.0.so.0+0x8c833) (BuildId: dc61914957dd0fe121ad2089adaf15c832526b63)
    #4 0x7fa8fa300f4a in parse_value_from_blob.isra.0 (/lib64/libgio-2.0.so.0+0xeef4a) (BuildId: fe6e790dadb8d9bc9a597e99d3a1bca974179bf0)
    #5 0x7fa8fa3017bf in parse_value_from_blob.isra.0 (/lib64/libgio-2.0.so.0+0xef7bf) (BuildId: fe6e790dadb8d9bc9a597e99d3a1bca974179bf0)
    #6 0x7fa8fa30152c in parse_value_from_blob.isra.0 (/lib64/libgio-2.0.so.0+0xef52c) (BuildId: fe6e790dadb8d9bc9a597e99d3a1bca974179bf0)
    #7 0x7fa8fa3063b4 in g_dbus_message_new_from_blob (/lib64/libgio-2.0.so.0+0xf43b4) (BuildId: fe6e790dadb8d9bc9a597e99d3a1bca974179bf0)
    #8 0x7fa8fa3140c9 in _g_dbus_worker_do_read_cb (/lib64/libgio-2.0.so.0+0x1020c9) (BuildId: fe6e790dadb8d9bc9a597e99d3a1bca974179bf0)
    polkit-org#9 0x7fa8fa29685b in g_task_return_now (/lib64/libgio-2.0.so.0+0x8485b) (BuildId: fe6e790dadb8d9bc9a597e99d3a1bca974179bf0)
    polkit-org#10 0x7fa8fa296894 in complete_in_idle_cb (/lib64/libgio-2.0.so.0+0x84894) (BuildId: fe6e790dadb8d9bc9a597e99d3a1bca974179bf0)
    polkit-org#11 0x7fa8fa094463 in g_idle_dispatch (/lib64/libglib-2.0.so.0+0x45463) (BuildId: dc61914957dd0fe121ad2089adaf15c832526b63)
    polkit-org#12 0x7fa8fa092e83 in g_main_context_dispatch_unlocked.lto_priv.0 (/lib64/libglib-2.0.so.0+0x43e83) (BuildId: dc61914957dd0fe121ad2089adaf15c832526b63)
    polkit-org#13 0x7fa8fa096f77 in g_main_context_iterate_unlocked.isra.0 (/lib64/libglib-2.0.so.0+0x47f77) (BuildId: dc61914957dd0fe121ad2089adaf15c832526b63)
    polkit-org#14 0x7fa8fa097226 in g_main_loop_run (/lib64/libglib-2.0.so.0+0x48226) (BuildId: dc61914957dd0fe121ad2089adaf15c832526b63)
    polkit-org#15 0x7fa8fa3096c1 in gdbus_shared_thread_func.lto_priv.0 (/lib64/libgio-2.0.so.0+0xf76c1) (BuildId: fe6e790dadb8d9bc9a597e99d3a1bca974179bf0)
    polkit-org#16 0x7fa8fa0cca51 in g_thread_proxy (/lib64/libglib-2.0.so.0+0x7da51) (BuildId: dc61914957dd0fe121ad2089adaf15c832526b63)
    polkit-org#17 0x7fa8fa42b606 in asan_thread_start(void*) (/lib64/libasan.so.8+0x2b606) (BuildId: 80bfc4ae44fdec6ef5fecfb01e2b57d28660991c)

SUMMARY: AddressSanitizer: 65 byte(s) leaked in 1 allocation(s).

The fix is simple - just unref the GVariant once we're done with it.

Also, fix a typo in the variable name (no_new_privis_value ->
no_new_privs_value).

Follow-up for a23d9ce.
@jrybar-rh
jrybar-rh merged commit 8ceeed8 into polkit-org:main Apr 27, 2026
40 checks passed
@mrc0mmand
mrc0mmand deleted the memleak-fix branch April 27, 2026 14:51
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