Bug 1985494

Summary: SELinux is blocking firewalld from dropping linux capabilities
Product: [Fedora] Fedora Reporter: Eric Garver <egarver>
Component: selinux-policyAssignee: Zdenek Pytela <zpytela>
Status: CLOSED RAWHIDE QA Contact: Fedora Extras Quality Assurance <extras-qa>
Severity: medium Docs Contact:
Priority: medium    
Version: 35CC: dwalsh, grepl.miroslav, lvrabec, mikhail.v.gavrilov, mmalik, omosnace, snemec, vmojzis, zpytela
Target Milestone: ---Keywords: Triaged
Target Release: ---   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of:
: 1989641 (view as bug list) Environment:
Last Closed: 2021-08-24 19:01:23 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:
Embargoed:
Bug Depends On:    
Bug Blocks: 1989641    

Description Eric Garver 2021-07-23 17:57:01 UTC
Description of problem:

Firewalld was rebased for bug 1982395. Rebase went fine other than libcap-ng (via libcap-ng-python3) not being able to manipulate the bounding set.

[root@vm-bos-fedora firewalld_rpm]# systemctl status firewalld
● firewalld.service - firewalld - dynamic firewall daemon
     Loaded: loaded (/usr/lib/systemd/system/firewalld.service; enabled; vendor preset: enabled)
     Active: active (running) since Fri 2021-07-23 13:48:30 EDT; 6s ago
       Docs: man:firewalld(1)
   Main PID: 4773 (firewalld)
      Tasks: 2 (limit: 2311)
     Memory: 25.4M
        CPU: 366ms
     CGroup: /system.slice/firewalld.service
             └─4773 /usr/bin/python3 -s /usr/sbin/firewalld --nofork --nopid
                                                                              
Jul 23 13:48:30 vm-bos-fedora systemd[1]: Starting firewalld - dynamic firewall daemon...
Jul 23 13:48:30 vm-bos-fedora firewalld[4773]: libcap-ng used by "/usr/bin/python3.9" failed dropping bounding set in capng_apply
Jul 23 13:48:30 vm-bos-fedora systemd[1]: Started firewalld - dynamic firewall daemon.


### Disabling SELinux avoids the log.

[root@vm-bos-fedora firewalld_rpm]# setenforce 0
[root@vm-bos-fedora firewalld_rpm]# systemctl restart firewalld
[root@vm-bos-fedora firewalld_rpm]# systemctl status firewalld
● firewalld.service - firewalld - dynamic firewall daemon
     Loaded: loaded (/usr/lib/systemd/system/firewalld.service; enabled; vendor preset: enabled
     Active: active (running) since Fri 2021-07-23 13:48:54 EDT; 1s ago
       Docs: man:firewalld(1)
   Main PID: 5357 (firewalld)
      Tasks: 2 (limit: 2311)
     Memory: 22.0M
        CPU: 298ms
     CGroup: /system.slice/firewalld.service
             └─5357 /usr/bin/python3 -s /usr/sbin/firewalld --nofork --nopid

Jul 23 13:48:53 vm-bos-fedora systemd[1]: Starting firewalld - dynamic firewall daemon...
Jul 23 13:48:54 vm-bos-fedora systemd[1]: Started firewalld - dynamic firewall daemon.


Version-Release number of selected component (if applicable):


How reproducible: always


Steps to Reproduce:
1. start firewalld-1.0.0

Actual results: error log


Expected results: no log

Comment 1 Zdenek Pytela 2021-07-26 13:16:41 UTC
After applying a workaround:

# cat local_firewalld.cil
(allow firewalld_t firewalld_t (capability (setpcap)))
(allow firewalld_t firewalld_t (process (setcap)))
# semodule -i local_firewalld.cil

the issue is gone:

# systemctl status firewalld --full --no-pager
● firewalld.service - firewalld - dynamic firewall daemon
     Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled; vendor preset: enabled)
     Active: active (running) since Mon 2021-07-26 09:13:54 EDT; 21s ago
       Docs: man:firewalld(1)
   Main PID: 648 (firewalld)
      Tasks: 2 (limit: 2108)
     Memory: 29.2M
        CPU: 901ms
     CGroup: /system.slice/firewalld.service
             └─648 /usr/bin/python3 -s /usr/sbin/firewalld --nofork --nopid

Jul 26 09:13:54 ci-vm-10-0-139-226.hosted.upshift.rdu2.redhat.com systemd[1]: Starting firewalld - dynamic firewall daemon...
Jul 26 09:13:54 ci-vm-10-0-139-226.hosted.upshift.rdu2.redhat.com systemd[1]: Started firewalld - dynamic firewall daemon.

# ausearch -i -m avc -ts boot
<no matches>

Eric,

Will firewalld-1.0 eventually land in F34, too?

Comment 2 Eric Garver 2021-07-26 13:32:24 UTC
(In reply to Zdenek Pytela from comment #1)
> After applying a workaround:
> 
> # cat local_firewalld.cil
> (allow firewalld_t firewalld_t (capability (setpcap)))
> (allow firewalld_t firewalld_t (process (setcap)))
> # semodule -i local_firewalld.cil
> 
> the issue is gone:
> 
> # systemctl status firewalld --full --no-pager
> ● firewalld.service - firewalld - dynamic firewall daemon
>      Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled;
> vendor preset: enabled)
>      Active: active (running) since Mon 2021-07-26 09:13:54 EDT; 21s ago
>        Docs: man:firewalld(1)
>    Main PID: 648 (firewalld)
>       Tasks: 2 (limit: 2108)
>      Memory: 29.2M
>         CPU: 901ms
>      CGroup: /system.slice/firewalld.service
>              └─648 /usr/bin/python3 -s /usr/sbin/firewalld --nofork --nopid
> 
> Jul 26 09:13:54 ci-vm-10-0-139-226.hosted.upshift.rdu2.redhat.com
> systemd[1]: Starting firewalld - dynamic firewall daemon...
> Jul 26 09:13:54 ci-vm-10-0-139-226.hosted.upshift.rdu2.redhat.com
> systemd[1]: Started firewalld - dynamic firewall daemon.
> 
> # ausearch -i -m avc -ts boot
> <no matches>

Thanks for the quick response!

> Eric,
> 
> Will firewalld-1.0 eventually land in F34, too?

No. It has breaking changes. It will never go to f34.

Comment 3 Zdenek Pytela 2021-07-26 14:28:40 UTC
Looking deeply at the denials:

----
type=PROCTITLE msg=audit(07/26/2021 09:09:29.689:855) : proctitle=/usr/bin/python3 -s /usr/sbin/firewalld --nofork --nopid
type=SYSCALL msg=audit(07/26/2021 09:09:29.689:855) : arch=x86_64 syscall=prctl success=yes exit=0 a0=PR_CAPBSET_DROP a1=chown a2=0x0 a3=0x0 items=0 ppid=1 pid=3783 auid=unset uid=root gid=root euid=root suid=root fsuid=root egid=root sgid=root fsgid=root tty=(none) ses=unset comm=firewalld exe=/usr/bin/python3.10 subj=system_u:system_r:firewalld_t:s0 key=(null)
type=AVC msg=audit(07/26/2021 09:09:29.689:855) : avc:  denied  { setpcap } for  pid=3783 comm=firewalld capability=setpcap  scontext=system_u:system_r:firewalld_t:s0 tcontext=system_u:system_r:firewalld_t:s0 tclass=capability permissive=1
----
type=PROCTITLE msg=audit(07/26/2021 09:09:29.691:856) : proctitle=/usr/bin/python3 -s /usr/sbin/firewalld --nofork --nopid
type=CAPSET msg=audit(07/26/2021 09:09:29.691:856) : pid=3783 cap_pi=net_admin,net_raw cap_pp=net_admin,net_raw cap_pe=net_admin,net_raw cap_pa=none
type=SYSCALL msg=audit(07/26/2021 09:09:29.691:856) : arch=x86_64 syscall=capset success=yes exit=0 a0=0x5578c56a2fa8 a1=0x5578c56a2fb0 a2=0x7f2d7f42f570 a3=0x7f2d7f6b3ac0 items=0 ppid=1 pid=3783 auid=unset uid=root gid=root euid=root suid=root fsuid=root egid=root sgid=root fsgid=root tty=(none) ses=unset comm=firewalld exe=/usr/bin/python3.10 subj=system_u:system_r:firewalld_t:s0 key=(null)
type=AVC msg=audit(07/26/2021 09:09:29.691:856) : avc:  denied  { setcap } for  pid=3783 comm=firewalld scontext=system_u:system_r:firewalld_t:s0 tcontext=system_u:system_r:firewalld_t:s0 tclass=process permissive=1

I see prctl() and capset(): Can you tell me what is it used for so that we have it properly documented?
Possibly we can use the firewalld comment:

+        # attempt to drop Linux capabilities to a minimal set:
+        #   - CAP_NET_ADMIN
+        #   - CAP_NET_RAW

Also, as a result, drop the remaining dac_read_search from selinux-policy:

# sesearch -A -s firewalld_t -c capability
allow firewalld_t firewalld_t:capability { dac_read_search net_admin net_raw setpcap };

Comment 4 Eric Garver 2021-07-26 14:47:54 UTC
(In reply to Zdenek Pytela from comment #3)
> Looking deeply at the denials:
> 
> ----
> type=PROCTITLE msg=audit(07/26/2021 09:09:29.689:855) :
> proctitle=/usr/bin/python3 -s /usr/sbin/firewalld --nofork --nopid
> type=SYSCALL msg=audit(07/26/2021 09:09:29.689:855) : arch=x86_64
> syscall=prctl success=yes exit=0 a0=PR_CAPBSET_DROP a1=chown a2=0x0 a3=0x0
> items=0 ppid=1 pid=3783 auid=unset uid=root gid=root euid=root suid=root
> fsuid=root egid=root sgid=root fsgid=root tty=(none) ses=unset
> comm=firewalld exe=/usr/bin/python3.10 subj=system_u:system_r:firewalld_t:s0
> key=(null)
> type=AVC msg=audit(07/26/2021 09:09:29.689:855) : avc:  denied  { setpcap }
> for  pid=3783 comm=firewalld capability=setpcap 
> scontext=system_u:system_r:firewalld_t:s0
> tcontext=system_u:system_r:firewalld_t:s0 tclass=capability permissive=1
> ----
> type=PROCTITLE msg=audit(07/26/2021 09:09:29.691:856) :
> proctitle=/usr/bin/python3 -s /usr/sbin/firewalld --nofork --nopid
> type=CAPSET msg=audit(07/26/2021 09:09:29.691:856) : pid=3783
> cap_pi=net_admin,net_raw cap_pp=net_admin,net_raw cap_pe=net_admin,net_raw
> cap_pa=none
> type=SYSCALL msg=audit(07/26/2021 09:09:29.691:856) : arch=x86_64
> syscall=capset success=yes exit=0 a0=0x5578c56a2fa8 a1=0x5578c56a2fb0
> a2=0x7f2d7f42f570 a3=0x7f2d7f6b3ac0 items=0 ppid=1 pid=3783 auid=unset
> uid=root gid=root euid=root suid=root fsuid=root egid=root sgid=root
> fsgid=root tty=(none) ses=unset comm=firewalld exe=/usr/bin/python3.10
> subj=system_u:system_r:firewalld_t:s0 key=(null)
> type=AVC msg=audit(07/26/2021 09:09:29.691:856) : avc:  denied  { setcap }
> for  pid=3783 comm=firewalld scontext=system_u:system_r:firewalld_t:s0
> tcontext=system_u:system_r:firewalld_t:s0 tclass=process permissive=1
> 
> I see prctl() and capset(): Can you tell me what is it used for so that we
> have it properly documented?

I guess these are being called by libcap-ng. firewalld does not call them directly. The support to drop capabilities was done for bug 1914945.

upstream change: https://github.com/firewalld/firewalld/pull/825/files#diff-78f6008d0ea9d25efff2f0b4d47f56167a9a643807f652977db7990a1af2f8f4

> Possibly we can use the firewalld comment:
> 
> +        # attempt to drop Linux capabilities to a minimal set:
> +        #   - CAP_NET_ADMIN
> +        #   - CAP_NET_RAW
> 
> Also, as a result, drop the remaining dac_read_search from selinux-policy:
> 
> # sesearch -A -s firewalld_t -c capability
> allow firewalld_t firewalld_t:capability { dac_read_search net_admin net_raw
> setpcap };

I don't recall why dac_read_search was originally there.

Comment 5 Zdenek Pytela 2021-07-30 07:46:36 UTC
*** Bug 1988138 has been marked as a duplicate of this bug. ***

Comment 6 Zdenek Pytela 2021-07-30 07:46:43 UTC
*** Bug 1988139 has been marked as a duplicate of this bug. ***

Comment 7 Zdenek Pytela 2021-08-06 11:57:14 UTC
I've submitted a Fedora PR to address the issue:
https://github.com/fedora-selinux/selinux-policy/pull/826

Comment 8 Ben Cotton 2021-08-10 13:46:42 UTC
This bug appears to have been reported against 'rawhide' during the Fedora 35 development cycle.
Changing version to 35.