Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 31c6e54

Browse files
committed
Secure Unix-domain sockets of "make check" temporary clusters.
Any OS user able to access the socket can connect as the bootstrap superuser and in turn execute arbitrary code as the OS user running the test. Protect against that by placing the socket in the temporary data directory, which has mode 0700 thanks to initdb. Back-patch to 8.4 (all supported versions). The hazard remains wherever the temporary cluster accepts TCP connections, notably on Windows. Attempts to run "make check" from a directory with a long name will now fail. An alternative not sharing that problem was to place the socket in a subdirectory of /tmp, but that is only secure if /tmp is sticky. The PG_REGRESS_SOCK_DIR environment variable is available as a workaround when testing from long directory paths. As a convenient side effect, this lets testing proceed smoothly in builds that override DEFAULT_PGSOCKET_DIR. Popular non-default values like /var/run/postgresql are often unwritable to the build user. Security: CVE-2014-0067
1 parent fbd32b0 commit 31c6e54

File tree

3 files changed

+48
-26
lines changed

3 files changed

+48
-26
lines changed

contrib/pg_upgrade/test.sh

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,6 @@ case $testhost in
2525
*) LISTEN_ADDRESSES="" ;;
2626
esac
2727

28-
POSTMASTER_OPTS="-F -c listen_addresses=$LISTEN_ADDRESSES"
29-
3028
temp_root=$PWD/tmp_check
3129

3230
if [ "$1" = '--install' ]; then
@@ -86,13 +84,16 @@ PGSERVICE=""; unset PGSERVICE
8684
PGSSLMODE=""; unset PGSSLMODE
8785
PGREQUIRESSL=""; unset PGREQUIRESSL
8886
PGCONNECT_TIMEOUT=""; unset PGCONNECT_TIMEOUT
89-
PGHOST=""; unset PGHOST
9087
PGHOSTADDR=""; unset PGHOSTADDR
9188

92-
# Select a non-conflicting port number, similarly to pg_regress.c
89+
# Select a port number and socket directory, similarly to pg_regress.c
9390
PG_VERSION_NUM=`grep '#define PG_VERSION_NUM' $newsrc/src/include/pg_config.h | awk '{print $3}'`
9491
PGPORT=`expr $PG_VERSION_NUM % 16384 + 49152`
9592
export PGPORT
93+
PGHOST=${PG_REGRESS_SOCK_DIR-$PGDATA}
94+
export PGHOST
95+
96+
POSTMASTER_OPTS="-F -c listen_addresses=$LISTEN_ADDRESSES -k \"$PGHOST\""
9697

9798
i=0
9899
while psql -X postgres </dev/null 2>/dev/null

doc/src/sgml/regress.sgml

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -58,21 +58,14 @@ make check
5858

5959
<warning>
6060
<para>
61-
This test method starts a temporary server, which is configured to accept
62-
any connection originating on the local machine. Any local user can gain
63-
database superuser privileges when connecting to this server, and could
64-
in principle exploit all privileges of the operating-system user running
65-
the tests. Therefore, it is not recommended that you use <literal>make
66-
check</> on machines shared with untrusted users. Instead, run the tests
67-
after completing the installation, as described in the next section.
68-
</para>
69-
70-
<para>
71-
On Unix-like machines, this danger can be avoided if the temporary
72-
server's socket file is made inaccessible to other users, for example
73-
by running the tests in a protected chroot. On Windows, the temporary
74-
server opens a locally-accessible TCP socket, so filesystem protections
75-
cannot help.
61+
On systems lacking Unix-domain sockets, notably Windows, this test method
62+
starts a temporary server configured to accept any connection originating
63+
on the local machine. Any local user can gain database superuser
64+
privileges when connecting to this server, and could in principle exploit
65+
all privileges of the operating-system user running the tests. Therefore,
66+
it is not recommended that you use <literal>make check</> on an affected
67+
system shared with untrusted users. Instead, run the tests after
68+
completing the installation, as described in the next section.
7669
</para>
7770
</warning>
7871

@@ -111,6 +104,17 @@ make MAX_CONNECTIONS=10 check
111104
</screen>
112105
runs no more than ten tests concurrently.
113106
</para>
107+
108+
<para>
109+
To protect your operating system user account, the test driver places the
110+
server's socket in a relative subdirectory inaccessible to other users.
111+
Since most systems constrain the length of socket paths well
112+
below <literal>_POSIX_PATH_MAX</>, testing may fail to start from a
113+
directory with a long name. Work around this problem by pointing
114+
the <envar>PG_REGRESS_SOCK_DIR</> environment variable to a substitute
115+
socket directory having a shorter path. On a multi-user system, give that
116+
directory mode <literal>0700</>.
117+
</para>
114118
</sect2>
115119

116120
<sect2>

src/test/regress/pg_regress.c

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ static const char *progname;
109109
static char *logfilename;
110110
static FILE *logfile;
111111
static char *difffilename;
112+
static char *sockdir;
112113

113114
static _resultmap *resultmap = NULL;
114115

@@ -758,8 +759,7 @@ initialize_environment(void)
758759
* the wrong postmaster, or otherwise behave in nondefault ways. (Note
759760
* we also use psql's -X switch consistently, so that ~/.psqlrc files
760761
* won't mess things up.) Also, set PGPORT to the temp port, and set
761-
* or unset PGHOST depending on whether we are using TCP or Unix
762-
* sockets.
762+
* PGHOST depending on whether we are using TCP or Unix sockets.
763763
*/
764764
unsetenv("PGDATABASE");
765765
unsetenv("PGUSER");
@@ -771,7 +771,23 @@ initialize_environment(void)
771771
if (hostname != NULL)
772772
doputenv("PGHOST", hostname);
773773
else
774-
unsetenv("PGHOST");
774+
{
775+
sockdir = getenv("PG_REGRESS_SOCK_DIR");
776+
if (!sockdir)
777+
{
778+
/*
779+
* Since initdb creates the data directory with secure
780+
* permissions, we place the socket there. This ensures no
781+
* other OS user can open our socket to exploit our use of
782+
* trust authentication. Compared to using the compiled-in
783+
* DEFAULT_PGSOCKET_DIR, this also permits testing to work in
784+
* builds that relocate it to a directory not writable to the
785+
* build/test user.
786+
*/
787+
sockdir = psprintf("%s/data", temp_install);
788+
}
789+
doputenv("PGHOST", sockdir);
790+
}
775791
unsetenv("PGHOSTADDR");
776792
if (port != -1)
777793
{
@@ -2265,10 +2281,11 @@ regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc
22652281
*/
22662282
header(_("starting postmaster"));
22672283
snprintf(buf, sizeof(buf),
2268-
SYSTEMQUOTE "\"%s/postgres\" -D \"%s/data\" -F%s -c \"listen_addresses=%s\" > \"%s/log/postmaster.log\" 2>&1" SYSTEMQUOTE,
2269-
bindir, temp_install,
2270-
debug ? " -d 5" : "",
2271-
hostname ? hostname : "",
2284+
SYSTEMQUOTE "\"%s/postgres\" -D \"%s/data\" -F%s "
2285+
"-c \"listen_addresses=%s\" -k \"%s\" "
2286+
"> \"%s/log/postmaster.log\" 2>&1" SYSTEMQUOTE,
2287+
bindir, temp_install, debug ? " -d 5" : "",
2288+
hostname ? hostname : "", sockdir ? sockdir : "",
22722289
outputdir);
22732290
postmaster_pid = spawn_process(buf);
22742291
if (postmaster_pid == INVALID_PID)

0 commit comments

Comments
 (0)