Fix file swapping race condition in pool_passwd.
authorTatsuo Ishii <ishii@sraoss.co.jp>
Mon, 30 Nov 2020 04:01:52 +0000 (13:01 +0900)
committerTatsuo Ishii <ishii@sraoss.co.jp>
Mon, 30 Nov 2020 04:01:52 +0000 (13:01 +0900)
Existing implementation first stats pool passwd file and then open the
file. To prevent file-swapping due to file race conditions, open the
key file before checking it by stat().

Patch by: Masaya Kawamoto

src/auth/pool_passwd.c

index d704f2c4b069f7ae6edd6e8ef695bc65d7201c65..db3a7c918b4913260f1f93f518b0dc3daff8b8cb 100644 (file)
@@ -6,7 +6,7 @@
  * pgpool: a language independent connection pool server for PostgreSQL
  * written by Tatsuo Ishii
  *
- * Copyright (c) 2003-2018     PgPool Global Development Group
+ * Copyright (c) 2003-2020     PgPool Global Development Group
  *
  * Permission to use, copy, modify, and distribute this software and
  * its documentation for any purpose and without fee is hereby
@@ -621,14 +621,25 @@ read_pool_key(char *key_file_path)
        if (strlen(key_file_path) == 0)
                return NULL;
 
+       /*
+        * To prevent file-swapping due to file race conditions,
+        * we open the key file before checking it by stat().
+        */
        /* If password file cannot be opened, ignore it. */
-       if (stat(key_file_path, &stat_buf) != 0)
+       if ( (fp = fopen(key_file_path, "r")) == NULL)
+               return NULL;
+
+       if (fstat(fileno(fp), &stat_buf) != 0)
+       {
+               fclose(fp);
                return NULL;
+       }
 
        if (!S_ISREG(stat_buf.st_mode))
        {
                ereport(WARNING,
                                (errmsg("pool key file \"%s\" is not a plain file\n", key_file_path)));
+               fclose(fp);
                return NULL;
        }
 
@@ -639,13 +650,10 @@ read_pool_key(char *key_file_path)
                                (errmsg("pool key file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n",
                                                key_file_path)));
                /* do we want to allow unsecure pool key file ? */
+               /* fclose(fp); */
                /* return NULL; */
        }
 
-       fp = fopen(key_file_path, "r");
-       if (fp == NULL)
-               return NULL;
-
        while (!feof(fp) && !ferror(fp))
        {
                int                     len;