Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 29d75b2

Browse files
committed
Fix pg_dumpall to cope with dangling OIDs in pg_auth_members.
There is a race condition between "GRANT role" and "DROP ROLE", which allows GRANT to install pg_auth_members entries that refer to dropped roles. (Commit 6566133 prevented that for the grantor field, but not for the granted or grantee roles.) We'll soon fix that, at least in HEAD, but pg_dumpall needs to cope with the situation in case of pre-existing inconsistency. As pg_dumpall stands, it will emit invalid commands like 'GRANT foo TO ""', which causes pg_upgrade to fail. Fix it to emit warnings and skip those GRANTs, instead. There was some discussion of removing the problem by changing dumpRoleMembership's query to use JOIN not LEFT JOIN, but that would result in silently ignoring such entries. It seems better to produce a warning. Pre-v16 branches already coped with dangling grantor OIDs by simply omitting the GRANTED BY clause. I left that behavior as-is, although it's somewhat inconsistent with the behavior of later branches. Reported-by: Virender Singla <virender.cse@gmail.com> Discussion: https://postgr.es/m/CAM6Zo8woa62ZFHtMKox6a4jb8qQ=w87R2L0K8347iE-juQL2EA@mail.gmail.com Backpatch-through: 13
1 parent dfd8e6c commit 29d75b2

File tree

1 file changed

+57
-9
lines changed

1 file changed

+57
-9
lines changed

src/bin/pg_dump/pg_dumpall.c

+57-9
Original file line numberDiff line numberDiff line change
@@ -986,6 +986,13 @@ dumpRoleMembership(PGconn *conn)
986986
total;
987987
bool dump_grantors;
988988
bool dump_grant_options;
989+
int i_role;
990+
int i_member;
991+
int i_grantor;
992+
int i_roleid;
993+
int i_memberid;
994+
int i_grantorid;
995+
int i_admin_option;
989996
int i_inherit_option;
990997
int i_set_option;
991998

@@ -995,6 +1002,10 @@ dumpRoleMembership(PGconn *conn)
9951002
* they didn't have ADMIN OPTION on the role, or a user that no longer
9961003
* existed. To avoid dump and restore failures, don't dump the grantor
9971004
* when talking to an old server version.
1005+
*
1006+
* Also, in older versions the roleid and/or member could be role OIDs
1007+
* that no longer exist. If we find such cases, print a warning and skip
1008+
* the entry.
9981009
*/
9991010
dump_grantors = (PQserverVersion(conn) >= 160000);
10001011

@@ -1006,8 +1017,10 @@ dumpRoleMembership(PGconn *conn)
10061017
/* Generate and execute query. */
10071018
printfPQExpBuffer(buf, "SELECT ur.rolname AS role, "
10081019
"um.rolname AS member, "
1009-
"ug.oid AS grantorid, "
10101020
"ug.rolname AS grantor, "
1021+
"a.roleid AS roleid, "
1022+
"a.member AS memberid, "
1023+
"a.grantor AS grantorid, "
10111024
"a.admin_option");
10121025
if (dump_grant_options)
10131026
appendPQExpBufferStr(buf, ", a.inherit_option, a.set_option");
@@ -1016,8 +1029,15 @@ dumpRoleMembership(PGconn *conn)
10161029
"LEFT JOIN %s um on um.oid = a.member "
10171030
"LEFT JOIN %s ug on ug.oid = a.grantor "
10181031
"WHERE NOT (ur.rolname ~ '^pg_' AND um.rolname ~ '^pg_')"
1019-
"ORDER BY 1,2,4", role_catalog, role_catalog, role_catalog);
1032+
"ORDER BY 1,2,3", role_catalog, role_catalog, role_catalog);
10201033
res = executeQuery(conn, buf->data);
1034+
i_role = PQfnumber(res, "role");
1035+
i_member = PQfnumber(res, "member");
1036+
i_grantor = PQfnumber(res, "grantor");
1037+
i_roleid = PQfnumber(res, "roleid");
1038+
i_memberid = PQfnumber(res, "memberid");
1039+
i_grantorid = PQfnumber(res, "grantorid");
1040+
i_admin_option = PQfnumber(res, "admin_option");
10211041
i_inherit_option = PQfnumber(res, "inherit_option");
10221042
i_set_option = PQfnumber(res, "set_option");
10231043

@@ -1041,24 +1061,32 @@ dumpRoleMembership(PGconn *conn)
10411061
total = PQntuples(res);
10421062
while (start < total)
10431063
{
1044-
char *role = PQgetvalue(res, start, 0);
1064+
char *role = PQgetvalue(res, start, i_role);
10451065
int i;
10461066
bool *done;
10471067
int remaining;
10481068
int prev_remaining = 0;
10491069
rolename_hash *ht;
10501070

1071+
/* If we hit a null roleid, we're done (nulls sort to the end). */
1072+
if (PQgetisnull(res, start, i_role))
1073+
{
1074+
/* translator: %s represents a numeric role OID */
1075+
pg_log_warning("found orphaned pg_auth_members entry for role %s",
1076+
PQgetvalue(res, start, i_roleid));
1077+
break;
1078+
}
1079+
10511080
/* All memberships for a single role should be adjacent. */
10521081
for (end = start; end < total; ++end)
10531082
{
10541083
char *otherrole;
10551084

1056-
otherrole = PQgetvalue(res, end, 0);
1085+
otherrole = PQgetvalue(res, end, i_role);
10571086
if (strcmp(role, otherrole) != 0)
10581087
break;
10591088
}
10601089

1061-
role = PQgetvalue(res, start, 0);
10621090
remaining = end - start;
10631091
done = pg_malloc0(remaining * sizeof(bool));
10641092
ht = rolename_create(remaining, NULL);
@@ -1098,10 +1126,30 @@ dumpRoleMembership(PGconn *conn)
10981126
if (done[i - start])
10991127
continue;
11001128

1101-
member = PQgetvalue(res, i, 1);
1102-
grantorid = PQgetvalue(res, i, 2);
1103-
grantor = PQgetvalue(res, i, 3);
1104-
admin_option = PQgetvalue(res, i, 4);
1129+
/* Complain about, then ignore, entries with orphaned OIDs. */
1130+
if (PQgetisnull(res, i, i_member))
1131+
{
1132+
/* translator: %s represents a numeric role OID */
1133+
pg_log_warning("found orphaned pg_auth_members entry for role %s",
1134+
PQgetvalue(res, i, i_memberid));
1135+
done[i - start] = true;
1136+
--remaining;
1137+
continue;
1138+
}
1139+
if (PQgetisnull(res, i, i_grantor))
1140+
{
1141+
/* translator: %s represents a numeric role OID */
1142+
pg_log_warning("found orphaned pg_auth_members entry for role %s",
1143+
PQgetvalue(res, i, i_grantorid));
1144+
done[i - start] = true;
1145+
--remaining;
1146+
continue;
1147+
}
1148+
1149+
member = PQgetvalue(res, i, i_member);
1150+
grantor = PQgetvalue(res, i, i_grantor);
1151+
grantorid = PQgetvalue(res, i, i_grantorid);
1152+
admin_option = PQgetvalue(res, i, i_admin_option);
11051153
if (dump_grant_options)
11061154
set_option = PQgetvalue(res, i, i_set_option);
11071155

0 commit comments

Comments
 (0)