Contributed by jason on from the swarm-of-unreadable-code-has-been-unleashed dept.
A recent thread on the misc@ mailing list reminded me of the obstacles faced when installing Perl CGI applications in the default OpenBSD httpd(8) chroot. Here is a brief guide at how I approached the problem by using mod_perl to import the necessary modules at execution.
Finding any Perl CGIs in the ports/www tree is the proverbial needle in a haystack. The obstacles facing chrooted CGIs are well documented. Simpler alternatives (read: php) have led to a lack of creative solutions, even at the expense of security holes and poor design practices.
I mentioned previously that I'd managed to overcome this problem for some of my own software. I talked with some colleagues about this leading up to c2k8, and we agreed that it should work as long as OpenBSD does privilege separation after mod_perl compiles its libraries and modules. This would mean that any external Perl modules an application needs could be imported when Apache is started. Fortunately for us, this is exactly what happens with OpenBSD's httpd(8).
Setting up Hatchet to use this method was incredibly simple. Beyond a few typical mod_perl directives, I just had to tell it where to find the file containing the list of modules I needed to import (startup.pl). Here is the example I include in README.OpenBSD:
<VirtualHost _default_:80> DocumentRoot /var/www/hatchet PerlModule Apache::PerlRun <Location /cgi/> SetHandler perl-script PerlHandler Apache::PerlRun PerlRequire /var/www/hatchet/cgi/startup.pl Options ExecCGI PerlSendHeader On allow from all </Location> </VirtualHost>The PerlModule and PerlRequire directives are analogous to Perl's use() and require() functions, respectively. The SetHandler and PerlHandler directives tell Apache that mod_perl should handle the content generation phase for any Perl scripts in this Location.
Because the startup.pl file is PerlRequire'd, it must return true. Any modules that your application use()'s should be included in here for importing:
use CGI (); use DBI (); use DBD::SQLite (); use HTML::Template (); use Time::Local (); use Data::Dumper (); 1;The final line guarantees that the file returns true. Parentheses following each package cause everything in that package's namespace to be imported. Because Perl is an interpreted language and mod_perl compiles your source code at startup, Apache must be restarted whenever there are changes to any affected source code. Once this is complete and configured properly, not only should your application work properly in the httpd chroot, but it will benefit from mod_perl's significant speed increase over native Perl CGI.
This article was not intended to be a comprehensive introduction to mod_perl. Rather, I hope that this motivates others to research mod_perl for themselves and see how it can be used to make their Perl applications shine on OpenBSD. Please refer to the official documentation for more information.
(Comments are closed)
By Anonymous Coward (88.72.238.247) on
Comments
By Motley Fool (MotleyFool) on
This is helpful. In the past I've loaded the appropriate Perl modules into chroot'd space.
By Anonymous Coward (66.185.204.43) on
Comments
By jason (jason) on http://www.dixongroup.net/
You mean Apache::StatINC? You might want to read this.
Comments
By Anonymous Coward (87.62.105.131) on
>
> You mean Apache::StatINC? You might want to read this.
Really like how you put the code examples in white blockquotes, that looks really neat. Way to go!
By Alexander Hall (alexander) alexander@beard.se on
In those cases, I've had to fall back to copying the lot into the chroot...
Comments
By Simon Bertrang (85.182.75.98) simon@ on
> getting all dynamical stuff loaded and parsed before privsep occurs.
>
> In those cases, I've had to fall back to copying the lot into the chroot...
That can actually hurt quite a lot.
In any case you need to find out all modules and libraries that will be
loaded at runtime, which can already be an exhaustive task unless i've
missed something obvious.
If you can preload all of them you'll be fine.
But I have one port that still isn't finished exactly because of that...
I wasn't able to figure out all modules and shared libraries it's using
at runtime as they're deeply hidden in the dependency chain.
In the end I was copying over /usr/libdata/perl5 to get it working in the
chroot at all.
I tried to think of simpler ways to solve this issue but didn't find a
nice solution to it yet.
If anyone has an idea to this i'd very much welcome a hint about it.
In general it would be nice to have some kind of tool that solves all
those problems on it's own but as it's highly language dependent i
suspect that there will be a unified solution to it (correct me if i'm wrong).
Comments
By Marc Espie (213.41.185.88) espie@openbsd.org on
The trick would be to be able to specify to install specific stuff under chroot. What I'm afraid of is that this may require lots of extra information... and since it's a knob, it won't get tested, so it won't work...
It should be as easy as possible to do, as always.
Anyways, I'm of the opinion that httpd's chroot doesn't serve any useful purpose, once you reach the point where you run complex code under httpd.
Think about it. Okay, so httpd is chroot'ed, and things run under www, in the chroot.
Cool.
Now, what's important ?
Usually, it's your webserver. And it's running several applications.
Some of them are critical.
oh, oh.
So you're fucked.
And apache is ridiculous. It's incredible that there's no actual *working* safe mechanism to run separate applications under apache as separate users in their own space.
By michael (belenus) belenus@bsdmail.de on
Tested with yabb2 and cvsweb.