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