diff --git a/src/backend/main/main.c b/src/backend/main/main.c index a8ab4c4ab6f64056e64682aa2d19e7c29ef933a0..1b9cbd1de360816aea194b601c0442a60be2514c 100644 --- a/src/backend/main/main.c +++ b/src/backend/main/main.c @@ -58,6 +58,8 @@ static void check_root(const char *progname); int main(int argc, char *argv[]) { + bool do_check_root = true; + progname = get_progname(argv[0]); /* @@ -151,7 +153,8 @@ main(int argc, char *argv[]) unsetenv("LC_ALL"); /* - * Catch standard options before doing much else + * Catch standard options before doing much else, in particular before we + * insist on not being root. */ if (argc > 1) { @@ -165,12 +168,29 @@ main(int argc, char *argv[]) puts("postgres (PostgreSQL) " PG_VERSION); exit(0); } + + /* + * In addition to the above, we allow "--describe-config" and "-C var" + * to be called by root. This is reasonably safe since these are + * read-only activities. The -C case is important because pg_ctl may + * try to invoke it while still holding administrator privileges on + * Windows. Note that while -C can normally be in any argv position, + * if you wanna bypass the root check you gotta put it first. This + * reduces the risk that we might misinterpret some other mode's -C + * switch as being the postmaster/postgres one. + */ + if (strcmp(argv[1], "--describe-config") == 0) + do_check_root = false; + else if (argc > 2 && strcmp(argv[1], "-C") == 0) + do_check_root = false; } /* - * Make sure we are not running as root. + * Make sure we are not running as root, unless it's safe for the selected + * option. */ - check_root(progname); + if (do_check_root) + check_root(progname); /* * Dispatch to one of various subprograms depending on first argument. diff --git a/src/bin/pg_ctl/pg_ctl.c b/src/bin/pg_ctl/pg_ctl.c index 1f921819c23563bc9068fb1bab83ba2bec61627d..fc87e7d76ed166af23cf83fa91991211605af409 100644 --- a/src/bin/pg_ctl/pg_ctl.c +++ b/src/bin/pg_ctl/pg_ctl.c @@ -2034,9 +2034,11 @@ adjust_data_dir(void) else my_exec_path = pg_strdup(exec_path); - snprintf(cmd, MAXPGPATH, SYSTEMQUOTE "\"%s\" %s%s -C data_directory" SYSTEMQUOTE, - my_exec_path, pgdata_opt ? pgdata_opt : "", post_opts ? - post_opts : ""); + /* it's important for -C to be the first option, see main.c */ + snprintf(cmd, MAXPGPATH, SYSTEMQUOTE "\"%s\" -C data_directory %s%s" SYSTEMQUOTE, + my_exec_path, + pgdata_opt ? pgdata_opt : "", + post_opts ? post_opts : ""); fd = popen(cmd, "r"); if (fd == NULL || fgets(filename, sizeof(filename), fd) == NULL)