Home / Alt manpages / pkcheck(1)

  • pkcheck(1)
  • User command
  • linux

Check a polkit Authorisation Safely with pkcheck

This guide shows you how to ask polkit whether a process may perform a named action, read the result in a script, and avoid the process-identity race that makes short PID forms unsafe. The examples use pkcheck 124 from polkitd 124-2ubuntu1.24.04.4, installed on Ubuntu 24.04 here. Allow about 10 minutes if you already know the action ID; finding the right policy action is usually the slower part.

Before you start

You need a running polkit service and the pkcheck command. You do not normally need root to check the authorisation of your own process. The action ID must come from the application or policy you are investigating. Do not guess one and treat a result as proof of a different operation.

List installed actions with pkaction. This is read-only and may produce a long report:

pkaction --verbose | less

Find the exact action ID, then inspect its policy fields, especially the active-session result. A policy can allow, deny, or require authentication depending on the subject and session.

Checkpoint

Write down one exact action ID, such as org.freedesktop.policykit.exec, before continuing. That example is useful for testing the command but commonly requires administrator authentication.

1. Build a race-resistant process subject

For a process check, pkcheck accepts a PID, an optional start time, and an optional UID. The manual warns against both the bare PID and the PID plus start-time forms: a process can exit and its PID can be reused between collecting the value and checking it. New code should provide all three values.

This shell snippet targets the shell running the snippet. It extracts the process start time from /proc and adds the current UID:

pid=$$
start_time=$(awk -F') ' '{print $2}' "/proc/$pid/stat" | awk '{print $20}')
uid=$(id -u)
printf 'pid=%s start_time=%s uid=%s\n' "$pid" "$start_time" "$uid"

The second awk is deliberate. The process name in /proc/PID/stat is enclosed in parentheses and may contain spaces, so splitting the whole line on whitespace is not a reliable general parser.

Checkpoint

Confirm that all three values are non-empty and numeric. If /proc/$pid/stat cannot be read, the process has probably already ended; collect the values again rather than weakening the subject.

2. Check an action without opening an authentication prompt

Pass the action ID and the complete process subject. The command below checks the example action for the shell that collected the values:

action_id=org.freedesktop.policykit.exec
pkcheck --action-id "$action_id" --process "$pid,$start_time,$uid"
check_status=$?
printf 'pkcheck exit status: %s\n' "$check_status"

On this machine, the example returned exit status 2 and printed Authorization requires authentication and -u wasn't passed. on standard error. That is a meaningful answer, not a command failure: pkcheck could not authorise the action without an authentication interaction.

Use the status immediately. The documented meanings are:

  • 0: the process is authorised. Any returned details are printed as KEY=VALUE lines on standard output.
  • 1: the process is not authorised.
  • 2: authorisation needs interaction, but no interaction was allowed, or no suitable agent is available.
  • 3: an authentication request was dismissed.
  • 126: an option was malformed.
  • 127: an error occurred while checking authorisation.

Do not collapse every non-zero result into "denied". Status 2 means that a policy decision may still be possible after authentication, while status 1 is an actual refusal.

3. Allow interaction only when a person is present

Add --allow-user-interaction when an interactive tool is allowed to wait for the registered authentication agent:

pkcheck --action-id "$action_id" \
  --process "$pid,$start_time,$uid" \
  --allow-user-interaction

This can display an authentication request and block until it completes. It is unsuitable for unattended jobs unless the wait and failure paths are explicitly handled. Never add it merely to make a script return success: doing so can turn a quick policy probe into a hanging service or an unexpected password prompt.

If the process has no suitable desktop agent, --enable-internal-agent asks pkcheck to register its own textual agent. That still requires a usable terminal and user interaction. It does not bypass policy or grant permission.

4. Pass action details when policy needs context

Some policies use details supplied by the caller. Add each key and value with --detail; do not place arbitrary shell text in a value without quoting it:

pkcheck --action-id "$action_id" \
  --process "$pid,$start_time,$uid" \
  --detail example-key 'example-value'

The accepted keys and their meanings belong to the action's policy and caller documentation. A detail does not override the policy. If the action does not use it, the check may produce the same decision.

5. Check a D-Bus service instead of a PID

When the operation belongs to a D-Bus service, use its system bus name rather than trying to identify a transient worker process:

pkcheck --action-id 'ACTION_ID_FROM_PKACTION' \
  --system-bus-name 'org.example.Service'

Replace both placeholders with values documented by that service. The bus-name subject is different from the process subject, so do not mix the two forms in one invocation.

6. Inspect or revoke temporary authorisations

These operations apply to the current session and change authorisation state. Listing is read-only:

pkcheck --list-temp

On a session with no temporary grants this produced no output and exit status 0 here. If it lists grants, treat the output as security-sensitive session information.

Warning

--revoke-temp revokes all temporary authorisations for the current session. It does not undo a configuration change or restore an earlier grant. The action is not selective, and there is no pkcheck undo command. Use it only when you intend to invalidate every temporary grant; affected applications must authenticate again when their policies require it.

Common traps

  • Using $$ after a command has changed the shell context. Capture the PID, start time, and UID together immediately before the check.
  • Reading only standard output. Diagnostics and authentication messages go to standard error, while policy details go to standard output.
  • Using --allow-user-interaction in a daemon or CI job. Prefer a non-interactive check and handle status 2 explicitly.
  • Assuming root makes every action authorised. The result still depends on polkit policy, subject details, and session state.
  • Confusing pkcheck with an action runner. It checks authorisation; it does not execute the protected operation.

Done means

  • You identified the exact action ID from installed policy or the owning application.
  • Your process check used pid,start-time,uid, not a bare PID.
  • Your script records and interprets pkcheck status 0, 1, 2, 3, 126, and 127 separately where that distinction matters.
  • You used authentication interaction only in a deliberately interactive context.
  • You treated --revoke-temp as a session-wide, irreversible authorisation change.