Skip to content

Commit c9b0cbe

Browse files
committed
Support having multiple Unix-domain sockets per postmaster.
Replace unix_socket_directory with unix_socket_directories, which is a list of socket directories, and adjust postmaster's code to allow zero or more Unix-domain sockets to be created. This is mostly a straightforward change, but since the Unix sockets ought to be created after the TCP/IP sockets for safety reasons (better chance of detecting a port number conflict), AddToDataDirLockFile needs to be fixed to support out-of-order updates of data directory lockfile lines. That's a change that had been foreseen to be necessary someday anyway. Honza Horak, reviewed and revised by Tom Lane
1 parent 85642ec commit c9b0cbe

File tree

17 files changed

+369
-126
lines changed

17 files changed

+369
-126
lines changed

doc/src/sgml/client-auth.sgml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -838,7 +838,7 @@ omicron bryanh guest1
838838
<varname>unix_socket_permissions</varname> (and possibly
839839
<varname>unix_socket_group</varname>) configuration parameters as
840840
described in <xref linkend="runtime-config-connection">. Or you
841-
could set the <varname>unix_socket_directory</varname>
841+
could set the <varname>unix_socket_directories</varname>
842842
configuration parameter to place the socket file in a suitably
843843
restricted directory.
844844
</para>

doc/src/sgml/config.sgml

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -445,17 +445,24 @@ SET ENABLE_SEQSCAN TO OFF;
445445
</listitem>
446446
</varlistentry>
447447

448-
<varlistentry id="guc-unix-socket-directory" xreflabel="unix_socket_directory">
449-
<term><varname>unix_socket_directory</varname> (<type>string</type>)</term>
448+
<varlistentry id="guc-unix-socket-directories" xreflabel="unix_socket_directories">
449+
<term><varname>unix_socket_directories</varname> (<type>string</type>)</term>
450450
<indexterm>
451-
<primary><varname>unix_socket_directory</> configuration parameter</primary>
451+
<primary><varname>unix_socket_directories</> configuration parameter</primary>
452452
</indexterm>
453453
<listitem>
454454
<para>
455-
Specifies the directory of the Unix-domain socket on which the
456-
server is to listen for
457-
connections from client applications. The default is normally
458-
<filename>/tmp</filename>, but can be changed at build time.
455+
Specifies the directory of the Unix-domain socket(s) on which the
456+
server is to listen for connections from client applications.
457+
Multiple sockets can be created by listing multiple directories
458+
separated by commas. Whitespace between entries is
459+
ignored; surround a directory name with double quotes if you need
460+
to include whitespace or commas in the name.
461+
An empty value
462+
specifies not listening on any Unix-domain sockets, in which case
463+
only TCP/IP sockets can be used to connect to the server.
464+
The default value is normally
465+
<filename>/tmp</filename>, but that can be changed at build time.
459466
This parameter can only be set at server start.
460467
</para>
461468

@@ -464,8 +471,8 @@ SET ENABLE_SEQSCAN TO OFF;
464471
<literal>.s.PGSQL.<replaceable>nnnn</></literal> where
465472
<replaceable>nnnn</> is the server's port number, an ordinary file
466473
named <literal>.s.PGSQL.<replaceable>nnnn</>.lock</literal> will be
467-
created in the <varname>unix_socket_directory</> directory. Neither
468-
file should ever be removed manually.
474+
created in each of the <varname>unix_socket_directories</> directories.
475+
Neither file should ever be removed manually.
469476
</para>
470477

471478
<para>
@@ -482,8 +489,8 @@ SET ENABLE_SEQSCAN TO OFF;
482489
</indexterm>
483490
<listitem>
484491
<para>
485-
Sets the owning group of the Unix-domain socket. (The owning
486-
user of the socket is always the user that starts the
492+
Sets the owning group of the Unix-domain socket(s). (The owning
493+
user of the sockets is always the user that starts the
487494
server.) In combination with the parameter
488495
<varname>unix_socket_permissions</varname> this can be used as
489496
an additional access control mechanism for Unix-domain connections.
@@ -506,7 +513,7 @@ SET ENABLE_SEQSCAN TO OFF;
506513
</indexterm>
507514
<listitem>
508515
<para>
509-
Sets the access permissions of the Unix-domain socket. Unix-domain
516+
Sets the access permissions of the Unix-domain socket(s). Unix-domain
510517
sockets use the usual Unix file system permission set.
511518
The parameter value is expected to be a numeric mode
512519
specified in the format accepted by the
@@ -1852,7 +1859,7 @@ SET ENABLE_SEQSCAN TO OFF;
18521859
<varname>commit_delay</varname> behaved differently and was much
18531860
less effective: it affected only commits, rather than all WAL flushes,
18541861
and waited for the entire configured delay even if the WAL flush
1855-
was completed sooner. Beginning in <productname>PostgreSQL</> 9.3,
1862+
was completed sooner. Beginning in <productname>PostgreSQL</> 9.3,
18561863
the first process that becomes ready to flush waits for the configured
18571864
interval, while subsequent processes wait only until the leader
18581865
completes the flush. The default <varname>commit_delay</> is zero
@@ -6556,7 +6563,7 @@ LOG: CleanUpLock: deleting: lock(0xb7acd844) id(24688,24696,0,0,0,1)
65566563
</row>
65576564
<row>
65586565
<entry><option>-k <replaceable>x</replaceable></option></entry>
6559-
<entry><literal>unix_socket_directory = <replaceable>x</replaceable></></entry>
6566+
<entry><literal>unix_socket_directories = <replaceable>x</replaceable></></entry>
65606567
</row>
65616568
<row>
65626569
<entry><option>-l</option></entry>

doc/src/sgml/ref/postgres-ref.sgml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -254,8 +254,14 @@ PostgreSQL documentation
254254
<para>
255255
Specifies the directory of the Unix-domain socket on which
256256
<command>postgres</command> is to listen for
257-
connections from client applications. The default is normally
258-
<filename>/tmp</filename>, but can be changed at build time.
257+
connections from client applications. The value can also be a
258+
comma-separated list of directories. An empty value
259+
specifies not listening on any Unix-domain sockets, in which case
260+
only TCP/IP sockets can be used to connect to the server.
261+
The default value is normally
262+
<filename>/tmp</filename>, but that can be changed at build time.
263+
Specifying this option is equivalent to setting the <xref
264+
linkend="guc-unix-socket-directories"> configuration parameter.
259265
</para>
260266
</listitem>
261267
</varlistentry>

doc/src/sgml/runtime.sgml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1718,7 +1718,7 @@ pg_dumpall -p 5432 | psql -d postgres -p 5433
17181718
<para>
17191719
The simplest way to prevent spoofing for <literal>local</>
17201720
connections is to use a Unix domain socket directory (<xref
1721-
linkend="guc-unix-socket-directory">) that has write permission only
1721+
linkend="guc-unix-socket-directories">) that has write permission only
17221722
for a trusted local user. This prevents a malicious user from creating
17231723
their own socket file in that directory. If you are concerned that
17241724
some applications might still reference <filename>/tmp</> for the

src/backend/libpq/pqcomm.c

Lines changed: 61 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
* StreamServerPort - Open postmaster's server port
4343
* StreamConnection - Create new connection with client
4444
* StreamClose - Close a client/backend connection
45-
* TouchSocketFile - Protect socket file against /tmp cleaners
45+
* TouchSocketFiles - Protect socket files against /tmp cleaners
4646
* pq_init - initialize libpq at backend startup
4747
* pq_comm_reset - reset libpq during error recovery
4848
* pq_close - shutdown libpq at backend exit
@@ -103,8 +103,8 @@ int Unix_socket_permissions;
103103
char *Unix_socket_group;
104104

105105

106-
/* Where the Unix socket file is */
107-
static char sock_path[MAXPGPATH];
106+
/* Where the Unix socket files are (list of palloc'd strings) */
107+
static List *sock_paths = NIL;
108108

109109

110110
/*
@@ -140,8 +140,8 @@ static int internal_flush(void);
140140
static void pq_set_nonblocking(bool nonblocking);
141141

142142
#ifdef HAVE_UNIX_SOCKETS
143-
static int Lock_AF_UNIX(unsigned short portNumber, char *unixSocketName);
144-
static int Setup_AF_UNIX(void);
143+
static int Lock_AF_UNIX(char *unixSocketDir, char *unixSocketPath);
144+
static int Setup_AF_UNIX(char *sock_path);
145145
#endif /* HAVE_UNIX_SOCKETS */
146146

147147

@@ -234,29 +234,43 @@ pq_close(int code, Datum arg)
234234

235235
/* StreamDoUnlink()
236236
* Shutdown routine for backend connection
237-
* If a Unix socket is used for communication, explicitly close it.
237+
* If any Unix sockets are used for communication, explicitly close them.
238238
*/
239239
#ifdef HAVE_UNIX_SOCKETS
240240
static void
241241
StreamDoUnlink(int code, Datum arg)
242242
{
243-
Assert(sock_path[0]);
244-
unlink(sock_path);
243+
ListCell *l;
244+
245+
/* Loop through all created sockets... */
246+
foreach(l, sock_paths)
247+
{
248+
char *sock_path = (char *) lfirst(l);
249+
250+
unlink(sock_path);
251+
}
252+
/* Since we're about to exit, no need to reclaim storage */
253+
sock_paths = NIL;
245254
}
246255
#endif /* HAVE_UNIX_SOCKETS */
247256

248257
/*
249258
* StreamServerPort -- open a "listening" port to accept connections.
250259
*
251-
* Successfully opened sockets are added to the ListenSocket[] array,
252-
* at the first position that isn't PGINVALID_SOCKET.
260+
* family should be AF_UNIX or AF_UNSPEC; portNumber is the port number.
261+
* For AF_UNIX ports, hostName should be NULL and unixSocketDir must be
262+
* specified. For TCP ports, hostName is either NULL for all interfaces or
263+
* the interface to listen on, and unixSocketDir is ignored (can be NULL).
264+
*
265+
* Successfully opened sockets are added to the ListenSocket[] array (of
266+
* length MaxListen), at the first position that isn't PGINVALID_SOCKET.
253267
*
254268
* RETURNS: STATUS_OK or STATUS_ERROR
255269
*/
256270

257271
int
258272
StreamServerPort(int family, char *hostName, unsigned short portNumber,
259-
char *unixSocketName,
273+
char *unixSocketDir,
260274
pgsocket ListenSocket[], int MaxListen)
261275
{
262276
pgsocket fd;
@@ -273,6 +287,9 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber,
273287
int listen_index = 0;
274288
int added = 0;
275289

290+
#ifdef HAVE_UNIX_SOCKETS
291+
char unixSocketPath[MAXPGPATH];
292+
#endif
276293
#if !defined(WIN32) || defined(IPV6_V6ONLY)
277294
int one = 1;
278295
#endif
@@ -286,10 +303,14 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber,
286303
#ifdef HAVE_UNIX_SOCKETS
287304
if (family == AF_UNIX)
288305
{
289-
/* Lock_AF_UNIX will also fill in sock_path. */
290-
if (Lock_AF_UNIX(portNumber, unixSocketName) != STATUS_OK)
306+
/*
307+
* Create unixSocketPath from portNumber and unixSocketDir and lock
308+
* that file path
309+
*/
310+
UNIXSOCK_PATH(unixSocketPath, portNumber, unixSocketDir);
311+
if (Lock_AF_UNIX(unixSocketDir, unixSocketPath) != STATUS_OK)
291312
return STATUS_ERROR;
292-
service = sock_path;
313+
service = unixSocketPath;
293314
}
294315
else
295316
#endif /* HAVE_UNIX_SOCKETS */
@@ -432,7 +453,7 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber,
432453
(IS_AF_UNIX(addr->ai_family)) ?
433454
errhint("Is another postmaster already running on port %d?"
434455
" If not, remove socket file \"%s\" and retry.",
435-
(int) portNumber, sock_path) :
456+
(int) portNumber, service) :
436457
errhint("Is another postmaster already running on port %d?"
437458
" If not, wait a few seconds and retry.",
438459
(int) portNumber)));
@@ -443,7 +464,7 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber,
443464
#ifdef HAVE_UNIX_SOCKETS
444465
if (addr->ai_family == AF_UNIX)
445466
{
446-
if (Setup_AF_UNIX() != STATUS_OK)
467+
if (Setup_AF_UNIX(service) != STATUS_OK)
447468
{
448469
closesocket(fd);
449470
break;
@@ -490,10 +511,8 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber,
490511
* Lock_AF_UNIX -- configure unix socket file path
491512
*/
492513
static int
493-
Lock_AF_UNIX(unsigned short portNumber, char *unixSocketName)
514+
Lock_AF_UNIX(char *unixSocketDir, char *unixSocketPath)
494515
{
495-
UNIXSOCK_PATH(sock_path, portNumber, unixSocketName);
496-
497516
/*
498517
* Grab an interlock file associated with the socket file.
499518
*
@@ -502,13 +521,23 @@ Lock_AF_UNIX(unsigned short portNumber, char *unixSocketName)
502521
* more portable, and second, it lets us remove any pre-existing socket
503522
* file without race conditions.
504523
*/
505-
CreateSocketLockFile(sock_path, true);
524+
CreateSocketLockFile(unixSocketPath, true, unixSocketDir);
506525

507526
/*
508527
* Once we have the interlock, we can safely delete any pre-existing
509528
* socket file to avoid failure at bind() time.
510529
*/
511-
unlink(sock_path);
530+
unlink(unixSocketPath);
531+
532+
/*
533+
* Arrange to unlink the socket file(s) at proc_exit. If this is the
534+
* first one, set up the on_proc_exit function to do it; then add this
535+
* socket file to the list of files to unlink.
536+
*/
537+
if (sock_paths == NIL)
538+
on_proc_exit(StreamDoUnlink, 0);
539+
540+
sock_paths = lappend(sock_paths, pstrdup(unixSocketPath));
512541

513542
return STATUS_OK;
514543
}
@@ -518,11 +547,8 @@ Lock_AF_UNIX(unsigned short portNumber, char *unixSocketName)
518547
* Setup_AF_UNIX -- configure unix socket permissions
519548
*/
520549
static int
521-
Setup_AF_UNIX(void)
550+
Setup_AF_UNIX(char *sock_path)
522551
{
523-
/* Arrange to unlink the socket file at exit */
524-
on_proc_exit(StreamDoUnlink, 0);
525-
526552
/*
527553
* Fix socket ownership/permission if requested. Note we must do this
528554
* before we listen() to avoid a window where unwanted connections could
@@ -704,20 +730,24 @@ StreamClose(pgsocket sock)
704730
}
705731

706732
/*
707-
* TouchSocketFile -- mark socket file as recently accessed
733+
* TouchSocketFiles -- mark socket files as recently accessed
708734
*
709735
* This routine should be called every so often to ensure that the socket
710-
* file has a recent mod date (ordinary operations on sockets usually won't
711-
* change the mod date). That saves it from being removed by
736+
* files have a recent mod date (ordinary operations on sockets usually won't
737+
* change the mod date). That saves them from being removed by
712738
* overenthusiastic /tmp-directory-cleaner daemons. (Another reason we should
713739
* never have put the socket file in /tmp...)
714740
*/
715741
void
716-
TouchSocketFile(void)
742+
TouchSocketFiles(void)
717743
{
718-
/* Do nothing if we did not create a socket... */
719-
if (sock_path[0] != '\0')
744+
ListCell *l;
745+
746+
/* Loop through all created sockets... */
747+
foreach(l, sock_paths)
720748
{
749+
char *sock_path = (char *) lfirst(l);
750+
721751
/*
722752
* utime() is POSIX standard, utimes() is a common alternative. If we
723753
* have neither, there's no way to affect the mod or access time of

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy