libpq: Fix minor TOCTOU violation
authorPeter Eisentraut <peter@eisentraut.org>
Fri, 16 Aug 2024 04:41:17 +0000 (06:41 +0200)
committerPeter Eisentraut <peter@eisentraut.org>
Fri, 16 Aug 2024 04:41:17 +0000 (06:41 +0200)
libpq checks the permissions of the password file before opening it.
The way this is done in two separate operations, a static analyzer
would flag as a time-of-check-time-of-use violation.  In practice, you
can't do anything with that, but it still seems better style to fix
it.

To fix it, open the file first and then check the permissions on the
opened file handle.

Reviewed-by: Aleksander Alekseev <aleksander@timescale.com>
Reviewed-by: Andreas Karlsson <andreas@proxel.se>
Discussion: https://www.postgresql.org/message-id/flat/a3356054-14ae-4e7a-acc6-249d19dac20b%40eisentraut.org

src/interfaces/libpq/fe-connect.c

index a5055271ae37eba1478a1153febeea1c72855511..246055df960ae525a1fd3a9f0ab9a2d674c69155 100644 (file)
@@ -7452,7 +7452,9 @@ passwordFromFile(const char *hostname, const char *port, const char *dbname,
                                 const char *username, const char *pgpassfile)
 {
        FILE       *fp;
+#ifndef WIN32
        struct stat stat_buf;
+#endif
        PQExpBufferData buf;
 
        if (dbname == NULL || dbname[0] == '\0')
@@ -7477,10 +7479,14 @@ passwordFromFile(const char *hostname, const char *port, const char *dbname,
                port = DEF_PGPORT_STR;
 
        /* If password file cannot be opened, ignore it. */
-       if (stat(pgpassfile, &stat_buf) != 0)
+       fp = fopen(pgpassfile, "r");
+       if (fp == NULL)
                return NULL;
 
 #ifndef WIN32
+       if (fstat(fileno(fp), &stat_buf) != 0)
+               return NULL;
+
        if (!S_ISREG(stat_buf.st_mode))
        {
                fprintf(stderr,
@@ -7505,10 +7511,6 @@ passwordFromFile(const char *hostname, const char *port, const char *dbname,
         */
 #endif
 
-       fp = fopen(pgpassfile, "r");
-       if (fp == NULL)
-               return NULL;
-
        /* Use an expansible buffer to accommodate any reasonable line length */
        initPQExpBuffer(&buf);