Paul Querna wrote:
Michael Clark wrote:
Hi Folks,
I posted a note about my privilege separation patches the other day
and received some good private help/feedback, and have now made the
patches a considerable amount more portable and they are using apr
much more extensively.
The patch is now fully modular and allows mod_privsep to be compiled
out (although it does add some additional hooks to the core).
First off, I want to say, this is a very cool set of patches, and I
would like to see it or some derivative go into trunk!
Thanks. BTW - I have filled out and sent in a CLA about a week ago.
I'll send an email later about issues that I think should be addressed
before a possibility of this or some derivative going in (perhaps just
the required vfs hooks).
There are also alternative approaches I'd like to mention - such as an
mpm with non-privileged accept threads that forward the accepted socket
to a dynamic pool of processes running as the desired uid - they could
be created on demand (out of band by a privileged parent process) for
authenticated users with a minimum pool size of 0 and timed out and
killed after so many seconds of inactivity. This would also get rid of
BIG_SECURITY_HOLE as there would be no race with the accept thread
running as root (as with the other approaches I've seen).
The advantage of this approach over the privsep patches' approach would
be higher performance as there would be no ping/pong for each stat/open
call although I don't think it would be quite as anally secure as my
approach (That said, it could still check a signed token in a separated
process before forwarding the accepted socket to reduce the potential of
a buffer overflow exploit in one of the unprivileged processes allowing
access as another uid). To do it this way we would need the ability to
forward a request mid-processing (need to see host headers, translated
path and authenticate before forwarding it) - so the process that gets
forwarded the accepted socket would need to receive the headers out of
band (perhaps in the message sending the accepted socket). This approach
would be more intrusive to the core than my current approach I think
(although it wouldn't need the modules to use hooked io functions).
There would still be the issue of needing the stat calls in
ap_directory_walk needing to be done with higher privs before the
map_to_storage and access hooks have completed (so this approach may
still benefit from the privilege separated process - it is also needed
for system authentication in the PAM case if using /etc/shadow).
Although I think the privsep patch approach is valid given a pluggable
vfs io layer which has the request_rec as context - it could then be
done unobtrusively. Perhaps I should add some notes to the
PrivilegeSeparation wiki page on wiki.apache.org?
Due to the nature of the patch it has to change some core code
to use privileged wrapper calls for file io. I can't see any way
around this - I have tried to minimise the impact by adding hooks.
How you stubbed out the file io seems fine for the lifetime of 2.2.x
and maybe 2.4.x, but in the long run, I believe we need to support
some kind of "VFS" layer, to make all IO pluggable. (open file,
directory listing, etc etc).
Yes. It would be nice to get some core changes that would support this
patch as an external module until it is ready (and make the filesystem
IO layer generally pluggable). Either way, I think having a pluggable IO
layer would be a good idea.
The core patch could be made more palatable by making the apr IO hook
API not privsep specific. So we could change the core patch as follows:
* Rename server/privsep.c -> server/vfs.c
* Rename include/privsep.h -> include/vfs.h
* Rename layered APR io calls from ap_privsep_<foo> to ap_vfs_<foo>
* Change context argument on io hooks calls from privsep_token_t* to
request_rec*
Shall I run up a patch set like this? This could perhaps be a starting
point for a vfs (I believe request_rec* would be the correct context for
these vfs indirected calls?).
There is only one place I need more context information than the
request_rec structure - this is for the apr_stat calls in
ap_directory_walk before the map_to_storage and authentication hooks
have completed. I can work around this somehow (by adding the preauth
stat token to the request before doing these stat calls - or perhaps
hook ap_directory_walk in this vfs).
Later the hook dispatcher in vfs.c (server/privsep.c) could be modified
to use the context/config from request_rec to work out where to dispatch
the io calls rather than the simple dispatch all calls here approach I
have currently. We could then have an ap_vfs_mount API to hook which
paths we want to go where.
Preferably Async IO and pluggable too :-)
The current approach doesn't preclude async IO as the returned file
descriptors inside of the apr_file_t could have async io operations
performed on them.
Although, yes a more general approach would be needed to get the
apr_file_open/apr_stat/etc to be performed asynchronously.
Dream mode on:
<Location /upload>
Dav On
Mount privsep:/opt/upload
</Location>
# static content
<Location /mysite>
Mount /www/content
</Location>
# proxied content
<Location /foo>
Mount balancer://bigcluster
</Location>
Anyways, if all IO was abstracted with a little VFS layer, it would
mean all modules would now work with your privilege separation code,
rather than just the core, mod_autoindex, and any other modules you
write patches for :-)
I like this idea.
Then the io hook layer (vfs) becomes justifiable on its own - and more
code could be converted to use it.
Michael.