Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 22 additions & 1 deletion src/backend/catalog/namespace.c
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ static SubTransactionId myTempNamespaceSubID = InvalidSubTransactionId;
* of the GUC variable 'search_path'.
*/
char *namespace_search_path = NULL;

bool prohibit_superuser_overrides = true;

/* Local functions */
static bool RelationIsVisibleExt(Oid relid, bool *is_missing);
Expand Down Expand Up @@ -1201,6 +1201,7 @@ FuncnameGetCandidates(List *names, int nargs, List *argnames,
Oid namespaceId;
CatCList *catlist;
int i;
bool has_superuser_candidate = false;

/* check for caller error */
Assert(nargs >= 0 || !(expand_variadic | expand_defaults));
Expand Down Expand Up @@ -1264,6 +1265,22 @@ FuncnameGetCandidates(List *names, int nargs, List *argnames,
continue; /* proc is not in search path */
}

/* prohibit overrides under superuser */
if (prohibit_superuser_overrides && superuser())
{
bool owned_by_superuser = superuser_arg(procform->proowner);

/* If we have superuser condidate, then ignore all non-supoeruser alternatives */
if (resultList && has_superuser_candidate && !owned_by_superuser)
continue;

/* If new candidate is owned by superuser then forget all non-superuser candidates */
if (owned_by_superuser && !has_superuser_candidate)
resultList = NULL;

has_superuser_candidate = owned_by_superuser;
}

/*
* If we are asked to match to OUT arguments, then use the
* proallargtypes array (which includes those); otherwise use
Expand Down Expand Up @@ -4252,6 +4269,10 @@ finalNamespacePath(List *oidlist, Oid *firstNS)
!list_member_oid(finalPath, myTempNamespace))
finalPath = lcons_oid(myTempNamespace, finalPath);

/* Always place pg_catalog at the beginning of search path */
if (prohibit_superuser_overrides && superuser())
finalPath = lcons_oid(PG_CATALOG_NAMESPACE, finalPath);

return finalPath;
}

Expand Down
9 changes: 9 additions & 0 deletions src/backend/utils/misc/guc_tables.c
Original file line number Diff line number Diff line change
Expand Up @@ -2183,6 +2183,15 @@ struct config_bool ConfigureNamesBool[] =
NULL, NULL, NULL
},

{
{"prohibit_superuser_overrides", PGC_SUSET, CLIENT_CONN_STATEMENT,
gettext_noop("Prevent overriding of functions defined by superuser by non-superuser candidates."),
},
&prohibit_superuser_overrides,
true,
NULL, NULL, NULL
},

/* End-of-list marker */
{
{NULL, 0, 0, NULL, NULL}, NULL, false, NULL, NULL, NULL
Expand Down
1 change: 1 addition & 0 deletions src/include/catalog/namespace.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ extern void AtEOSubXact_Namespace(bool isCommit, SubTransactionId mySubid,

/* stuff for search_path GUC variable */
extern PGDLLIMPORT char *namespace_search_path;
extern bool prohibit_superuser_overrides;

extern List *fetch_search_path(bool includeImplicit);
extern int fetch_search_path_array(Oid *sarray, int sarray_len);
Expand Down
2 changes: 1 addition & 1 deletion src/test/regress/expected/stats.out
Original file line number Diff line number Diff line change
Expand Up @@ -955,7 +955,7 @@ SELECT wal_bytes > :backend_wal_bytes_before FROM pg_stat_get_backend_wal(pg_bac
-- Test pg_stat_get_backend_idset() and some allied functions.
-- In particular, verify that their notion of backend ID matches
-- our temp schema index.
SELECT (current_schemas(true))[1] = ('pg_temp_' || beid::text) AS match
SELECT (current_schemas(true))[2] = ('pg_temp_' || beid::text) AS match
FROM pg_stat_get_backend_idset() beid
WHERE pg_stat_get_backend_pid(beid) = pg_backend_pid();
match
Expand Down
2 changes: 1 addition & 1 deletion src/test/regress/sql/stats.sql
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,7 @@ SELECT wal_bytes > :backend_wal_bytes_before FROM pg_stat_get_backend_wal(pg_bac
-- Test pg_stat_get_backend_idset() and some allied functions.
-- In particular, verify that their notion of backend ID matches
-- our temp schema index.
SELECT (current_schemas(true))[1] = ('pg_temp_' || beid::text) AS match
SELECT (current_schemas(true))[2] = ('pg_temp_' || beid::text) AS match
FROM pg_stat_get_backend_idset() beid
WHERE pg_stat_get_backend_pid(beid) = pg_backend_pid();

Expand Down