By Jake Edge
March 2, 2011
Linux capabilities are still a work in progress. They have been in the
kernel for a long time—since the 2.1 days in 1998—but
for various reasons, it has taken more than a decade for distributions to
really
start using the feature. While capabilities ostensibly provide a way to
give limited privileges to processes, rather than the all-or-none setuid
model, the feature has been beset with incompleteness, limitations,
complexity concerns,
and other problems. Now that Fedora, Openwall, and other distributions are
working on
actually using capabilities to reduce the privileges extended to
system binaries we are seeing some of those problems shake out.
A patch
that was merged for 2.6.32 is one such example. The idea behind it was
that the CAP_NET_ADMIN capability should be enough to allow
loading network modules, rather than requiring CAP_SYS_MODULE.
The CAP_SYS_MODULE capability allows loading modules from
anywhere, rather than restricting the module search path to
/lib/modules/.... So, by switching to use CAP_NET_ADMIN,
network utilities, like ifconfig, could be restricted to only load
system modules, rather than arbitrary code.
There is one problem with that scheme, though, as Vasiliy Kulikov pointed out, because it allows processes with
CAP_NET_ADMIN to load any module from /lib/modules, not
just those that are networking related. Or, as he puts it:
root@albatros:~# grep Cap /proc/$$/status
CapInh: 0000000000000000
CapPrm: fffffffc00001000
CapEff: fffffffc00001000
CapBnd: fffffffc00001000
root@albatros:~# lsmod | grep xfs
root@albatros:~# ifconfig xfs
xfs: error fetching interface information: Device not found
root@albatros:~# lsmod | grep xfs
xfs 767011 0
exportfs 4226 2 xfs,nfsd
That example deserves a bit of explanation. The first command
establishes that the capabilities of the shell are just
CAP_NET_ADMIN (capability number 12 of the 34 currently defined
capabilities). Kulikov then goes on to show that the xfs module is not
loaded until he loads it via ifconfig. That is clearly not
the expected behavior. In fact it is now CVE-2011-1019
(which is just reserved at the time of this writing). For those that want
to try this out at home, Kulikov gives the proper incantation in his v2 patch:
# capsh --drop=$(seq -s, 0 11),$(seq -s, 13 34) --
Note that on not-quite-bleeding-edge kernels (e.g. Fedora 14's kernel), the
34 should be changed to 33 to account for the lack of a
CAP_SYSLOG, which was just recently added. Running that command
will give you a shell with just CAP_NET_ADMIN.
Kulikov's first patch proposal simply
changed the request_module() call in the core networking
dev_load() function to only load modules that start with "netdev-",
with udev expected to set up the appropriate aliases. There are three
modules that already have aliases (ip_gre.c, ipip.c, and
sit.c) in the code, so the patch changes those to prefix
"netdev-". But David Miller was not happy with changing those names, as it
will break existing code.
There was also a bit of a digression regarding attackers recompiling
modules with a "netdev-" alias, but unless that attacker can install the
code in /lib/modules, it isn't a real problem. In this case, the
threat model is a subverted binary that has CAP_NET_ADMIN, which
is not a capability that would allow it to write to
/lib/modules. But Miller's
complaint is more substantial, as anything that used to do
"ifconfig sit0", for example, will no longer work.
After some discussion of various ways to handle that problem, Arnd Bergmann
noted that the backward compatibility
problem is only for systems that are not splitting up capabilities
(i.e. they just use root or setuid with the full capability set). For
those, the CAP_SYS_MODULE capability can be required, while the
programs that only have CAP_NET_ADMIN will be new, and thus can use the
new "netdev-" names. The code
will look something like:
no_module = !dev;
if (no_module && capable(CAP_NET_ADMIN))
no_module = request_module("netdev-%s", name);
if (no_module && capable(CAP_SYS_MODULE)) {
if (!request_module("%s", name))
pr_err("Loading kernel module for a network device "
"with CAP_SYS_MODULE (deprecated). Use CAP_NET_ADMIN and alias netdev-%s "
"instead\n", name);
That solution seemed to be acceptable to Miller and others, so we may well
see it in the mainline soon. One thing to note, though, is that
capabilities are part of the kernel ABI, so changes to their behavior will
be difficult to sell, in general. This change is fixing a security
problem—and is hopefully not a behavior that any user-space application
is relying on—so it is likely to find a reasonably smooth path into
the kernel. Other changes that come up as more systems start to actually
use the various capability bits may be more difficult to do, though
we have already seen some problems
with the current definitions of various capabilities.
(
Log in to post comments)