Re: Earlier /tmp cleanup in /etc/rc
patrick keshishian <[email protected]>
| Newsgroups | gmane.os.openbsd.tech |
|---|---|
| Message-ID | <[email protected]> |
On Wed, Aug 26, 2026 at 09:14:25PM -0600, Theo de Raadt wrote:
> I think that email failed to explain the various parts of the problem
> and the solution we've arrived at.
>
> It needs to be explained, in case we still have something wrong after
> the 50th iteration...
>
> > 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 27 Aug 2026 01:25:03 -0000
> > @@ -502,6 +502,24 @@ 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
>
> We mount /tmp very early, so that we can prune it early. Look below and
> you see reorder_libs &. That runs asyncronously. We don't know if a /tmp
> pruner running in parallel to that will delete files. The same applies to
> other daemons that get started. Previous sersion of the /tmp pruning code
> could still be running while sshd is starting, or possibly later.
>
> So the goals now are:
>
> 1) free up at least one inode, because mkstemp needs at least one
> 2) free up a few more, just in case. We settled on 50.
> 3) With an inode freed up for mktemp, create a directory and move all the
> deleteable files into that directory and remove it asyncronously.
I don't have a patch, and it is late, so I shouldn't be making
any noise, but, just perchance this does help I had to chime in.
Reading the clearly stated description above, I had to wonder if
all this making a temp dir, to which to move deletable files, so
that the pruner does not delete files created by reorder_libs and
friends, can be avoided if one hoisted up the patching of /etc/motd,
appended "! -anewer /etc/motd" to $skip to be used in one simple
find and delete command.
(sorry about the run-on sentence)
--patrick
> > +
> > +# 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="-mindepth 1 -maxdepth 1 ! -name lost+found ! -name quota.user
> > + ! -name quota.group ! -name vi.recover"
> > + find . $skip ! -perm -1000 -print0 |
> > + xargs -r0J % find -d % -exec rm -rf -- {} \; -print |
> > + head -50 >/dev/null 2>&1
>
> This is the step which prunes 50 inodes. It is very complicated.
>
> The first find runs without -d, so that it can generate a list of top-level
> objects except for a) +t directories, b) lost+found, quota.user, quota.group,
> vi.recover.
>
> Anything else at the top-level is a target for removing inodes.
>
> The next clever put is that we are going to print every (single file
> or directory) as we delete it, and pipe that to head -50. head -50
> will stop file deletions when we reach the limit. This printing may
> include files with newlines in it, which means we may delete less than
> 50. In reality we definately only need 1, ok maybe 3, inodes
>
> The nested find now processes the permitted files and directories, finding
> one file at a time, bottom up, because of -d. The -print is located
> after the rm -rf -- {} so that the failure to remove a file (for whatever
> reason does not) advance the counter towards 50 files.
>
> Of course, the failure to remove files will be noisy, so the entire
> contraption redirects errors to /dev/null.
>
> Now that we have enough inodes, we to hunt the other files:
>
> > + tmpdir=$(mktemp -d .delXXXXXXXXXX) && {
> > + find . $skip ! -name "$tmpdir" -print0 |
> > + xargs -r0J % mv -f -- % "$tmpdir"
> > + rm -rf -- "$tmpdir" &
> > + }
> > +} )
>
> We create a mktemp directory, move all the permitted files into that
> directory, and then asyncronously delete that directory. This can
> take as long as it needs to, while the system boots, because those
> files cannot be reached because they are inside a mktemp directory.
>
> I think there is still reason to redirect the final rm -rf (or maybe
> even the find + mv to /dev/null, becuase noone wants to see any noise
> from this.
>