8000 pg_dump: avoid unsafe function calls in getPolicies(). · postgres/postgres@b7333e8 · GitHub
[go: up one dir, main page]

Skip to content

Commit b7333e8

Browse files
committed
pg_dump: avoid unsafe function calls in getPolicies().
getPolicies() had the same disease I fixed in other places in commit e3fcbbd, i.e., it was calling pg_get_expr() for expressions on tables that we don't necessarily have lock on. To fix, restrict the query to only collect interesting rows, rather than doing the filtering on the client side. Back-patch of commit 3e6e86a. That's been in v15/HEAD long enough to have some confidence about it, so now let's fix the problem in older branches. Discussion: https://postgr.es/m/2273648.1634764485@sss.pgh.pa.us Discussion: https://postgr.es/m/7d7eb6128f40401d81b3b7a898b6b4de@W2012-02.nidsa.loc Discussion: https://postgr.es/m/45c93d57-9973-248e-d2df-e02ca9af48d4@darold.net
1 parent b1f1064 commit b7333e8

File tree

1 file changed

+29
-13
lines changed

1 file changed

+29
-13
lines changed

src/bin/pg_dump/pg_dump.c

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3468,6 +3468,7 @@ void
34683468
getPolicies(Archive *fout, TableInfo tblinfo[], int numTables)
34693469
{
34703470
PQExpBuffer query;
3471+
PQExpBuffer tbloids;
34713472
PGresult *res;
34723473
PolicyInfo *polinfo;
34733474
int i_oid;
@@ -3483,15 +3484,17 @@ getPolicies(Archive *fout, TableInfo tblinfo[], int numTables)
34833484
j,
34843485
ntups;
34853486

3487+
/* No policies before 9.5 */
34863488
if (fout->remoteVersion < 90500)
34873489
return;
34883490

34893491
query = createPQExpBuffer();
3492+
tbloids = createPQExpBuffer();
34903493

34913494
/*
3492-
* First, check which tables have RLS enabled. We represent RLS being
3493-
* enabled on a table by creating a PolicyInfo object with null polname.
3495+
* Identify tables of interest, and check which ones have RLS enabled.
34943496
*/
3497+
appendPQExpBufferChar(tbloids, '{');
34953498
for (i = 0; i < numTables; i++)
34963499
{
34973500
TableInfo *tbinfo = &tblinfo[i];
@@ -3500,9 +3503,23 @@ getPolicies(Archive *fout, TableInfo tblinfo[], int numTables)
35003503
if (!(tbinfo->dobj.dump & DUMP_COMPONENT_POLICY))
35013504
continue;
35023505

3506+
/* It can't have RLS or policies if it's not a table */
3507+
if (tbinfo->relkind != RELKIND_RELATION &&
3508+
tbinfo->relkind != RELKIND_PARTITIONED_TABLE)
3509+
continue;
3510+
3511+
/* Add it to the list of table OIDs to be probed below */
3512+
if (tbloids->len > 1) /* do we have more than the '{'? */
3513+
appendPQExpBufferChar(tbloids, ',');
3514+
appendPQExpBuffer(tbloids, "%u", tbinfo->dobj.catId.oid);
3515+
3516+
/* Is RLS enabled? (That's separate from whether it has policies) */
35033517
if (tbinfo->rowsec)
35043518
{
35053519
/*
3520+
* We represent RLS being enabled on a table by creating a
3521+
* PolicyInfo object with null polname.
3522+
*
35063523
* Note: use tableoid 0 so that this object won't be mistaken for
35073524
* something that pg_depend entries apply to.
35083525
*/
@@ -3522,16 +3539,19 @@ getPolicies(Archive *fout, TableInfo tblinfo[], int numTables)
35223539
polinfo->polwithcheck = NULL;
35233540
}
35243541
}
3542+
appendPQExpBufferChar(tbloids, '}');
35253543

35263544
/*
3527-
* Now, read all RLS policies, and create PolicyInfo objects for all those
3528-
* that are of interest.
3545+
* Now, read all RLS policies belonging to the tables of interest, and
3546+
* create PolicyInfo objects for them. (Note that we must filter the
3547+
* results server-side not locally, because we dare not apply pg_get_expr
3548+
* to tables we don't have lock on.)
35293549
*/
35303550
if (g_verbose)
35313551
write_msg(NULL, "reading row-level security policies\n");
35323552

35333553
printfPQExpBuffer(query,
3534-
"SELECT oid, tableoid, pol.polrelid, pol.polname, pol.polcmd, ");
3554+
"SELECT pol.oid, pol.tableoid, pol.polrelid, pol.polname, pol.polcmd, ");
35353555
if (fout->remoteVersion >= 100000)
35363556
appendPQExpBuffer(query, "pol.polpermissive, ");
35373557
else
@@ -3541,7 +3561,9 @@ getPolicies(Archive *fout, TableInfo tblinfo[], int numTables)
35413561
" pg_catalog.array_to_string(ARRAY(SELECT pg_catalog.quote_ident(rolname) from pg_catalog.pg_roles WHERE oid = ANY(pol.polroles)), ', ') END AS polroles, "
35423562
"pg_catalog.pg_get_expr(pol.polqual, pol.polrelid) AS polqual, "
35433563
"pg_catalog.pg_get_expr(pol.polwithcheck, pol.polrelid) AS polwithcheck "
3544-
"FROM pg_catalog.pg_policy pol");
3564+
"FROM unnest('%s'::pg_catalog.oid[]) AS src(tbloid)\n"
3565+
"JOIN pg_catalog.pg_policy pol ON (src.tbloid = pol.polrelid)",
3566+
tbloids->data);
35453567

35463568
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
35473569

@@ -3565,13 +3587,6 @@ getPolicies(Archive *fout, TableInfo tblinfo[], int numTables)
35653587
Oid polrelid = atooid(PQgetvalue(res, j, i_polrelid));
35663588
TableInfo *tbinfo = findTableByOid(polrelid);
35673589

3568-
/*
3569-
* Ignore row security on tables not to be dumped. (This will
3570-
* result in some harmless wasted slots in polinfo[].)
3571-
*/
3572-
if (!(tbinfo->dobj.dump & DUMP_COMPONENT_POLICY))
3573-
continue;
3574-
35753590
polinfo[j].dobj.objType = DO_POLICY;
35763591
polinfo[j].dobj.catId.tableoid =
35773592
atooid(PQgetvalue(res, j, i_tableoid));
@@ -3606,6 +3621,7 @@ getPolicies(Archive *fout, TableInfo tblinfo[], int numTables)
36063621
PQclear(res);
36073622

36083623
destroyPQExpBuffer(query);
3624+
destroyPQExpBuffer(tbloids);
36093625
}
36103626

36113627
/*

0 commit comments

Comments
 (0)
0