Bug 1989641

Summary: SELinux is blocking firewalld from dropping linux capabilities
Product: Red Hat Enterprise Linux 9 Reporter: Tomas Dolezal <todoleza>
Component: selinux-policyAssignee: Zdenek Pytela <zpytela>
Status: CLOSED CURRENTRELEASE QA Contact: Milos Malik <mmalik>
Severity: medium Docs Contact:
Priority: medium    
Version: 9.0CC: dwalsh, egarver, extras-qa, grepl.miroslav, jjaburek, jstodola, lvrabec, mikhail.v.gavrilov, mmalik, omosnace, snemec, ssekidde, vmojzis, zpytela
Target Milestone: betaKeywords: AutoVerified, Triaged
Target Release: 9.0 Beta   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: selinux-policy-34.1.14-1.el9 Doc Type: No Doc Update
Doc Text:
Story Points: ---
Clone Of: 1985494 Environment:
Last Closed: 2021-12-07 21:35:16 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: 1985494    
Bug Blocks: 1914945, 1942219    

Description Tomas Dolezal 2021-08-03 16:11:06 UTC
As part of implementation of bug 1914945 to enable firewalld to drop selected capabilities, selinux-policy has to be updated to allow this.

In enforcing mode, capabilities are not dropped and selinux denial is logged. Firewalld is quiet about failure to drop those caps, they can be observed via pscap as shown bellow.

Version-Release number of selected component (if applicable):
firewalld-1.0.0-1.el9.noarch (SCRATCH BUILD TASKID#38491834)
selinux-policy-34.1.10-1.el9.noarch

# systemctl restart firewalld
# pscap | grep firewall
1     2144  root        firewalld           full +
# setenforce 0
# systemctl restart firewalld
# pscap | grep firewall
1     2102  root        firewalld           net_admin, net_raw +

# ausearch -m avc -r | audit2allow 

#============= firewalld_t ==============
allow firewalld_t self:capability setpcap;
allow firewalld_t self:process setcap;


+++ This bug was initially created as a clone of Bug #1985494 +++

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

--- Additional comment from Zdenek Pytela on 2021-07-26 15:16:41 CEST ---

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?

--- Additional comment from Eric Garver on 2021-07-26 15:32:24 CEST ---

(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.

--- Additional comment from Zdenek Pytela on 2021-07-26 16:28:40 CEST ---

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 };

--- Additional comment from Eric Garver on 2021-07-26 16:47:54 CEST ---

(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 2 Zdenek Pytela 2021-08-06 11:57:45 UTC
I've submitted a Fedora PR to address the issue:
https://github.com/fedora-selinux/selinux-policy/pull/826

Comment 3 Eric Garver 2021-08-11 18:15:34 UTC
(In reply to Zdenek Pytela from comment #2)
> I've submitted a Fedora PR to address the issue:
> https://github.com/fedora-selinux/selinux-policy/pull/826

firewalld also needs CAP_SYS_MODULE as per 1990271 comment 14. However, it looks like firewalld never had that listed in the selinux-policy.

Do you know if it also needs to be added?

Comment 4 Zdenek Pytela 2021-08-12 16:12:19 UTC
(In reply to Eric Garver from comment #3)
> (In reply to Zdenek Pytela from comment #2)
> > I've submitted a Fedora PR to address the issue:
> > https://github.com/fedora-selinux/selinux-policy/pull/826
> 
> firewalld also needs CAP_SYS_MODULE as per 1990271 comment 14. However, it
> looks like firewalld never had that listed in the selinux-policy.
> 
> Do you know if it also needs to be added?

I suppose it is. Is there a Fedora build available already?

Comment 5 Eric Garver 2021-08-12 18:45:19 UTC
(In reply to Zdenek Pytela from comment #4)
> (In reply to Eric Garver from comment #3)
> > (In reply to Zdenek Pytela from comment #2)
> > > I've submitted a Fedora PR to address the issue:
> > > https://github.com/fedora-selinux/selinux-policy/pull/826
> > 
> > firewalld also needs CAP_SYS_MODULE as per 1990271 comment 14. However, it
> > looks like firewalld never had that listed in the selinux-policy.
> > 
> > Do you know if it also needs to be added?
> 
> I suppose it is. Is there a Fedora build available already?

Here is a Fedora 35 build: https://koji.fedoraproject.org/koji/taskinfo?taskID=73738461