]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core: populate $REMOTE_ADDR for AF_UNIX sockets
authorKamil Szczęk <kamil@szczek.dev>
Mon, 3 Jun 2024 15:56:42 +0000 (17:56 +0200)
committerLuca Boccassi <luca.boccassi@gmail.com>
Tue, 11 Jun 2024 23:11:10 +0000 (00:11 +0100)
Set the $REMOTE_ADDR environment variable for AF_UNIX socket connections
when using per-connection socket activation (Accept=yes). $REMOTE_ADDR
will now contain the remote socket's file system path (starting with a
slash "/") or its address in the abstract namespace (starting with an
at symbol "@").

This information is essential for identifying the remote peer in AF_UNIX
socket connections, but it's not easy to obtain in a shell script for
example without pulling in a ton of additional tools. By setting
$REMOTE_ADDR, we make this information readily available to the
activated service.

man/systemd.exec.xml
man/systemd.socket.xml
src/core/service.c

index 56eb6af8728c91d7c5b77e7f633979e11b1ad48d..49099b2ee9773b8b272c498cf01ec0078986ae04 100644 (file)
@@ -4101,8 +4101,17 @@ StandardInputData=V2XigLJyZSBubyBzdHJhbmdlcnMgdG8gbG92ZQpZb3Uga25vdyB0aGUgcnVsZX
           <term><varname>$REMOTE_PORT</varname></term>
 
           <listitem><para>If this is a unit started via per-connection socket activation (i.e. via a socket
-          unit with <varname>Accept=yes</varname>), these environment variables contain the IP address and
-          port number of the remote peer of the socket connection.</para>
+          unit with <varname>Accept=yes</varname>), these environment variables contain information about the
+          remote peer of the socket connection.</para>
+
+          <para>For IPv4 and IPv6 connections, <varname>$REMOTE_ADDR</varname> contains the IP address, and
+          <varname>$REMOTE_PORT</varname> contains the port number of the remote peer.</para>
+
+          <para>For <constant>AF_UNIX</constant> socket connections, <varname>$REMOTE_ADDR</varname> contains
+          either the remote socket's file system path starting with a slash (<literal>/</literal>), its
+          address in the abstract namespace starting with an at symbol (<literal>@</literal>), or is unset
+          in case of an unnamed socket. <varname>$REMOTE_PORT</varname> is not set for <constant>AF_UNIX</constant>
+          sockets.</para>
 
           <xi:include href="version-info.xml" xpointer="v254"/></listitem>
         </varlistentry>
index a944efad3bd71d9d4af90fc5a866fe6ba942ca7c..aa0e661002afcab7538243eb51fc49778d40de9e 100644 (file)
         services (in case of <varname>Accept=</varname><option>yes</option>). See the Description section
         above for a more detailed discussion of the naming rules of triggered services.</para>
 
-        <para>For IPv4 and IPv6 connections, the <varname>REMOTE_ADDR</varname> environment variable will
-        contain the remote IP address, and <varname>REMOTE_PORT</varname> will contain the remote port. This
+        <para>For IPv4 and IPv6 connections, the <varname>$REMOTE_ADDR</varname> environment variable will
+        contain the remote IP address, and <varname>$REMOTE_PORT</varname> will contain the remote port. This
         is the same as the format used by CGI. For <constant>SOCK_RAW</constant>, the port is the IP
         protocol.</para>
 
+        <para>For <constant>AF_UNIX</constant> socket connections, the <varname>$REMOTE_ADDR</varname>
+        environment variable will contain either the remote socket's file system path starting with a slash
+        (<literal>/</literal>) or its address in the abstract namespace starting with an at symbol
+        (<literal>@</literal>). If the socket is unnamed, <varname>$REMOTE_ADDR</varname> won't be set.</para>
+
         <para>It is recommended to set <varname>CollectMode=inactive-or-failed</varname> for service
         instances activated via <varname>Accept=yes</varname>, to ensure that failed connection services are
         cleaned up and released from memory, and do not accumulate.</para></listitem>
index 8ec27c463a4d8ee0f076223bb80e42d5b98ed0af..3d27db0272f6c85a74211072ba70d15dd1cb8cb1 100644 (file)
@@ -1723,27 +1723,32 @@ static int service_spawn_internal(
                  * in ENOTCONN), and just use whate we can use. */
 
                 if (getpeername(s->socket_fd, &sa.sa, &salen) >= 0 &&
-                    IN_SET(sa.sa.sa_family, AF_INET, AF_INET6, AF_VSOCK)) {
+                    IN_SET(sa.sa.sa_family, AF_INET, AF_INET6, AF_VSOCK, AF_UNIX)) {
                         _cleanup_free_ char *addr = NULL;
                         char *t;
-                        unsigned port;
 
-                        r = sockaddr_pretty(&sa.sa, salen, true, false, &addr);
+                        r = sockaddr_pretty(&sa.sa, salen, /* translate_ipv6= */ true, /* include_port= */ false, &addr);
                         if (r < 0)
                                 return r;
 
-                        t = strjoin("REMOTE_ADDR=", addr);
-                        if (!t)
-                                return -ENOMEM;
-                        our_env[n_env++] = t;
+                        if (sa.sa.sa_family != AF_UNIX || IN_SET(addr[0], '/', '@')) {
+                                t = strjoin("REMOTE_ADDR=", addr);
+                                if (!t)
+                                        return -ENOMEM;
+                                our_env[n_env++] = t;
+                        }
 
-                        r = sockaddr_port(&sa.sa, &port);
-                        if (r < 0)
-                                return r;
+                        if (IN_SET(sa.sa.sa_family, AF_INET, AF_INET6, AF_VSOCK)) {
+                                unsigned port;
 
-                        if (asprintf(&t, "REMOTE_PORT=%u", port) < 0)
-                                return -ENOMEM;
-                        our_env[n_env++] = t;
+                                r = sockaddr_port(&sa.sa, &port);
+                                if (r < 0)
+                                        return r;
+
+                                if (asprintf(&t, "REMOTE_PORT=%u", port) < 0)
+                                        return -ENOMEM;
+                                our_env[n_env++] = t;
+                        }
                 }
         }