Subject: Kernel authorization in NetBSD
To: None <current-users@NetBSD.org>
From: Elad Efrat <elad@NetBSD.org>
List: current-users
Date: 04/18/2006 04:21:02
Hi,
I'd like to merge the elad-kernelauth branch to the trunk soon. This
mail should provide some clue about the work, and more importantly, how
you can help.
1. Introduction
Kernel authorization was designed and developed by Apple. It's a new
framework to handle all authorization requests inside the kernel.
What are authorization requests? every time an operation is made, for
now let's assume these are all privileged operations -- such as
mounting a file-system, or changing a process' user-id, or attaching
ptrace to a process, or a special file-flag is set -- the kernel
usually does one of two things:
- Checks if the user making that request is the superuser by
calling the suser() routine with the user credentials
- Directly checks if the effective user-id of the process is zero
While this held pretty nice in Unix-land for a while, we're in a more
modern and complicated world today. Many of you might've heard some
of the buzzwords in this field, such as "POSIX capabilities" or Sun's
"process privileges"; some of you may even be familiar with ACLs
and role-based access controls. :)
Implementing all of these require finer-grained separation of each
request: who's making this request? what is the specific operation
requested? under what context? etc.
Having the kernel authorization framework allows us to have this
separation, and build on top of it.
For example, instead of simply checking if the user has effective
user-id of zero, We issue a request for a specific operation. We also
provide our credentials (more on this below), and perhaps some
context.
The kernel authorization framework is divided to "scopes". Each of
these is in charge of a different area in the system: we can have the
process scope for handling process-related authorization requests, a
vnode scope, a network scope, and so on.
Continuing with the above example, we issue the request using the
authorization wrapper provided by the scope. Then, the authorization
wrapper will dispatch our request -- with the credentials and context
-- to the handlers associated with the scope. These handlers are
referred to as "listeners".
Every scope has a default listener, but more listeners can be
attached, allowing you to customize your system's behavior. I'll give
an example for this later.
As I said above, we provide credentials to the authorization
wrappers. It's worth noting that the credentials have become an
opaque type: it's no longer possible to directly access members like
"effective user-id" or "saved group-id". In fact, there are very few
cases where you should be doing that. This opacity allows us to
freely modify the credentials structure. One of the side-effects is
that we just might implement a capabilities system! ;)
There's a lot more to it than just that, but let's keep it simple,
for now. You can read more about kernel authorization, or kauth for
short, at:
http://developer.apple.com/technotes/tn2005/tn2127.html
An online reference to the kauth(9) man-page, describing the
interface, can be found at:
http://www.bsd.org.il/netbsd/kauth.9.html
But keep in mind that as this is still work-in-progress, the
interface can still change.
2. NetBSD specific notes
Assuming we all have a slight clue about what kernel authorization is
at this point, here are some notes regarding the NetBSD
implementation.
First, for now we're implementing only the "process" and "generic"
scopes. There are also the "vnode" and "fileop" scopes, used to
provide an interface to file-system ACLs and attaching to
file-related events respectively, but we haven't implemented them
just yet. Of course, the real work was doing the interface and
integrating it -- adding them is *probably* just a matter of time.
To make things clear: we still don't have capabilities or file-system
ACLs. While the first could be implemented using an interface similar
to Solaris' ppriv(3) (dropping capabilities using system calls), the
real benefit will be when we've added support for extended attributes
in our file-system to associate these capabilities with files
on-disk.
There's a SoC project for this one so if you think you're capable you
should give it a shot; writing a (BSD-licensed!) file-system that
supports journaling and extended attributes -- or subfiles -- will
earn you unlimited fame and glory. ;)
Last but not least, keep in mind that the work that was done so far
is merely integrating the kauth(9) interface. If you'll take a look
at the code changes, you'll see that in some places we end up
basically checking if the user-id is zero; make no mistake, these are
just placeholders to make the merging less painful. This is also
where *YOU* come into the picture. Read on...
3. What can *YOU* do
If it wasn't implied already, these are some big, heavy changes to
the tree. True: most of these are mechanical, and I tried to mimic
the exact behavior we have now, in order to have kauth(9)
transparently integrated. I've also stress-tested the code on my
machines at home.
However... as with most stuff, breakage is usually to be expected.
The code could still use some testing, especially in configurations
that heavily utilize NFS or layared file-systems, for example.
If it's not too much to ask, it would be *VERY* helpful if people
could spend some of their time testing this branch a bit before we
merge it.
To fetch the code from CVS, you should use:
cvs checkout -f -relad-kernelauth src
And then try to build a GENERIC kernel with the DIAGNOSTIC option
uncommented. If you really feel crazy try DEBUG and LOCKDEBUG.. :)
Build a kernel and start using it... and report any "anomalies" to
the list(s). Anomalies may include but are not limited to:
- Unprivileged users can issue privileged operations
- Machine panics, crashes, or hangs, in situations it didn't before
- Things that used to work now don't work; usually with an
"Operation not permitted" (EPERM) error
So, again, if you have the time, *please* try it on your own machine.
4. Example usage: securelevels
Those of you who follow tech-kern@, saw I posted about integrating
our securelevels with kauth(9) at some point. Here's a little
breakdown of the hows and whats...
I'll assume we all know the BSD securelevel -- -1, 0, 1, and 2, each
having its own meaning and implications. As great as it may be, some
could argue that the powers-that-be who chose the implications of
each level were doing something other than *B*SD. ;) In fact, other
people may want to be able to use a custom set of "knobs" from
different levels.
This is something we can easily use kauth(9) for. Due its wonderful
pluggability (heh!) we're now in the position to let you choose.
Each securelevel scheme we use -- and, at this point, we should
really stop referring to the non-traditional scheme as "securelevel"
-- has its own set of listeners. Switching schemes is as easy as
uncommenting a kernel option, and what you get is that the
authorization requests will be routed to a different handler each
time.
If you choose the traditional scheme, you get what you have now; and
the handlers simply check the security level to allow or deny a
request. If you choose the other scheme, the request gets to a
different handler, that checks for the specific knob in charge of the
operation.
Same code all around the kernel, only different code for the
listener. Simple, elegant, and clean. Exactly the opposite of your
sex life. :)
5. Future directions
Unless it was obvious from the above, kauth(9) buys us a lot of
granularity with regard to authorization and privilege handling in
the kernel. It's the framework that makes it easy for us to implement
features like capabilities, ACLs, and allows third-party developers
to easily integrate their code with the NetBSD kernel plugging on top
of existing authorization schemes, extending, modifying, or changing
them entirely.
With time you'll see more and more development done in this area: the
above mentioned securelevel changes will go first, hopefully shortly
followed by capabilities, ACLs, and whatever ideas we -- or you --
have.
Remember that with your help we can get there faster! so test,
comment, send feedback, and bring up new ideas (either in public or
directly to me)
Thanks for your time and waiting for feedback,
-e.
--
Elad Efrat