]> granicus.if.org Git - postgresql/commitdiff
Ensure that all temp files made during pg_upgrade are non-world-readable.
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 5 Feb 2018 15:58:27 +0000 (10:58 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 5 Feb 2018 15:58:27 +0000 (10:58 -0500)
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

src/bin/pg_upgrade/dump.c
src/bin/pg_upgrade/file.c
src/bin/pg_upgrade/pg_upgrade.c
src/bin/pg_upgrade/pg_upgrade.h

index 1f6fe53d201b83cab0f156a0393d066e13d48bf5..1abcb06da38a82f2f1cb8aa5cdee2782add7d981 100644 (file)
@@ -18,7 +18,6 @@ void
 generate_old_dump(void)
 {
        int                     dbnum;
-       mode_t          old_umask;
 
        prep_status("Creating dump of global objects");
 
@@ -33,13 +32,6 @@ generate_old_dump(void)
 
        prep_status("Creating dump of database schemas\n");
 
-       /*
-        * Set umask for this function, all functions it calls, and all
-        * subprocesses/threads it creates.  We can't use fopen_priv() as Windows
-        * uses threads and umask is process-global.
-        */
-       old_umask = umask(S_IRWXG | S_IRWXO);
-
        /* create per-db dump files */
        for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
        {
@@ -74,8 +66,6 @@ generate_old_dump(void)
        while (reap_child(true) == true)
                ;
 
-       umask(old_umask);
-
        end_progress_output();
        check_ok();
 }
index ae8d89fb66ba1618d914adf54ff8c4f1fa1b6e73..b8be9a5bda022bd98fcfd993a36d33a9e1ae62da 100644 (file)
@@ -314,18 +314,3 @@ win32_pghardlink(const char *src, const char *dst)
                return 0;
 }
 #endif
-
-
-/* fopen() file with no group/other permissions */
-FILE *
-fopen_priv(const char *path, const char *mode)
-{
-       mode_t          old_umask = umask(S_IRWXG | S_IRWXO);
-       FILE       *fp;
-
-       fp = fopen(path, mode);
-
-       umask(old_umask);                       /* we assume this can't change errno */
-
-       return fp;
-}
index ed0ac928622b4ecc93da93dd51e5fbdfc27c53f4..78f356c24c8eb28b84845217bcb5db0bc10cc6ca 100644 (file)
@@ -77,6 +77,10 @@ main(int argc, char **argv)
        bool            live_check = false;
 
        set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_upgrade"));
+
+       /* Ensure that all files created by pg_upgrade are non-world-readable */
+       umask(S_IRWXG | S_IRWXO);
+
        parseCommandLine(argc, argv);
 
        get_restricted_token(os_info.progname);
index ee6676ce55a3284d7a5c93e8dbb3516327b20cf1..dccc3e3b63f2543e156b8d8a2a0f19466d047797 100644 (file)
@@ -374,7 +374,9 @@ void linkFile(const char *src, const char *dst,
 void rewriteVisibilityMap(const char *fromfile, const char *tofile,
                                         const char *schemaName, const char *relName);
 void           check_hard_link(void);
-FILE      *fopen_priv(const char *path, const char *mode);
+
+/* fopen_priv() is no longer different from fopen() */
+#define fopen_priv(path, mode) fopen(path, mode)
 
 /* function.c */