RHEL Engineering is moving the tracking of its product development work on RHEL 6 through RHEL 9 to Red Hat Jira (issues.redhat.com). If you're a Red Hat customer, please continue to file support cases via the Red Hat customer portal. If you're not, please head to the "RHEL project" in Red Hat Jira and file new tickets here. Individual Bugzilla bugs in the statuses "NEW", "ASSIGNED", and "POST" are being migrated throughout September 2023. Bugs of Red Hat partners with an assigned Engineering Partner Manager (EPM) are migrated in late September as per pre-agreed dates. Bugs against components "kernel", "kernel-rt", and "kpatch" are only migrated if still in "NEW" or "ASSIGNED". If you cannot log in to RH Jira, please consult article #7032570. That failing, please send an e-mail to the RH Jira admins at rh-issues@redhat.com to troubleshoot your issue as a user management inquiry. The email creates a ServiceNow ticket with Red Hat. Individual Bugzilla bugs that are migrated will be moved to status "CLOSED", resolution "MIGRATED", and set with "MigratedToJIRA" in "Keywords". The link to the successor Jira issue will be found under "Links", have a little "two-footprint" icon next to it, and direct you to the "RHEL project" in Red Hat Jira (issue links are of type "https://issues.redhat.com/browse/RHEL-XXXX", where "X" is a digit). This same link will be available in a blue banner at the top of the page informing you that that bug has been migrated.
Bug 1386233 - haproxy requires fowner capability when non-root user is used for a socket file
Summary: haproxy requires fowner capability when non-root user is used for a socket file
Keywords:
Status: CLOSED ERRATA
Alias: None
Product: Red Hat Enterprise Linux 7
Classification: Red Hat
Component: selinux-policy
Version: 7.4
Hardware: All
OS: Linux
medium
medium
Target Milestone: rc
: ---
Assignee: Lukas Vrabec
QA Contact: Milos Malik
URL:
Whiteboard:
Depends On:
Blocks: 1420851
TreeView+ depends on / blocked
 
Reported: 2016-10-18 12:58 UTC by Zdenek Pytela
Modified: 2020-09-10 09:52 UTC (History)
10 users (show)

Fixed In Version: selinux-policy-3.13.1-133.el7
Doc Type: If docs needed, set a value
Doc Text:
Clone Of:
Environment:
Last Closed: 2017-08-01 15:15:11 UTC
Target Upstream Version:
Embargoed:


Attachments (Terms of Use)


Links
System ID Private Priority Status Summary Last Updated
Red Hat Knowledge Base (Solution) 3047061 0 None None None 2017-05-22 13:26:55 UTC
Red Hat Product Errata RHBA-2017:1861 0 normal SHIPPED_LIVE selinux-policy bug fix update 2017-08-01 17:50:24 UTC

Description Zdenek Pytela 2016-10-18 12:58:42 UTC
Description of problem:
The haproxy daemon can be configured with a socket file owned by a non-root user and permissions of 0600 to give another process exclusive access to this socket in order to configure and monitor the haproxy service. With such a configuration, the service fails to start.

Version-Release number of selected component (if applicable):
haproxy-1.5.14-3.el7.x86_64
selinux-policy-3.13.1-60.el7_2.9.noarch


How reproducible:
always


Steps to Reproduce:
1. Add a line like this to default haproxy configuration:
    stats socket /var/run/haproxy.sock level admin user lb-admin mode 755

2. systemctl start haproxy; sleep 2; systemctl status haproxy -l

Actual results:
Oct 18 14:38:53 rhel7 haproxy-systemd-wrapper[11465]: haproxy-systemd-wrapper: exit, haproxy RC=15
Oct 18 14:38:53 rhel7 systemd[1]: haproxy.service: main process exited, code=exited, status=15/n/a
Oct 18 14:38:53 rhel7 systemd[1]: Stopped HAProxy Load Balancer.
Oct 18 14:38:53 rhel7 systemd[1]: Unit haproxy.service entered failed state.
Oct 18 14:38:53 rhel7 systemd[1]: haproxy.service failed.
Oct 18 14:38:57 rhel7 systemd[1]: Started HAProxy Load Balancer.
Oct 18 14:38:57 rhel7 systemd[1]: Starting HAProxy Load Balancer...
Oct 18 14:38:57 rhel7 haproxy-systemd-wrapper[11541]: haproxy-systemd-wrapper: executing /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -Ds
Oct 18 14:38:57 rhel7 haproxy-systemd-wrapper[11541]: [ALERT] 291/145544 (13356) : Starting frontend GLOBAL: cannot change UNIX socket ownership [/var/run/haproxy.sock]
Oct 18 14:38:57 rhel7 haproxy-systemd-wrapper[11541]: haproxy-systemd-wrapper: exit, haproxy RC=256

alternatively, if the socket file exists:
Oct 18 14:38:57 rhel7 haproxy-systemd-wrapper[11541]: [ALERT] 291/143857 (11543) : Starting frontend GLOBAL: error when trying to preserve previous UNIX socket [/var/run/haproxy.sock]


Expected results:
* haproxy.service - HAProxy Load Balancer
   Loaded: loaded (/usr/lib/systemd/system/haproxy.service; disabled; vendor preset: disabled)
   Active: active (running) since Tue 2016-10-18 14:40:44 CEST; 2s ago
 Main PID: 11608 (haproxy-systemd)
   CGroup: /system.slice/haproxy.service
           |-11608 /usr/sbin/haproxy-systemd-wrapper -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid
           |-11609 /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -Ds
           `-11611 /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -Ds

Oct 18 14:40:44 rhel7 systemd[1]: Started HAProxy Load Balancer.
Oct 18 14:40:44 rhel7 systemd[1]: Starting HAProxy Load Balancer...
Oct 18 14:40:44 rhel7 haproxy-systemd-wrapper[11608]: haproxy-systemd-wrapper: executing /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -Ds


Additional info:
ausearch -i -m avc,user_avc,selinux_err,user_selinux_err -ts today
----
type=SYSCALL msg=audit(10/14/16 11:01:25.317:838) : arch=x86_64 syscall=chmod success=yes exit=0 a0=0x7ffd0f227450 a1=0755 a2=0xffffffff a3=0x0 items=0 ppid=4038 pid=4039 auid=unset uid=root gid=root euid=root suid=root fsuid=root egid=root sgid=root fsgid=root tty=(none) ses=unset comm=haproxy exe=/usr/sbin/haproxy subj=system_u:system_r:haproxy_t:s0 key=(null)
type=AVC msg=audit(10/14/16 11:01:25.317:838) : avc:  denied  { fowner } for  pid=4039 comm=haproxy capability=fowner  scontext=system_u:system_r:haproxy_t:s0 tcontext=system_u:system_r:haproxy_t:s0 tclass=capability
----

sesearch -s haproxy_t -t haproxy_t -c capability --allow
----
Found 2 semantic av rules:
   allow haproxy_t haproxy_t : capability { chown dac_override kill setgid setuid net_bind_service net_admin net_raw sys_chroot sys_nice sys_resource } ;
   allow haproxy_t haproxy_t : capability net_bind_service ;
----
^^ fowner cap is missing

Making haproxy_t a permissive domain helps to start the service.

Comment 1 Daniel Borek 2016-10-18 13:19:03 UTC
This strace output shows what haproxy is up to when it fails:
464   00:52:09.832823 chown("/var/run/haproxy.sock.464.tmp", 188, 4294967295) = 0 <0.000081>
464   00:52:09.833261 chmod("/var/run/haproxy.sock.464.tmp", 0755) = -1 EPERM (Operation not permitted) <0.000466> <----- here
464   00:52:09.833829 unlink("/var/run/haproxy.sock.464.tmp") = 0 <0.000041>
464   00:52:09.833950 close(4)          = 0 <0.000105>
464   00:52:09.834119 unlink("/var/run/haproxy.sock.464.bak") = -1 ENOENT (No such file or directory) <0.000040>
464   00:52:09.834293 write(2, "[ALERT] 291/005149 (464) : ", 27) = 27 <0.000589>
464   00:52:09.835018 write(2, "Starting frontend GLOBAL: cannot change UNIX socket ownership [/var/run/haproxy.sock]\n", 86) = 86 <0.001536>

And this is where it happens in src/proto_uxst.c:

        if (!ext && path[0] && 
            (((listener->bind_conf->ux.uid != -1 || listener->bind_conf->ux.gid != -1) &&
              (chown(tempname, listener->bind_conf->ux.uid, listener->bind_conf->ux.gid) == -1)) ||
             (listener->bind_conf->ux.mode != 0 && chmod(tempname, listener->bind_conf->ux.mode) == -1))) {
                err |= ERR_FATAL | ERR_ALERT;
                msg = "cannot change UNIX socket ownership";
                goto err_unlink_temp;
        }

Comment 4 Milos Malik 2016-10-18 15:19:32 UTC
Accidentally, I found out that file context pattern for the /var/run/haproxy.sock socket is incorrect:

# semanage fcontext -l | grep '/var/run/haproxy.*sock'
/var/run/haproxy\.sock.*                           regular file       system_u:object_r:haproxy_var_run_t:s0 
# ls -l /var/run/haproxy.sock 
srwxr-xr-x. 1 haproxy root 0 Oct 18 16:40 /var/run/haproxy.sock
# matchpathcon /var/run/haproxy.sock 
/var/run/haproxy.sock	system_u:object_r:var_run_t:s0
# rm -f /var/run/haproxy.sock
# matchpathcon /var/run/haproxy.sock 
/var/run/haproxy.sock	system_u:object_r:haproxy_var_run_t:s0
# 

The file context pattern matches only regular files, but it should match sockets:

# semanage fcontext -l | grep '/var/run/haproxy.*sock'
/var/run/haproxy\.sock.*                           socket       system_u:object_r:haproxy_var_run_t:s0 
#

Comment 5 Zdenek Pytela 2016-10-20 07:20:59 UTC
Milosi,

Once the daemon manages to start, the socket file context looks like the correct one, either it is in /var/run or /var/lib/haproxy directory:

  $ ls -lZ /var/run/haproxy.sock /var/lib/haproxy/haproxy2.sock
srwxr-xr-x. root root system_u:object_r:haproxy_var_lib_t:s0 /var/lib/haproxy/haproxy2.sock
srwxr-xr-x. root root system_u:object_r:haproxy_var_run_t:s0 /var/run/haproxy.sock

Not quite sure if it is related, but the files are actually created in the /run directory which is a tmpfs linked to from /var/run. The policy does not seem to contain any reference to ^/run.

Comment 6 Milos Malik 2016-10-20 08:07:36 UTC
RHEL-6 and RHEL-7 support a feature called  file context equivalences which define that /run will be treated the same way as /var/run:

# semanage fcontext -l | grep -A 100 -i equivalence
SELinux Distribution fcontext Equivalence 

/usr/local/lib64 = /usr/lib
/etc/systemd/system = /usr/lib/systemd/system
/run/systemd/system = /usr/lib/systemd/system
/run/systemd/generator = /usr/lib/systemd/system
/var/home = /home
/var/roothome = /root
/usr/lib64 = /usr/lib
/var/lib/xguest/home = /home
/var/named/chroot/lib64 = /usr/lib
/var/named/chroot/usr/lib64 = /usr/lib
/run = /var/run
/usr/local/lib32 = /usr/lib
/lib64 = /usr/lib
/lib = /usr/lib
/run/lock = /var/lock
#

This feature is heavily used by RHSCL components.

Comment 7 Terry Bowling 2016-11-28 20:40:41 UTC
Could we confirm if this is a simple selinux policy that needs corrected?  Or does it need updated to use the file context equivalence as noted in cmt6?

Comment 8 Lukas Vrabec 2016-11-28 23:29:09 UTC
(In reply to Terry Bowling from comment #7)
> Could we confirm if this is a simple selinux policy that needs corrected? 
> Or does it need updated to use the file context equivalence as noted in cmt6?

According to comment#4 we should update haproxy context file policy.

Thanks guys for investigation.

Comment 9 Nils Fredrik Gjerull 2017-02-01 10:08:48 UTC
I set a non-root group on the haproxy socket file and are also affected by this. This prevents HAProxy from being reloaded and can also prevent haproxy from starting. I sometimes have to manually remove the socket file before I can start HAProxy.

This is in my audit.log.
---
type=AVC msg=audit(1485174334.322:170648): avc:  denied  { link } for  pid=62485 comm="haproxy" name="haproxy.sock" dev="tmpfs" ino=57340817 scontext=system_u:system_r:haproxy_t:s0 tcontext=system_u:object_r:var_run_t:s0 tclass=sock_file

type=AVC msg=audit(1485175066.360:171290): avc:  denied  { fsetid } for  pid=65435 comm="haproxy" capability=4  scontext=system_u:system_r:haproxy_t:s0 tcontext=system_u:system_r:haproxy_t:s0 tclass=capability
---

The first denial is caused by having the wrong file context (var_run_t in stead of haproxy_var_run_t), but the second I am not sure.

Perhaps the second one is a missing permission for the HAProxy process?

Comment 15 errata-xmlrpc 2017-08-01 15:15:11 UTC
Since the problem described in this bug report should be
resolved in a recent advisory, it has been closed with a
resolution of ERRATA.

For information on the advisory, and where to find the updated
files, follow the link below.

If the solution does not work for you, open a new bug report.

https://access.redhat.com/errata/RHBA-2017:1861


Note You need to log in before you can comment on or make changes to this bug.