atom feed1 message in com.apple.lists.darwin-kernelMAC policy lifecycle and label invali...
FromSent OnAttachments
Phil JordanJan 9, 2013 11:02 am 
Subject:MAC policy lifecycle and label invalidation
From:Phil Jordan (lis@philjordan.eu)
Date:Jan 9, 2013 11:02:37 am
List:com.apple.lists.darwin-kernel

Hi,

I'm currently implementing a Mandatory Access Control (MAC) policy for a customer and trying to come up with a good architecture for labeling vnodes and mount points. During policy registration with mac_policy_register(), I receive a label slot index which lets me deposit a void* or long within the label struct associated with each kernel object (mount_t and vnode_t in this case).

This sounds fine in theory, but in practice, the kernel APIs don't seem to allow me to clean up the label slots when deregistering a MAC policy. When I call mac_policy_unregister(), "my" slot is recycled, and when another MAC policy registers (which can be another kext, or a new instance of mine), it will get my old label slot values for vnodes and mount points which have survived. So unless I can clean up before deregistration, I can't trust any pointer values in label slots, as they might point anywhere.

My approach to cleaning up would be to call vnode_iterate() and vfs_iterate() and zero out my label slots prior to deregistering the policy (and set a flag to prevent any MAC callbacks from re-setting it in the meantime). But there doesn't seem to be any (public) API for gaining access to the label directly given a vnode or mountpoint pointer. (vfs_mntlabel() is private, and the vnode struct is opaque; Apple code just uses its v_label field directly)

One alternative is to store unique IDs in the label slot and look them up in a hash table or similar; if an unknown ID is encountered, we know it's a leftover from a previously registered MAC policy. There's still a risk that the IDs aren't as unique as hoped, especially on 32-bit kernels. So it might actually be better to use the vnode_t or mount_t pointer value directly as the key into the hash table, which raises the question: If that's what we need to do, what's the point of the labels then?

The second option is to just not allow kext unloading and never deregister the policy. This seems bad, too.

So: how are we *supposed* to use the labels in MAC policies? Are there some public APIs that I've missed?

Many thanks, phil

This email sent to