For some reason, /dev/net/tun is inaccessible to unprivileged processes in Puppy, and this breaks Podman. /dev/net is always 666 instead of 755, while /dev/net/tun itself is owned by root and 600 instead of 666.
The first problem is caused by this:
#130618 devtmpfs-enabled kernel, initrd may have loaded it on /dev #device nodes created by kernel in initrd are all 'root' group. #fix (before starting udevd)... chmod 666 /dev/* 2>/dev/null
This original author of this line probably meant to do that only for device nodes, and not for directories containing device nodes (which makes no sense). Therefore, the fix is:
#130618 devtmpfs-enabled kernel, initrd may have loaded it on /dev #device nodes created by kernel in initrd are all 'root' group. #fix (before starting udevd)... for DEV in /dev/*; do [ ! -d ${DEV} ] && chmod 666 ${DEV} 2>/dev/null; done <=
The second part of this problem is much harder to fix, because it's more than one problem. I use a kernel with CONFIG_TUN=y, almost identical to the Ubuntu 22.04 kernel, while all other Puppy kernels have CONFIG_TUN=m. Therefore, modprobe tun doesn't happen and the udev rule that changes /dev/net/tun to 666 doesn't get trigered. But why is this problem Puppy-specific, and doesn't affect Ubuntu 22.04 as well? After all, it's the same kernel and the same udev.
The answer, as usual, is systemd (or the lack of it). In other distros, this problem doesn't happen because systemd-tmpfiles --create --boot takes the "static device nodes" responsibility away from udev, and systemd-tmpfiles doesn't care if CONFIG_TUN=y. It obeys the instructions in static-nodes-permissions.conf, and runs in every boot.
ExecStart=systemd-tmpfiles --prefix=/dev --create --boot
systemd-tmpfiles-setup-dev.service, line 21
The line that matters to us here is this one:
z /dev/net/tun 0666 - - -
static-nodes-permissions.conf.in, line 15
systemd-tmpfiles supplements this list with the output of kmod static-nodes --format=tmpfiles, which adds other device nodes (and disagrees with static-nodes-permissions.conf about some permissions, but that's probably a story for another time):
ExecStart={{KMOD}} static-nodes --format=tmpfiles --output=/run/tmpfiles.d/static-nodes.conf
kmod-static-nodes.service.in, line 20
Puppy doesn't have systemd (and running systemd-tmpfiles in rc.sysinit is not an option), but Puppy *does* run kmod static-nodes --format=tmpfiles:
# -- from slackware's /etc/rc.d/rc.udev -- modded. kmod 14+ kmod static-nodes -f tmpfiles | \ while read F1 F2 F3 F4 F5 F6 F7 F8 ETC ; do case $F1 in "c!"*|"b!"*|"u!"*|"p!"*) ok=1 ;; *) continue ;; esac [ -z "$F7" ] && continue #precaution # mknod: /dev/net/tun: No such file or directory [ ! -d ${F2%/*} ] && mkdir -p -m $F3 ${F2%/*} # c! /dev/cuse 0600 - - - 10:203 mknod -m $F3 $F2 ${F1:0:1} ${F7%:*} ${F7#*:} 2>/dev/null #mknod -m 0600 /dev/cuse c 10 203 done
The output of kmod static-nodes -t tmpfiles is in the tmpfiles.d format, and this block is essentially a poor man's shell script version of systemd-tmpfiles --create --boot.
Therefore, the solution is to handle static-nodes-permissions.conf too:
# -- from slackware's /etc/rc.d/rc.udev -- modded. kmod 14+ ( kmod static-nodes -f tmpfiles cat /usr/lib/tmpfiles.d/static-nodes-permissions.conf 2>/dev/null <= ) | while read F1 F2 F3 F4 F5 F6 F7 F8 ETC ; do case $F1 in "c!"*|"b!"*|"u!"*|"p!"*) ok=1 ;; "z"*) chmod $F3 $F2 2>/dev/null ;; <= *) continue ;; esac [ -z "$F7" ] && continue #precaution # mknod: /dev/net/tun: No such file or directory [ ! -d ${F2%/*} ] && mkdir -p ${F2%/*} <= # c! /dev/cuse 0600 - - - 10:203 mknod -m $F3 $F2 ${F1:0:1} ${F7%:*} ${F7#*:} 2>/dev/null #mknod -m 0600 /dev/cuse c 10 203 done