Branch data Line data Source code
1 : : /*-------------------------------------------------------------------------
2 : : *
3 : : * superuser.c
4 : : * The superuser() function. Determines if user has superuser privilege.
5 : : *
6 : : * All code should use either of these two functions to find out
7 : : * whether a given user is a superuser, rather than examining
8 : : * pg_authid.rolsuper directly, so that the escape hatch built in for
9 : : * the single-user case works.
10 : : *
11 : : *
12 : : * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
13 : : * Portions Copyright (c) 1994, Regents of the University of California
14 : : *
15 : : *
16 : : * IDENTIFICATION
17 : : * src/backend/utils/misc/superuser.c
18 : : *
19 : : *-------------------------------------------------------------------------
20 : : */
21 : : #include "postgres.h"
22 : :
23 : : #include "access/htup_details.h"
24 : : #include "catalog/pg_authid.h"
25 : : #include "miscadmin.h"
26 : : #include "utils/inval.h"
27 : : #include "utils/syscache.h"
28 : :
29 : : /*
30 : : * In common cases the same roleid (ie, the session or current ID) will
31 : : * be queried repeatedly. So we maintain a simple one-entry cache for
32 : : * the status of the last requested roleid. The cache can be flushed
33 : : * at need by watching for cache update events on pg_authid.
34 : : */
35 : : static Oid last_roleid = InvalidOid; /* InvalidOid == cache not valid */
36 : : static bool last_roleid_is_super = false;
37 : : static bool roleid_callback_registered = false;
38 : :
39 : : static void RoleidCallback(Datum arg, int cacheid, uint32 hashvalue);
40 : :
41 : :
42 : : /*
43 : : * The Postgres user running this command has Postgres superuser privileges
44 : : */
45 : : bool
46 : 6699 : superuser(void)
47 : : {
48 : 6699 : return superuser_arg(GetUserId());
49 : : }
50 : :
51 : :
52 : : /*
53 : : * The specified role has Postgres superuser privileges
54 : : */
55 : : bool
56 : 1322326 : superuser_arg(Oid roleid)
57 : : {
58 : 1322326 : bool result;
59 : 1322326 : HeapTuple rtup;
60 : :
61 : : /* Quick out for cache hit */
62 [ + + + + ]: 1322326 : if (OidIsValid(last_roleid) && last_roleid == roleid)
63 : 1311553 : return last_roleid_is_super;
64 : :
65 : : /* Special escape path in case you deleted all your users. */
66 [ + + + + ]: 10773 : if (!IsUnderPostmaster && roleid == BOOTSTRAP_SUPERUSERID)
67 : 4199 : return true;
68 : :
69 : : /* OK, look up the information in pg_authid */
70 : 6574 : rtup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
71 [ + + ]: 6574 : if (HeapTupleIsValid(rtup))
72 : : {
73 : 6572 : result = ((Form_pg_authid) GETSTRUCT(rtup))->rolsuper;
74 : 6572 : ReleaseSysCache(rtup);
75 : 6572 : }
76 : : else
77 : : {
78 : : /* Report "not superuser" for invalid roleids */
79 : 2 : result = false;
80 : : }
81 : :
82 : : /* If first time through, set up callback for cache flushes */
83 [ + + ]: 6574 : if (!roleid_callback_registered)
84 : : {
85 : 794 : CacheRegisterSyscacheCallback(AUTHOID,
86 : : RoleidCallback,
87 : : (Datum) 0);
88 : 794 : roleid_callback_registered = true;
89 : 794 : }
90 : :
91 : : /* Cache the result for next time */
92 : 6574 : last_roleid = roleid;
93 : 6574 : last_roleid_is_super = result;
94 : :
95 : 6574 : return result;
96 : 1322326 : }
97 : :
98 : : /*
99 : : * RoleidCallback
100 : : * Syscache inval callback function
101 : : */
102 : : static void
103 : 4917 : RoleidCallback(Datum arg, int cacheid, uint32 hashvalue)
104 : : {
105 : : /* Invalidate our local cache in case role's superuserness changed */
106 : 4917 : last_roleid = InvalidOid;
107 : 4917 : }
|