Subject: Re: Integrating securelevel and kauth(9)
To: David Laight <david@l8s.co.uk>
From: Robert Watson <rwatson@FreeBSD.org>
List: tech-kern
Date: 03/28/2006 17:36:41
On Tue, 28 Mar 2006, David Laight wrote:

> On Tue, Mar 28, 2006 at 11:34:37AM +0000, Robert Watson wrote:
>> When we switched from a smaller number of indexed checks to
>> a larger number of function prototypes with explicit type checking, these
>> went away.
>
> I also suspect that the code paths get a lot shorter. And probably easier to 
> read...

This is true.  On the other hand, we ended up with a god-awful number of 
interfaces that each module needs to provide.  :-)  The LSM/MAC Framework 
model uses C99 sparse structure initialization to populate large structures of 
possibly defined function pointers with function pointers defined by the 
policy.  The older MAC Framework, FLASK, and now kauth(9) interface specifies 
a small number of entry functions but a large number of index value(s) 
specifying what event it is, which allows interpretation of the arguments.

Finding a middle ground between those two is tricky, since the C language 
wasn't every really meant to be able to do this sort of thing :-).

> If all the calls to a routine end up passing a constant parameter telling 
> the called function what to do (which I suspect ends up being the case 
> here), you save the cost of pushing the argument + the cost of the switch 
> statement (and can maybe even sensibly inline the code itself)....
>
> If, for instance, you run netbsd under bochs, you can get an instruction 
> trace output.  Executing simple system calls shows that a lot of the time is 
> spend faffing about in lockmgr. We don't want to do the same for the 
> authorization checks.

I'm much happier with the newer FreeBSD kernel locking APIs for this very 
reason -- you can see them separately in trace and profile output, you can 
substitute definitions at the symbol level, you get strong type checking, etc. 
All that said, I recognize there is a lot of value to the indexed argument 
method -- you may lose type checking and the function behavior, but it greatly 
reduces the amount of C glue required for the registration process, and allows 
very simple policies to coalesce decision logic if they're able to 
consistently ignore arguments.  TrustedBSD MAC modules tend to be quite long 
with a lot of fairly empty functions that map the specific typed arguments 
into something the logic of the policy can operate on.  I.e.:

static int
mac_mls_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred,
     struct vnode *vp, struct label *label)
{
         struct mac_mls *subj, *obj;

         if (!mac_mls_enabled || !revocation_enabled)
                 return (0);

         subj = SLOT(active_cred->cr_label);
         obj = SLOT(label);

         if (!mac_mls_dominate_effective(subj, obj))
                 return (EACCES);

         return (0);
}

Because the argument order and types of arguments vary, we can't easily 
combine functions implementing similar checks for different object types.

My currently leaning is that the MAC Framework slightly overshot in the 
direction of specific functions for each check.  I'd also like to pass 
specific label slot pointers in as well as the object pointers so that I can 
avoid encoding the mapping mechanism from objects to labels.  I may get a 
chance to retrofit all this for FreeBSD 7.0, but am currently preoccupied with 
finishing up the last of security event audit support for FreeBSD 6.2/7.0.

It's nice to think we could end up with a common authorization interface 
across the relevant BSD's, but in the short term it's hard to see how we would 
get there.  The MAC Framework is much more comprehensive than kauth, providing 
a variety of entry points for things like "A vnode has been instantiated, 
initialize it's in-memory label cache", "A vnode has been associated with an 
inode on a file system with extended attributes, perform I/O to derive the 
in-memory label", etc.  On the other hand, it's much more complicated.  We're 
currently working on optimizing the MAC Framework so it can be turned on by 
default in the GENERIC kernel, but this is tricky because it supports things 
like confidentiality, type enforcement, and biba labels on mbufs... :-)

If anyone interested in this discussion is going to be at BSDCan, it would be 
great to have a BOF session on pluggable security frameworks.  Having done 
work with a number of them (RSBAC, LSM, FLASK, TrustedBSD MAC Framework, 
kauth), I feel like I have something to say on the topic, but also feel the 
last word hasn't yet been said -- these frameworks all have different 
properties, making some things easier, and some things harder.  Finding one 
that meets the needs of immediate consumers is, and should be, the driving 
force behind integration.  On the other hand, since it is a framework for 
pluggable security services, and there are a lot out there, closing the door 
on the future is also bad.  The MAC Framework has successfully integrated 
things like our SEBSD port of FLASK/TE from SELinux to FreeBSD, which is quite 
neat, but possibly less practical than providing a good abstraction to put 
securelevels behind.  The MAC Framework has intentionally not addressed the 
issue of replacing current discretionary access control in FreeBSD, and that's 
something kauth has addressed, since that was Apple's practical requirement. 
I have had severral quite long discussions with Mike Smith along these lines, 
and we both think there's quite a bit more to do.

Robert N M Watson