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 Passed
Unit
No Test Coverage
Build Status
Buildable 14146
Build 14318: arc lint + arc unit

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 ↗(On Diff #38973)

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 ↗(On Diff #38973)

.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?