Bug 2238224

Summary: Passkey authentication: SELinux transition missing
Product: [Fedora] Fedora Reporter: Alexander Bokovoy <abokovoy>
Component: selinux-policyAssignee: Zdenek Pytela <zpytela>
Status: CLOSED ERRATA QA Contact: Fedora Extras Quality Assurance <extras-qa>
Severity: high Docs Contact:
Priority: medium    
Version: 39CC: dwalsh, lvrabec, mmalik, nknazeko, omosnacek, pkoncity, vmojzis, zpytela
Target Milestone: ---   
Target Release: ---   
Hardware: x86_64   
OS: Linux   
Whiteboard:
Fixed In Version: selinux-policy-38.28-1.fc39 Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2023-09-21 00:16:03 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Bug Depends On:    
Bug Blocks: 2233246    

Description Alexander Bokovoy 2023-09-10 14:32:23 UTC
I have updated an IPA client system from Fedora 37 to Fedora 39 and cannot use passkey (FIDO2) authentication that my IPA server advertises because of SELinux AVCs.

Some of these AVCs should be addressed already with `sssd_use_usb` boolean but some aren't. In particular, `sssd_pam` process cannot launch `passkey_child` because the latter is labelled with `ipa_otpd_exec_t` and does not allow transition from `sssd_t`:

type=AVC msg=audit(1694353884.158:395): avc:  denied  { execute } for  pid=8553 comm="sssd_pam" name="passkey_child" dev="dm-1" ino=1835817 scontext=system_u:system_r:sssd_t:s0 tcontext=system_u:object_r:ipa_otpd_exec_t:s0 tclass=file permissive=1
type=AVC msg=audit(1694353884.158:396): avc:  denied  { read open } for  pid=8553 comm="sssd_pam" path="/usr/libexec/sssd/passkey_child" dev="dm-1" ino=1835817 scontext=system_u:system_r:sssd_t:s0 tcontext=system_u:object_r:ipa_otpd_exec_t:s0 tclass=file permissive=1
type=AVC msg=audit(1694353884.158:397): avc:  denied  { execute_no_trans } for  pid=8553 comm="sssd_pam" path="/usr/libexec/sssd/passkey_child" dev="dm-1" ino=1835817 scontext=system_u:system_r:sssd_t:s0 tcontext=system_u:object_r:ipa_otpd_exec_t:s0 tclass=file permissive=1
type=AVC msg=audit(1694353884.162:398): avc:  denied  { map } for  pid=8553 comm="passkey_child" path="/usr/libexec/sssd/passkey_child" dev="dm-1" ino=1835817 scontext=system_u:system_r:sssd_t:s0 tcontext=system_u:object_r:ipa_otpd_exec_t:s0 tclass=file permissive=1
type=AVC msg=audit(1694353884.172:399): avc:  denied  { read write } for  pid=8553 comm="passkey_child" name="hidraw3" dev="devtmpfs" ino=1467 scontext=system_u:system_r:sssd_t:s0 tcontext=system_u:object_r:usb_device_t:s0 tclass=chr_file permissive=1
type=AVC msg=audit(1694353884.172:400): avc:  denied  { open } for  pid=8553 comm="passkey_child" path="/dev/hidraw3" dev="devtmpfs" ino=1467 scontext=system_u:system_r:sssd_t:s0 tcontext=system_u:object_r:usb_device_t:s0 tclass=chr_file permissive=1
type=AVC msg=audit(1694353884.224:401): avc:  denied  { getattr } for  pid=8553 comm="passkey_child" path="/dev/hidraw3" dev="devtmpfs" ino=1467 scontext=system_u:system_r:sssd_t:s0 tcontext=system_u:object_r:usb_device_t:s0 tclass=chr_file permissive=1
type=AVC msg=audit(1694353884.224:402): avc:  denied  { ioctl } for  pid=8553 comm="passkey_child" path="/dev/hidraw3" dev="devtmpfs" ino=1467 ioctlcmd=0x4801 scontext=system_u:system_r:sssd_t:s0 tcontext=system_u:object_r:usb_device_t:s0 tclass=chr_file permissive=1
type=AVC msg=audit(1694353884.515:403): avc:  denied  { lock } for  pid=8553 comm="passkey_child" path="/dev/hidraw3" dev="devtmpfs" ino=1467 scontext=system_u:system_r:sssd_t:s0 tcontext=system_u:object_r:usb_device_t:s0 tclass=chr_file permissive=1

I think we are missing at least the following transition:

-----------------------
gen_require(`
    type sssd_t;
')

ipa_domtrans_otpd(sssd_t);
-----------------------

The `ipa_domtrans_otpd` interface is defined in IPA SELinux policy but also (optionally) in the main SELinux policy.

I think we should be able to add this transition safely to the main policy, under the same `sssd_use_usb` boolean.

What is still unclear to me is the need for `execute_no_trans`:

type=AVC msg=audit(1694353884.158:397): avc:  denied  { execute_no_trans } for  pid=8553 comm="sssd_pam" path="/usr/libexec/sssd/passkey_child" dev="dm-1" ino=1835817 scontext=system_u:system_r:sssd_t:s0 tcontext=system_u:object_r:ipa_otpd_exec_t:s0 tclass=file permissive=1

It cannot be covered by the `ipa_domtrans_otpd(sssd_t)` because that interface does not grant no_trans access:

-----------------------
# macro-expander ipa_domtrans_otpd
allow  bin_t:dir { getattr search open };
allow  bin_t:lnk_file { getattr read };
allow  bin_t:dir { getattr search open };
allow  bin_t:dir { getattr search open };
allow  ipa_otpd_exec_t:file { getattr open map read execute ioctl };
allow  ipa_otpd_t:process transition;
allow ipa_otpd_t :fd use;
allow ipa_otpd_t :fifo_file { getattr read write append ioctl lock };
allow ipa_otpd_t :process sigchld;
-----------------------

I guess we need this rule explicitly.

Reproducible: Always




# rpm -q selinux-policy
selinux-policy-38.27-1.fc39.noarch

# rpm -q freeipa-selinux 
freeipa-selinux-4.11.0-1.beta1.fc39.noarch

Comment 1 Zdenek Pytela 2023-09-11 07:05:27 UTC
Thank you for the analysis. I believe execute_no_trans will not be needed as it applies only in cases of execution in the caller domain.

However, when the transition is allowed:
type=AVC msg=audit(1694353884.158:395): avc:  denied  { execute } for  pid=8553 comm="sssd_pam" name="passkey_child" dev="dm-1" ino=1835817 scontext=system_u:system_r:sssd_t:s0 tcontext=system_u:object_r:ipa_otpd_exec_t:s0 tclass=file permissive=1

these permissions:
type=AVC msg=audit(1694353884.172:399): avc:  denied  { read write } for  pid=8553 comm="passkey_child" name="hidraw3" dev="devtmpfs" ino=1467 scontext=system_u:system_r:sssd_t:s0 tcontext=system_u:object_r:usb_device_t:s0 tclass=chr_file permissive=1

will be needed for ipa_otpd_t which currently is not:
# sesearch -A -s ipa_otpd_t -t usb_device_t -c chr_file 
<>

What is passkey_child expected to do? Is it reasonable to allow it read usb devices as it is to sssd? We can consider also just allow the execution without transition, i. e.

# cat local_sssd_ipaotpd.cil
(allow sssd_t ipa_otpd_exec_t (file (getattr open map read execute execute_no_trans ioctl)))
# semodule -i local_sssd_ipaotpd.cil
#

While the transition would be:
# cat local_sssd_ipaotpd_domtrans.cil
(typetransition sssd_t ipa_otpd_exec_t ipa_otpd_t)
(allow sssd_t ipa_otpd_exec_t (file (getattr open map read execute ioctl)))
(allow sssd_t ipa_otpd_t (process (transition)))
# semodule -i local_sssd_ipaotpd_domtrans.cil
#

Comment 2 Alexander Bokovoy 2023-09-11 18:17:33 UTC
passkey_child is a process provided by SSSD which implements operations with FIDO2 tokens using libfido2 library. libfido2 needs USB access for that for USB tokens to work. Since ipa-otpd context operates with passkey_child in two different modes, its context needs to be allowed to read usb devices. One mode is when ipa-otpd daemon is used on IPA server and another mode is when SSSD PAM backend uses passkey_child on IPA client. We have to cover both.

I think it would be reasonable to add this permission to ipa_otpd_t.

Comment 3 Zdenek Pytela 2023-09-14 13:10:08 UTC
So I will allow (the equivalent of)

(typetransition sssd_t ipa_otpd_exec_t ipa_otpd_t)
(allow sssd_t ipa_otpd_exec_t (file (getattr open map read execute ioctl)))
(allow sssd_t ipa_otpd_t (process (transition)))

(allow ipa_otpd_t usb_device_t (chr_file (read write)))

Can you try this local module to see if additional denials appear for ipa_otpd_t? I'd like to create a build with the permissions as complete as possible.

Comment 4 Alexander Bokovoy 2023-09-15 06:00:53 UTC
Hi Zdenek,

I tried the proposal, though I needed to fix the typetransition line to have 'process' before ipa_otpd_t. I think we still need some work as there are still missing AVCs:

type=AVC msg=audit(1694756500.690:3096): avc:  denied  { read } for  pid=432676 comm="passkey_child" name="bus" dev="sysfs" ino=8 scontext=system_u:system_r:ipa_otpd_t:s0 tcontext=system_u:object_r:sysfs_t:s0 tclass=dir permissive=1
type=AVC msg=audit(1694756500.690:3097): avc:  denied  { getattr } for  pid=432676 comm="passkey_child" path="/sys/class/hidraw/hidraw6" dev="sysfs" ino=38353 scontext=system_u:system_r:ipa_otpd_t:s0 tcontext=system_u:object_r:sysfs_t:s0 tclass=lnk_file permissive=1
type=AVC msg=audit(1694756500.690:3098): avc:  denied  { read } for  pid=432676 comm="passkey_child" name="hidraw6" dev="sysfs" ino=38353 scontext=system_u:system_r:ipa_otpd_t:s0 tcontext=system_u:object_r:sysfs_t:s0 tclass=lnk_file permissive=1
type=AVC msg=audit(1694756500.695:3099): avc:  denied  { read } for  pid=432676 comm="passkey_child" name="uevent" dev="sysfs" ino=64389 scontext=system_u:system_r:ipa_otpd_t:s0 tcontext=system_u:object_r:sysfs_t:s0 tclass=file permissive=1
type=AVC msg=audit(1694756500.695:3100): avc:  denied  { open } for  pid=432676 comm="passkey_child" path="/sys/devices/pci0000:00/0000:00:01.2/0000:20:00.0/0000:21:08.0/0000:2a:00.1/usb1/1-6/1-6.4/1-6.4:1.0/0003:262A:9123.0011/hidraw/hidraw4/uevent" dev="sysfs" ino=64389 scontext=system_u:system_r:ipa_otpd_t:s0 tcontext=system_u:object_r:sysfs_t:s0 tclass=file permissive=1
type=AVC msg=audit(1694756500.695:3101): avc:  denied  { getattr } for  pid=432676 comm="passkey_child" path="/sys/devices/pci0000:00/0000:00:01.2/0000:20:00.0/0000:21:08.0/0000:2a:00.1/usb1/1-6/1-6.4/1-6.4:1.0/0003:262A:9123.0011/hidraw/hidraw4/uevent" dev="sysfs" ino=64389 scontext=system_u:system_r:ipa_otpd_t:s0 tcontext=system_u:object_r:sysfs_t:s0 tclass=file permissive=1
type=AVC msg=audit(1694756500.695:3102): avc:  denied  { open } for  pid=432676 comm="passkey_child" path="/dev/hidraw4" dev="devtmpfs" ino=1483 scontext=system_u:system_r:ipa_otpd_t:s0 tcontext=system_u:object_r:usb_device_t:s0 tclass=chr_file permissive=1
type=AVC msg=audit(1694756500.747:3103): avc:  denied  { getattr } for  pid=432676 comm="passkey_child" path="/dev/hidraw4" dev="devtmpfs" ino=1483 scontext=system_u:system_r:ipa_otpd_t:s0 tcontext=system_u:object_r:usb_device_t:s0 tclass=chr_file permissive=1
type=AVC msg=audit(1694756500.747:3104): avc:  denied  { ioctl } for  pid=432676 comm="passkey_child" path="/dev/hidraw4" dev="devtmpfs" ino=1483 ioctlcmd=0x4801 scontext=system_u:system_r:ipa_otpd_t:s0 tcontext=system_u:object_r:usb_device_t:s0 tclass=chr_file permissive=1
type=AVC msg=audit(1694756501.093:3105): avc:  denied  { lock } for  pid=432676 comm="passkey_child" path="/dev/hidraw3" dev="devtmpfs" ino=1507 scontext=system_u:system_r:ipa_otpd_t:s0 tcontext=system_u:object_r:usb_device_t:s0 tclass=chr_file permissive=1

Following CIL file helped:

# cat local_sssd_t_ipa_otpd_t_transition.cil 
(typetransition sssd_t ipa_otpd_exec_t process ipa_otpd_t)
(allow sssd_t ipa_otpd_exec_t (file (getattr open map read execute ioctl)))
(allow sssd_t ipa_otpd_t (process (transition)))
(allow ipa_otpd_t usb_device_t (chr_file (read write getattr ioctl lock open)))
(allow ipa_otpd_t sysfs_t (file (open read getattr)))
(allow ipa_otpd_t sysfs_t (dir (read)))
(allow ipa_otpd_t sysfs_t (lnk_file (read getattr)))

Comment 5 Alexander Bokovoy 2023-09-15 06:04:29 UTC
There is one potential problem we want to address as well: SSSD should be able to perform FIDO2 authentication even on non-IPA clients. 

This means ipa_otpd_t rules would need to be used in both primary SELinux policy and in IPA policy. If we keep the subset above in the primary policy, though, we don't need to add them to IPA subpolicy, right?

Comment 6 Zdenek Pytela 2023-09-15 07:05:38 UTC
(In reply to Alexander Bokovoy from comment #5)
> There is one potential problem we want to address as well: SSSD should be
> able to perform FIDO2 authentication even on non-IPA clients. 
> 
> This means ipa_otpd_t rules would need to be used in both primary SELinux
> policy and in IPA policy. If we keep the subset above in the primary policy,
> though, we don't need to add them to IPA subpolicy, right?

Depends on what sssd does when ipa is not present: accesses the usb devices on its own? In that case selinux-policy will need
dev_read_sysfs(sssd_t)
dev_rw_generic_usb_dev(sssd_t)

and freeipa-selinux
dev_read_sysfs(ipa_otpd_t)
dev_rw_generic_usb_dev(ipa_otpd_t)

Comment 7 Alexander Bokovoy 2023-09-15 07:17:04 UTC
Yes, it does the same by using passkey_child to perform all required operations.

I submitted https://github.com/freeipa/freeipa/pull/7006 for IPA part

Comment 8 Zdenek Pytela 2023-09-15 07:56:34 UTC
OK. I've undrafted my PR as the permissions already are there for sssd_t. There will be new build for f38/f39/f40, f39 state is currently freezed though.

Comment 9 Fedora Update System 2023-09-17 20:20:28 UTC
FEDORA-2023-22190b6562 has been submitted as an update to Fedora 39. https://bodhi.fedoraproject.org/updates/FEDORA-2023-22190b6562

Comment 10 Fedora Update System 2023-09-18 02:05:15 UTC
FEDORA-2023-22190b6562 has been pushed to the Fedora 39 testing repository.
Soon you'll be able to install the update with the following command:
`sudo dnf upgrade --enablerepo=updates-testing --refresh --advisory=FEDORA-2023-22190b6562`
You can provide feedback for this update here: https://bodhi.fedoraproject.org/updates/FEDORA-2023-22190b6562

See also https://fedoraproject.org/wiki/QA:Updates_Testing for more information on how to test updates.

Comment 11 Fedora Update System 2023-09-21 00:16:03 UTC
FEDORA-2023-22190b6562 has been pushed to the Fedora 39 stable repository.
If problem still persists, please make note of it in this bug report.