]> granicus.if.org Git - postgresql/commitdiff
Treat EPERM as a non-error case when checking to see if old postmaster
authorTom Lane <tgl@sss.pgh.pa.us>
Fri, 18 Mar 2005 03:48:49 +0000 (03:48 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Fri, 18 Mar 2005 03:48:49 +0000 (03:48 +0000)
is still alive.  This improves our odds of not getting fooled by an
unrelated process when checking a stale lock file.  Other checks already
in place, plus one newly added in checkDataDir(), ensure that we cannot
attempt to usurp the place of a postmaster belonging to a different userid,
so there is no need to error out.  Add comments indicating the importance
of these other checks.

src/backend/postmaster/postmaster.c
src/backend/utils/init/miscinit.c

index 8df917e4e8e643bfffd8cc316db9d3f8a98320e0..300d0442e0839d263ec67cf0bc549f135cbde0a8 100644 (file)
@@ -37,7 +37,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.446 2005/03/10 07:14:03 neilc Exp $
+ *       $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.447 2005/03/18 03:48:49 tgl Exp $
  *
  * NOTES
  *
@@ -952,9 +952,32 @@ checkDataDir(void)
                                        DataDir)));
        }
 
+       /*
+        * Check that the directory belongs to my userid; if not, reject.
+        *
+        * This check is an essential part of the interlock that prevents two
+        * postmasters from starting in the same directory (see CreateLockFile()).
+        * Do not remove or weaken it.
+        *
+        * XXX can we safely enable this check on Windows?
+        */
+#if !defined(WIN32) && !defined(__CYGWIN__)
+       if (stat_buf.st_uid != geteuid())
+               ereport(FATAL,
+                               (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+                                errmsg("data directory \"%s\" has wrong ownership",
+                                               DataDir),
+                                errhint("The server must be started by the user that owns the data directory.")));
+#endif
+
        /*
         * Check if the directory has group or world access.  If so, reject.
         *
+        * It would be possible to allow weaker constraints (for example, allow
+        * group access) but we cannot make a general assumption that that is
+        * okay; for example there are platforms where nearly all users customarily
+        * belong to the same group.  Perhaps this test should be configurable.
+        *
         * XXX temporarily suppress check when on Windows, because there may not
         * be proper support for Unix-y file permissions.  Need to think of a
         * reasonable check to apply on Windows.
index 322d3a767428783774d8ab28dee950ee51d99ac5..b906ee581d95cca2555087a6e6fa2ee80817422e 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/init/miscinit.c,v 1.137 2004/12/31 22:01:40 pgsql Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/init/miscinit.c,v 1.138 2005/03/18 03:48:49 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -505,6 +505,9 @@ CreateLockFile(const char *filename, bool amPostmaster,
        {
                /*
                 * Try to create the lock file --- O_EXCL makes this atomic.
+                *
+                * Think not to make the file protection weaker than 0600.  See
+                * comments below.
                 */
                fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
                if (fd >= 0)
@@ -564,6 +567,21 @@ CreateLockFile(const char *filename, bool amPostmaster,
                 * then all but the immediate parent shell will be root-owned processes
                 * and so the kill test will fail with EPERM.
                 *
+                * We can treat the EPERM-error case as okay because that error implies
+                * that the existing process has a different userid than we do, which
+                * means it cannot be a competing postmaster.  A postmaster cannot
+                * successfully attach to a data directory owned by a userid other
+                * than its own.  (This is now checked directly in checkDataDir(),
+                * but has been true for a long time because of the restriction that
+                * the data directory isn't group- or world-accessible.)  Also,
+                * since we create the lockfiles mode 600, we'd have failed above
+                * if the lockfile belonged to another userid --- which means that
+                * whatever process kill() is reporting about isn't the one that
+                * made the lockfile.  (NOTE: this last consideration is the only
+                * one that keeps us from blowing away a Unix socket file belonging
+                * to an instance of Postgres being run by someone else, at least
+                * on machines where /tmp hasn't got a stickybit.)
+                *
                 * Windows hasn't got getppid(), but doesn't need it since it's not
                 * using real kill() either...
                 *
@@ -577,11 +595,11 @@ CreateLockFile(const char *filename, bool amPostmaster,
                        )
                {
                        if (kill(other_pid, 0) == 0 ||
-                               (errno != ESRCH
+                               (errno != ESRCH &&
 #ifdef __BEOS__
-                                && errno != EINVAL
+                                errno != EINVAL &&
 #endif
-                                ))
+                                errno != EPERM))
                        {
                                /* lockfile belongs to a live process */
                                ereport(FATAL,