Add a permission check to pg_stat_get_backend_subxact()

Started by shihao zhong13 days ago7 messageshackers
Beta feature

Hackorum builds and tests every patch posted to the lists, not only commitfest submissions. This is Hackorum's own CI rather than the PostgreSQL project's, and it is still under testing - please report anything that looks wrong.

won't retrysuccessCI history

This thread has been committed, so CI has stopped here. Anything below is the last result it produced.

You can run a PostgreSQL built from this patch straight from Docker, with no checkout and no build:

docker run --rm -p 5432:5432 ghcr.io/hackorum-dev/postgres-patch:t253703
psql -h localhost -U postgres

Built from patchset v6 (message #6), September 13, 2026 at 01:11 PM.

Every patchset is also pushed to a branch of our PostgreSQL fork, so you can check out the same tree CI built. Without a PostgreSQL checkout:

git clone --branch t253703_6 https://github.com/hackorum-dev/postgres.git

In a checkout you already have, add the fork once:

git remote add hackorum https://github.com/hackorum-dev/postgres.git

then, for this patchset and every later one:

git fetch hackorum t253703_6 && git checkout t253703_6

Patchset v6 (message #6) is on t253703_6

Jump to latest
#1shihao zhong
zhong950419@gmail.com

Hi hackers,

pg_stat_get_backend_subxact() does not check the caller's permissions.
Every other function in the "Per-Backend Statistics Functions" table
that reports what a session is doing calls HAS_PGSTAT_PERMISSIONS()
first and returns NULL to a caller who may not see it. This one is the
only exception.

I reported this to pgsql-security first. Michael Paquier replied that
it is not a vulnerability, since the count and the flag are of no use to
an unprivileged user, and suggested that a consistency fix on HEAD be
discussed here.

The patch:

- adds the HAS_PGSTAT_PERMISSIONS() check, with a regression test that
fails without it;

- documents the rule above that table. The table says nothing about
permissions today; the rule is only written down for the dynamic
statistics views;

- corrects one column name in the docs: subxact_overflow should be
subxact_overflowed.

pid, dbid, userid and idset stay open to everyone, and I think that is
right: they leak nothing new, since pg_stat_get_activity() already hands
datid, pid, usesysid and application_name to every caller before it
reaches its permission check. subxact_count and subxact_overflowed are
different. They are not columns of pg_stat_activity at all, so this
function is the only way to read them, and today it is an unchecked one.

Thanks,
Shihao

Attachments:

t253703_1
0001-Make-pg_stat_get_backend_subxact-respect-statistics-.patchapplication/octet-stream; name=0001-Make-pg_stat_get_backend_subxact-respect-statistics-.patchDownload+62-3
#2Jim Jones
jim.jones@uni-muenster.de
In reply to: shihao zhong (#1)
Re: Add a permission check to pg_stat_get_backend_subxact()

On 08/09/2026 02:33, shihao zhong wrote:

pg_stat_get_backend_subxact() does not check the caller's permissions.
Every other function in the "Per-Backend Statistics Functions" table
that reports what a session is doing calls HAS_PGSTAT_PERMISSIONS()
first and returns NULL to a caller who may not see it.  This one is the
only exception.

pg_stat_get_backend_wal, pg_stat_get_backend_io, and
pg_stat_get_backend_lock also lack this check. Out of scope here, but
perhaps worth a followup patch?

- adds the HAS_PGSTAT_PERMISSIONS() check, with a regression test that
  fails without it;

I believe the tests should also cover a non-superuser with explicit
pg_read_all_stats permission (see 0002 attached)

- documents the rule above that table.  The table says nothing about
  permissions today; the rule is only written down for the dynamic
  statistics views;

- corrects one column name in the docs: subxact_overflow should be
  subxact_overflowed.

The C tuple descriptor still says "subxact_overflow" -- most likely the
source of the confusion.

TupleDescInitEntry(tupdesc, (AttrNumber) 2, "subxact_overflow",
BOOLOID, -1, 0);

Best, Jim

Attachments:

t253703_2
v2-0001-Make-pg_stat_get_backend_subxact-respect-statisti.patchtext/x-patch; charset=UTF-8; name=v2-0001-Make-pg_stat_get_backend_subxact-respect-statisti.patchDownload+62-3
v2-0002-Add-test-case-for-explicit-pg_read_all_stats-gran.patchtext/x-patch; charset=UTF-8; name=v2-0002-Add-test-case-for-explicit-pg_read_all_stats-gran.patchDownload+21-1
#3Michael Paquier
michael@paquier.xyz
In reply to: Jim Jones (#2)
Re: Add a permission check to pg_stat_get_backend_subxact()

On Thu, Sep 10, 2026 at 05:47:36PM +0200, Jim Jones wrote:

On 08/09/2026 02:33, shihao zhong wrote:
pg_stat_get_backend_wal, pg_stat_get_backend_io, and
pg_stat_get_backend_lock also lack this check. Out of scope here, but
perhaps worth a followup patch?

Hmm, yeah. You have a consistency point here. None of these stats
are critical in any way, but cleaning up all that on HEAD shoulds like
a good thing to do, while we are on it. Let's group all that in a
single patch. All these functions treat similar backend-level stats.

I believe the tests should also cover a non-superuser with explicit
pg_read_all_stats permission (see 0002 attached)

Yep. Let's make that also cheaper: one role for all of the functions.

The C tuple descriptor still says "subxact_overflow" -- most likely the
source of the confusion.

TupleDescInitEntry(tupdesc, (AttrNumber) 2, "subxact_overflow",
BOOLOID, -1, 0);

Ahah, nice catch. The value that primes (reported back to the user)
is not the one set in the TupleDesc but the one defined in pg_proc.dat.

Could you group all your findings in a single patch? The doc entry
needs to be at least backpatched, mentioning "overflow" instead of
"overflowed" is not correct.
--
Michael

#4Jim Jones
jim.jones@uni-muenster.de
In reply to: Michael Paquier (#3)
Re: Add a permission check to pg_stat_get_backend_subxact()

On 11/09/2026 09:53, Michael Paquier wrote:

Could you group all your findings in a single patch? The doc entry
needs to be at least backpatched, mentioning "overflow" instead of
"overflowed" is not correct.

Attached v3 with these changes.

0001 - docs fix for backpatching
0002 - adds the same permission checks into pg_stat_get_backend_subxact,
pg_stat_get_backend_io, pg_stat_get_backend_lock, and
pg_stat_get_backend_wal.

Shihao, feel free to modify or reject these changes (it's your patch)

Thanks!

Best, Jim

Attachments:

t253703_4
v3-0001-Fix-output-column-name-for-pg_stat_get_backend_su.patchtext/x-patch; charset=UTF-8; name=v3-0001-Fix-output-column-name-for-pg_stat_get_backend_su.patchDownload+1-2
v3-0002-Make-per-backend-statistics-functions-respect-sta.patchtext/x-patch; charset=UTF-8; name=v3-0002-Make-per-backend-statistics-functions-respect-sta.patchDownload+147-12
#5Michael Paquier
michael@paquier.xyz
In reply to: Jim Jones (#4)
Re: Add a permission check to pg_stat_get_backend_subxact()

On Fri, Sep 11, 2026 at 12:58:50PM +0200, Jim Jones wrote:

0001 - docs fix for backpatching

Applied this one for now.

0002 - adds the same permission checks into pg_stat_get_backend_subxact,
pg_stat_get_backend_io, pg_stat_get_backend_lock, and
pg_stat_get_backend_wal.

And will look at that later..
--
Michael

#6shihao zhong
zhong950419@gmail.com
In reply to: Michael Paquier (#5)
Re: Add a permission check to pg_stat_get_backend_subxact()

Hi Jim, Michael,

Shihao, feel free to modify or reject these changes (it's your patch)

Thanks Jim, grouping the four functions is the right thing. v4 attached,
with three small changes to 0002:

Applied this one for now.

Thanks for committing that, I will not include 0001 in the following emails.

1. The first test block ran as superuser, so the owner branch of
HAS_PGSTAT_PERMISSIONS() was never exercised: with "userid" forced to
InvalidOid the test still passed. The block now grants the test role
membership in the session's role instead. With that, forcing userid
to InvalidOid fails the test, and removing the checks fails the
"unrelated role" block.

2. The doc paragraph above the per-backend table said the functions
"return NULL", but activity/wait_event return "<insufficient
privilege>" and the SRFs return no rows. Reworded.

3. Commit message: noted that processes owned by no role (autovacuum
workers, WAL writer, ...) are now visible only to superusers and
pg_read_all_stats, as in pg_stat_activity, and that no backpatch is
done.

Thanks,
Shihao

Attachments:

t253703_6
v4-0002-Make-per-backend-statistics-functions-respect-sta.patchapplication/octet-stream; name=v4-0002-Make-per-backend-statistics-functions-respect-sta.patchDownload+157-12
#7Michael Paquier
michael@paquier.xyz
In reply to: shihao zhong (#6)
Re: Add a permission check to pg_stat_get_backend_subxact()

On Sat, Sep 12, 2026 at 08:43:28AM -0400, shihao zhong wrote:

Thanks for committing that, I will not include 0001 in the following emails.

Fixed the subxact_overflow -> subxact_overflowed, as that's
independent.

1. The first test block ran as superuser, so the owner branch of
HAS_PGSTAT_PERMISSIONS() was never exercised: with "userid" forced to
InvalidOid the test still passed. The block now grants the test role
membership in the session's role instead. With that, forcing userid
to InvalidOid fails the test, and removing the checks fails the
"unrelated role" block.

2. The doc paragraph above the per-backend table said the functions
"return NULL", but activity/wait_event return "<insufficient
privilege>" and the SRFs return no rows. Reworded.

3. Commit message: noted that processes owned by no role (autovacuum
workers, WAL writer, ...) are now visible only to superusers and
pg_read_all_stats, as in pg_stat_activity, and that no backpatch is
done.

That seems globally sensible, at quick glance. I am also adding
Bertrand Drouvot in CC to comment about this change, as he has worked
on three of these functions.

@Bertrand, what do you think?
--
Michael