aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorStephen Frost <sfrost@snowman.net>2017-01-31 16:24:11 -0500
committerStephen Frost <sfrost@snowman.net>2017-01-31 16:24:11 -0500
commite2090d9d20d8091c9478a674d9c22fc8006909ce (patch)
tree5819b938424f81eec850e13efdf5a550a406e2ea /src
parent6af8b89adba16f97bee0d3b01256861e10d0e4f1 (diff)
downloadpostgresql-e2090d9d20d8091c9478a674d9c22fc8006909ce.tar.gz
postgresql-e2090d9d20d8091c9478a674d9c22fc8006909ce.zip
pg_dump: Fix handling of ALTER DEFAULT PRIVILEGES
In commit 23f34fa, we changed how ACLs were handled to use the new pg_init_privs catalog and to dump out the ACL commands as REVOKE+GRANT combinations instead of trying to REVOKE all rights always and then GRANT back just the ones which were in place. Unfortunately, the DEFAULT PRIVILEGES system didn't quite get the correct treatment with this change and ended up (incorrectly) only including positive GRANTs instead of both the REVOKEs and GRANTs necessary to preserve the correct privileges. There are only a couple cases where such REVOKEs are possible because, generally speaking, there's few rights which exist on objects by default to be revoked. Examples of REVOKEs which weren't being correctly preserved are when privileges are REVOKE'd from the creator/owner, like so: ALTER DEFAULT PRIVILEGES FOR ROLE myrole REVOKE SELECT ON TABLES FROM myrole; or when other default privileges are being revoked, such as EXECUTE rights granted to public for functions: ALTER DEFAULT PRIVILEGES FOR ROLE myrole REVOKE EXECUTE ON FUNCTIONS FROM PUBLIC; Fix this by correctly working out what the correct REVOKE statements are (if any) and dump them out, just as we do for everything else. Noticed while developing additional regression tests for pg_dump, which will be landing shortly. Back-patch to 9.6 where the bug was introduced.
Diffstat (limited to 'src')
-rw-r--r--src/bin/pg_dump/dumputils.c23
-rw-r--r--src/bin/pg_dump/dumputils.h4
-rw-r--r--src/bin/pg_dump/pg_dump.c63
-rw-r--r--src/bin/pg_dump/pg_dump.h3
4 files changed, 78 insertions, 15 deletions
diff --git a/src/bin/pg_dump/dumputils.c b/src/bin/pg_dump/dumputils.c
index 81ec650e5ca..b41f2b91258 100644
--- a/src/bin/pg_dump/dumputils.c
+++ b/src/bin/pg_dump/dumputils.c
@@ -364,11 +364,12 @@ buildACLCommands(const char *name, const char *subname,
*/
bool
buildDefaultACLCommands(const char *type, const char *nspname,
- const char *acls, const char *owner,
+ const char *acls, const char *racls,
+ const char *initacls, const char *initracls,
+ const char *owner,
int remoteVersion,
PQExpBuffer sql)
{
- bool result;
PQExpBuffer prefix;
prefix = createPQExpBuffer();
@@ -384,14 +385,22 @@ buildDefaultACLCommands(const char *type, const char *nspname,
if (nspname)
appendPQExpBuffer(prefix, "IN SCHEMA %s ", fmtId(nspname));
- result = buildACLCommands("", NULL,
- type, acls, "", owner,
- prefix->data, remoteVersion,
- sql);
+ if (strlen(initacls) != 0 || strlen(initracls) != 0)
+ {
+ appendPQExpBuffer(sql, "SELECT pg_catalog.binary_upgrade_set_record_init_privs(true);\n");
+ if (!buildACLCommands("", NULL, type, initacls, initracls, owner,
+ prefix->data, remoteVersion, sql))
+ return false;
+ appendPQExpBuffer(sql, "SELECT pg_catalog.binary_upgrade_set_record_init_privs(false);\n");
+ }
+
+ if (!buildACLCommands("", NULL, type, acls, racls, owner,
+ prefix->data, remoteVersion, sql))
+ return false;
destroyPQExpBuffer(prefix);
- return result;
+ return true;
}
/*
diff --git a/src/bin/pg_dump/dumputils.h b/src/bin/pg_dump/dumputils.h
index ba61fa9bd27..d7eecdfb3cf 100644
--- a/src/bin/pg_dump/dumputils.h
+++ b/src/bin/pg_dump/dumputils.h
@@ -41,7 +41,9 @@ extern bool buildACLCommands(const char *name, const char *subname,
const char *owner, const char *prefix, int remoteVersion,
PQExpBuffer sql);
extern bool buildDefaultACLCommands(const char *type, const char *nspname,
- const char *acls, const char *owner,
+ const char *acls, const char *racls,
+ const char *initacls, const char *initracls,
+ const char *owner,
int remoteVersion,
PQExpBuffer sql);
extern void buildShSecLabelQuery(PGconn *conn, const char *catalog_name,
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index a6de9d7bc21..35ac05e851f 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -8683,6 +8683,9 @@ getDefaultACLs(Archive *fout, int *numDefaultACLs)
int i_defaclnamespace;
int i_defaclobjtype;
int i_defaclacl;
+ int i_rdefaclacl;
+ int i_initdefaclacl;
+ int i_initrdefaclacl;
int i,
ntups;
@@ -8697,13 +8700,50 @@ getDefaultACLs(Archive *fout, int *numDefaultACLs)
/* Make sure we are in proper schema */
selectSourceSchema(fout, "pg_catalog");
- appendPQExpBuffer(query, "SELECT oid, tableoid, "
- "(%s defaclrole) AS defaclrole, "
- "defaclnamespace, "
- "defaclobjtype, "
- "defaclacl "
- "FROM pg_default_acl",
- username_subquery);
+ if (fout->remoteVersion >= 90600)
+ {
+ PQExpBuffer acl_subquery = createPQExpBuffer();
+ PQExpBuffer racl_subquery = createPQExpBuffer();
+ PQExpBuffer initacl_subquery = createPQExpBuffer();
+ PQExpBuffer initracl_subquery = createPQExpBuffer();
+
+ buildACLQueries(acl_subquery, racl_subquery, initacl_subquery,
+ initracl_subquery, "defaclacl", "defaclrole",
+ "CASE WHEN defaclobjtype = 'S' THEN 's' ELSE defaclobjtype END::\"char\"",
+ dopt->binary_upgrade);
+
+ appendPQExpBuffer(query, "SELECT d.oid, d.tableoid, "
+ "(%s d.defaclrole) AS defaclrole, "
+ "d.defaclnamespace, "
+ "d.defaclobjtype, "
+ "%s AS defaclacl, "
+ "%s AS rdefaclacl, "
+ "%s AS initdefaclacl, "
+ "%s AS initrdefaclacl "
+ "FROM pg_default_acl d "
+ "LEFT JOIN pg_init_privs pip ON "
+ "(d.oid = pip.objoid "
+ "AND pip.classoid = 'pg_default_acl'::regclass "
+ "AND pip.objsubid = 0) ",
+ username_subquery,
+ acl_subquery->data,
+ racl_subquery->data,
+ initacl_subquery->data,
+ initracl_subquery->data);
+ }
+ else
+ {
+ appendPQExpBuffer(query, "SELECT oid, tableoid, "
+ "(%s defaclrole) AS defaclrole, "
+ "defaclnamespace, "
+ "defaclobjtype, "
+ "defaclacl, "
+ "NULL AS rdefaclacl, "
+ "NULL AS initdefaclacl, "
+ "NULL AS initrdefaclacl "
+ "FROM pg_default_acl",
+ username_subquery);
+ }
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
@@ -8718,6 +8758,9 @@ getDefaultACLs(Archive *fout, int *numDefaultACLs)
i_defaclnamespace = PQfnumber(res, "defaclnamespace");
i_defaclobjtype = PQfnumber(res, "defaclobjtype");
i_defaclacl = PQfnumber(res, "defaclacl");
+ i_rdefaclacl = PQfnumber(res, "rdefaclacl");
+ i_initdefaclacl = PQfnumber(res, "initdefaclacl");
+ i_initrdefaclacl = PQfnumber(res, "initrdefaclacl");
for (i = 0; i < ntups; i++)
{
@@ -8738,6 +8781,9 @@ getDefaultACLs(Archive *fout, int *numDefaultACLs)
daclinfo[i].defaclrole = pg_strdup(PQgetvalue(res, i, i_defaclrole));
daclinfo[i].defaclobjtype = *(PQgetvalue(res, i, i_defaclobjtype));
daclinfo[i].defaclacl = pg_strdup(PQgetvalue(res, i, i_defaclacl));
+ daclinfo[i].rdefaclacl = pg_strdup(PQgetvalue(res, i, i_rdefaclacl));
+ daclinfo[i].initdefaclacl = pg_strdup(PQgetvalue(res, i, i_initdefaclacl));
+ daclinfo[i].initrdefaclacl = pg_strdup(PQgetvalue(res, i, i_initrdefaclacl));
/* Decide whether we want to dump it */
selectDumpableDefaultACL(&(daclinfo[i]), dopt);
@@ -14038,6 +14084,9 @@ dumpDefaultACL(Archive *fout, DefaultACLInfo *daclinfo)
daclinfo->dobj.namespace != NULL ?
daclinfo->dobj.namespace->dobj.name : NULL,
daclinfo->defaclacl,
+ daclinfo->rdefaclacl,
+ daclinfo->initdefaclacl,
+ daclinfo->initrdefaclacl,
daclinfo->defaclrole,
fout->remoteVersion,
q))
diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h
index 77de22fcb8b..a466527ec68 100644
--- a/src/bin/pg_dump/pg_dump.h
+++ b/src/bin/pg_dump/pg_dump.h
@@ -539,6 +539,9 @@ typedef struct _defaultACLInfo
char *defaclrole;
char defaclobjtype;
char *defaclacl;
+ char *rdefaclacl;
+ char *initdefaclacl;
+ char *initrdefaclacl;
} DefaultACLInfo;
typedef struct _blobInfo