diff --git a/man/systemd.socket.xml b/man/systemd.socket.xml
index e9fd39bf7f..bbcd7f051a 100644
--- a/man/systemd.socket.xml
+++ b/man/systemd.socket.xml
@@ -375,7 +375,7 @@
SocketGroup=
Takes a UNIX user/group name. When specified, all AF_UNIX
- 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.
@@ -385,10 +385,9 @@
SocketMode=
- 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.
+ 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.
diff --git a/src/core/socket.c b/src/core/socket.c
index 8519aefa68..fce50e28e4 100644
--- a/src/core/socket.c
+++ b/src/core/socket.c
@@ -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
index 0000000000..19116d19d1
--- /dev/null
+++ b/test/units/TEST-07-PID1.mqueue-ownership.sh
@@ -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" ]]