]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
socket: support setting ownership of message queues
authorDavid Michael <dmichael@owlcyberdefense.com>
Fri, 25 Oct 2024 14:45:44 +0000 (10:45 -0400)
committerLennart Poettering <lennart@poettering.net>
Mon, 28 Oct 2024 22:40:42 +0000 (23:40 +0100)
This applies the existing SocketUser=/SocketGroup= options to units
defining a POSIX message queue, bringing them in line with UNIX
sockets and FIFOs.  They are set on the file descriptor rather than
a file system path because the /dev/mqueue path interface is an
optional mount unit.

man/systemd.socket.xml
src/core/socket.c
test/units/TEST-07-PID1.mqueue-ownership.sh [new file with mode: 0755]

index e9fd39bf7f2485156523209810065ae77d7d909b..bbcd7f051a362309e15268644d9ab43b963c95e6 100644 (file)
         <term><varname>SocketGroup=</varname></term>
 
         <listitem><para>Takes a UNIX user/group name. When specified, all <constant>AF_UNIX</constant>
-        sockets and FIFO nodes in the file system are owned by the specified user and group. If unset (the
+        sockets, FIFO nodes, and message queues are owned by the specified user and group. If unset (the
         default), the nodes are owned by the root user/group (if run in system context) or the invoking
         user/group (if run in user context).  If only a user is specified but no group, then the group is
         derived from the user's default group.</para>
 
       <varlistentry>
         <term><varname>SocketMode=</varname></term>
-        <listitem><para>If listening on a file system socket or FIFO,
-        this option specifies the file system access mode used when
-        creating the file node. Takes an access mode in octal
-        notation. Defaults to 0666.</para></listitem>
+        <listitem><para>If listening on a file system socket, FIFO, or message queue, this option specifies
+        the file system access mode used when creating the file node. Takes an access mode in octal notation.
+        Defaults to 0666.</para></listitem>
       </varlistentry>
 
       <varlistentry>
index 8519aefa68916c5f32d21f4678f5468adac1307d..fce50e28e4fcb3525ca86a7bfd612420e064b2a7 100644 (file)
@@ -2024,6 +2024,14 @@ static int socket_chown(Socket *s, PidRef *ret_pid) {
                                 path = socket_address_get_path(&p->address);
                         else if (p->type == SOCKET_FIFO)
                                 path = p->path;
+                        else if (p->type == SOCKET_MQUEUE) {
+                                /* Use fchown on the fd since /dev/mqueue might not be mounted. */
+                                if (fchown(p->fd, uid, gid) < 0) {
+                                        log_unit_error_errno(UNIT(s), errno, "Failed to fchown(): %m");
+                                        _exit(EXIT_CHOWN);
+                                }
+                                continue;
+                        }
 
                         if (!path)
                                 continue;
diff --git a/test/units/TEST-07-PID1.mqueue-ownership.sh b/test/units/TEST-07-PID1.mqueue-ownership.sh
new file mode 100755 (executable)
index 0000000..19116d1
--- /dev/null
@@ -0,0 +1,46 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: LGPL-2.1-or-later
+set -eux
+set -o pipefail
+
+# Verify ownership attributes are applied to message queues
+
+# Select arbitrary non-default attributes to apply to the queue.
+queue=/attr_q  # Pick any unused queue name.
+user=nobody  # Choose a core system user.
+group=adm  # Choose a core system group.
+mode=0420  # Allow the owner to read messages and anyone in the group to write.
+
+at_exit() {
+    set +e
+    systemctl stop mqueue-ownership.{service,socket}
+    rm -f /run/systemd/system/mqueue-ownership.{service,socket}
+    systemctl daemon-reload
+}
+trap at_exit EXIT
+
+cat << EOF > /run/systemd/system/mqueue-ownership.socket
+[Unit]
+Description=Create a message queue with customized ownership
+[Socket]
+ListenMessageQueue=/${queue#/}
+RemoveOnStop=true
+SocketUser=$user
+SocketGroup=$group
+SocketMode=$mode
+EOF
+
+cat << 'EOF' > /run/systemd/system/mqueue-ownership.service
+[Unit]
+Description=Dummy service for the socket unit
+Requires=%N.socket
+[Service]
+ExecStart=/usr/bin/true
+Type=oneshot
+EOF
+
+systemctl daemon-reload
+systemctl start mqueue-ownership.socket
+
+systemctl start dev-mqueue.mount  # Ensure this file path interface is mounted.
+[[ $(stat -c '%04a %U %G' "/dev/mqueue/${queue#/}") == "$mode $user $group" ]]