Bug 135068
Summary: | Apache/PHP can't communicate with local postgres with selinux-policy-targeted | ||
---|---|---|---|
Product: | [Fedora] Fedora | Reporter: | David Hollis <dhollis> |
Component: | selinux-policy-targeted | Assignee: | Daniel Walsh <dwalsh> |
Status: | CLOSED RAWHIDE | QA Contact: | |
Severity: | low | Docs Contact: | |
Priority: | medium | ||
Version: | rawhide | CC: | tgl |
Target Milestone: | --- | ||
Target Release: | --- | ||
Hardware: | All | ||
OS: | Linux | ||
Whiteboard: | |||
Fixed In Version: | Doc Type: | Bug Fix | |
Doc Text: | Story Points: | --- | |
Clone Of: | Environment: | ||
Last Closed: | 2004-10-18 20:19:25 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
David Hollis
2004-10-08 13:29:04 UTC
This one is rather difficult to fix without pulling postgres into the targeted policy. One workaround might be to change postgres to put its socket somewhere like /var/run/postgresql/, and label that directory specially, and allow Apache access to that type. Hm, actually from looking at the current policy it appears Postgresql should be doing just that - but maybe that's only on Debian? I disagree with moving the socket. That has been proposed and rejected repeatedly by the upstream community, mainly on backwards-compatibility grounds, and so if we do it we are going to be effectively protocol-incompatible with clients built from source distributions. (Yeah, I know Debian is being deliberately incompatible. With my upstream-maintainer hat on, I don't like them either.) Why exactly is SELinux forbidding writes to globally writable objects in /tmp? That seems to me to be well beyond the bounds of reasonable paranoia. I don't understand why it has to be protocol-incompatible? Can't the client libraries be modified to first look in /var/run, and if that fails, then look in /tmp? This is something that should be upstream anyways. The SELinux policy is forbidding access to random objects in /tmp because they could be anything - they could be one of your email files that your editor has open, for example. A buggy postgresql daemon could then arbitrarily overwrite your email composition. Not to mention things like the X connection socket, ssh-agent sockets, etc etc. Indeed ... so are you going to insist that all those other sockets be moved? I can believe that this policy is reasonable for ordinary files in /tmp. I disagree that it is reasonable for sockets. As for your compatibility argument, "we have to modify the clients" is pretty much the definition of "we broke the protocol", in my book. The X socket should probably be moved too, yes. The ssh-agent socket is only used for communication between a single userid, so it's not a problem. As for compatibility - the point is that you change the client libraries and the server at the same time. In order for this to fail, someone would have to recompile the client libraries from an older upstream version, but still use a newer server. For that we can just say "Not supported". Especially for RHEL where we only support the binaries we ship. I don't think you got my point before. Upstream is not changing; they've had this discussion already, and if Debian couldn't persuade them to change, Red Hat won't either. So your dismissal of the issue as "older upstream versions" isn't going to fly. Yes, we can put blinders on and say that we only support our own binaries, but there is still going to be a real compatibility problem. Another issue is that the SELinux policy breaks ordinary PG builds-from-source, or externally supplied RPMs, regardless of what we do to the version we ship. Since there are a lot of application-visible incompatibilities between different major PG releases, people frequently want to run a version that is not what we include in Fedora or RHEL --- it could be either older or newer. Calling that unsupported isn't going to stop people from needing to do it. So I really think we have to adjust the policy. You didn't respond to my question about why sockets need this much protection. I see the point that sloppily written applications might put world-writable files into /tmp unintentionally, but I really doubt that any app is going to create a world-writable socket there without knowing exactly what it is doing. Apache becomes compromized, hacker gets a shell running as user apache. The Xserver has a world R/W socket in /tmp. Hacker uses this socket to break further into the system. In a tight SELinux world SELinux would have prevented this further access. Dan Exactly how does it get in the hacker's way if the world-writable socket is kept somewhere else than /tmp? It's equally world-writable either place, so I don't see that a policy that discriminates against sockets in /tmp is stopping anything. The way SELinux works is it assigns "types" to files (and in fact all objects). When a new file is created, by default the assigned type will be inherited from the parent directory it's created in. So when a process creates a file in /tmp (which has type tmp_t), the file will by default also get the tmp_t type. tmp_t is very generic, and is used for any random application that creates a file in /tmp. If the file is moved into /var/run/postgresql, which would have a type like postgresql_var_run_t, then the newly created socket would inherit that type, and we could grant Apache access to *just* postgresql_var_run_t, not all of tmp_t, which is a much wider set of files. Another alternative is to patch postgresql to assign the type itself - but that's problematic for a number of reasons. Simply moving the socket is far easier. Does that make sense? As for upstream - maybe Debian alone couldn't push this change, but it seems plausible to me that Debian and Red Hat together could. Also, SELinux isn't breaking postgresql here. We could quite easily grant Apache the requisite permissions to read the tmp_t socket. The point is that it's a very bad idea from a system security standpoint. Frankly I'd prefer the assign-the-type patch to moving the socket. None of this has convinced me that you have good reasons for preventing access to sockets in /tmp. If an application is putting a world-writable socket in /tmp, that presumably means that it *wants* to receive data from other processes on the same machine. Your arguments seem to revolve around the notion that it's a good idea to shut down interprocess communication against the express design intent of the applications involved, and I just don't buy that. (Am I going to have to explicitly security-enable every program I write that needs to talk to Postgres? No thanks.) I am even less convinced that putting the sockets somewhere else represents a gain in system security. I can see the value of being able to attach a separate security type to the postgres socket, for those who *do* want draconian restrictions on interprocess communication, but it does not follow that we have to move the socket to make that happen. What else besides parent directory can we use to determine object type? An application that creates a socket file world-readable could simply
be misconfigured or buggy. Or it could be compromised. SELinux
protects your system from this.
It is indeed a good idea to shut down socket communication paths (and
indeed all information flow) unless they are explicitly needed. For
example, the portmap daemon has no need to talk to the postgresql
socket - but just because postgres has to make it socket
world-readable, it can. That could be one beginning to privilege
escalation, because portmap runs with uid 0, and perhaps postgresql
does uid-based permission checking that allows root.
> What else besides parent
> directory can we use to determine object type?
The parent directory is the only source for the default. We can give
applications the ability to explicitly relabel files, but that opens
up its own large security problems, in addition to forcing the daemon
to carry a very SELinux-specific patch.
Changing the socket directory only breaks in a very specific, and I
think quite obscure case: older client libraries and a newer server.
The case of older client libraries and older server works, as does
newer client libraries and older server, and obviously newer client
libraries and newer server.
The parent directory is the *only* control knob available? Meseems you have a remarkably inflexible system there. Your argument that this "only breaks older clients with a newer server" is quite wrong, as you are ignoring all the points I made above. The SELinux policy breaks older servers (regardless of client), and older clients (regardless of server), period. If there were no reason for anyone to want to run anything but the latest and greatest Postgres release then maybe this would not matter, but there are plenty of reasons to want to. Simply copying the parent directory's type isn't the only option; you can define a special type for when a particular domain (e.g. postgresql_t) creates a new file in a directory (e.g. tmp_t). But this would require running postgresql in its own unique domain, instead of simply running it as unconfined_t as it is now, which means it's basically unaffected by SELinux. That's what I meant with my very first comment about pulling postgresql into the targeted policy. We could do this - but it would be much cleaner to put it in /var/run. How does it break older servers? Remember, I was suggesting to modify the client libraries to first look in /var/run, and then fall back to /tmp. It breaks older servers because they'll put their socket in /tmp, whence their clients (old or new) will be unable to communicate with them. Could we pursue the other option you mentioned about giving postgres its own domain? How is that identified exactly, is it just on the name of the program, or what? Huh? New clients will first look in /var/run, not find the socket, then fall back to /tmp. Old clients will simply look for it in /tmp in the first place. Where is the problem? Sure, the clients will *find* the socket just fine. *Using* it is where the SELinux policy breaks things. I thought we were discussing the effects of this change for upstream. As for the SELinux policy - yes, that's true, Apache won't be allowed to connect to a /tmp socket. But people affected by that can either modify the policy, or disable SELinux protection for Apache, or simply upgrade postgres. So what is the easy way to grant httpd access to the socket without A) disabling SELinux protection for httpd or B) moving the socket around, or C) waiting for postgres to be pulled into the targeted policy? I'm not terribly familiar with the selinux policy syntax and would prefer to not start tweaking them with local changes and having to maintain them every time the targeted policy is updated by RH. I have no problem executing a chcon on the socket to make it work properly with postgres and httpd. That is a tolerable workaround for the short term. Current targeted policy allows apache to read/write sockets in /tmp. This is not an ideal situation and I am thinking of adding a boolean to allow users to tighten up security. Putting sockets and files in /var/run/PACKAGENAME/ Makes doing SELinux policy easier, because we can set a security context on the /var/run/PACKAGENAME directory and then all files created in that directory will get that default context. Then we can setup policy to allow secured applications (apache) to communicate with files of that type. This is much more difficult to do when many applications share a single directory /tmp for instance. |