Implement a cgroup using the LSM interface to enforce open and mknod on device files. This implements a simple device access whitelist. A whitelist entry has 4 fields. 'type' is a (all), c (char), or b (block). 'all' means it applies to all types, all major numbers, and all minor numbers. Major and minor are obvious. Access is a composition of r (read), w (write), and m (mknod). The root devcgroup starts with rwm to 'all'. A child devcg gets a copy of the parent. Admins can then add and remove devices to the whitelist. Once CAP_HOST_ADMIN is introduced it will be needed to add entries as well or remove entries from another cgroup, though just CAP_SYS_ADMIN will suffice to remove entries for your own group. An entry is added by doing "echo <type> <maj> <min> <access>" > devcg.allow, for instance: echo b 7 0 mrw > /cgroups/1/devcg.allow An entry is removed by doing likewise into devcg.deny. Since this is a pure whitelist, not acls, you can only remove entries which exist in the whitelist. You must explicitly echo a 0 0 mrw > /cgroups/1/devcg.deny to remove the "allow all" entry which is automatically inherited from the root cgroup. While composing this with the ns_cgroup may seem logical, it is not the right thing to do, because updates to /cg/cg1/devcg.deny are not reflected in /cg/cg1/cg2/devcg.allow. A task may only be moved to another devcgroup if it is moving to a direct descendent of its current devcgroup. CAP_NS_OVERRIDE is defined as the capability needed to cross namespaces. A task needs both CAP_NS_OVERRIDE and CAP_SYS_ADMIN to create a new devcgroup, update a devcgroup's access, or move a task to a new devcgroup. CONFIG_COMMONCAP is defined whenever security/commoncap.c should be compiled, so that the decision of whether to show the option for FILE_CAPABILITIES can be a bit cleaner. Changelog: Mar 13 2008: move the dev_cgroup support into capability hooks instead of having it as a separate security module. Support ...
Actually, I'm not sure that the LSM approach in general is best here. The LSM model is that standard DAC logic lives in the core kernel, and that extended security logic (e.g. MAC) is called after DAC via hooks. cgroups has introduced new security logic of its own, which is arguably "standard DAC" when cgroups is enabled. I can understand Greg not wanting this security logic in the core kernel, but it is specific to cgroups (which itself is security model agnostic) and does not stand alone as a distinct security framework. The fact that all existing LSMs need to invoke exactly the same code is an indicator that it doesn't belong in LSM. Moving this logic into LSM means that instead of the cgroups security logic being called from one place in the main kernel (where cgroups lives), it must be called identically from each LSM (none of which are even aware of cgroups), which I think is pretty obviously the wrong solution. This is baggage which comes with cgroups -- please don't push it into LSM to try and hide that. - James -- James Morris <jmorris@namei.org> --
I agree with the above, and would further note that I would expect the SELinux solution to the problem would be done not by stacking with or calling this device whitelist lsm but instead by introducing the ability to bind security labels to devices within the kernel (independent of the particular device node(s) in the filesystem used to access that device) and applying permission checks on those device labels when processes attempt to create or access those devices (again independent of the particular device node used to access them). That keeps the policy integrated and analyzable and avoids an external dependency. -- Stephen Smalley National Security Agency --
I completely disagree. We have two separate frameworks in the kernel, one to enforce generic additional security stuff, and one to track tasks. When I need a feature which tracks tasks to do some security tasks, it seems obvious that I would use both, just like to enforce a certain type of MAC I end up using both netfilter and LSM through No, that's like saying capabilities don't belong in LSM because all LSMS need to invoke it the same way. What it is an indicator of is that there are (not-quite-)orthogonal pieces of security which users might want to use together. As I told stephen I hope to provide the enhanced selinux support for devices, and at that point perhaps you won't want to support SELINUX+CGROUPS_DEV anymore. Now that's just my opinion and it doesn't count for much. I'll do whatever everyone can agree on, but will wait for Paul's opinion about Agreed. -serge --
Depends on whether you think LSM hooks are like netfilter hooks (i.e. fine for each module to just implement a few here and there, then combine resulting modules), or whether they are about implementing complete security models (ala SELinux or Smack). As they currently exist, they aren't very well suited to the former - they impose a cost on all hooked operations in order to hook any at all, as has been a Likely not a popular view, but capabilities don't belong in LSM. Look at them: the capability state is still directly embedded in the relevant kernel data structures, various bits of capability specific logic and interfaces remain in the core kernel, they don't present a complete security model (just an auxiliary to some other model like DAC or Smack for privilege purposes), they use only a small subset of the hooks, they force LSM to violate its usual restrictive-only paradigm to support capable(), CONFIG_SECURITY=n still has to invoke the capability functions, and all of the other LSMs do need to call it the same way to keep Linux working as expected for applications and users. The original promise was that LSM would allow kernels to be built that shed capabilities altogether, but in practice no one seems to do that as both users and applications expect them to exist in Linux. In fact, the possibility of not having capabilities present has caused problems that have led to the dummy module being turned more and more into a clone of the capabilities module (actually managing and testing the capability bits rather than just uid == 0 as originally). So I wouldn't point to capabilities as a counter example to James' point -- Stephen Smalley National Security Agency --
I don't intend that Smack be thought of as a complete security model. Smack implements Mandatory Access Control, but leaves the privilege mechanism (root and/or capabilities) to the whims of others. Similarly Smack does not do DAC (unlike SELinux with MCS) although "owned rules" has been proposed as an additional feature. I certainly wouldn't want every new facility that comes in to require multiple versions that depend on the other LSMs involved. It's true that today's LSM is optimized for the only LSM that existed a year ago, and that was a I share this view, which add credibility to the claim that it's It does seem as if a separate Linux Privilege Module framework might be a better scheme. It would be very easy to pull out, and simple to create the obvious LPMs: - Traditional root hooks look like "return (euid == 0) ? 0 : -EACCES;" - No access check at all hooks look like "return 0;" - Root or capabilities hooks look like "return (euid == 0 || capable(xxx)) ? 0 : -EACCES;" - Pure capabilities Plus, if SELinux wants to abandon capabilities they can add thier own scheme or insist the user use the noop LPM and do whatever they like in the LSM. Smack has no intention of mucking with the privilege mechanism, and will happily go along with whatever the rest of the system wants to use, although the noop LSM seems a bit pointless in This is why Smack is sticking to MAC rather than trying to be a wholistic security policy mechanism. To quote the prophet, "God created the world in 7 days, but then, He didn't have an install In particular, capabilities are not an access control mechanism, they are a privilege mechanism. A lot of discussion about LSM has centered around the appropriate charactoristics of an LSM, and these discussions always assume that the LSM in question is exactly an access control mechanism. If we split the LSM into a LACM for access control and an LPM for privilege management maybe we can eliminate the most contentious issues. Does ...
No I'd like to see those patches. It would ideally allow LSM to become *purely* restrictive and LPM to be purely empowering, presumably making the resulting hook sets easier to review and maintain. The LPM wouldn't (I assume) gain any *new* hook points so we wouldn't be adding any new places for hooks to be overriden by a rootkit. -serge --
I don't expect to put in any additional hooks points, although
it's safe to bet that someone will want to pretty quickly. What
I see as the big concern is our old friend the granularity question.
I can pretty well predict that we'll have quite a bruhaha over
whether each hook point should have it's own hook or if they should
be shared based on the privilege supported. For example, in namei.c
the function generic_permission() currently calls
capable(CAP_DAC_OVERRIDE). The privilege supported approach would
be to create a hook that gets used in many places that is a drop-in
replacement for that,
if (capable(CAP_DAC_OVERRIDE))
becomes
if (lpm_dac_override())
The alternative is to go the same route as the LSM, where it
becomes
if (lpm_generic_permission_may_exec())
The former scheme is much easier to implement. It also would
mean that if would wanted to implement a finer granularity on
DAC overrides (e.g. CAP_DAC_READ, CAP_DAC_WRITE, CAP_DAC_EXECUTE)
you would have to introduce new hooks. That wouldn't be any worse
than today's situation where you would have to change the argument
passed to capable as far as the calling (e.g. generic_permission)
code is concerned, but it would mean updating all the LPMs. I
currently count 1084 calls to capable (sloppy grep method) and that's
way too many hooks in my mind. But, if there's anyone who thinks
that the way to go is for each existing capable call to be a hook,
feel free to make a convincing argument.
This should be fun.
Casey Schaufler
casey@schaufler-ca.com
--
nit: I'd use priv_ rather than lpm_, just as we use security_ rather than lsm_. Do you plan to pass other arguments to the privilege hook call, like the object? If not, then there is no point in changing the capable call sites at all - just change its implementation to invoke a priv_capable() Changing all of the call sites seems a bit prohibitive for an initial implementation; rewiring the internals of capable() to use a new privilege hook interface would be a lot simpler. You also have to migrate the other security hooks presently used to support capabilities to your privilege framework. -- Stephen Smalley National Security Agency --
By complete security model, I don't mean it has to be MAC+DAC +privileges. Just that it does in fact implement a well formed security model, not just an ad hoc set of stupid security tricks. Smack and "One of the explicit requirements to get LSM into the kernel was to have the ability to make capabilities be a module. This allows the embedded people to completely remove capabilities, as they really want this. I don't think we can ignore this, no matter how much of a pain in the butt it is :)" - Greg KH Quoted from: http://marc.info/?l=linux-security-module&m=99236500727804&w=2 Ironically, since that time, capabilities have doubled in size and still can't be removed from the core kernel since LSM didn't push the state If you do re-factor it in that manner, SELinux will have to register under both schemes in order to preserve its current logic, of course. And there are points of overlap between the two schemes even for non-privilege-managing security modules (e.g. they both need hooks on ptrace, inode_setxattr, etc). Lastly, since LSM didn't really do the job of migrating the capability state out of the core kernel data structures and fully encapsulating the capability logic, you'd have to do that work too to do it right. -- Stephen Smalley National Security Agency --
Maybe we need to seriously revisit this and perhaps rip capabilities back out and put it always into the kernel if it's always a requirement. Comments made 7 years ago might be totally wrong when we have now learned how this all has worked out... thanks, greg k-h --
