Skip to content

Commit 6d25eb3

Browse files
committed
Allow "-C variable" and "--describe-config" even to root users.
There's no really compelling reason to refuse to do these read-only, non-server-starting options as root, and there's at least one good reason to allow -C: pg_ctl uses -C to find out the true data directory location when pointed at a config-only directory. On Windows, this is done before dropping administrator privileges, which means that pg_ctl fails for administrators if and only if a config-only layout is used. Since the root-privilege check is done so early in startup, it's a bit awkward to check for these switches. Make the somewhat arbitrary decision that we'll only skip the root check if -C is the first switch. This is not just to make the code a bit simpler: it also guarantees that we can't misinterpret a --boot mode switch. (While AuxiliaryProcessMain doesn't currently recognize any such switch, it might have one in the future.) This is no particular problem for pg_ctl, and since the whole behavior is undocumented anyhow, it's not a documentation issue either. (--describe-config only works as the first switch anyway, so this is no restriction for that case either.) Back-patch to 9.2 where pg_ctl first began to use -C. MauMau, heavily edited by me
1 parent ed1cb42 commit 6d25eb3

File tree

2 files changed

+28
-6
lines changed

2 files changed

+28
-6
lines changed

src/backend/main/main.c

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ static char *get_current_username(const char *progname);
6262
int
6363
main(int argc, char *argv[])
6464
{
65+
bool do_check_root = true;
66+
6567
progname = get_progname(argv[0]);
6668

6769
/*
@@ -156,7 +158,8 @@ main(int argc, char *argv[])
156158
unsetenv("LC_ALL");
157159

158160
/*
159-
* Catch standard options before doing much else
161+
* Catch standard options before doing much else, in particular before we
162+
* insist on not being root.
160163
*/
161164
if (argc > 1)
162165
{
@@ -170,12 +173,29 @@ main(int argc, char *argv[])
170173
puts("postgres (PostgreSQL) " PG_VERSION);
171174
exit(0);
172175
}
176+
177+
/*
178+
* In addition to the above, we allow "--describe-config" and "-C var"
179+
* to be called by root. This is reasonably safe since these are
180+
* read-only activities. The -C case is important because pg_ctl may
181+
* try to invoke it while still holding administrator privileges on
182+
* Windows. Note that while -C can normally be in any argv position,
183+
* if you wanna bypass the root check you gotta put it first. This
184+
* reduces the risk that we might misinterpret some other mode's -C
185+
* switch as being the postmaster/postgres one.
186+
*/
187+
if (strcmp(argv[1], "--describe-config") == 0)
188+
do_check_root = false;
189+
else if (argc > 2 && strcmp(argv[1], "-C") == 0)
190+
do_check_root = false;
173191
}
174192

175193
/*
176-
* Make sure we are not running as root.
194+
* Make sure we are not running as root, unless it's safe for the selected
195+
* option.
177196
*/
178-
check_root(progname);
197+
if (do_check_root)
198+
check_root(progname);
179199

180200
/*
181201
* Dispatch to one of various subprograms depending on first argument.

src/bin/pg_ctl/pg_ctl.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1968,9 +1968,11 @@ adjust_data_dir(void)
19681968
else
19691969
my_exec_path = xstrdup(exec_path);
19701970

1971-
snprintf(cmd, MAXPGPATH, SYSTEMQUOTE "\"%s\" %s%s -C data_directory" SYSTEMQUOTE,
1972-
my_exec_path, pgdata_opt ? pgdata_opt : "", post_opts ?
1973-
post_opts : "");
1971+
/* it's important for -C to be the first option, see main.c */
1972+
snprintf(cmd, MAXPGPATH, SYSTEMQUOTE "\"%s\" -C data_directory %s%s" SYSTEMQUOTE,
1973+
my_exec_path,
1974+
pgdata_opt ? pgdata_opt : "",
1975+
post_opts ? post_opts : "");
19741976

19751977
fd = popen(cmd, "r");
19761978
if (fd == NULL || fgets(filename, sizeof(filename), fd) == NULL)

0 commit comments

Comments
 (0)