How to kill Gio.Subprocess child if it was spawned with elevated privileges via pkexec?

import Gio from 'gi://Gio';
import GLib from 'gi://GLib';

function spawnAndKillPing() {
    try {
        const proc = new Gio.Subprocess({
            //argv: ['pkexec', 'ping', 'localhost'],
            argv: ['ping', 'localhost'],
            flags: Gio.SubprocessFlags.NONE,
        });

        proc.init(null);

        print('Started ping localhost with PID:', proc.get_identifier());

        GLib.timeout_add_seconds(
            GLib.PRIORITY_DEFAULT,
            5, // seconds
            () => {
                try {
                    print('Killing ping process...');
                    proc.force_exit();
                } catch (e) {
                    logError(e);
                }
                return GLib.SOURCE_REMOVE;
            }
        );

    } catch (e) {
        logError(e);
    }
}

spawnAndKillPing();

const loop = new GLib.MainLoop(null, false);
loop.run();

When I spawn ping without pkexec, force_exit() function works fine. With pkexec however, it only kills the process before I type the password and authorize elevating privileges, otherwise ping process continues to live. I can’t spawn kill command to close this process because I will need to elevate privileges again, which I don’t want to do. I thought about sending Ctrl + C signal (SIGINT**),** but proc.send_signal(2) also doesn’t work just like force_exit().

I don’t think you can, not with pkexec at least.

In general, a process can only send a signal to another process if its own real or effective UID matches the real or saved UID of the other process (see kill(2)). As far as I can see in its source, pkexec calls setreuid to change its UIDs without setting the saved UID, so consequently your process no longer has authority to kill pkexec subsequently.

I’m not sure whether this supposed to work like this, that’s perhaps a question for the polkit maintainers.

For ping at least you don’t need privileges tho, but presumably ping was just an example?

Yes, I took ping as an example. I’m actually writing an extension that blocks keyboard input (so my cat can sleep on the keys) using this command:

evtest --grab

This program needs elevated privileges to be able to block keyboard input. And there’s no problem calling pkexec once and typing your password, but when the time comes to unblock your keyboard, you probably don’t want to type password using screen keyboard or something like this. In X11 you could use xinput --disable, in Wayland I don’t think there’s anything that convenient like evtest. I guess that the only option left for me is to create some kind of root shell controlled by JS code, spawn evtest and kill commands from there and hope that my extension isn’t that vulnerable.

Bustle does this for its dbus-monitor subprocess, which is launched with pkexec when monitoring the system bus. I wrote a blog post about how to do it here: