socket: support setting ownership of message queues

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.
This commit is contained in:
David Michael 2024-10-25 10:45:44 -04:00 committed by Lennart Poettering
parent 2b7a56d286
commit 3eec82f6b3
3 changed files with 58 additions and 5 deletions

View File

@ -375,7 +375,7 @@
<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>
@ -385,10 +385,9 @@
<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>

View 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;

View File

@ -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" ]]