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