Skip to content

Commit 6918d90

Browse files
committed
pg_upgrade_ACL_check_v9.patch
1 parent 350f477 commit 6918d90

File tree

3 files changed

+374
-0
lines changed

3 files changed

+374
-0
lines changed

src/bin/pg_upgrade/check.c

Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
static void check_new_cluster_is_empty(void);
1818
static void check_databases_are_compatible(void);
19+
static void check_for_changed_signatures(void);
1920
static void check_locale_and_encoding(DbInfo *olddb, DbInfo *newdb);
2021
static bool equivalent_locale(int category, const char *loca, const char *locb);
2122
static void check_is_install_user(ClusterInfo *cluster);
@@ -142,6 +143,8 @@ check_and_dump_old_cluster(bool live_check)
142143
if (GET_MAJOR_VERSION(old_cluster.major_version) <= 804)
143144
new_9_0_populate_pg_largeobject_metadata(&old_cluster, true);
144145

146+
get_non_default_acl_infos(&old_cluster);
147+
145148
/*
146149
* While not a check option, we do this now because this is the only time
147150
* the old server is running.
@@ -161,6 +164,7 @@ check_new_cluster(void)
161164

162165
check_new_cluster_is_empty();
163166
check_databases_are_compatible();
167+
check_for_changed_signatures();
164168

165169
check_loadable_libraries();
166170

@@ -443,6 +447,223 @@ check_databases_are_compatible(void)
443447
}
444448
}
445449

450+
/*
451+
* Find the location of the last dot, return NULL if not found.
452+
*/
453+
static char *
454+
last_dot_location(const char *identity)
455+
{
456+
const char *p,
457+
*ret = NULL;
458+
459+
for (p = identity; *p; p++)
460+
if (*p == '.')
461+
ret = p;
462+
return unconstify(char *, ret);
463+
}
464+
465+
/*
466+
* check_for_changed_signatures()
467+
*
468+
* Check that the old cluster doesn't have non-default ACL's for system objects
469+
* (relations, attributes, functions and procedures) which have different
470+
* signatures in the new cluster. Otherwise generate revoke_objects.sql.
471+
*/
472+
static void
473+
check_for_changed_signatures(void)
474+
{
475+
PGconn *conn;
476+
char subquery[QUERY_ALLOC];
477+
PGresult *res;
478+
int ntups;
479+
int i_obj_ident;
480+
int dbnum;
481+
bool need_check = false;
482+
FILE *script = NULL;
483+
bool found_changed = false;
484+
char output_path[MAXPGPATH];
485+
486+
prep_status("Checking for system objects with non-default ACL");
487+
488+
for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
489+
if (old_cluster.dbarr.dbs[dbnum].non_def_acl_arr.nacls > 0)
490+
{
491+
need_check = true;
492+
break;
493+
}
494+
/*
495+
* The old cluster doesn't have system objects with non-default ACL so
496+
* quickly exit.
497+
*/
498+
if (!need_check)
499+
{
500+
check_ok();
501+
return;
502+
}
503+
504+
snprintf(output_path, sizeof(output_path), "revoke_objects.sql");
505+
506+
snprintf(subquery, sizeof(subquery),
507+
/* Get system relations which created in pg_catalog */
508+
"SELECT 'pg_class'::regclass classid, oid objid, 0 objsubid "
509+
"FROM pg_catalog.pg_class "
510+
"WHERE relnamespace = 'pg_catalog'::regnamespace "
511+
"UNION ALL "
512+
/* Get system relations attributes which created in pg_catalog */
513+
"SELECT 'pg_class'::regclass, att.attrelid, att.attnum "
514+
"FROM pg_catalog.pg_class rel "
515+
"INNER JOIN pg_catalog.pg_attribute att ON rel.oid = att.attrelid "
516+
"WHERE rel.relnamespace = 'pg_catalog'::regnamespace "
517+
"UNION ALL "
518+
/* Get system functions and procedure which created in pg_catalog */
519+
"SELECT 'pg_proc'::regclass, oid, 0 "
520+
"FROM pg_catalog.pg_proc "
521+
"WHERE pronamespace = 'pg_catalog'::regnamespace ");
522+
523+
conn = connectToServer(&new_cluster, "template1");
524+
res = executeQueryOrDie(conn,
525+
"SELECT ident.type, ident.identity "
526+
"FROM (%s) obj, "
527+
"LATERAL pg_catalog.pg_identify_object("
528+
" obj.classid, obj.objid, obj.objsubid) ident "
529+
/*
530+
* Don't rely on database collation, since we use strcmp
531+
* comparison to find non-default ACLs.
532+
*/
533+
"ORDER BY ident.identity COLLATE \"C\";", subquery);
534+
ntups = PQntuples(res);
535+
536+
i_obj_ident = PQfnumber(res, "identity");
537+
538+
for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
539+
{
540+
DbInfo *dbinfo = &old_cluster.dbarr.dbs[dbnum];
541+
bool db_used = false;
542+
int aclnum = 0,
543+
objnum = 0;
544+
545+
/*
546+
* For every database check system objects with non-default ACL.
547+
*
548+
* AclInfo array is sorted by obj_ident. This allows us to compare
549+
* AclInfo entries with the query result above efficiently.
550+
*/
551+
for (aclnum = 0; aclnum < dbinfo->non_def_acl_arr.nacls; aclnum++)
552+
{
553+
AclInfo *aclinfo = &dbinfo->non_def_acl_arr.aclinfos[aclnum];
554+
bool report = false;
555+
556+
while (objnum < ntups)
557+
{
558+
int ret;
559+
560+
ret = strcmp(aclinfo->obj_ident,
561+
PQgetvalue(res, objnum, i_obj_ident));
562+
563+
/*
564+
* The new cluster doesn't have an object with same identity,
565+
* exit the loop, report below and check next object.
566+
*/
567+
if (ret < 0)
568+
{
569+
report = true;
570+
break;
571+
}
572+
/*
573+
* The new cluster has an object with same identity, just exit
574+
* the loop.
575+
*/
576+
else if (ret == 0)
577+
{
578+
objnum++;
579+
break;
580+
}
581+
else
582+
objnum++;
583+
}
584+
585+
if (report)
586+
{
587+
found_changed = true;
588+
if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
589+
pg_fatal("could not open file \"%s\": %s\n",
590+
output_path, strerror(errno));
591+
if (!db_used)
592+
{
593+
PQExpBufferData conn_buf;
594+
595+
initPQExpBuffer(&conn_buf);
596+
appendPsqlMetaConnect(&conn_buf, dbinfo->db_name);
597+
fputs(conn_buf.data, script);
598+
termPQExpBuffer(&conn_buf);
599+
600+
db_used = true;
601+
}
602+
603+
/* Handle columns separately */
604+
if (strstr(aclinfo->obj_type, "column") != NULL)
605+
{
606+
char *pdot = last_dot_location(aclinfo->obj_ident);
607+
PQExpBufferData ident_buf;
608+
609+
if (pdot == NULL || *(pdot + 1) == '\0')
610+
pg_fatal("invalid column identity \"%s\"",
611+
aclinfo->obj_ident);
612+
613+
initPQExpBuffer(&ident_buf);
614+
appendBinaryPQExpBuffer(&ident_buf, aclinfo->obj_ident,
615+
pdot - aclinfo->obj_ident);
616+
617+
fprintf(script, "REVOKE ALL (%s) ON %s FROM %s;\n",
618+
/* pg_identify_object() quotes identity if necessary */
619+
pdot + 1, ident_buf.data,
620+
/* role_names is already quoted */
621+
aclinfo->role_names);
622+
termPQExpBuffer(&ident_buf);
623+
}
624+
/*
625+
* For relations except sequences we don't need to specify
626+
* the object type.
627+
*/
628+
else if (aclinfo->is_relation &&
629+
strcmp(aclinfo->obj_type, "sequence") != 0)
630+
fprintf(script, "REVOKE ALL ON %s FROM %s;\n",
631+
/* pg_identify_object() quotes identity if necessary */
632+
aclinfo->obj_ident,
633+
/* role_names is already quoted */
634+
aclinfo->role_names);
635+
/* Other object types */
636+
else
637+
fprintf(script, "REVOKE ALL ON %s %s FROM %s;\n",
638+
aclinfo->obj_type,
639+
/* pg_identify_object() quotes identity if necessary */
640+
aclinfo->obj_ident,
641+
/* role_names is already quoted */
642+
aclinfo->role_names);
643+
}
644+
}
645+
}
646+
647+
PQclear(res);
648+
PQfinish(conn);
649+
650+
if (script)
651+
fclose(script);
652+
653+
if (found_changed)
654+
{
655+
pg_log(PG_REPORT, "fatal\n");
656+
pg_fatal("Your installation contains non-default privileges for system objects\n"
657+
"for which the API has changed. To perform the upgrade, reset these\n"
658+
"privileges to default. The file\n"
659+
" %s\n"
660+
"when executed by psql will revoke non-default privileges for those objects.\n\n",
661+
output_path);
662+
}
663+
else
664+
check_ok();
665+
}
666+
446667

447668
/*
448669
* create_script_for_cluster_analyze()

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy