Bug 1045530

Summary: RHEL7 avc denial for AD user ssh using kerberos ticket
Product: Red Hat Enterprise Linux 7 Reporter: Scott Poore <spoore>
Component: selinux-policyAssignee: Miroslav Grepl <mgrepl>
Status: CLOSED CURRENTRELEASE QA Contact: Milos Malik <mmalik>
Severity: medium Docs Contact:
Priority: medium    
Version: 7.2CC: alikins, dhowells, dwalsh, eparis, howey.vernon, mgrepl, mmalik, nalin, plautrba, pmoore, rharwood, sbose, sdsmall, sgallagh, ssorce, stephan.wiesand
Target Milestone: rc   
Target Release: ---   
Hardware: Unspecified   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2015-09-29 11:26:42 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Bug Depends On:    
Bug Blocks: 991169, 1205796    

Description Scott Poore 2013-12-20 16:34:35 UTC
Description of problem:

In an IPA environment with a trust setup to AD domain, I am seeing some AVC denials when the AD user tries to ssh to IPA server with kerberos ticket.

[root@rhel7-1 ~]# kdestroy -A
[root@rhel7-1 ~]# kinit aduser1.TEST
Password for aduser1.TEST: 
[root@rhel7-1 ~]# klist
Ticket cache: KEYRING:persistent:0:0
Default principal: aduser1.TEST

Valid starting       Expires              Service principal
12/20/2013 10:02:20  12/20/2013 20:02:20  krbtgt/AD2.EXAMPLE.TEST.TEST
	renew until 12/21/2013 10:02:18
[root@rhel7-1 ~]# ssh -K -l aduser1.test $(hostname)
Last login: Fri Dec 20 10:03:37 2013 from rhel7-1.ipa1.example.test
-sh-4.2$ exit
logout
Connection to rhel7-1.ipa1.example.test closed.
[root@rhel7-1 ~]# date
Fri Dec 20 10:05:44 CST 2013
[root@rhel7-1 ~]# ausearch -m avc -ts 10:05
----
time->Fri Dec 20 10:05:41 2013
type=SYSCALL msg=audit(1387555541.289:1315): arch=c000003e syscall=250 success=yes exit=0 a0=7 a1=28acd7b0 a2=1 a3=0 items=0 ppid=5736 pid=22954 auid=4294967295 uid=0 gid=0 euid=551801125 suid=0 fsuid=551801125 egid=551801125 sgid=0 fsgid=551801125 tty=(none) ses=4294967295 comm="sshd" exe="/usr/sbin/sshd" subj=system_u:system_r:sshd_t:s0-s0:c0.c1023 key=(null)
type=AVC msg=audit(1387555541.289:1315): avc:  denied  { write } for  pid=22954 comm="sshd" scontext=system_u:system_r:sshd_t:s0-s0:c0.c1023 tcontext=system_u:system_r:sssd_t:s0 tclass=key
----
time->Fri Dec 20 10:05:41 2013
type=SYSCALL msg=audit(1387555541.289:1316): arch=c000003e syscall=250 success=yes exit=8 a0=b a1=28acd7b0 a2=0 a3=0 items=0 ppid=5736 pid=22954 auid=4294967295 uid=0 gid=0 euid=551801125 suid=0 fsuid=551801125 egid=551801125 sgid=0 fsgid=551801125 tty=(none) ses=4294967295 comm="sshd" exe="/usr/sbin/sshd" subj=system_u:system_r:sshd_t:s0-s0:c0.c1023 key=(null)
type=AVC msg=audit(1387555541.289:1316): avc:  denied  { read } for  pid=22954 comm="sshd" scontext=system_u:system_r:sshd_t:s0-s0:c0.c1023 tcontext=system_u:system_r:sssd_t:s0 tclass=key
----
time->Fri Dec 20 10:05:41 2013
type=SYSCALL msg=audit(1387555541.289:1317): arch=c000003e syscall=250 success=yes exit=0 a0=f a1=28acd7b0 a2=8bd7 a3=0 items=0 ppid=5736 pid=22954 auid=4294967295 uid=0 gid=0 euid=551801125 suid=0 fsuid=551801125 egid=551801125 sgid=0 fsgid=551801125 tty=(none) ses=4294967295 comm="sshd" exe="/usr/sbin/sshd" subj=system_u:system_r:sshd_t:s0-s0:c0.c1023 key=(null)
type=AVC msg=audit(1387555541.289:1317): avc:  denied  { setattr } for  pid=22954 comm="sshd" scontext=system_u:system_r:sshd_t:s0-s0:c0.c1023 tcontext=system_u:system_r:sssd_t:s0 tclass=key

Version-Release number of selected component (if applicable):
selinux-policy-3.12.1-110.el7.noarch
sssd-1.11.2-15.el7.x86_64
openssh-6.4p1-3.el7.x86_64

How reproducible:
Not sure yet but, I'm seeing it often in my automated tests.  And the above was from a manual test.

Steps to Reproduce:
1.  Setup IPA Server
2.  Setup Trust to AD domain
3.  setenforce 0 # was doing this to avoid another bug
4.  kdestroy -A # make sure all clear
5.  kinit aduser
6.  ssh -K -l aduser $(hostname)

Actual results:
ssh works (possibly due to permissive mode) but, see AVC denials.


Expected results:
no AVC denials


Additional info:

Comment 2 Daniel Walsh 2014-01-06 19:12:28 UTC
These AVC's indicate a kernel keyring was created by sssd and is being written to by sshd.

I know there was work being done with Kerberos around this.

Do I need to allow all login programs to use sssd_t keyrings?

Comment 3 Daniel Walsh 2014-01-06 19:49:18 UTC
Does this keyring end up getting handed to a logged in user?  IE Should we have the keyring owned by unconfined_t/staff_t rather then sssd_t?

Comment 4 Sumit Bose 2014-01-07 08:43:30 UTC
(In reply to Daniel Walsh from comment #3)
> Does this keyring end up getting handed to a logged in user?  IE Should we
> have the keyring owned by unconfined_t/staff_t rather then sssd_t?

Yes, this Kernel keyring hold the credential cache of the user. If the user logs in with a password sssd will create the credential cache for the user. If the user use GSSAPI with credential forwarding sshd will put the Kerberos TGT of the user into the credential cache. If the session is running the user might want to call kinit which would write the new TGT into the credential cache as well.

Comment 5 Daniel Walsh 2014-01-07 14:22:11 UTC
Right but if the user does a 
kdestroy/kinit the user cache would be unconfined_t:key.  If they login with sssd getting the keyring it is owned by sssd_t.

We have seen another case where the user logged in as staff_t, then ran ssh which created an empty keyring ssh_t:key, when ssh tried to do kerberos.  The user then did a kinit, and got a rule saying staff_t wants to write to ssh_t:key.

The problem I have is the user keyring should always be labeled based on the user, and we need to figure a way to get this right, otherwise we might as well eliminate the checking of the keyring from an SELinux point of view, because It will end up allowing all users of kerberos to use all keyrings.

Comment 6 Sumit Bose 2014-01-07 15:02:47 UTC
Stephen, Simo, what do you think should be the right solution with respect to SELinux?

Comment 7 Stephen Gallagher 2014-01-07 15:15:30 UTC
Including David Howells in the discussion.

I'm not sure what exactly we want to do with regards to SELinux. When SELinux isn't in the picture, the standard behavior is that the kerberos keyring is accessible only to the user ID associated with it or root. Beyond that, any processor owned by the user or root can update it.

We definitely need for all login programs and kerberos-workstation tools to be able to have access to it.

I *thought* that the keyring was created as kernel_t when created with the keyctl() system calls, but I could be mistaken. David might have more insight here.

Comment 8 Stephen Gallagher 2014-01-07 15:16:09 UTC
Including David Howells in the discussion.

I'm not sure what exactly we want to do with regards to SELinux. When SELinux isn't in the picture, the standard behavior is that the kerberos keyring is accessible only to the user ID associated with it or root. Beyond that, any processor owned by the user or root can update it.

We definitely need for all login programs and kerberos-workstation tools to be able to have access to it.

I *thought* that the keyring was created as kernel_t when created with the keyctl() system calls, but I could be mistaken. David might have more insight here.

Comment 9 Daniel Walsh 2014-01-07 15:21:22 UTC
From an SELinux point of view the kernel keyring is assigned to the label of the process that creates it.  sshd_t, sssd_t, ssh_t, staff_t, unconfined_t.  My belief is that if a daemon is creating a keyring on behalf of a user we need to have the keyring created with the user type.  

setkeycreatecon (3)  - get or set the SELinux security context used for creating a new kernel key...

We have a function in SELinux that can do this.  Does sssd create a keyring for the user and somehow pass it to him?  

The AVC's above lead to the following allow rule.

allow sshd_t sssd_t:key { write read setattr };


Which indicates that sshd daemon needs access to the sshd_t keyring?  Is this keyring related to a user session or something different?

Comment 10 Stephan Wiesand 2014-01-09 12:38:34 UTC
This also affects at least credentials acquired when logging in on a VT (local_login_t) or with gdm (xdm_t).

Wouldn't it be best to have a different credentials cache for each session?

Comment 11 Daniel Walsh 2014-01-10 19:05:41 UTC
If the credential cache is for a logged in user to use, IE You assign it a UID, then it should have a user context, unconfined_t, staff_t, guest_t.

If the CC is to be used for a service then it should have the services label httpd_t, nfsd_t.

Bottom line if the user executes kinit in his login session the key ring he is using should have the same type as the process running kinit.

Otherwise we will not be able to write sane policy.

I want to have stuff that says 

allow login_pgm userdomain:key manage_key_perms;

But I am ending up with

allow userdomain login_pgm:key manage_key_perms;

And worse.

Comment 12 Eric Paris 2014-03-04 21:30:48 UTC
dwalsh:  two possibilities that might make things a little better....

1) type transitions on key creation, so you can get something other than the label of the creating process...

2) setkeycreatecon() interface so programs doing work on behalf of another process can explicitly set the label on the newly created key...

Do either/both of these help?  (neither exists today that I know of)

dhowells, i know we've talked about this a little...

Comment 13 Miroslav Grepl 2014-03-04 21:45:04 UTC
(In reply to Eric Paris from comment #12)
> dwalsh:  two possibilities that might make things a little better....
> 
> 1) type transitions on key creation, so you can get something other than the
> label of the creating process...

So it would require only policy changes to have login_pgm domains creating userdomain_key_t for example and

allow userdomain userdomain_key_t:key manage_key_perms;

> 
> 2) setkeycreatecon() interface so programs doing work on behalf of another
> process can explicitly set the label on the newly created key...

I believe it is a preferred solution. Also how Dan described above.

> 
> Do either/both of these help?  (neither exists today that I know of)
> 
> dhowells, i know we've talked about this a little...

Comment 14 Paul Moore 2014-03-04 22:28:52 UTC
(In reply to Miroslav Grepl from comment #13)
> (In reply to Eric Paris from comment #12)
> > 2) setkeycreatecon() interface so programs doing work on behalf of another
> > process can explicitly set the label on the newly created key...
> 
> I believe it is a preferred solution. Also how Dan described above.

We already have "/proc/self/attr/keycreate", don't we have an associated libselinux API?

Comment 15 Miroslav Grepl 2014-03-05 07:06:59 UTC
My understanding is we want to call setkeycreatecon() with a context which we get from a username for which a daemon is creating a keyring.

Comment 16 Miroslav Grepl 2014-03-05 07:13:56 UTC
(In reply to Miroslav Grepl from comment #15)
> My understanding is we want to call setkeycreatecon() with a context which
> we get from a username for which a daemon is creating a keyring.

Or how Dan described here

https://bugzilla.redhat.com/show_bug.cgi?id=1001703#c6

Comment 17 Paul Moore 2014-03-05 13:04:17 UTC
Thanks for the clarification, I thought the second possibility above was for the creation of a setkeycreatecon() interface which left me a bit confused.

Comment 18 Simo Sorce 2014-03-05 18:40:43 UTC
The problem is that these operations are done during the login phase, there is no 'user process' yet, and we do not know what pam_selinux will decide to give to a user as context, could be unconfined_t, staff_t, guest_t ... etc.

Comment 19 Eric Paris 2014-03-05 18:53:32 UTC
dwalsh: How does sshd handle this?  They manage to get the label things will run as.

Simo:  is there a way we can rearchitect things to not put a key into the kernel until we know the label of the process?

if we can't find such a way, pretty much every gov't certified installation is going to have to ban all kernel keyring usage...

Comment 20 Miroslav Grepl 2014-03-05 19:07:20 UTC
(In reply to Eric Paris from comment #19)
> dwalsh: How does sshd handle this?  They manage to get the label things will
> run as.
 
It uses 

ssh_selinux_getctxbyname() 
 getseuserbyname()
 get_default_context_with_level()

> Simo:  is there a way we can rearchitect things to not put a key into the
> kernel until we know the label of the process?
> 
> if we can't find such a way, pretty much every gov't certified installation
> is going to have to ban all kernel keyring usage...

Comment 21 Simo Sorce 2014-03-05 21:58:15 UTC
(In reply to Eric Paris from comment #19)
> dwalsh: How does sshd handle this?  They manage to get the label things will
> run as.
> 
> Simo:  is there a way we can rearchitect things to not put a key into the
> kernel until we know the label of the process?

Probably not, but we might be able to relabel the keyring after the fact ?
I was asking Dan if pam_selinux could actually do it once it determines the user's label.
 
> if we can't find such a way, pretty much every gov't certified installation
> is going to have to ban all kernel keyring usage...

Uh, why would that be ?

Comment 22 Eric Paris 2014-03-05 22:13:23 UTC
(In reply to Simo Sorce from comment #21)
> (In reply to Eric Paris from comment #19)
> > dwalsh: How does sshd handle this?  They manage to get the label things will
> > run as.
> > 
> > Simo:  is there a way we can rearchitect things to not put a key into the
> > kernel until we know the label of the process?
> 
> Probably not, but we might be able to relabel the keyring after the fact ?
> I was asking Dan if pam_selinux could actually do it once it determines the
> user's label.

Relabeling data is almost always a bad idea.  I'll certainly roll around in the back of my head and see what I think of it.  The basic idea is the problem I describe below.  Who can access the key/data before it is relabeled?  One of primary concepts of the SELinux mandatory access control system is something called 'label tranquility', aka labels on object should never change.  We do a lot of work to make sure data is labeled correctly at the beginning to take care of these races.  The question comes down to, who can relabel the key?  Can I race in and relabel a key that should belong to some other SELinux user?

>  
> > if we can't find such a way, pretty much every gov't certified installation
> > is going to have to ban all kernel keyring usage...
> 
> Uh, why would that be ?

because any time multiple labels of users are able to read/write to the same labeled object you have completely broken the security model.  If a classified user is able to write to a key and the same user logged in unclassified was able to read that data out the system is a failure.  No different that having a mechanism by which a classified user could put data in a file and have the unclassified user read it out.  Policy must be able to prove that such things are impossible.  So if we can't make sure data is never labeled in a way that information can leak between two selinux labels (of the same user) they are going to have to use policy to block all access to those resources.  And I think that's a big deal, we know we have lots of machines that need these kinds of promises   :-(

Comment 23 Simo Sorce 2014-03-05 22:41:32 UTC
Ok I see 2 options here.

A) with relabeling:
we label with a label no user is allowed to access until a login process relabels it, it stinks a bit and has pessimal failure modes in usability if the login program 'forgets' to relabel ...

B) we find a way to figure out what the label *will* be in the auth phase so sssd, pam_krb5 and other actors can find out the label before doing the AS request.


Keep in mind however that 'changing labels' may be needed anyway in some edge cases.
For example if a user label is changed and the user logs back in, but the old keyring (with the old label) is still available. Of course we can simply try to detect that and blow away the keyring and then re-create it.

Here's the problem with (B)
pam_selinux.so at the moment is executed only in the session phase, not the auth phase, plus selinux users are dumped into the right file (to be read by pam_selinux) by sssd (when a central authority like a freeipa server serves these policies) only after authentication.
So we have quite a bit of chickens and eggs around here.

Ideas ?

Comment 26 Daniel Walsh 2014-03-14 18:06:46 UTC
So I have been buried with docker issues.  But after the call to pam_selinux, the login programs can call getfscreatecon() which will return the label that the user will run with.  If sssd/login programs can not wait to create the keyring until after that call then we will have to do some kind of transition hack.

Comment 28 Miroslav Grepl 2014-11-11 14:21:08 UTC
We have workaround in 7.1 coming from Fedora.

Comment 34 Milos Malik 2015-09-29 10:53:54 UTC
Based on AVCs in comment#0, the latest policy contains the fix:

# rpm -qa selinux-policy\*
selinux-policy-sandbox-3.13.1-53.el7.noarch
selinux-policy-mls-3.13.1-53.el7.noarch
selinux-policy-minimum-3.13.1-53.el7.noarch
selinux-policy-3.13.1-53.el7.noarch
selinux-policy-doc-3.13.1-53.el7.noarch
selinux-policy-targeted-3.13.1-53.el7.noarch
selinux-policy-devel-3.13.1-53.el7.noarch
# sesearch -s sshd_t -t sssd_t -c key -p setattr -A -C
Found 2 semantic av rules:
   allow nsswitch_domain sssd_t : key { view read write search link setattr create } ; 
   allow login_pgm nsswitch_domain : key { view read write search link setattr create } ; 

# 

It seems that the rules are present for a long time. Why are we shifting the bug to RHEL-7.3?