Date: Mon, 13 Sep 1999 12:10:38 +0400
From: Solar Designer <[email protected]>
To: [email protected]Subject: Linux 2.2.12 mini-audit
Hello,
This post serves three purposes: (1) let people know that they could
want to upgrade to 2.2.13 when it comes out, for security reasons;
(2) announce the new location for downloading my patches, as well as
the fact that they're now available for Linux 2.2; and (3) distribute
the fingerprint of the PGP key I'll be using to sign future versions
of the patches.
I've finally ported (actually, mostly re-coded) my patch to Linux
2.2, which has obviously resulted in some form of an audit of the
relevant parts of the kernel. Many of the issues have already been
discussed on the security-audit list, and some are even fixed in
2.2.13 pre-patches. Of course, my patches for both 2.2 and 2.0 (as
some of the issues turned out to affect 2.0 as well) have either
fixes or workarounds (to be improved in the future) for all of the
issues I'll be talking about, below. ;-) Note that the issues are
relatively minor, no instant root or such, but are still bad enough
to be worth fixing.
As this post is going to be fairly long, let me start by providing
the new URL and the key fingerprint. The new download location for
future versions of my patches, is:
http://www.openwall.com/linux/
The patches also no longer call themselves "Secure Linux", to stop
giving a false sense of security (I've spent quite a while to make
sure the documentation doesn't, either, as those things appear to be
quite important), and to avoid confusion with the Linux distribution
being developed under the same codename. On the new site, you will
also find a link to the PGP key:
Type Bits/KeyID Date User ID
pub 1024/295029F1 1999/09/13 Openwall Project <[email protected]>
Key fingerprint = 0C 29 43 AE 1E CD 24 EA 6E 0C B6 EE F5 84 25 69
(Some people were concerned about the site getting moved without a
prior announcement, and thus suspected a break-in. In reality, one
of the reasons for the move was exactly to ensure better security, as
I have physical access to this new place. As no site is perfectly
secure, I also took this opportunity to start signing the patches,
and will do the same for other stuff I'm distributing, soon. This is
something that I should have done quite a bit earlier, but I'm lazy,
and, fortunately, nothing bad has happened, anyway.)
Well, done with that, now we can get to the security issues. To save
space, I'll put either (2.0.38) or (2.2.12), or both, before every
description, to indicate which kernel versions it applies to. Also,
a (*) will mean that 2.2.13pre7 contains a fix, and a (+) will mean
that this hasn't been on security-audit, to let those on both lists
look through this post a bit faster. ;-)
(2.2.12) (*)
Tymm Twillman has reported a problem with execve(2) halting the
system when passed some illegal addresses. After some testing, the
problem turned out to be a missing error check on the return from
strlen_user(), which was used on user-supplied arguments, and thus
could indicate a fault; execve(2), in turn, should have converted
that into a EFAULT.
(2.0.38) (2.2.12) (*)
While investigating the problem mentioned above, as well as porting
Pavel Kankovsky's fd 0-2 fix to Linux 2.2, I've noticed yet another
problem with execve(2), which has a similar impact. The problem is
that all arguments are first counted, and their lengths measured, and
only after that the results are checked against the limit (32 pages,
or 128 KB on x86). Thus, it is possible to make execve(2) spend a
significant amount of CPU cycles in the kernel, with the big kernel
lock obtained. In terms of real time, I was able to get 25 minutes
for one execve(2) call on Alpha (the 64-bit address space helps), and
several seconds on modern x86 boxes. The latter can still be halted
to death by repeating the call in a loop, and in a few processes.
Fixing this required a trivial modification to the argument counting
function, and a switch to strnlen_user() for the strings (on 2.2).
The latter is an architecture-specific assembly function. My patch
only fixes it on x86 and Alpha, and 2.2.13 will do that for some more
architectures (but maybe not all supported by Linux 2.2, yet). Linux
2.0 didn't have a strlen_user(), and thus used a simple loop in this
place, which had the same vulnerability (but not in my 2.0.38 patch,
of course).
Note that RLIMIT_AS can be used as a workaround for this problem, and
you should probably be using it for other reasons, anyway.
(2.0.38) (+)
There was an intentional lack of fault checking when accessing the
arguments, as indicated by a comment in the code. This allowed a
user to generate kernel-mode faults inside execve(2), after some
kernel resources have been allocated (and would never be freed).
Simply fixing the problem mentioned above seemed uninteresting, so
I've re-written the argument counting code to do all the necessary
checking, and to share the same checks with measuring the lengths of
individual arguments. I've even managed to make it have the same
performance that it used to; the new count() function looks a bit
like a puzzle because of that, though. Actually, this is something
that should have been done earlier; now it can only remain in my
2.0.38 patch.
(2.0.38) (2.2.12) (*)
/proc/<pid> directories, and /proc/<pid>/fd symlinks could also be
accessed with any amount of zeroes prepended to their names. This
could be used, say, to obtain an overly long cwd. There's no obvious
security impact, but something to be fixed anyway (and that has been
done).
(2.0.38) (2.2.12) (*)
CLONE_PID could be set from the user-space, thus producing two user
processes with the same PID. Attacks include: stopping SUID programs
from sending signals to themselves (even raise(3) wouldn't work),
covering your high resource usage by the other dummy process, making
unkillable processes that can still be running just fine (covered by
dummy zombie processes with the same PID).
(2.0.38) (2.2.12)
It is possible to request any exit_signal, not just SIGCHLD, via
clone(2). This is normally not a problem, but there's one exception:
the parent could have executed a SUID program, and that program could
have done a "setuid(geteuid())", expecting to protect itself from
signals sent by the original user. This feature of clone(2) can be
used to send an arbitrary signal to such a program. I've put a
workaround into my patches, that restricts the allowed signal numbers
to SIGCHLD, SIGUSR1, SIGUSR2, or no signal, with SIGUSR1 and SIGUSR2
allowed specifically for LinuxThreads to work. This also means that
SUID programs which use LinuxThreads remain unprotected. A solution
to this should be developed. I've proposed one in a comment in the
patches, and Pavel Kankovsky has offered another one. Unfortunately,
both of them have some (different) disadvantages. This problem isn't
fixed in 2.2.13pre7, and isn't likely to be any time soon. :-(
(2.2.12) (*)
We have now reverted to the behavior of chown(2) we had in 2.0: reset
SUID/SGID bits on ownership change even if done by root. Until now,
Linux 2.2 didn't do that for root (and not even for CAP_FSETID, like
it was supposed to do), which allowed for some races that have been
discussed on the security-audit list a few months ago.
(2.0.38) (+)
Linux 2.0's version of process_unauthorized() forgot to check the
dumpable flag, so it was possible to access memory of a SUID process
a user has started, via PID re-use. Linux 2.2 did the right thing,
and isn't vulnerable.
(2.0.37 with secure-linux-11) (+)
I don't like it when others fix their vulnerabilities silently, so I
won't do so myself. :-) It was possible to bypass some restrictions
of CONFIG_SECURE_PROC via PID re-use in 2.0.36 and 2.0.37 kernels
with my patches. I simply didn't re-check the code closely enough
when updating the patch for 2.0.36. Thanks to Pavel Kankovsky for
noticing this.
(2.0.38) (2.2.12) (+)
User-space values of the instruction and stack pointers are available
via /proc, -- for every process in the system, and to everyone. This
information should in fact be treated just as private as the address
space of the processes (such a patch will likely get into 2.2.13pre
soon). Imagine a crypto algorithm implementation that does branches
based on its key bits. Thanks to Thomas <[email protected]>, who has
reported this to me (but underestimated the impact).
One final note: I am still going to fix all 2.0.38 security issues
that are any serious, in my patches, for a few months more.
Signed,
Solar Designer