Re: [RFC] [Stacking v4 2/3] New version of SELinux patch to support stacking

From: Serge Hallyn (serue@private)
Date: Tue Dec 07 2004 - 11:17:03 PST


On Tue, 2004-12-07 at 09:14 -0500, Stephen Smalley wrote:
> On second thought, we are presently relying on that behavior, e.g. to
> ensure that SELinux capability permission checks are also applied when
> cap_ptrace or cap_bprm_apply_creds checks a capability (and SELinux does
> not presently apply redundant checking in its own hooks for those
> cases).  Likewise, when SELinux checks CAP_FOWNER in inode_setxattr, we
> expect the capability module to also be consulted.  The alternative to
> calling the top-level capable() function in such cases is to explicitly
> duplicate the processing in the SELinux hook functions when we want this
> to occur.  That doesn't seem very clean, but neither does having a
> ptrace_attach-> stacker_ptrace-> cap_ptrace-> capable->
> stacker_capable-> {cap_capable, selinux_capable} call chain.  The

Right.  So there are several ways of looking at this:

   1. This is a case where two modules are coded to know about each
other.  So perhaps trying to stack them with an arbitrary stacker is not

   2. This is evidence that capable does need to be handled differently,
and the possibility of having capable() return >0 to imply "override"
should be investigated.

But (2) can't be right - for instance cap_inode_setxattr() calls capable
(CAP_SYS_ADMIN), which will call all modules' capable(CAP_SYS_ADMIN) but
not give them any idea of why.  In other words, capable(CAP_SYS_ADMIN)
is too coarse-grained in this case :)

A third option might be

   3. commoncap should really be seen as a set of building blocks,
exploitable by either building simpler capability_custom.ko's, or by
making capability.ko more configurable, or by having LSMs directly call
cap_ptrace, for instance.

A variation, which I rather like, is:

   4. a simpler capability_track.ko should exist, which tracks POSIX
capabilities and defines capable(), but does not define most other
checks, such as inode_setxattr or settime.  So, it would define:

   struct security_operations capability_track_ops = {
	.capable = cap_capable,
        .cap_get = cap_capget,
	.capset_check = cap_capset_check,
	.capset_set = cap_capset_set,
	.bprm_set_security = cap_bprm_set_security,
	.bprm_apply_creds = cap_bprm_apply_creds,
	.task_post_setuid = cap_task_post_setuid,
	.task_reparent_to_init = cap_task_reparent_to_init,

A LSM could then use capable(CAP_PTRACE) or cap_capable(CAP_PTRACE) or
cap_ptrace() manually when it felt the need, and more than one module
could be intimately tied to capability without having to worry about
recomputing/messing up the actual capability set (as would happen if we
loaded capability under selinux and again under subdomain).  Capable
(CAP_PTRACE) would ask all LSMs (so we could still have capable become
authoritative, perhaps), cap_capable(CAP_PTRACE) would only ask
commoncap, and cap_ptrace() would do the full commoncap ptrace check.

Does SELinux expect any other LSM to be loaded as secondary than
capability?  Could the secondary_ops stuff be replaced by capability-
specific code?

Serge Hallyn <serue@private>

This archive was generated by hypermail 2.1.3 : Tue Dec 07 2004 - 10:04:49 PST