Index | Thread | Search

From:
Andrew Hewus Fresh <afresh1@openbsd.org>
Subject:
Earlier /tmp cleanup in /etc/rc
To:
tech@openbsd.org
Date:
Mon, 24 Aug 2026 11:30:42 -0700

Download raw body.

Thread
  • Andrew Hewus Fresh:

    Earlier /tmp cleanup in /etc/rc

With the recent adjustments to clean up /tmp asynchronously, deraadt and
others noticed an existing race that some of the relinking and early
daemons using /tmp while it was being cleaned.

This patch solves those known problems and possibly some unknown (trying
to ktrace the startup affects things) by moving /tmp mounting and
cleanup before any async processes that would potentially access /tmp,
making the cleanup safer.

The interaction with find, rm, and flushing is a bit weird, so many of
30+ email in this solution were finding the correct incantation to make
`find -exec rm | head` delete the expected number of entries, but ended
up with a more reliable and easier to read solution.

I was also reminded that we are not on the install media and we have
access to more reasonable tools and so can avoid the confusing `sh -c`
and instead use xargs to make find and mv cooperate.


Index: rc
===================================================================
RCS file: /cvs/src/etc/rc,v
diff -u -p -r1.590 rc
--- rc	17 Aug 2026 22:41:38 -0000	1.590
+++ rc	24 Aug 2026 16:05:01 -0000
@@ -502,6 +502,21 @@ sysctl_conf
 mount -s /var >/dev/null 2>&1		# cannot be on NFS
 mount -s /var/log >/dev/null 2>&1	# cannot be on NFS
 mount -s /usr >/dev/null 2>&1		# if NFS, fstab must use IP address
+mount -s /tmp >/dev/null 2>&1		# if NFS, fstab must use IP address
+
+# Prune /tmp before users can authenticate.  A few files are removed
+# immediately, but most of the deletion happens asynchronously while
+# daemons are being started
+( cd /tmp && {
+    echo clearing /tmp
+    skip="! -path . ! -path ./lost+found ! -path ./quota.user 
+	! -path ./quota.group ! -path ./vi.recover"
+    find -d . $skip -print -exec rm -rf {} \; | head -50 >/dev/null
+    tmpdir=$(mktemp -d .delXXXXXXXXXX) &&
+	find . -maxdepth 1 $skip ! -name "$tmpdir" -print0 | \
+	    xargs -r0J % mv -f % "$tmpdir"
+    rm -rf "$tmpdir" &
+} )
 
 reorder_libs 2>&1 |&
 
@@ -597,26 +612,6 @@ if [[ -f /etc/ptmp ]]; then
 	    'password file may be incorrect -- /etc/ptmp exists'
 fi
 
-echo clearing /tmp
-
-# Prune /tmp before users can authenticate.  A few files are removed
-# immediately, but most of the deletion happens asyncronously while
-# daemons are being started
-clear_tmp_dir=$(cd /tmp && {
-    rm -rf .{X11,ICE}-unix
-
-    set -- rm -rf
-    TMPDIR=$(mktemp -d /tmp/.delXXXXXXXXXX) && export TMPDIR &&
-	set -- sh -c 'mv -f -- "$@" "$TMPDIR"'
-    find . -maxdepth 1 ! -name . ! -name lost+found ! -name quota.user \
-	! -name quota.group ! -name vi.recover ! -name "$(basename "$TMPDIR")" \
-	-exec "$@" -- {} \+
-    rm -rfv "$TMPDIR" 2>&1 | head -20 >/dev/null
-    echo "$TMPDIR"
-} )
-rm -rf "$clear_tmp_dir" &
-clear_tmp_pid=$!
-
 # Create Unix sockets directories for X if needed and make sure they have
 # correct permissions.
 [[ -d /usr/X11R6/lib ]] && mkdir -m 1777 /tmp/.{X11,ICE}-unix
@@ -666,8 +661,6 @@ start_daemon dhcp6leased rad hostapd lpd
 start_daemon ftpproxy ftpproxy6 tftpd tftpproxy identd inetd rarpd bootparamd
 start_daemon rbootd mopd vmd spamd spamlogd sndiod
 echo '.'
-
-wait $clear_tmp_pid
 
 # If rc.firsttime exists, run it just once, and make sure it is deleted.
 run_upgrade_script firsttime