Page MenuHomeFreeBSD

rc.d/cleanvar: purgedir function has shell expansion vulnerability
ClosedPublic

Authored by feld on Jan 5 2018, 10:29 PM.
Tags
None
Referenced Files
Unknown Object (File)
Mar 7 2024, 8:42 PM
Unknown Object (File)
Jan 5 2024, 3:19 AM
Unknown Object (File)
Dec 22 2023, 10:37 PM
Unknown Object (File)
Sep 17 2023, 6:23 AM
Unknown Object (File)
Aug 11 2023, 7:09 PM
Unknown Object (File)
Jun 26 2023, 12:25 PM
Unknown Object (File)
Jun 15 2023, 6:51 PM
Unknown Object (File)
Jan 28 2023, 2:11 PM

Details

Summary

cleanvar is enabled by default on FreeBSD systems. Its purpose is to
clean out stale files from three directories:

  • /var/run
  • /var/spool/lock
  • /var/spool/uucp/.Temp/

For /var/run and /var/spool/lock a local function called purgedir is used.
This function has a vulnerability by shell expansion.

If any process creates a directory named "-P" in /var/run or
/var/spool/lock it will cause the purgedir function to start to rm -r /.
This seems to only be reproducible on boot or startup of a jail
(exec.start= "/bin/sh /etc/rc";).

Only /var/run and /var/spool/lock use the purgedir function. The
purgedir function has the following properties:

  • If zero arguments are given to purgedir, run purgedir on .
  • skip sockets named "log" and "logpriv" (intended for /var/run)
  • a hack to avoid following "." and ".."
  • if it's a directory, run the purgedir function against this directory
  • otherwise rm -f -- $file

I believe the vulnerability we are seeing is at line 32:

cd "$dir" && for file in .* *

-P is alphasorted as the first item in the directory and the CWD=/,
which means you get

CWD=/
/usr/bin/cd "-P" && for file in .* *

Which will inevitably cause it to start deleting /

These tasks are much better handled with find(1).

Test Plan

mkdir -- /var/run/-P
mkdir -- /var/spool/lock/-P

Restart system

Observe that cleanvar is not deleting your OS

Diff Detail

Repository
rS FreeBSD src repository - subversion
Lint
Lint Not Applicable
Unit
Tests Not Applicable

Event Timeline

Improved find(1) syntax per BigKnife

Escape parens

Do not try to clear out the uucp Temp dir unless it exists

allanjude added a subscriber: allanjude.

This seems like a much safer approach

This revision is now accepted and ready to land.Feb 6 2018, 8:24 PM
This revision was automatically updated to reflect the committed changes.
head/etc/rc.d/cleanvar
42

This removes the .Temp file always, no? The old code only deleted what was under it. And how is this different than just rm -rf? Seems like the complicated way of doing it, unlike the other cleanups to the file which made things less obscure and easier to follow.

head/etc/rc.d/cleanvar
42

.Temp is a directory, not a file. The idea was to keep it consistent with the other cleanup commands which are now leveraging find(1). I don't know how many files may end up under /var/spool/uucp/.Temp/* but it would be a shame for boot to hang because of glob expansion taking forever or fail with "too many arguments". Does that make sense?