From: ebiederm@xmission.com (Eric W. Biederman)
To: linux-security-module@vger.kernel.org
Subject: [RFC][PATCH] security: Make the selinux setxattr and removexattr hooks behave
Date: Sat, 30 Sep 2017 15:40:43 -0500 [thread overview]
Message-ID: <87d167ncms.fsf@xmission.com> (raw)
In-Reply-To: <db1c58f3-5a01-5276-eba7-5aac7cdcbcf5@schaufler-ca.com> (Casey Schaufler's message of "Sat, 30 Sep 2017 10:01:48 -0700")
Casey Schaufler <casey@schaufler-ca.com> writes:
> On 9/30/2017 9:22 AM, Eric W. Biederman wrote:
>> Casey Schaufler <casey@schaufler-ca.com> writes:
>>
>>> On 9/29/2017 7:18 AM, Stephen Smalley wrote:
>>>> On Thu, 2017-09-28 at 18:16 -0700, Casey Schaufler wrote:
>>>>> On 9/28/2017 3:34 PM, Eric W. Biederman wrote:
>>>>>> It looks like once upon a time a long time ago selinux copied code
>>>>>> from cap_inode_removexattr and cap_inode_setxattr into
>>>>>> selinux_inode_setotherxattr.??However the code has now diverged and
>>>>>> selinux is implementing a policy that is quite different than
>>>>>> cap_inode_setxattr and cap_inode_removexattr especially when it
>>>>>> comes
>>>>>> to the security.capable xattr.
>>>>> What leads you to believe that this isn't intentional?
>>>>> It's most likely the case that this change occurred as
>>>>> part of the first round module stacking change. What behavior
>>>>> do you see that you're unhappy with?
>>>>>
>>>>>> To keep things working
>>>>> Which "things"? How are they not "working"?
>>>>>
>>>>>> ?and to make the comments in security/security.c
>>>>>> correct when the xattr is securit.capable, call cap_inode_setxattr
>>>>>> or cap_inode_removexattr as appropriate.
>>>>>>
>>>>>> I suspect there is a larger conversation to be had here but this
>>>>>> is enough to keep selinux from implementing a non-sense hard coded
>>>>>> policy that breaks other parts of the kernel.
>>>>> Specifics, please. Since I can't guess what problem you've
>>>>> encountered I can't tell if it's here, in the infrastructure,
>>>>> or in your perception of what constitutes "broken".
>>>>>
>>>>>> Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
>>>>>> ---
>>>>>> ?security/selinux/hooks.c | 6 ++++++
>>>>>> ?1 file changed, 6 insertions(+)
>>>>>>
>>>>>> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
>>>>>> index f5d304736852..edf4bd292dc7 100644
>>>>>> --- a/security/selinux/hooks.c
>>>>>> +++ b/security/selinux/hooks.c
>>>>>> @@ -3167,6 +3167,9 @@ static int selinux_inode_setxattr(struct
>>>>>> dentry *dentry, const char *name,
>>>>>> ? u32 newsid, sid = current_sid();
>>>>>> ? int rc = 0;
>>>>>> ?
>>>>>> + if (strcmp(name, XATTR_NAME_CAPS) == 0)
>>>>>> + return cap_inode_setxattr(dentry, name, value,
>>>>>> size, flags);
>>>>>> +
>>>>> No. Don't even think of contemplating considering embedding the cap
>>>>> attribute check in the SELinux code. cap_inode_setxattr() is called
>>>>> in
>>>>> the infrastructure.
>>>> Except that it isn't, not if any other security module is enabled and
>>>> implements those hooks, to prevent imposing CAP_SYS_ADMIN checks when
>>>> setting security.selinux or security.SMACK*.
>>> OK. Yes, this bit of the infrastructure is some of the
>>> worst I've done in a long time. This is a case where we
>>> already need special case stacking infrastructure. It looks
>>> like we'll have to separate setting the cap attribute from
>>> checking the cap state in order to make this work. In any
>>> case, the security_inode_setxattr() code is where the change
>>> belongs. There will likely be fallout changes in the modules,
>>> including the cap module.
>>> ?
>>>
>>>> An alternative approach to fixing this would be to change the cap
>>>> functions to only apply their checks if setting the capability
>>>> attribute and defer any checks on other security.* attributes to either
>>>> the security framework or the other security modules. Then the
>>>> framework could always call all the modules on the inode_setxattr and
>>>> inode_removexattr hooks as with other hooks. The security framework
>>>> would then need to ensure that a check is still applied when setting
>>>> security.* attributes if it isn't already handled by one of the enabled
>>>> security modules, as you don't want unprivileged userspace to be able
>>>> to set arbitrary security.foo attributes or to set up security.selinux
>>>> or security.SMACK* attributes if those modules happen to be disabled.
>>> Agreed. This isn't a two line change. Grumble.
>>>
>>> I can guess at what the problem might be, but I hate making
>>> assumptions when I go to fix a problem. I will start looking
>>> at a patch, but it would really help if I could say for sure
>>> what I'm out to accomplish. It may be obvious to the casual
>>> observer, but that description has not been applied to me very
>>> often.
>> Apologies for the delayed reply.
>>
>> I am looking at security_inode_setxattr.
>>
>> For setting attributes in the security.* the generic code in fs/xattr.c
>> applies no permission checks.
>>
>> Each security module that implements an xattr in security.* then imposes
>> it's own policy on it's own attribute.
>>
>> For smack the basic rule is smack_privileged(CAP_MAC_ADMIN).
>> For selinux the basic rule is inode_or_owner_capable(inode).
>> For commoncap the basic rule is capable_wrt_inode_uidgid(inode, CAP_SETFCAP).
>>
>> commoncap also applies a default policity to setting security.* xattrs.
>> ns_capable(dentry->d_sb->s_userns, CAP_SYS_ADMIN).
>>
>> smack reuses that default policy by calling cap_inode_setxattr if it
>> isn't a smack security.* xattr.
>>
>> selinux has what looks like an old copy of the commoncap checks for
>> the security.* in selinux_inode_setotherxattr. Testing for
>> capable(CAP_SETFCAP) for security.capable and capable(CAP_SYS_ADMIN)
>> for the others.
>>
>> With the added complication that selinux calls
>> selinux_inode_setotherxattr also for the remove_xattr case. So fixing
>> this in selinux_inode_setotherxattr is not appropriate.
>>
>> I believe selinux also has general policy hooks it applies to all
>> invocations of setxattr.
>>
>> So I think to really fix this we need to separate the cases of is this
>> your security modules attribute from general policy checks added by the
>> security modules. Perhaps something like this for
>> security_inode_setxattr:
>>
>> Hmm. Looking at least ima also has the distinction between protecting
>> it's own xattr writes and running generaly security module policy on
>> xattr writes.
>>
>> int security_inode_setxattr(struct dentry *dentry, const char *name,
>> const void *value, size_t size, int flags)
>> {
>> int ret = 0;
>>
>> if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
>> return 0;
>>
>> if (strncmp(name, XATTR_SECURITY_PREFIX,
>> sizeof(XATTR_SECURITY_PREFIX) - 1) == 0) {
>> /* Call the security modules and see if they all return
>> * -EOPNOTSUPP if so apply the default permission
>> * check of ns_capable(dentry->d_sb->s_user_ns, CAP_SYS_ADMIN)
>> * otherwise if one of the security modules supports
>> * this attribute (signaled by returning something other
>> * -EOPNOTSUPP) then set ret to that result.
>> *
>> * The security modules include at least smack, selinux,
>> * commoncap, ima, and evm.
>> */
>> ret = magic_inode_protect_setxattr(dentry, name, value, size);
>> }
>> if (ret)
>> return ret;
>>
>> /* Run all of the security module policy against this setxattr call */
>> return magic_inode_policy_setxattr(dentry, name, value, size);
>> }
>>
>> Eric
>
> Yup, that's pretty much what I'm thinking. It's unfortunate
> that the magic_ API isn't fully implemented. There's going to
> be a good deal of code surgery instead. Is there an observed
> problem today? This is going to have to get addressed for stacking,
> so if there isn't a behavioral issue that impacts something real
> I would like to defer spending significant time on it. Do you have
> a case where this is not working correctly?
Merged as of 4.14-rc1 is the support for user namespace root to set
sercurity.capable. This fails when selinux is loaded.
removexattr has the same problem and the code is a little less
convoluted in that case.
Not being able to set the capability when you should be able to is
very noticable. Like running into a brick wall noticable.
Which is where the minimal patch for selinux comes in. I think it
solves the exact case in question, even if it isn't the perfect long
term solution.
Eric
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
next prev parent reply other threads:[~2017-09-30 20:40 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-09-28 22:34 [RFC][PATCH] security: Make the selinux setxattr and removexattr hooks behave Eric W. Biederman
2017-09-29 1:16 ` Casey Schaufler
2017-09-29 14:18 ` Stephen Smalley
2017-09-29 15:46 ` Casey Schaufler
2017-09-30 16:22 ` Eric W. Biederman
2017-09-30 17:01 ` Casey Schaufler
2017-09-30 20:40 ` Eric W. Biederman [this message]
2017-09-30 23:22 ` Casey Schaufler
2017-10-01 1:02 ` Eric W. Biederman
2017-10-01 18:52 ` Casey Schaufler
2017-10-01 19:54 ` Serge E. Hallyn
2017-10-01 22:11 ` Eric W. Biederman
2017-09-29 12:36 ` Stephen Smalley
2017-10-02 3:26 ` Eric W. Biederman
2017-10-02 14:38 ` [PATCH] selinux: Perform both commoncap and selinux xattr checks Eric W. Biederman
2017-10-02 15:52 ` Serge E. Hallyn
2017-10-03 16:24 ` Stephen Smalley
2017-10-03 21:08 ` Paul Moore
2017-10-03 21:26 ` Eric W. Biederman
2017-10-04 14:53 ` Paul Moore
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87d167ncms.fsf@xmission.com \
--to=ebiederm@xmission.com \
--cc=linux-security-module@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).