bin/108547: top allows local denial of service attack
bde at zeta.org.au
Wed Jan 31 18:10:26 UTC 2007
The following reply was made to PR bin/108547; it has been noted by GNATS.
From: Bruce Evans <bde at zeta.org.au>
To: "Dr. Markus Waldeck" <waldeck at gmx.de>
Cc: freebsd-gnats-submit at freebsd.org, freebsd-bugs at freebsd.org
Subject: Re: bin/108547: top allows local denial of service attack
Date: Thu, 1 Feb 2007 05:06:15 +1100 (EST)
On Tue, 30 Jan 2007, Dr. Markus Waldeck wrote:
> An unprivileged user could waste all CPU time by setting a low delay value in top (interactive or via -s).
An unprivileged user can waste all CPU time using almost any program. This
might matter for set[ug]id ones, but top isn't set*id under FreeBSD.
> Is there any possibility to deactivate this functionality without recompilation?
I would have thought that the possibility of making this mistake was
too small for it to happen, but the mistake of not allowing a delay
of 0 has already been made. Neither restriction is needed. The
latter restriction is close to being not even wrong, since it is easy
to work around using "while :; do top; done | cat". (This differs
from top -s 0 mainly in not printing the "CPU states" line. It also
has formatting bugs, so the null filter (cat) isn't quite enough to
give the same display as top -s 0.) To actually be wrong, top would
have to ensure that it runs for at least its minumum interval, so that
top in a loop is rate limited. Non-interactive top for non-DOS purposes
would then be broken. Fortunately, top can't ensure this, since it
can be SIGKILLed. All it can do is subtract more value by not displaying
anything until after it has run for its minimum interval (instead of
displaying something and then sleeping), so that anyone who SIGKILLs
it gets nothing.
> There are other top implementations that use a "secure mode" configuration
> which avoids the setting of the delay value for unprivileged users.
Maybe they are worried about it being set*id. I think most set*id programs
don't actually handle this. E.g., ping(8) doesn't -- "ping -c1" in a loop
works around ping's limits on -f and its interval. This actually matters,
since ping can be used for remote DOS. Fix: ensure that ping runs for at
least its minimum interval. I think most setuid programs with resource
limits need to do something like:
setuid() to drop the user's real ids (until here, can be SIGKILLed by user)
delay for an interval before exiting or using resource again
ping does most of this already.
More information about the freebsd-bugs