Package: udev
Followup-For: Bug #1140336

Control: tags 1140336 + patch

Hi Benjamin,

I ran into the same issue with sbuild --unshare and /dev/kvm bind-mounted.

The failure is caused by dh_installtmpfiles in debhelper 14 removing the '|| 
true' fallback from the udev.postinst snippet. When setting permissions on 
static device nodes in unprivileged namespaces, fchownat() returns EPERM and 
systemd-tmpfiles aborts with exit code 73.

Attached is a patch that:
1. Treats ERRNO_IS_PRIVILEGE (EPERM, EACCES) as non-fatal debug in 
fd_set_perms() on character and block devices.
2. Changes the action prefix from 'z' to 'z-' in 
static-nodes-permissions.conf.in so permission errors are tolerated on static 
device nodes.

Also tracked in Ubuntu LP: #2160036:
https://bugs.launchpad.net/ubuntu/+source/systemd/+bug/2160036

-- 
Viktor Pashaiev
<[email protected]>
Description: tmpfiles: ignore privilege errors on device nodes
 In unprivileged containers or namespaces with bind-mounted device nodes,
 adjusting ownership or permissions on device nodes returns EPERM.
 Ignore privilege errors on device nodes in fd_set_perms() and mark
 static-nodes-permissions.conf entries with z- so failure is tolerated.
Author: Viktor Pashaiev <[email protected]>
Bug-Debian: https://bugs.debian.org/1140336
Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/systemd/+bug/2160036
Forwarded: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1140336
Last-Update: 2026-10-07

Index: systemd-261.3/src/tmpfiles/tmpfiles.c
===================================================================
--- systemd-261.3.orig/src/tmpfiles/tmpfiles.c
+++ systemd-261.3/src/tmpfiles/tmpfiles.c
@@ -1017,8 +1017,14 @@ static int fd_set_perms(
                                            "%s \"%s\" to mode %o", path, m);
                                 if (!arg_dry_run) {
                                         r = fchmod_opath(fd, m);
-                                        if (r < 0)
-                                                return log_error_errno(r, "fchmod() of %s failed: %m", path);
+                                        if (r < 0) {
+                                                if ((S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) && ERRNO_IS_PRIVILEGE(r))
+                                                        log_debug_errno(r, "Lacking privilege to temporarily chmod device node %s, skipping: %m", path);
+                                                else if (i->allow_failure)
+                                                        log_debug_errno(r, "fchmod() of %s failed, ignoring: %m", path);
+                                                else
+                                                        return log_error_errno(r, "fchmod() of %s failed: %m", path);
+                                        }
                                 }
                         }
                 }
@@ -1032,8 +1038,14 @@ static int fd_set_perms(
                     fchownat(fd, "",
                              new_uid != st->st_uid ? new_uid : UID_INVALID,
                              new_gid != st->st_gid ? new_gid : GID_INVALID,
-                             AT_EMPTY_PATH) < 0)
-                        return log_error_errno(errno, "fchownat() of %s failed: %m", path);
+                             AT_EMPTY_PATH) < 0) {
+                        if ((S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) && ERRNO_IS_PRIVILEGE(errno))
+                                log_debug_errno(errno, "Lacking privilege to chown device node %s, skipping: %m", path);
+                        else if (i->allow_failure)
+                                log_debug_errno(errno, "fchownat() of %s failed, ignoring: %m", path);
+                        else
+                                return log_error_errno(errno, "fchownat() of %s failed: %m", path);
+                }
         }
 
         /* Now, apply the final mode. We do this in two cases: when the user set a mode explicitly, or after a
@@ -1045,8 +1057,14 @@ static int fd_set_perms(
                         log_action("Would change", "Changing", "%s \"%s\" to mode %o", path, new_mode);
                         if (!arg_dry_run) {
                                 r = fchmod_opath(fd, new_mode);
-                                if (r < 0)
-                                        return log_error_errno(r, "fchmod() of %s failed: %m", path);
+                                if (r < 0) {
+                                        if ((S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) && ERRNO_IS_PRIVILEGE(r))
+                                                log_debug_errno(r, "Lacking privilege to chmod device node %s, skipping: %m", path);
+                                        else if (i->allow_failure)
+                                                log_debug_errno(r, "fchmod() of %s failed, ignoring: %m", path);
+                                        else
+                                                return log_error_errno(r, "fchmod() of %s failed: %m", path);
+                                }
                         }
                 }
         }
Index: systemd-261.3/tmpfiles.d/static-nodes-permissions.conf.in
===================================================================
--- systemd-261.3.orig/tmpfiles.d/static-nodes-permissions.conf.in
+++ systemd-261.3/tmpfiles.d/static-nodes-permissions.conf.in
@@ -9,12 +9,12 @@
 # kmod-static-nodes.service. Rules specified here should match the
 # permissions specified for udev in 50-udev-default.rules.
 
-z /dev/snd/seq      0660 - audio -
-z /dev/snd/timer    0660 - audio -
-z /dev/loop-control 0660 - disk  -
-z /dev/net/tun      0666 - -     -
-z /dev/fuse         0666 - -     -
-z /dev/vfio/vfio    0666 - -     -
-z /dev/kvm          {{DEV_KVM_MODE}} - kvm -
-z /dev/vhost-net    {{DEV_KVM_MODE}} - kvm -
-z /dev/vhost-vsock  {{DEV_KVM_MODE}} - kvm -
+z- /dev/snd/seq      0660 - audio -
+z- /dev/snd/timer    0660 - audio -
+z- /dev/loop-control 0660 - disk  -
+z- /dev/net/tun      0666 - -     -
+z- /dev/fuse         0666 - -     -
+z- /dev/vfio/vfio    0666 - -     -
+z- /dev/kvm          {{DEV_KVM_MODE}} - kvm -
+z- /dev/vhost-net    {{DEV_KVM_MODE}} - kvm -
+z- /dev/vhost-vsock  {{DEV_KVM_MODE}} - kvm -

Reply via email to