mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-02-23 19:39:53 +08:00
pg_upgrade has always attempted to ensure that the transient dump files
it creates are inaccessible except to the owner. However, refactoring
in commit 76a7650c4
broke that for the file containing "pg_dumpall -g"
output; since then, that file was protected according to the process's
default umask. Since that file may contain role passwords (hopefully
encrypted, but passwords nonetheless), this is a particularly unfortunate
oversight. Prudent users of pg_upgrade on multiuser systems would
probably run it under a umask tight enough that the issue is moot, but
perhaps some users are depending only on pg_upgrade's umask changes to
protect their data.
To fix this in a future-proof way, let's just tighten the umask at
process start. There are no files pg_upgrade needs to write at a
weaker security level; and if there were, transiently relaxing the
umask around where they're created would be a safer approach.
Report and patch by Tom Lane; the idea for the fix is due to Noah Misch.
Back-patch to all supported branches.
Security: CVE-2018-1053
72 lines
1.8 KiB
C
72 lines
1.8 KiB
C
/*
|
|
* dump.c
|
|
*
|
|
* dump functions
|
|
*
|
|
* Copyright (c) 2010-2013, PostgreSQL Global Development Group
|
|
* contrib/pg_upgrade/dump.c
|
|
*/
|
|
|
|
#include "postgres_fe.h"
|
|
|
|
#include "pg_upgrade.h"
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
|
void
|
|
generate_old_dump(void)
|
|
{
|
|
int dbnum;
|
|
|
|
prep_status("Creating dump of global objects");
|
|
|
|
/* run new pg_dumpall binary for globals */
|
|
exec_prog(UTILITY_LOG_FILE, NULL, true,
|
|
"\"%s/pg_dumpall\" %s --schema-only --globals-only "
|
|
"--quote-all-identifiers --binary-upgrade %s -f %s",
|
|
new_cluster.bindir, cluster_conn_opts(&old_cluster),
|
|
log_opts.verbose ? "--verbose" : "",
|
|
GLOBALS_DUMP_FILE);
|
|
check_ok();
|
|
|
|
prep_status("Creating dump of database schemas\n");
|
|
|
|
/* create per-db dump files */
|
|
for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
|
|
{
|
|
char sql_file_name[MAXPGPATH],
|
|
log_file_name[MAXPGPATH];
|
|
DbInfo *old_db = &old_cluster.dbarr.dbs[dbnum];
|
|
PQExpBufferData connstr,
|
|
escaped_connstr;
|
|
|
|
initPQExpBuffer(&connstr);
|
|
appendPQExpBuffer(&connstr, "dbname=");
|
|
appendConnStrVal(&connstr, old_db->db_name);
|
|
initPQExpBuffer(&escaped_connstr);
|
|
appendShellString(&escaped_connstr, connstr.data);
|
|
termPQExpBuffer(&connstr);
|
|
|
|
pg_log(PG_STATUS, "%s", old_db->db_name);
|
|
snprintf(sql_file_name, sizeof(sql_file_name), DB_DUMP_FILE_MASK, old_db->db_oid);
|
|
snprintf(log_file_name, sizeof(log_file_name), DB_DUMP_LOG_FILE_MASK, old_db->db_oid);
|
|
|
|
parallel_exec_prog(log_file_name, NULL,
|
|
"\"%s/pg_dump\" %s --schema-only --quote-all-identifiers "
|
|
"--binary-upgrade --format=custom %s --file=\"%s\" %s",
|
|
new_cluster.bindir, cluster_conn_opts(&old_cluster),
|
|
log_opts.verbose ? "--verbose" : "",
|
|
sql_file_name, escaped_connstr.data);
|
|
|
|
termPQExpBuffer(&escaped_connstr);
|
|
}
|
|
|
|
/* reap all children */
|
|
while (reap_child(true) == true)
|
|
;
|
|
|
|
end_progress_output();
|
|
check_ok();
|
|
}
|