Index: postgresql-9.5.4/src/bin/pg_ctl/pg_ctl.c
|
|
===================================================================
|
|
--- postgresql-9.5.4.orig/src/bin/pg_ctl/pg_ctl.c
|
|
+++ postgresql-9.5.4/src/bin/pg_ctl/pg_ctl.c
|
|
@@ -95,6 +95,7 @@ static char *event_source = NULL;
|
|
static char *register_servicename = "PostgreSQL"; /* FIXME: + version ID? */
|
|
static char *register_username = NULL;
|
|
static char *register_password = NULL;
|
|
+static char *username = "";
|
|
static char *argv0 = NULL;
|
|
static bool allow_core_files = false;
|
|
static time_t start_time;
|
|
@@ -2114,6 +2115,9 @@ do_help(void)
|
|
#endif
|
|
printf(_(" -s, --silent only print errors, no informational messages\n"));
|
|
printf(_(" -t, --timeout=SECS seconds to wait when using -w option\n"));
|
|
+#if !defined(WIN32) && !defined(__CYGWIN__)
|
|
+ printf(_(" -U USERNAME user name of account PostgreSQL server is running as\n"));
|
|
+#endif
|
|
printf(_(" -V, --version output version information, then exit\n"));
|
|
printf(_(" -w wait until operation completes\n"));
|
|
printf(_(" -W do not wait until operation completes\n"));
|
|
@@ -2310,6 +2314,7 @@ main(int argc, char **argv)
|
|
{"pgdata", required_argument, NULL, 'D'},
|
|
{"silent", no_argument, NULL, 's'},
|
|
{"timeout", required_argument, NULL, 't'},
|
|
+ {"username", required_argument, NULL, 'U'},
|
|
{"core-files", no_argument, NULL, 'c'},
|
|
{NULL, 0, NULL, 0}
|
|
};
|
|
@@ -2350,20 +2355,6 @@ main(int argc, char **argv)
|
|
}
|
|
}
|
|
|
|
- /*
|
|
- * Disallow running as root, to forestall any possible security holes.
|
|
- */
|
|
-#ifndef WIN32
|
|
- if (geteuid() == 0)
|
|
- {
|
|
- write_stderr(_("%s: cannot be run as root\n"
|
|
- "Please log in (using, e.g., \"su\") as the "
|
|
- "(unprivileged) user that will\n"
|
|
- "own the server process.\n"),
|
|
- progname);
|
|
- exit(1);
|
|
- }
|
|
-#endif
|
|
|
|
env_wait = getenv("PGCTLTIMEOUT");
|
|
if (env_wait != NULL)
|
|
@@ -2449,11 +2440,15 @@ main(int argc, char **argv)
|
|
wait_seconds_arg = true;
|
|
break;
|
|
case 'U':
|
|
+#if defined(WIN32) || defined(__CYGWIN__)
|
|
if (strchr(optarg, '\\'))
|
|
register_username = pg_strdup(optarg);
|
|
else
|
|
/* Prepend .\ for local accounts */
|
|
register_username = psprintf(".\\%s", optarg);
|
|
+#else
|
|
+ username = pg_strdup(optarg);
|
|
+#endif
|
|
break;
|
|
case 'w':
|
|
do_wait = true;
|
|
@@ -2535,6 +2530,41 @@ main(int argc, char **argv)
|
|
exit(1);
|
|
}
|
|
|
|
+ /*
|
|
+ * Disallow running as root, to forestall any possible security holes.
|
|
+ */
|
|
+#if !defined(WIN32) && !defined(__CYGWIN__)
|
|
+ if (geteuid() == 0)
|
|
+ {
|
|
+ struct passwd *p;
|
|
+ if (!username || !strlen(username)) {
|
|
+ fprintf(stderr,
|
|
+ _("%s: when run as root, username needs to be provided\n"),
|
|
+ progname);
|
|
+ exit(1);
|
|
+ }
|
|
+ p = getpwnam(username);
|
|
+ if (!p) {
|
|
+ fprintf(stderr,
|
|
+ _("%s: invalid username: %s\n"),
|
|
+ progname, username);
|
|
+ exit(1);
|
|
+ }
|
|
+ if (!p->pw_uid) {
|
|
+ fprintf(stderr,
|
|
+ _("%s: user needs to be non-root\n"),
|
|
+ progname);
|
|
+ exit(1);
|
|
+ }
|
|
+ if (setgid(p->pw_gid) || setuid(p->pw_uid)) {
|
|
+ fprintf(stderr,
|
|
+ _("%s: failed to set user id %d: %d (%s)\n"),
|
|
+ progname, p->pw_uid, errno, strerror(errno));
|
|
+ exit(1);
|
|
+ }
|
|
+ }
|
|
+#endif
|
|
+
|
|
/* Note we put any -D switch into the env var above */
|
|
pg_config = getenv("PGDATA");
|
|
if (pg_config)
|