Bug 772084
| Summary: | Can't connect to local Postgresql server from Apache httpd / PHP | ||
|---|---|---|---|
| Product: | [Fedora] Fedora | Reporter: | Yann Droneaud <yann> |
| Component: | selinux-policy-targeted | Assignee: | Miroslav Grepl <mgrepl> |
| Status: | CLOSED NOTABUG | QA Contact: | Ben Levenson <benl> |
| Severity: | unspecified | Docs Contact: | |
| Priority: | unspecified | ||
| Version: | 16 | CC: | devrim, dwalsh, hhorak, tgl |
| Target Milestone: | --- | ||
| Target Release: | --- | ||
| Hardware: | x86_64 | ||
| OS: | Linux | ||
| Whiteboard: | |||
| Fixed In Version: | Doc Type: | Bug Fix | |
| Doc Text: | Story Points: | --- | |
| Clone Of: | Environment: | ||
| Last Closed: | 2012-01-06 18:50:50 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: | |||
|
Description
Yann Droneaud
2012-01-05 21:59:19 UTC
Using strace, I'm getting
socket(PF_INET6, SOCK_STREAM, IPPROTO_IP) = 12
setsockopt(12, SOL_TCP, TCP_NODELAY, [1], 4) = 0
fcntl(12, F_SETFL, O_RDONLY|O_NONBLOCK) = 0
fcntl(12, F_SETFD, FD_CLOEXEC) = 0
setsockopt(12, SOL_SOCKET, SO_KEEPALIVE, [1], 4) = 0
connect(12, {sa_family=AF_INET6, sin6_port=htons(5432), inet_pton(AF_INET6, "::1", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, 28) = -1 EACCES (Permission denied)
close(12) = 0
socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 12
setsockopt(12, SOL_TCP, TCP_NODELAY, [1], 4) = 0
fcntl(12, F_SETFL, O_RDONLY|O_NONBLOCK) = 0
fcntl(12, F_SETFD, FD_CLOEXEC) = 0
setsockopt(12, SOL_SOCKET, SO_KEEPALIVE, [1], 4) = 0
connect(12, {sa_family=AF_INET, sin_port=htons(5432), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 EACCES (Permission denied)
close(12) = 0
But when I'm starting httpd as root using /usr/bin/httpd -k start instead of systemctl start httpd.service, everything works.
With strace I'm getting:
socket(PF_INET6, SOCK_STREAM, IPPROTO_IP) = 12
setsockopt(12, SOL_TCP, TCP_NODELAY, [1], 4) = 0
fcntl(12, F_SETFL, O_RDONLY|O_NONBLOCK) = 0
fcntl(12, F_SETFD, FD_CLOEXEC) = 0
setsockopt(12, SOL_SOCKET, SO_KEEPALIVE, [1], 4) = 0
connect(12, {sa_family=AF_INET6, sin6_port=htons(5432), inet_pton(AF_INET6, "::1", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, 28) = -1 EINPROGRESS (Operation now in progress)
poll([{fd=12, events=POLLOUT|POLLERR}], 1, -1) = 1 ([{fd=12, revents=POLLOUT}])
getsockopt(12, SOL_SOCKET, SO_ERROR, [0], [4]) = 0
getsockname(12, {sa_family=AF_INET6, sin6_port=htons(50963), inet_pton(AF_INET6, "::1", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, [28]) = 0
The PHP application is correctly working.
In fact, my problem is related to selinux: When starting httpd with /usr/bin/httpd -k start, error_log reports: SELinux policy enabled; httpd running as context unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 Instead, when started with systemctl start httpd.service, error_log reports: SELinux policy enabled; httpd running as context system_u:system_r:httpd_t:s0 So I think the fix is to try to convince Dolibarr to connect to Postgresql using local Unix socket /tmp/.s.PGSQL.5432 instead of TCP socket 127.0.0.1:5432 or [::1]:5432. Yeah, that looks like a selinux problem not a postgres problem; httpd_t ought to be allowed to make this connection. Reassigning. What AVC's are you seeing? in /var/log/audit/audit.log. I think the problem is the Postgesql sockets are in /tmp rather then in /var/run or /run. (In reply to comment #6) > What AVC's are you seeing? in /var/log/audit/audit.log. > Oh, I thought I would see them with dmesg (or in /var/log/messages). But here they are: type=SERVICE_START msg=audit(1325715234.546:1332): user pid=1 uid=0 auid=4294967295 ses=4294967295 subj=system_u:system_r:init_t:s0 msg=': comm="httpd" exe="/bin/systemd" hostname=? addr=? terminal=? res=success' type=AVC msg=audit(1325715237.030:1333): avc: denied { name_connect } for pid=30650 comm="httpd" dest=5432 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:postgresql_port_t:s0 tclass=tcp_socket type=SYSCALL msg=audit(1325715237.030:1333): arch=c000003e syscall=42 success=no exit=-13 a0=b a1=7f2523a7e300 a2=1c a3=7fffbe735a58 items=0 ppid=30648 pid=30650 auid=4294967295 uid=48 gid=48 euid=48 suid=48 fsuid=48 egid=48 sgid=48 fsgid=48 tty=(none) ses=4294967295 comm="httpd" exe="/usr/sbin/httpd" subj=system_u:system_r:httpd_t:s0 key=(null) type=AVC msg=audit(1325715237.030:1334): avc: denied { name_connect } for pid=30650 comm="httpd" dest=5432 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:postgresql_port_t:s0 tclass=tcp_socket type=SYSCALL msg=audit(1325715237.030:1334): arch=c000003e syscall=42 success=no exit=-13 a0=b a1=7f2523a7dcd0 a2=10 a3=7fffbe735a58 items=0 ppid=30648 pid=30650 auid=4294967295 uid=48 gid=48 euid=48 suid=48 fsuid=48 egid=48 sgid=48 fsgid=48 tty=(none) ses=4294967295 comm="httpd" exe="/usr/sbin/httpd" subj=system_u:system_r:httpd_t:s0 key=(null) etc. > I think the problem is the Postgesql sockets are in /tmp rather then in > /var/run or /run. It's not a problem with Unix domain socket: it seems it's working fine with them. But when using TCP socket to connect to localhost, Apache HTTPd get is denied rights to connect to 127.0.0.1:5432 or [::1]:5432. audit2allow -i /tmp/t #============= httpd_t ============== #!!!! This avc can be allowed using one of the these booleans: # httpd_can_network_connect, httpd_can_network_connect_db allow httpd_t postgresql_port_t:tcp_socket name_connect; If I looked at the setroubleshoot I see something like: sealert -a /tmp/t 100% donefound 1 alerts in /tmp/t -------------------------------------------------------------------------------- SELinux is preventing /usr/sbin/httpd from name_connect access on the tcp_socket . ***** Plugin catchall_boolean (47.5 confidence) suggests ******************* If you want to allow HTTPD scripts and modules to connect to the network using any TCP port. Then you must tell SELinux about this by enabling the 'httpd_can_network_connect' boolean. Do setsebool -P httpd_can_network_connect 1 ***** Plugin catchall_boolean (47.5 confidence) suggests ******************* If you want to allow HTTPD scripts and modules to connect to databases over the network. Then you must tell SELinux about this by enabling the 'httpd_can_network_connect_db' boolean. Do setsebool -P httpd_can_network_connect_db 1 ***** Plugin catchall (6.38 confidence) suggests *************************** If you believe that httpd should be allowed name_connect access on the tcp_socket by default. Then you should report this as a bug. You can generate a local policy module to allow this access. Do allow this access for now by executing: # grep httpd /var/log/audit/audit.log | audit2allow -M mypol # semodule -i mypol.pp # semanage boolean -l | grep http | grep database httpd_can_network_connect_db (off , off) Allow HTTPD scripts and modules to connect to databases over the network. Bottom line. Set the httpd_can_network_connect_db boolean and your good to go. # setsebool -P httpd_can_network_connect_db 1 (In reply to comment #8) > Bottom line. Set the httpd_can_network_connect_db boolean and your good to go. > # setsebool -P httpd_can_network_connect_db 1 That will allow httpd to connect to anything at all, right? That's certainly enough to solve the immediate problem, but I wonder whether it would be sensible to provide another, narrower-in-scope boolean that allows connections to only a few "likely" ports, such as 5432 for postgres and 3306 for mysql. In particular I don't like the idea that there's no way to allow database access without also turning httpd into a potential spam engine (ie, with the ability to connect to remote port 25). (In reply to comment #8) Thanks for the audit.log analysis and suggestions. But I think there's still a bug in the documentation: in the release-notes from F15 to F16 there's nothing about this new restriction. My Apache HTTPd / PHP / PostgreSQL setup was working fine in F14 but not after upgrading which was a bit disturbing. In the meantime, I have reported a bug against dolibarr and fixed it by using the Unix domain socket for local connections https://doliforge.org/tracker/?func=detail&aid=270&group_id=144 httpd_can_network_connect_db only allows you to connect to the "Database ports" not to the mail ports.
sesearch -A -s httpd_t -C -c tcp_socket| grep connect_db
WARNING: Policy would be downgraded from version 27 to 26.
DT allow httpd_t postgresql_port_t : tcp_socket { recv_msg send_msg name_connect } ; [ httpd_can_network_connect_db ]
DT allow httpd_t mssql_port_t : tcp_socket name_connect ; [ httpd_can_network_connect_db ]
DT allow httpd_t postgresql_t : tcp_socket recvfrom ; [ httpd_can_network_connect_db ]
DT allow httpd_t netlabel_peer_t : tcp_socket recvfrom ; [ httpd_can_network_connect_db ]
DT allow httpd_t oracle_port_t : tcp_socket name_connect ; [ httpd_can_network_connect_db ]
DT allow httpd_t mysqld_port_t : tcp_socket { recv_msg send_msg name_connect } ; [ httpd_can_network_connect_db ]
DT allow httpd_t firebird_port_t : tcp_socket name_connect ; [ httpd_can_network_connect_db ]
DT allow httpd_t mysqld_t : tcp_socket recvfrom ; [ httpd_can_network_connect_db ]
|