openwrt-packages/libs/postgresql/patches/900-pg_ctl-setuid.patch

108 lines
3.2 KiB
Diff

--- a/src/bin/pg_ctl/pg_ctl.c
+++ b/src/bin/pg_ctl/pg_ctl.c
@@ -96,6 +96,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;
@@ -2086,6 +2087,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=NAME user name of account PostgreSQL server is running as\n"));
+#endif
printf(_(" -V, --version output version information, then exit\n"));
printf(_(" -w, --wait wait until operation completes (default)\n"));
printf(_(" -W, --no-wait do not wait until operation completes\n"));
@@ -2298,6 +2302,7 @@ main(int argc, char **argv)
{"options", required_argument, NULL, 'o'},
{"silent", no_argument, NULL, 's'},
{"timeout", required_argument, NULL, 't'},
+ {"username", required_argument, NULL, 'U'},
{"core-files", no_argument, NULL, 'c'},
{"wait", no_argument, NULL, 'w'},
{"no-wait", no_argument, NULL, 'W'},
@@ -2338,20 +2343,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)
@@ -2437,11 +2428,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;
@@ -2523,6 +2518,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)