Re: generating function default settings from pg_proc.dat - Mailing list pgsql-hackers

From Tom Lane
Subject Re: generating function default settings from pg_proc.dat
Date
Msg-id 2659121.1771523629@sss.pgh.pa.us
Whole thread Raw
In response to Re: generating function default settings from pg_proc.dat  (Tom Lane <tgl@sss.pgh.pa.us>)
List pgsql-hackers
I wrote:
> However, I'm not sure I love it in this form, because what it
> asks developers to do is populate proacl using aclitemin's
> notation, eg
> +  proacl => '{postgres=X/postgres,pg_read_all_stats=X/postgres}' },

After sleeping on it, I decided that much of the cognitive dissonance
here comes from the fact that elsewhere in the catalog data files
we represent the bootstrap user's name as POSTGRES, making it more
obvious that that's a placeholder and not the real value.  If we do
that here and also drop the redundant grantor specifications, we get

+  proacl => '{POSTGRES=X,pg_read_all_stats=X}' },

which is still not the world's prettiest notation, but it feels
manageable for this purpose.

I tried to write it that way and found that it failed miserably,
because initdb tried to substitute the real superuser's name
for POSTGRES, and we don't want that here (the bootstrap backend
can't possibly know what that is yet).  So 0001 attached is a
preliminary patch to tighten initdb so it only replaces complete
tokens bounded by whitespace, rather than any arbitrary substrings
of postgres.bki lines.  (Note this depends on 2f248ad57.)  Then
0002 is the same patch as before plus this notational adjustment.

            regards, tom lane

From 041f37c0980eec91edb6924726d3806d37426e25 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Thu, 19 Feb 2026 12:00:25 -0500
Subject: [PATCH v2 1/2] Be more wary of false matches in initdb's
 replace_token().

Do not replace the target string unless the occurrence is surrounded
by whitespace or line start/end.  This avoids potential false match
to a substring of a field.  While we've not had trouble with that
up to now, the next patch creates hazards of false matches to
POSTGRES within an ACL field.

There is one call site that needs adjustment, as it was presuming
it could write "::1" and have that match "::1/128".  For all the
others, this restriction is okay and strictly safer.

Author: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/183292bb-4891-4c96-a3ca-e78b5e0e1358@dunslane.net
---
 src/bin/initdb/initdb.c | 23 ++++++++++++++++++-----
 1 file changed, 18 insertions(+), 5 deletions(-)

diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c
index 7c49dd433a7..e9e1014bce9 100644
--- a/src/bin/initdb/initdb.c
+++ b/src/bin/initdb/initdb.c
@@ -461,7 +461,8 @@ add_stringlist_item(_stringlist **listhead, const char *str)

 /*
  * Modify the array of lines, replacing "token" by "replacement"
- * the first time it occurs on each line.
+ * the first time it occurs on each line.  To prevent false matches, the
+ * occurrence of "token" must be surrounded by whitespace or line start/end.
  *
  * The array must be a malloc'd array of individually malloc'd strings.
  * We free any discarded strings.
@@ -483,6 +484,7 @@ replace_token(char **lines, const char *token, const char *replacement)
     for (int i = 0; lines[i]; i++)
     {
         char       *where;
+        char       *endwhere;
         char       *newline;
         int            pre;

@@ -490,6 +492,17 @@ replace_token(char **lines, const char *token, const char *replacement)
         if ((where = strstr(lines[i], token)) == NULL)
             continue;

+        /*
+         * Reject false match.  Note a blind spot: we don't check for a valid
+         * match following a false match.  That case can't occur at present,
+         * so not worth complicating this code for it.
+         */
+        if (!(where == lines[i] || isspace((unsigned char) where[-1])))
+            continue;
+        endwhere = where + strlen(token);
+        if (!(*endwhere == '\0' || isspace((unsigned char) *endwhere)))
+            continue;
+
         /* if we get here a change is needed - set up new line */

         newline = (char *) pg_malloc(strlen(lines[i]) + diff + 1);
@@ -1496,11 +1509,11 @@ setup_config(void)
             getaddrinfo("::1", NULL, &hints, &gai_result) != 0)
         {
             conflines = replace_token(conflines,
-                                      "host    all             all             ::1",
-                                      "#host    all             all             ::1");
+                                      "host    all             all             ::1/128",
+                                      "#host    all             all             ::1/128");
             conflines = replace_token(conflines,
-                                      "host    replication     all             ::1",
-                                      "#host    replication     all             ::1");
+                                      "host    replication     all             ::1/128",
+                                      "#host    replication     all             ::1/128");
         }
     }

--
2.43.7

From 02cf96109455d9aff9775dbb665474a20eea1352 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Thu, 19 Feb 2026 12:25:05 -0500
Subject: [PATCH v2 2/2] Simplify creation of built-in functions with
 non-default ACLs.

Up to now, to create such a function, one had to make a pg_proc.dat
entry and then modify it with GRANT/REVOKE commands, which we put in
system_functions.sql.  That seems a little ugly though, because it
violates the idea of having a single source of truth about the initial
contents of pg_proc, and it results in leaving dead rows in the
initial contents of pg_proc.

This patch improves matters by allowing aclitemin to work during
early bootstrap, before pg_authid has been loaded.  On the same
principle that we use for early access to pg_type details, put
a table of known built-in role names into bootstrap.c, and use
that in bootstrap mode.

In this form of the patch, one must write ACL lists in pg_proc.dat
proacl entries in a simplified version of aclitemout's notation:
omit the grantor (if it is the bootstrap superuser, which it
pretty much always should be) and spell the bootstrap superuser's
name as POSTGRES, similarly to the notation used elsewhere in
src/include/catalog.  This results in entries like
  proacl => '{POSTGRES=X,pg_monitor=X}'

In addition to fixing up pg_proc.dat entries, I got rid of some
role grants that had been stuck into system_functions.sql,
and instead put them into a new file pg_auth_members.dat;
that seems like a far less random place to put the information.

The correctness of the data changes can be verified by comparing
the initial contents of pg_proc and pg_auth_members before and
after.  pg_proc should match exactly, but the OID column of
pg_auth_members will probably be different because those OIDs
now get assigned a little earlier in bootstrap.

Author: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/183292bb-4891-4c96-a3ca-e78b5e0e1358@dunslane.net
---
 src/backend/bootstrap/bootstrap.c        |  59 +++++++
 src/backend/catalog/system_functions.sql | 166 +------------------
 src/backend/catalog/system_views.sql     |  14 --
 src/backend/utils/adt/acl.c              |  26 ++-
 src/include/bootstrap/bootstrap.h        |   2 +
 src/include/catalog/Makefile             |   1 +
 src/include/catalog/meson.build          |   1 +
 src/include/catalog/pg_auth_members.dat  |  20 +++
 src/include/catalog/pg_auth_members.h    |  27 ++-
 src/include/catalog/pg_authid.dat        |   6 +-
 src/include/catalog/pg_proc.dat          | 201 +++++++++++++++--------
 11 files changed, 262 insertions(+), 261 deletions(-)
 create mode 100644 src/include/catalog/pg_auth_members.dat

diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c
index e7699be55aa..17118f2fe76 100644
--- a/src/backend/bootstrap/bootstrap.c
+++ b/src/backend/bootstrap/bootstrap.c
@@ -25,6 +25,7 @@
 #include "access/xact.h"
 #include "bootstrap/bootstrap.h"
 #include "catalog/index.h"
+#include "catalog/pg_authid.h"
 #include "catalog/pg_collation.h"
 #include "catalog/pg_proc.h"
 #include "catalog/pg_type.h"
@@ -115,6 +116,8 @@ static const struct typinfo TypInfo[] = {
     F_JSONB_IN, F_JSONB_OUT},
     {"oid", OIDOID, 0, 4, true, TYPALIGN_INT, TYPSTORAGE_PLAIN, InvalidOid,
     F_OIDIN, F_OIDOUT},
+    {"aclitem", ACLITEMOID, 0, 16, false, TYPALIGN_DOUBLE, TYPSTORAGE_PLAIN, InvalidOid,
+    F_ACLITEMIN, F_ACLITEMOUT},
     {"pg_node_tree", PG_NODE_TREEOID, 0, -1, false, TYPALIGN_INT, TYPSTORAGE_EXTENDED, DEFAULT_COLLATION_OID,
     F_PG_NODE_TREE_IN, F_PG_NODE_TREE_OUT},
     {"int2vector", INT2VECTOROID, INT2OID, -1, false, TYPALIGN_INT, TYPSTORAGE_PLAIN, InvalidOid,
@@ -144,6 +147,43 @@ struct typmap
 static List *Typ = NIL;            /* List of struct typmap* */
 static struct typmap *Ap = NULL;

+/*
+ * Basic information about built-in roles.
+ *
+ * Presently, this need only list roles that are mentioned in aclitem arrays
+ * in the catalog .dat files.  We might as well list everything that is in
+ * pg_authid.dat, since there aren't that many.  Like pg_authid.dat, we
+ * represent the bootstrap superuser's name as "POSTGRES", even though it
+ * (probably) won't be that in the finished installation; this means aclitem
+ * entries in .dat files must spell it like that.
+ */
+struct rolinfo
+{
+    const char *rolname;
+    Oid            oid;
+};
+
+static const struct rolinfo RolInfo[] = {
+    {"POSTGRES", BOOTSTRAP_SUPERUSERID},
+    {"pg_database_owner", ROLE_PG_DATABASE_OWNER},
+    {"pg_read_all_data", ROLE_PG_READ_ALL_DATA},
+    {"pg_write_all_data", ROLE_PG_WRITE_ALL_DATA},
+    {"pg_monitor", ROLE_PG_MONITOR},
+    {"pg_read_all_settings", ROLE_PG_READ_ALL_SETTINGS},
+    {"pg_read_all_stats", ROLE_PG_READ_ALL_STATS},
+    {"pg_stat_scan_tables", ROLE_PG_STAT_SCAN_TABLES},
+    {"pg_read_server_files", ROLE_PG_READ_SERVER_FILES},
+    {"pg_write_server_files", ROLE_PG_WRITE_SERVER_FILES},
+    {"pg_execute_server_program", ROLE_PG_EXECUTE_SERVER_PROGRAM},
+    {"pg_signal_backend", ROLE_PG_SIGNAL_BACKEND},
+    {"pg_checkpoint", ROLE_PG_CHECKPOINT},
+    {"pg_maintain", ROLE_PG_MAINTAIN},
+    {"pg_use_reserved_connections", ROLE_PG_USE_RESERVED_CONNECTIONS},
+    {"pg_create_subscription", ROLE_PG_CREATE_SUBSCRIPTION},
+    {"pg_signal_autovacuum_worker", ROLE_PG_SIGNAL_AUTOVACUUM_WORKER}
+};
+
+
 static Datum values[MAXATTR];    /* current row's attribute values */
 static bool Nulls[MAXATTR];

@@ -1034,6 +1074,25 @@ boot_get_type_io_data(Oid typid,
     }
 }

+/* ----------------
+ *        boot_get_role_oid
+ *
+ * Look up a role name at bootstrap time.  This is equivalent to
+ * get_role_oid(rolname, true): return the role OID or InvalidOid if
+ * not found.  We only need to cope with built-in role names.
+ * ----------------
+ */
+Oid
+boot_get_role_oid(const char *rolname)
+{
+    for (int i = 0; i < lengthof(RolInfo); i++)
+    {
+        if (strcmp(RolInfo[i].rolname, rolname) == 0)
+            return RolInfo[i].oid;
+    }
+    return InvalidOid;
+}
+
 /* ----------------
  *        AllocateAttribute
  *
diff --git a/src/backend/catalog/system_functions.sql b/src/backend/catalog/system_functions.sql
index 69699f8830a..1c5b6d6df05 100644
--- a/src/backend/catalog/system_functions.sql
+++ b/src/backend/catalog/system_functions.sql
@@ -14,12 +14,8 @@
  * definitions of such functions into pg_proc.dat and then replace them
  * here.  The stub definitions would be unnecessary were it not that we'd
  * like these functions to have stable OIDs, the same as other built-in
- * functions.
- *
- * This file also takes care of adjusting privileges for those functions
- * that should not have the default public-EXECUTE privileges.  (However,
- * a small number of functions that exist mainly to underlie system views
- * are dealt with in system_views.sql, instead.)
+ * functions.  (That's important, for example, to their treatment by
+ * postgres_fdw.)
  *
  * Note: this file is read in single-user -j mode, which means that the
  * command terminator is semicolon-newline-newline; whenever the backend
@@ -376,161 +372,3 @@ CREATE OR REPLACE FUNCTION ts_debug(document text,
 BEGIN ATOMIC
     SELECT * FROM ts_debug(get_current_ts_config(), $1);
 END;
-
-
---
--- The default permissions for functions mean that anyone can execute them.
--- A number of functions shouldn't be executable by just anyone, but rather
--- than use explicit 'superuser()' checks in those functions, we use the GRANT
--- system to REVOKE access to those functions at initdb time.  Administrators
--- can later change who can access these functions, or leave them as only
--- available to superuser / cluster owner, if they choose.
---
-
-REVOKE EXECUTE ON FUNCTION pg_backup_start(text, boolean) FROM public;
-
-REVOKE EXECUTE ON FUNCTION pg_backup_stop(boolean) FROM public;
-
-REVOKE EXECUTE ON FUNCTION pg_create_restore_point(text) FROM public;
-
-REVOKE EXECUTE ON FUNCTION pg_switch_wal() FROM public;
-
-REVOKE EXECUTE ON FUNCTION pg_log_standby_snapshot() FROM public;
-
-REVOKE EXECUTE ON FUNCTION pg_wal_replay_pause() FROM public;
-
-REVOKE EXECUTE ON FUNCTION pg_wal_replay_resume() FROM public;
-
-REVOKE EXECUTE ON FUNCTION pg_rotate_logfile() FROM public;
-
-REVOKE EXECUTE ON FUNCTION pg_reload_conf() FROM public;
-
-REVOKE EXECUTE ON FUNCTION pg_current_logfile() FROM public;
-
-REVOKE EXECUTE ON FUNCTION pg_current_logfile(text) FROM public;
-
-REVOKE EXECUTE ON FUNCTION pg_promote(boolean, integer) FROM public;
-
-REVOKE EXECUTE ON FUNCTION pg_stat_reset() FROM public;
-
-REVOKE EXECUTE ON FUNCTION pg_stat_reset_shared(text) FROM public;
-
-REVOKE EXECUTE ON FUNCTION pg_stat_reset_slru(text) FROM public;
-
-REVOKE EXECUTE ON FUNCTION pg_stat_reset_single_table_counters(oid) FROM public;
-
-REVOKE EXECUTE ON FUNCTION pg_stat_reset_single_function_counters(oid) FROM public;
-
-REVOKE EXECUTE ON FUNCTION pg_stat_reset_backend_stats(integer) FROM public;
-
-REVOKE EXECUTE ON FUNCTION pg_stat_reset_replication_slot(text) FROM public;
-
-REVOKE EXECUTE ON FUNCTION pg_stat_have_stats(text, oid, int8) FROM public;
-
-REVOKE EXECUTE ON FUNCTION pg_stat_reset_subscription_stats(oid) FROM public;
-
-REVOKE EXECUTE ON FUNCTION lo_import(text) FROM public;
-
-REVOKE EXECUTE ON FUNCTION lo_import(text, oid) FROM public;
-
-REVOKE EXECUTE ON FUNCTION lo_export(oid, text) FROM public;
-
-REVOKE EXECUTE ON FUNCTION pg_ls_logdir() FROM public;
-
-REVOKE EXECUTE ON FUNCTION pg_ls_waldir() FROM public;
-
-REVOKE EXECUTE ON FUNCTION pg_ls_archive_statusdir() FROM public;
-
-REVOKE EXECUTE ON FUNCTION pg_ls_summariesdir() FROM public;
-
-REVOKE EXECUTE ON FUNCTION pg_ls_tmpdir() FROM public;
-
-REVOKE EXECUTE ON FUNCTION pg_ls_tmpdir(oid) FROM public;
-
-REVOKE EXECUTE ON FUNCTION pg_read_file(text) FROM public;
-
-REVOKE EXECUTE ON FUNCTION pg_read_file(text,boolean) FROM public;
-
-REVOKE EXECUTE ON FUNCTION pg_read_file(text,bigint,bigint) FROM public;
-
-REVOKE EXECUTE ON FUNCTION pg_read_file(text,bigint,bigint,boolean) FROM public;
-
-REVOKE EXECUTE ON FUNCTION pg_read_binary_file(text) FROM public;
-
-REVOKE EXECUTE ON FUNCTION pg_read_binary_file(text,boolean) FROM public;
-
-REVOKE EXECUTE ON FUNCTION pg_read_binary_file(text,bigint,bigint) FROM public;
-
-REVOKE EXECUTE ON FUNCTION pg_read_binary_file(text,bigint,bigint,boolean) FROM public;
-
-REVOKE EXECUTE ON FUNCTION pg_replication_origin_advance(text, pg_lsn) FROM public;
-
-REVOKE EXECUTE ON FUNCTION pg_replication_origin_create(text) FROM public;
-
-REVOKE EXECUTE ON FUNCTION pg_replication_origin_drop(text) FROM public;
-
-REVOKE EXECUTE ON FUNCTION pg_replication_origin_oid(text) FROM public;
-
-REVOKE EXECUTE ON FUNCTION pg_replication_origin_progress(text, boolean) FROM public;
-
-REVOKE EXECUTE ON FUNCTION pg_replication_origin_session_is_setup() FROM public;
-
-REVOKE EXECUTE ON FUNCTION pg_replication_origin_session_progress(boolean) FROM public;
-
-REVOKE EXECUTE ON FUNCTION pg_replication_origin_session_reset() FROM public;
-
-REVOKE EXECUTE ON FUNCTION pg_replication_origin_session_setup(text, integer) FROM public;
-
-REVOKE EXECUTE ON FUNCTION pg_replication_origin_xact_reset() FROM public;
-
-REVOKE EXECUTE ON FUNCTION pg_replication_origin_xact_setup(pg_lsn, timestamp with time zone) FROM public;
-
-REVOKE EXECUTE ON FUNCTION pg_show_replication_origin_status() FROM public;
-
-REVOKE EXECUTE ON FUNCTION pg_stat_file(text) FROM public;
-
-REVOKE EXECUTE ON FUNCTION pg_stat_file(text,boolean) FROM public;
-
-REVOKE EXECUTE ON FUNCTION pg_ls_dir(text) FROM public;
-
-REVOKE EXECUTE ON FUNCTION pg_ls_dir(text,boolean,boolean) FROM public;
-
-REVOKE EXECUTE ON FUNCTION pg_log_backend_memory_contexts(integer) FROM PUBLIC;
-
-REVOKE EXECUTE ON FUNCTION pg_ls_logicalsnapdir() FROM PUBLIC;
-
-REVOKE EXECUTE ON FUNCTION pg_ls_logicalmapdir() FROM PUBLIC;
-
-REVOKE EXECUTE ON FUNCTION pg_ls_replslotdir(text) FROM PUBLIC;
-
---
--- We also set up some things as accessible to standard roles.
---
-
-GRANT EXECUTE ON FUNCTION pg_ls_logdir() TO pg_monitor;
-
-GRANT EXECUTE ON FUNCTION pg_ls_waldir() TO pg_monitor;
-
-GRANT EXECUTE ON FUNCTION pg_ls_archive_statusdir() TO pg_monitor;
-
-GRANT EXECUTE ON FUNCTION pg_ls_summariesdir() TO pg_monitor;
-
-GRANT EXECUTE ON FUNCTION pg_ls_tmpdir() TO pg_monitor;
-
-GRANT EXECUTE ON FUNCTION pg_ls_tmpdir(oid) TO pg_monitor;
-
-GRANT EXECUTE ON FUNCTION pg_ls_logicalsnapdir() TO pg_monitor;
-
-GRANT EXECUTE ON FUNCTION pg_ls_logicalmapdir() TO pg_monitor;
-
-GRANT EXECUTE ON FUNCTION pg_ls_replslotdir(text) TO pg_monitor;
-
-GRANT EXECUTE ON FUNCTION pg_current_logfile() TO pg_monitor;
-
-GRANT EXECUTE ON FUNCTION pg_current_logfile(text) TO pg_monitor;
-
-GRANT pg_read_all_settings TO pg_monitor;
-
-GRANT pg_read_all_stats TO pg_monitor;
-
-GRANT pg_stat_scan_tables TO pg_monitor;
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 1ea8f1faa9e..56106d92eaf 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -650,19 +650,16 @@ CREATE VIEW pg_file_settings AS
    SELECT * FROM pg_show_all_file_settings() AS A;

 REVOKE ALL ON pg_file_settings FROM PUBLIC;
-REVOKE EXECUTE ON FUNCTION pg_show_all_file_settings() FROM PUBLIC;

 CREATE VIEW pg_hba_file_rules AS
    SELECT * FROM pg_hba_file_rules() AS A;

 REVOKE ALL ON pg_hba_file_rules FROM PUBLIC;
-REVOKE EXECUTE ON FUNCTION pg_hba_file_rules() FROM PUBLIC;

 CREATE VIEW pg_ident_file_mappings AS
    SELECT * FROM pg_ident_file_mappings() AS A;

 REVOKE ALL ON pg_ident_file_mappings FROM PUBLIC;
-REVOKE EXECUTE ON FUNCTION pg_ident_file_mappings() FROM PUBLIC;

 CREATE VIEW pg_timezone_abbrevs AS
     SELECT * FROM pg_timezone_abbrevs_zone() z
@@ -679,39 +676,30 @@ CREATE VIEW pg_config AS
     SELECT * FROM pg_config();

 REVOKE ALL ON pg_config FROM PUBLIC;
-REVOKE EXECUTE ON FUNCTION pg_config() FROM PUBLIC;

 CREATE VIEW pg_shmem_allocations AS
     SELECT * FROM pg_get_shmem_allocations();

 REVOKE ALL ON pg_shmem_allocations FROM PUBLIC;
 GRANT SELECT ON pg_shmem_allocations TO pg_read_all_stats;
-REVOKE EXECUTE ON FUNCTION pg_get_shmem_allocations() FROM PUBLIC;
-GRANT EXECUTE ON FUNCTION pg_get_shmem_allocations() TO pg_read_all_stats;

 CREATE VIEW pg_shmem_allocations_numa AS
     SELECT * FROM pg_get_shmem_allocations_numa();

 REVOKE ALL ON pg_shmem_allocations_numa FROM PUBLIC;
 GRANT SELECT ON pg_shmem_allocations_numa TO pg_read_all_stats;
-REVOKE EXECUTE ON FUNCTION pg_get_shmem_allocations_numa() FROM PUBLIC;
-GRANT EXECUTE ON FUNCTION pg_get_shmem_allocations_numa() TO pg_read_all_stats;

 CREATE VIEW pg_dsm_registry_allocations AS
     SELECT * FROM pg_get_dsm_registry_allocations();

 REVOKE ALL ON pg_dsm_registry_allocations FROM PUBLIC;
 GRANT SELECT ON pg_dsm_registry_allocations TO pg_read_all_stats;
-REVOKE EXECUTE ON FUNCTION pg_get_dsm_registry_allocations() FROM PUBLIC;
-GRANT EXECUTE ON FUNCTION pg_get_dsm_registry_allocations() TO pg_read_all_stats;

 CREATE VIEW pg_backend_memory_contexts AS
     SELECT * FROM pg_get_backend_memory_contexts();

 REVOKE ALL ON pg_backend_memory_contexts FROM PUBLIC;
 GRANT SELECT ON pg_backend_memory_contexts TO pg_read_all_stats;
-REVOKE EXECUTE ON FUNCTION pg_get_backend_memory_contexts() FROM PUBLIC;
-GRANT EXECUTE ON FUNCTION pg_get_backend_memory_contexts() TO pg_read_all_stats;

 -- Statistics views

@@ -1471,5 +1459,3 @@ CREATE VIEW pg_aios AS
     SELECT * FROM pg_get_aios();
 REVOKE ALL ON pg_aios FROM PUBLIC;
 GRANT SELECT ON pg_aios TO pg_read_all_stats;
-REVOKE EXECUTE ON FUNCTION pg_get_aios() FROM PUBLIC;
-GRANT EXECUTE ON FUNCTION pg_get_aios() TO pg_read_all_stats;
diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c
index 641673f0b0e..071e3f2c49e 100644
--- a/src/backend/utils/adt/acl.c
+++ b/src/backend/utils/adt/acl.c
@@ -17,6 +17,7 @@
 #include <ctype.h>

 #include "access/htup_details.h"
+#include "bootstrap/bootstrap.h"
 #include "catalog/catalog.h"
 #include "catalog/namespace.h"
 #include "catalog/pg_auth_members.h"
@@ -261,6 +262,9 @@ putid(char *p, const char *s)
  *        This routine is called by the parser as well as aclitemin(), hence
  *        the added generality.
  *
+ *        In bootstrap mode, we consult a hard-wired list of role names
+ *        (see bootstrap.c) rather than trying to access the catalogs.
+ *
  * RETURNS:
  *        the string position in 's' immediately following the ACL
  *        specification.  Also:
@@ -376,7 +380,10 @@ aclparse(const char *s, AclItem *aip, Node *escontext)
         aip->ai_grantee = ACL_ID_PUBLIC;
     else
     {
-        aip->ai_grantee = get_role_oid(name, true);
+        if (IsBootstrapProcessingMode())
+            aip->ai_grantee = boot_get_role_oid(name);
+        else
+            aip->ai_grantee = get_role_oid(name, true);
         if (!OidIsValid(aip->ai_grantee))
             ereturn(escontext, NULL,
                     (errcode(ERRCODE_UNDEFINED_OBJECT),
@@ -385,7 +392,8 @@ aclparse(const char *s, AclItem *aip, Node *escontext)

     /*
      * XXX Allow a degree of backward compatibility by defaulting the grantor
-     * to the superuser.
+     * to the superuser.  We condone that practice in the catalog .dat files
+     * (i.e., in bootstrap mode) for brevity; otherwise, issue a warning.
      */
     if (*s == '/')
     {
@@ -396,7 +404,10 @@ aclparse(const char *s, AclItem *aip, Node *escontext)
             ereturn(escontext, NULL,
                     (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
                      errmsg("a name must follow the \"/\" sign")));
-        aip->ai_grantor = get_role_oid(name2, true);
+        if (IsBootstrapProcessingMode())
+            aip->ai_grantor = boot_get_role_oid(name2);
+        else
+            aip->ai_grantor = get_role_oid(name2, true);
         if (!OidIsValid(aip->ai_grantor))
             ereturn(escontext, NULL,
                     (errcode(ERRCODE_UNDEFINED_OBJECT),
@@ -405,10 +416,11 @@ aclparse(const char *s, AclItem *aip, Node *escontext)
     else
     {
         aip->ai_grantor = BOOTSTRAP_SUPERUSERID;
-        ereport(WARNING,
-                (errcode(ERRCODE_INVALID_GRANTOR),
-                 errmsg("defaulting grantor to user ID %u",
-                        BOOTSTRAP_SUPERUSERID)));
+        if (!IsBootstrapProcessingMode())
+            ereport(WARNING,
+                    (errcode(ERRCODE_INVALID_GRANTOR),
+                     errmsg("defaulting grantor to user ID %u",
+                            BOOTSTRAP_SUPERUSERID)));
     }

     ACLITEM_SET_PRIVS_GOPTIONS(*aip, privs, goption);
diff --git a/src/include/bootstrap/bootstrap.h b/src/include/bootstrap/bootstrap.h
index 21447a3d661..e967b2b1885 100644
--- a/src/include/bootstrap/bootstrap.h
+++ b/src/include/bootstrap/bootstrap.h
@@ -56,6 +56,8 @@ extern void boot_get_type_io_data(Oid typid,
                                   Oid *typoutput,
                                   Oid *typcollation);

+extern Oid    boot_get_role_oid(const char *rolname);
+
 union YYSTYPE;
 typedef void *yyscan_t;

diff --git a/src/include/catalog/Makefile b/src/include/catalog/Makefile
index 24b527230d4..444fc76eed6 100644
--- a/src/include/catalog/Makefile
+++ b/src/include/catalog/Makefile
@@ -94,6 +94,7 @@ POSTGRES_BKI_DATA = \
     pg_amop.dat \
     pg_amproc.dat \
     pg_authid.dat \
+    pg_auth_members.dat \
     pg_cast.dat \
     pg_class.dat \
     pg_collation.dat \
diff --git a/src/include/catalog/meson.build b/src/include/catalog/meson.build
index 433bcc908ad..bcc01c87c2e 100644
--- a/src/include/catalog/meson.build
+++ b/src/include/catalog/meson.build
@@ -78,6 +78,7 @@ bki_data = [
   'pg_amop.dat',
   'pg_amproc.dat',
   'pg_authid.dat',
+  'pg_auth_members.dat',
   'pg_cast.dat',
   'pg_class.dat',
   'pg_collation.dat',
diff --git a/src/include/catalog/pg_auth_members.dat b/src/include/catalog/pg_auth_members.dat
new file mode 100644
index 00000000000..246373251d4
--- /dev/null
+++ b/src/include/catalog/pg_auth_members.dat
@@ -0,0 +1,20 @@
+#----------------------------------------------------------------------
+#
+# pg_auth_members.dat
+#    Initial contents of the pg_auth_members system catalog.
+#
+# Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
+# Portions Copyright (c) 1994, Regents of the University of California
+#
+# src/include/catalog/pg_auth_members.dat
+#
+#----------------------------------------------------------------------
+
+[
+
+# We grant these roles to pg_monitor.
+{ roleid => 'pg_read_all_settings', member => 'pg_monitor' },
+{ roleid => 'pg_read_all_stats', member => 'pg_monitor' },
+{ roleid => 'pg_stat_scan_tables', member => 'pg_monitor' },
+
+]
diff --git a/src/include/catalog/pg_auth_members.h b/src/include/catalog/pg_auth_members.h
index 92cf5271496..15806df95bf 100644
--- a/src/include/catalog/pg_auth_members.h
+++ b/src/include/catalog/pg_auth_members.h
@@ -29,13 +29,26 @@
  */
 CATALOG(pg_auth_members,1261,AuthMemRelationId) BKI_SHARED_RELATION BKI_ROWTYPE_OID(2843,AuthMemRelation_Rowtype_Id)
BKI_SCHEMA_MACRO
 {
-    Oid            oid;            /* oid */
-    Oid            roleid BKI_LOOKUP(pg_authid);    /* ID of a role */
-    Oid            member BKI_LOOKUP(pg_authid);    /* ID of a member of that role */
-    Oid            grantor BKI_LOOKUP(pg_authid);    /* who granted the membership */
-    bool        admin_option;    /* granted with admin option? */
-    bool        inherit_option; /* exercise privileges without SET ROLE? */
-    bool        set_option;        /* use SET ROLE to the target role? */
+    /* OID for this record (needed for dependencies) */
+    Oid            oid;
+
+    /* ID of a role */
+    Oid            roleid BKI_LOOKUP(pg_authid);
+
+    /* ID of a member of that role */
+    Oid            member BKI_LOOKUP(pg_authid);
+
+    /* who granted the membership */
+    Oid            grantor BKI_DEFAULT(POSTGRES) BKI_LOOKUP(pg_authid);
+
+    /* granted with admin option? */
+    bool        admin_option BKI_DEFAULT(f);
+
+    /* exercise privileges without SET ROLE? */
+    bool        inherit_option BKI_DEFAULT(t);
+
+    /* use SET ROLE to the target role? */
+    bool        set_option BKI_DEFAULT(t);
 } FormData_pg_auth_members;

 /* ----------------
diff --git a/src/include/catalog/pg_authid.dat b/src/include/catalog/pg_authid.dat
index 26b5c9971a4..2960707c729 100644
--- a/src/include/catalog/pg_authid.dat
+++ b/src/include/catalog/pg_authid.dat
@@ -16,8 +16,10 @@
 # so make sure every entry has an oid_symbol value.

 # The bootstrap superuser is named POSTGRES according to this data and
-# according to BKI_DEFAULT entries in other catalogs.  However, initdb
-# will replace that at database initialization time.
+# according to BKI_DEFAULT entries and ACL entries in other catalogs.
+# initdb will replace that at database initialization time for standalone
+# references (the rolname below and various owner-OID columns), while
+# boot_get_role_oid() deals with it for ACL entries.

 { oid => '10', oid_symbol => 'BOOTSTRAP_SUPERUSERID',
   rolname => 'POSTGRES', rolsuper => 't', rolinherit => 't',
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index dac40992cbc..4950bff2804 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -1822,14 +1822,17 @@

 { oid => '764', descr => 'large object import',
   proname => 'lo_import', provolatile => 'v', proparallel => 'u',
-  prorettype => 'oid', proargtypes => 'text', prosrc => 'be_lo_import' },
+  prorettype => 'oid', proargtypes => 'text', prosrc => 'be_lo_import',
+  proacl => '{POSTGRES=X}' },
 { oid => '767', descr => 'large object import',
   proname => 'lo_import', provolatile => 'v', proparallel => 'u',
   prorettype => 'oid', proargtypes => 'text oid',
-  prosrc => 'be_lo_import_with_oid' },
+  prosrc => 'be_lo_import_with_oid',
+  proacl => '{POSTGRES=X}' },
 { oid => '765', descr => 'large object export',
   proname => 'lo_export', provolatile => 'v', proparallel => 'u',
-  prorettype => 'int4', proargtypes => 'oid text', prosrc => 'be_lo_export' },
+  prorettype => 'int4', proargtypes => 'oid text', prosrc => 'be_lo_export',
+  proacl => '{POSTGRES=X}' },

 { oid => '766', descr => 'increment',
   proname => 'int4inc', prorettype => 'int4', proargtypes => 'int4',
@@ -5709,7 +5712,8 @@
 { oid => '6230', descr => 'statistics: check if a stats object exists',
   proname => 'pg_stat_have_stats', provolatile => 'v', proparallel => 'r',
   prorettype => 'bool', proargtypes => 'text oid int8',
-  prosrc => 'pg_stat_have_stats' },
+  prosrc => 'pg_stat_have_stats',
+  proacl => '{POSTGRES=X}' },

 { oid => '6231', descr => 'statistics: information about subscription stats',
   proname => 'pg_stat_get_subscription_stats', provolatile => 's',
@@ -6170,43 +6174,51 @@
 { oid => '2274',
   descr => 'statistics: reset collected statistics for current database',
   proname => 'pg_stat_reset', proisstrict => 'f', provolatile => 'v',
-  prorettype => 'void', proargtypes => '', prosrc => 'pg_stat_reset' },
+  prorettype => 'void', proargtypes => '', prosrc => 'pg_stat_reset',
+  proacl => '{POSTGRES=X}' },
 { oid => '3775',
   descr => 'statistics: reset collected statistics shared across the cluster',
   proname => 'pg_stat_reset_shared', proisstrict => 'f', provolatile => 'v',
   prorettype => 'void', proargtypes => 'text',
   proargnames => '{target}', proargdefaults => '{NULL}',
-  prosrc => 'pg_stat_reset_shared' },
+  prosrc => 'pg_stat_reset_shared',
+  proacl => '{POSTGRES=X}' },
 { oid => '3776',
   descr => 'statistics: reset collected statistics for a single table or index in the current database or shared
acrossall databases in the cluster', 
   proname => 'pg_stat_reset_single_table_counters', provolatile => 'v',
   prorettype => 'void', proargtypes => 'oid',
-  prosrc => 'pg_stat_reset_single_table_counters' },
+  prosrc => 'pg_stat_reset_single_table_counters',
+  proacl => '{POSTGRES=X}' },
 { oid => '3777',
   descr => 'statistics: reset collected statistics for a single function in the current database',
   proname => 'pg_stat_reset_single_function_counters', provolatile => 'v',
   prorettype => 'void', proargtypes => 'oid',
-  prosrc => 'pg_stat_reset_single_function_counters' },
+  prosrc => 'pg_stat_reset_single_function_counters',
+  proacl => '{POSTGRES=X}' },
 { oid => '6387', descr => 'statistics: reset statistics for a single backend',
   proname => 'pg_stat_reset_backend_stats', provolatile => 'v',
   prorettype => 'void', proargtypes => 'int4',
-  prosrc => 'pg_stat_reset_backend_stats' },
+  prosrc => 'pg_stat_reset_backend_stats',
+  proacl => '{POSTGRES=X}' },
 { oid => '2307',
   descr => 'statistics: reset collected statistics for a single SLRU',
   proname => 'pg_stat_reset_slru', proisstrict => 'f', provolatile => 'v',
   prorettype => 'void', proargtypes => 'text', proargnames => '{target}',
   proargdefaults => '{NULL}',
-  prosrc => 'pg_stat_reset_slru' },
+  prosrc => 'pg_stat_reset_slru',
+  proacl => '{POSTGRES=X}' },
 { oid => '6170',
   descr => 'statistics: reset collected statistics for a single replication slot',
   proname => 'pg_stat_reset_replication_slot', proisstrict => 'f',
   provolatile => 'v', prorettype => 'void', proargtypes => 'text',
-  prosrc => 'pg_stat_reset_replication_slot' },
+  prosrc => 'pg_stat_reset_replication_slot',
+  proacl => '{POSTGRES=X}' },
 { oid => '6232',
   descr => 'statistics: reset collected statistics for a single subscription',
   proname => 'pg_stat_reset_subscription_stats', proisstrict => 'f',
   provolatile => 'v', prorettype => 'void', proargtypes => 'oid',
-  prosrc => 'pg_stat_reset_subscription_stats' },
+  prosrc => 'pg_stat_reset_subscription_stats',
+  proacl => '{POSTGRES=X}' },

 { oid => '3163', descr => 'current trigger depth',
   proname => 'pg_trigger_depth', provolatile => 's', proparallel => 'r',
@@ -6553,21 +6565,24 @@
   proallargtypes => '{text,int4,int4,text,text,bool,text}',
   proargmodes => '{o,o,o,o,o,o,o}',
   proargnames => '{sourcefile,sourceline,seqno,name,setting,applied,error}',
-  prosrc => 'show_all_file_settings' },
+  prosrc => 'show_all_file_settings',
+  proacl => '{POSTGRES=X}' },
 { oid => '3401', descr => 'show pg_hba.conf rules',
   proname => 'pg_hba_file_rules', prorows => '1000', proretset => 't',
   provolatile => 'v', prorettype => 'record', proargtypes => '',
   proallargtypes => '{int4,text,int4,text,_text,_text,text,text,text,_text,text}',
   proargmodes => '{o,o,o,o,o,o,o,o,o,o,o}',
   proargnames =>
'{rule_number,file_name,line_number,type,database,user_name,address,netmask,auth_method,options,error}',
-  prosrc => 'pg_hba_file_rules' },
+  prosrc => 'pg_hba_file_rules',
+  proacl => '{POSTGRES=X}' },
 { oid => '6250', descr => 'show pg_ident.conf mappings',
   proname => 'pg_ident_file_mappings', prorows => '1000', proretset => 't',
   provolatile => 'v', prorettype => 'record', proargtypes => '',
   proallargtypes => '{int4,text,int4,text,text,text,text}',
   proargmodes => '{o,o,o,o,o,o,o}',
   proargnames => '{map_number,file_name,line_number,map_name,sys_name,pg_username,error}',
-  prosrc => 'pg_ident_file_mappings' },
+  prosrc => 'pg_ident_file_mappings',
+  proacl => '{POSTGRES=X}' },
 { oid => '1371', descr => 'view system lock information',
   proname => 'pg_lock_status', prorows => '1000', proretset => 't',
   provolatile => 'v', prorettype => 'record', proargtypes => '',
@@ -6737,30 +6752,36 @@
   proname => 'pg_backup_start', provolatile => 'v', proparallel => 'r',
   prorettype => 'pg_lsn', proargtypes => 'text bool',
   proargnames => '{label,fast}', proargdefaults => '{false}',
-  prosrc => 'pg_backup_start' },
+  prosrc => 'pg_backup_start',
+  proacl => '{POSTGRES=X}' },
 { oid => '2739', descr => 'finish taking an online backup',
   proname => 'pg_backup_stop', provolatile => 'v', proparallel => 'r',
   prorettype => 'record', proargtypes => 'bool',
   proallargtypes => '{bool,pg_lsn,text,text}', proargmodes => '{i,o,o,o}',
   proargnames => '{wait_for_archive,lsn,labelfile,spcmapfile}',
   proargdefaults => '{true}',
-  prosrc => 'pg_backup_stop' },
+  prosrc => 'pg_backup_stop',
+  proacl => '{POSTGRES=X}' },
 { oid => '3436', descr => 'promote standby server',
   proname => 'pg_promote', provolatile => 'v', prorettype => 'bool',
   proargtypes => 'bool int4', proargnames => '{wait,wait_seconds}',
   proargdefaults => '{true,60}',
-  prosrc => 'pg_promote' },
+  prosrc => 'pg_promote',
+  proacl => '{POSTGRES=X}' },
 { oid => '2848', descr => 'switch to new wal file',
   proname => 'pg_switch_wal', provolatile => 'v', prorettype => 'pg_lsn',
-  proargtypes => '', prosrc => 'pg_switch_wal' },
+  proargtypes => '', prosrc => 'pg_switch_wal',
+  proacl => '{POSTGRES=X}' },
 { oid => '6305', descr => 'log details of the current snapshot to WAL',
   proname => 'pg_log_standby_snapshot', provolatile => 'v',
   prorettype => 'pg_lsn', proargtypes => '',
-  prosrc => 'pg_log_standby_snapshot' },
+  prosrc => 'pg_log_standby_snapshot',
+  proacl => '{POSTGRES=X}' },
 { oid => '3098', descr => 'create a named restore point',
   proname => 'pg_create_restore_point', provolatile => 'v',
   prorettype => 'pg_lsn', proargtypes => 'text',
-  prosrc => 'pg_create_restore_point' },
+  prosrc => 'pg_create_restore_point',
+  proacl => '{POSTGRES=X}' },
 { oid => '2849', descr => 'current wal write location',
   proname => 'pg_current_wal_lsn', provolatile => 'v', prorettype => 'pg_lsn',
   proargtypes => '', prosrc => 'pg_current_wal_lsn' },
@@ -6816,10 +6837,12 @@

 { oid => '3071', descr => 'pause wal replay',
   proname => 'pg_wal_replay_pause', provolatile => 'v', prorettype => 'void',
-  proargtypes => '', prosrc => 'pg_wal_replay_pause' },
+  proargtypes => '', prosrc => 'pg_wal_replay_pause',
+  proacl => '{POSTGRES=X}' },
 { oid => '3072', descr => 'resume wal replay, if it was paused',
   proname => 'pg_wal_replay_resume', provolatile => 'v', prorettype => 'void',
-  proargtypes => '', prosrc => 'pg_wal_replay_resume' },
+  proargtypes => '', prosrc => 'pg_wal_replay_resume',
+  proacl => '{POSTGRES=X}' },
 { oid => '3073', descr => 'true if wal replay is paused',
   proname => 'pg_is_wal_replay_paused', provolatile => 'v',
   prorettype => 'bool', proargtypes => '',
@@ -6845,17 +6868,21 @@

 { oid => '2621', descr => 'reload configuration files',
   proname => 'pg_reload_conf', provolatile => 'v', prorettype => 'bool',
-  proargtypes => '', prosrc => 'pg_reload_conf' },
+  proargtypes => '', prosrc => 'pg_reload_conf',
+  proacl => '{POSTGRES=X}' },
 { oid => '2622', descr => 'rotate log file',
   proname => 'pg_rotate_logfile', provolatile => 'v', prorettype => 'bool',
-  proargtypes => '', prosrc => 'pg_rotate_logfile' },
+  proargtypes => '', prosrc => 'pg_rotate_logfile',
+  proacl => '{POSTGRES=X}' },
 { oid => '3800', descr => 'current logging collector file location',
   proname => 'pg_current_logfile', proisstrict => 'f', provolatile => 'v',
-  prorettype => 'text', proargtypes => '', prosrc => 'pg_current_logfile' },
+  prorettype => 'text', proargtypes => '', prosrc => 'pg_current_logfile',
+  proacl => '{POSTGRES=X,pg_monitor=X}' },
 { oid => '3801', descr => 'current logging collector file location',
   proname => 'pg_current_logfile', proisstrict => 'f', provolatile => 'v',
   prorettype => 'text', proargtypes => 'text',
-  prosrc => 'pg_current_logfile_1arg' },
+  prosrc => 'pg_current_logfile_1arg',
+  proacl => '{POSTGRES=X,pg_monitor=X}' },

 { oid => '2623', descr => 'get information about file',
   proname => 'pg_stat_file', provolatile => 'v', prorettype => 'record',
@@ -6863,48 +6890,60 @@
   proallargtypes => '{text,int8,timestamptz,timestamptz,timestamptz,timestamptz,bool}',
   proargmodes => '{i,o,o,o,o,o,o}',
   proargnames => '{filename,size,access,modification,change,creation,isdir}',
-  prosrc => 'pg_stat_file_1arg' },
+  prosrc => 'pg_stat_file_1arg',
+  proacl => '{POSTGRES=X}' },
 { oid => '3307', descr => 'get information about file',
   proname => 'pg_stat_file', provolatile => 'v', prorettype => 'record',
   proargtypes => 'text bool',
   proallargtypes => '{text,bool,int8,timestamptz,timestamptz,timestamptz,timestamptz,bool}',
   proargmodes => '{i,i,o,o,o,o,o,o}',
   proargnames => '{filename,missing_ok,size,access,modification,change,creation,isdir}',
-  prosrc => 'pg_stat_file' },
+  prosrc => 'pg_stat_file',
+  proacl => '{POSTGRES=X}' },
 { oid => '2624', descr => 'read text from a file',
   proname => 'pg_read_file', provolatile => 'v', prorettype => 'text',
-  proargtypes => 'text int8 int8', prosrc => 'pg_read_file_off_len' },
+  proargtypes => 'text int8 int8', prosrc => 'pg_read_file_off_len',
+  proacl => '{POSTGRES=X}' },
 { oid => '3293', descr => 'read text from a file',
   proname => 'pg_read_file', provolatile => 'v', prorettype => 'text',
   proargtypes => 'text int8 int8 bool',
-  prosrc => 'pg_read_file_off_len_missing' },
+  prosrc => 'pg_read_file_off_len_missing',
+  proacl => '{POSTGRES=X}' },
 { oid => '3826', descr => 'read text from a file',
   proname => 'pg_read_file', provolatile => 'v', prorettype => 'text',
-  proargtypes => 'text', prosrc => 'pg_read_file_all' },
+  proargtypes => 'text', prosrc => 'pg_read_file_all',
+  proacl => '{POSTGRES=X}' },
 { oid => '6208', descr => 'read text from a file',
   proname => 'pg_read_file', provolatile => 'v', prorettype => 'text',
-  proargtypes => 'text bool', prosrc => 'pg_read_file_all_missing' },
+  proargtypes => 'text bool', prosrc => 'pg_read_file_all_missing',
+  proacl => '{POSTGRES=X}' },
 { oid => '3827', descr => 'read bytea from a file',
   proname => 'pg_read_binary_file', provolatile => 'v', prorettype => 'bytea',
-  proargtypes => 'text int8 int8', prosrc => 'pg_read_binary_file_off_len' },
+  proargtypes => 'text int8 int8', prosrc => 'pg_read_binary_file_off_len',
+  proacl => '{POSTGRES=X}' },
 { oid => '3295', descr => 'read bytea from a file',
   proname => 'pg_read_binary_file', provolatile => 'v', prorettype => 'bytea',
   proargtypes => 'text int8 int8 bool',
-  prosrc => 'pg_read_binary_file_off_len_missing' },
+  prosrc => 'pg_read_binary_file_off_len_missing',
+  proacl => '{POSTGRES=X}' },
 { oid => '3828', descr => 'read bytea from a file',
   proname => 'pg_read_binary_file', provolatile => 'v', prorettype => 'bytea',
-  proargtypes => 'text', prosrc => 'pg_read_binary_file_all' },
+  proargtypes => 'text', prosrc => 'pg_read_binary_file_all',
+  proacl => '{POSTGRES=X}' },
 { oid => '6209', descr => 'read bytea from a file',
   proname => 'pg_read_binary_file', provolatile => 'v', prorettype => 'bytea',
-  proargtypes => 'text bool', prosrc => 'pg_read_binary_file_all_missing' },
+  proargtypes => 'text bool', prosrc => 'pg_read_binary_file_all_missing',
+  proacl => '{POSTGRES=X}' },
 { oid => '2625', descr => 'list all files in a directory',
   proname => 'pg_ls_dir', prorows => '1000', proretset => 't',
   provolatile => 'v', prorettype => 'text', proargtypes => 'text',
-  prosrc => 'pg_ls_dir_1arg' },
+  prosrc => 'pg_ls_dir_1arg',
+  proacl => '{POSTGRES=X}' },
 { oid => '3297', descr => 'list all files in a directory',
   proname => 'pg_ls_dir', prorows => '1000', proretset => 't',
   provolatile => 'v', prorettype => 'text', proargtypes => 'text bool bool',
-  prosrc => 'pg_ls_dir' },
+  prosrc => 'pg_ls_dir',
+  proacl => '{POSTGRES=X}' },
 { oid => '2626', descr => 'sleep for the specified time in seconds',
   proname => 'pg_sleep', provolatile => 'v', prorettype => 'void',
   proargtypes => 'float8', prosrc => 'pg_sleep' },
@@ -8602,7 +8641,8 @@
   provolatile => 'v', prorettype => 'record', proargtypes => '',
   proallargtypes => '{text,int8,int8,int8}', proargmodes => '{o,o,o,o}',
   proargnames => '{name,off,size,allocated_size}',
-  prosrc => 'pg_get_shmem_allocations' },
+  prosrc => 'pg_get_shmem_allocations',
+  proacl => '{POSTGRES=X,pg_read_all_stats=X}' },

 { oid => '4099', descr => 'Is NUMA support available?',
   proname => 'pg_numa_available', provolatile => 's', prorettype => 'bool',
@@ -8614,7 +8654,8 @@
   provolatile => 'v', prorettype => 'record', proargtypes => '',
   proallargtypes => '{text,int4,int8}', proargmodes => '{o,o,o}',
   proargnames => '{name,numa_node,size}',
-  prosrc => 'pg_get_shmem_allocations_numa' },
+  prosrc => 'pg_get_shmem_allocations_numa',
+  proacl => '{POSTGRES=X,pg_read_all_stats=X}' },

 { oid => '9314',
   descr => 'shared memory allocations tracked in the DSM registry',
@@ -8622,7 +8663,8 @@
   proretset => 't', provolatile => 'v', prorettype => 'record',
   proargtypes => '', proallargtypes => '{text,text,int8}',
   proargmodes => '{o,o,o}', proargnames => '{name,type,size}',
-  prosrc => 'pg_get_dsm_registry_allocations' },
+  prosrc => 'pg_get_dsm_registry_allocations',
+  proacl => '{POSTGRES=X,pg_read_all_stats=X}' },

 # memory context of local backend
 { oid => '2282',
@@ -8633,13 +8675,15 @@
   proallargtypes => '{text,text,text,int4,_int4,int8,int8,int8,int8,int8}',
   proargmodes => '{o,o,o,o,o,o,o,o,o,o}',
   proargnames => '{name, ident, type, level, path, total_bytes, total_nblocks, free_bytes, free_chunks, used_bytes}',
-  prosrc => 'pg_get_backend_memory_contexts' },
+  prosrc => 'pg_get_backend_memory_contexts',
+  proacl => '{POSTGRES=X,pg_read_all_stats=X}' },

 # logging memory contexts of the specified backend
 { oid => '4543', descr => 'log memory contexts of the specified backend',
   proname => 'pg_log_backend_memory_contexts', provolatile => 'v',
   prorettype => 'bool', proargtypes => 'int4',
-  prosrc => 'pg_log_backend_memory_contexts' },
+  prosrc => 'pg_log_backend_memory_contexts',
+  proacl => '{POSTGRES=X}' },

 # non-persistent series generator
 { oid => '1066', descr => 'non-persistent series generator',
@@ -12312,63 +12356,74 @@
 { oid => '6003', descr => 'create a replication origin',
   proname => 'pg_replication_origin_create', provolatile => 'v',
   proparallel => 'u', prorettype => 'oid', proargtypes => 'text',
-  prosrc => 'pg_replication_origin_create' },
+  prosrc => 'pg_replication_origin_create',
+  proacl => '{POSTGRES=X}' },

 { oid => '6004', descr => 'drop replication origin identified by its name',
   proname => 'pg_replication_origin_drop', provolatile => 'v',
   proparallel => 'u', prorettype => 'void', proargtypes => 'text',
-  prosrc => 'pg_replication_origin_drop' },
+  prosrc => 'pg_replication_origin_drop',
+  proacl => '{POSTGRES=X}' },

 { oid => '6005',
   descr => 'translate the replication origin\'s name to its id',
   proname => 'pg_replication_origin_oid', provolatile => 's',
   prorettype => 'oid', proargtypes => 'text',
-  prosrc => 'pg_replication_origin_oid' },
+  prosrc => 'pg_replication_origin_oid',
+  proacl => '{POSTGRES=X}' },

 { oid => '6006',
   descr => 'configure session to maintain replication progress tracking for the passed in origin',
   proname => 'pg_replication_origin_session_setup', provolatile => 'v',
   proparallel => 'u', prorettype => 'void', proargtypes => 'text int4',
   proargnames => '{node_name,pid}', proargdefaults => '{0}',
-  prosrc => 'pg_replication_origin_session_setup' },
+  prosrc => 'pg_replication_origin_session_setup',
+  proacl => '{POSTGRES=X}' },

 { oid => '6007', descr => 'teardown configured replication progress tracking',
   proname => 'pg_replication_origin_session_reset', provolatile => 'v',
   proparallel => 'u', prorettype => 'void', proargtypes => '',
-  prosrc => 'pg_replication_origin_session_reset' },
+  prosrc => 'pg_replication_origin_session_reset',
+  proacl => '{POSTGRES=X}' },

 { oid => '6008',
   descr => 'is a replication origin configured in this session',
   proname => 'pg_replication_origin_session_is_setup', provolatile => 'v',
   proparallel => 'r', prorettype => 'bool', proargtypes => '',
-  prosrc => 'pg_replication_origin_session_is_setup' },
+  prosrc => 'pg_replication_origin_session_is_setup',
+  proacl => '{POSTGRES=X}' },

 { oid => '6009',
   descr => 'get the replication progress of the current session',
   proname => 'pg_replication_origin_session_progress', provolatile => 'v',
   proparallel => 'u', prorettype => 'pg_lsn', proargtypes => 'bool',
-  prosrc => 'pg_replication_origin_session_progress' },
+  prosrc => 'pg_replication_origin_session_progress',
+  proacl => '{POSTGRES=X}' },

 { oid => '6010', descr => 'setup the transaction\'s origin lsn and timestamp',
   proname => 'pg_replication_origin_xact_setup', provolatile => 'v',
   proparallel => 'r', prorettype => 'void', proargtypes => 'pg_lsn timestamptz',
-  prosrc => 'pg_replication_origin_xact_setup' },
+  prosrc => 'pg_replication_origin_xact_setup',
+  proacl => '{POSTGRES=X}' },

 { oid => '6011', descr => 'reset the transaction\'s origin lsn and timestamp',
   proname => 'pg_replication_origin_xact_reset', provolatile => 'v',
   proparallel => 'r', prorettype => 'void', proargtypes => '',
-  prosrc => 'pg_replication_origin_xact_reset' },
+  prosrc => 'pg_replication_origin_xact_reset',
+  proacl => '{POSTGRES=X}' },

 { oid => '6012', descr => 'advance replication origin to specific location',
   proname => 'pg_replication_origin_advance', provolatile => 'v',
   proparallel => 'u', prorettype => 'void', proargtypes => 'text pg_lsn',
-  prosrc => 'pg_replication_origin_advance' },
+  prosrc => 'pg_replication_origin_advance',
+  proacl => '{POSTGRES=X}' },

 { oid => '6013',
   descr => 'get an individual replication origin\'s replication progress',
   proname => 'pg_replication_origin_progress', provolatile => 'v',
   proparallel => 'u', prorettype => 'pg_lsn', proargtypes => 'text bool',
-  prosrc => 'pg_replication_origin_progress' },
+  prosrc => 'pg_replication_origin_progress',
+  proacl => '{POSTGRES=X}' },

 { oid => '6014', descr => 'get progress for all replication origins',
   proname => 'pg_show_replication_origin_status', prorows => '100',
@@ -12376,7 +12431,8 @@
   prorettype => 'record', proargtypes => '',
   proallargtypes => '{oid,text,pg_lsn,pg_lsn}', proargmodes => '{o,o,o,o}',
   proargnames => '{local_id, external_id, remote_lsn, local_lsn}',
-  prosrc => 'pg_show_replication_origin_status' },
+  prosrc => 'pg_show_replication_origin_status',
+  proacl => '{POSTGRES=X}' },

 # publications
 { oid => '6119',
@@ -12414,7 +12470,8 @@
   proname => 'pg_config', prorows => '23', proretset => 't', provolatile => 's',
   proparallel => 'r', prorettype => 'record', proargtypes => '',
   proallargtypes => '{text,text}', proargmodes => '{o,o}',
-  proargnames => '{name,setting}', prosrc => 'pg_config' },
+  proargnames => '{name,setting}', prosrc => 'pg_config',
+  proacl => '{POSTGRES=X}' },

 # pg_controldata related functions
 { oid => '3441',
@@ -12489,49 +12546,57 @@
   proname => 'pg_ls_logdir', procost => '10', prorows => '20', proretset => 't',
   provolatile => 'v', prorettype => 'record', proargtypes => '',
   proallargtypes => '{text,int8,timestamptz}', proargmodes => '{o,o,o}',
-  proargnames => '{name,size,modification}', prosrc => 'pg_ls_logdir' },
+  proargnames => '{name,size,modification}', prosrc => 'pg_ls_logdir',
+  proacl => '{POSTGRES=X,pg_monitor=X}' },
 { oid => '3354', descr => 'list of files in the WAL directory',
   proname => 'pg_ls_waldir', procost => '10', prorows => '20', proretset => 't',
   provolatile => 'v', prorettype => 'record', proargtypes => '',
   proallargtypes => '{text,int8,timestamptz}', proargmodes => '{o,o,o}',
-  proargnames => '{name,size,modification}', prosrc => 'pg_ls_waldir' },
+  proargnames => '{name,size,modification}', prosrc => 'pg_ls_waldir',
+  proacl => '{POSTGRES=X,pg_monitor=X}' },
 { oid => '6400', descr => 'list of files in the pg_wal/summaries directory',
   proname => 'pg_ls_summariesdir', procost => '10', prorows => '20',
   proretset => 't', provolatile => 'v', prorettype => 'record',
   proargtypes => '', proallargtypes => '{text,int8,timestamptz}',
   proargmodes => '{o,o,o}', proargnames => '{name,size,modification}',
-  prosrc => 'pg_ls_summariesdir' },
+  prosrc => 'pg_ls_summariesdir',
+  proacl => '{POSTGRES=X,pg_monitor=X}' },
 { oid => '5031', descr => 'list of files in the archive_status directory',
   proname => 'pg_ls_archive_statusdir', procost => '10', prorows => '20',
   proretset => 't', provolatile => 'v', prorettype => 'record',
   proargtypes => '', proallargtypes => '{text,int8,timestamptz}',
   proargmodes => '{o,o,o}', proargnames => '{name,size,modification}',
-  prosrc => 'pg_ls_archive_statusdir' },
+  prosrc => 'pg_ls_archive_statusdir',
+  proacl => '{POSTGRES=X,pg_monitor=X}' },
 { oid => '5029', descr => 'list files in the pgsql_tmp directory',
   proname => 'pg_ls_tmpdir', procost => '10', prorows => '20', proretset => 't',
   provolatile => 'v', prorettype => 'record', proargtypes => '',
   proallargtypes => '{text,int8,timestamptz}', proargmodes => '{o,o,o}',
-  proargnames => '{name,size,modification}', prosrc => 'pg_ls_tmpdir_noargs' },
+  proargnames => '{name,size,modification}', prosrc => 'pg_ls_tmpdir_noargs',
+  proacl => '{POSTGRES=X,pg_monitor=X}' },
 { oid => '5030', descr => 'list files in the pgsql_tmp directory',
   proname => 'pg_ls_tmpdir', procost => '10', prorows => '20', proretset => 't',
   provolatile => 'v', prorettype => 'record', proargtypes => 'oid',
   proallargtypes => '{oid,text,int8,timestamptz}', proargmodes => '{i,o,o,o}',
   proargnames => '{tablespace,name,size,modification}',
-  prosrc => 'pg_ls_tmpdir_1arg' },
+  prosrc => 'pg_ls_tmpdir_1arg',
+  proacl => '{POSTGRES=X,pg_monitor=X}' },
 { oid => '6270',
   descr => 'list of files in the pg_logical/snapshots directory',
   proname => 'pg_ls_logicalsnapdir', procost => '10', prorows => '20',
   proretset => 't', provolatile => 'v', prorettype => 'record',
   proargtypes => '', proallargtypes => '{text,int8,timestamptz}',
   proargmodes => '{o,o,o}', proargnames => '{name,size,modification}',
-  prosrc => 'pg_ls_logicalsnapdir' },
+  prosrc => 'pg_ls_logicalsnapdir',
+  proacl => '{POSTGRES=X,pg_monitor=X}' },
 { oid => '6271',
   descr => 'list of files in the pg_logical/mappings directory',
   proname => 'pg_ls_logicalmapdir', procost => '10', prorows => '20',
   proretset => 't', provolatile => 'v', prorettype => 'record',
   proargtypes => '', proallargtypes => '{text,int8,timestamptz}',
   proargmodes => '{o,o,o}', proargnames => '{name,size,modification}',
-  prosrc => 'pg_ls_logicalmapdir' },
+  prosrc => 'pg_ls_logicalmapdir',
+  proacl => '{POSTGRES=X,pg_monitor=X}' },
 { oid => '6272',
   descr => 'list of files in the pg_replslot/slot_name directory',
   proname => 'pg_ls_replslotdir', procost => '10', prorows => '20',
@@ -12539,7 +12604,8 @@
   proargtypes => 'text', proallargtypes => '{text,text,int8,timestamptz}',
   proargmodes => '{i,o,o,o}',
   proargnames => '{slot_name,name,size,modification}',
-  prosrc => 'pg_ls_replslotdir' },
+  prosrc => 'pg_ls_replslotdir',
+  proacl => '{POSTGRES=X,pg_monitor=X}' },

 # hash partitioning constraint function
 { oid => '5028', descr => 'hash partition CHECK constraint',
@@ -12702,7 +12768,8 @@
   proallargtypes => '{int4,int4,int8,text,text,int8,int8,text,int2,int4,text,text,bool,bool,bool}',
   proargmodes => '{o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}',
   proargnames =>
'{pid,io_id,io_generation,state,operation,off,length,target,handle_data_len,raw_result,result,target_desc,f_sync,f_localmem,f_buffered}',
-  prosrc => 'pg_get_aios' },
+  prosrc => 'pg_get_aios',
+  proacl => '{POSTGRES=X,pg_read_all_stats=X}' },

 # oid8 related functions
 { oid => '8255', descr => 'convert oid to oid8',
--
2.43.7


pgsql-hackers by date:

Previous
From: Dmitry Dolgov
Date:
Subject: Add ssl_(supported|shared)_groups to sslinfo
Next
From: Ants Aasma
Date:
Subject: Re: pg_stat_io_histogram