Example 5-1 shows a sample setuid Apache startup script.
Note the line marked WORKAROUND, which fixes an obscure error when starting a mod_perl-enabled Apache, by setting the real UID to the effective UID. Without this workaround, a mismatch between the real and the effective UIDs causes Perl to croak on the -e switch.
This script depends on using a version of Perl that recognizes and emulates the setuid bits. This script will do different things depending on whether it is named start_httpd, stop_httpd, or restart_httpd; use symbolic links to create the names in the filesystem.
#!/usr/bin/perl -T use strict; # These constants will need to be adjusted. my $PID_FILE = '/home/httpd/httpd_perl/logs/httpd.pid'; my $HTTPD = '/home/httpd/httpd_perl/bin/httpd_perl '; $HTTPD .= '-d /home/httpd/httpd_perl'; # These prevent taint checking failures $ENV{PATH} = '/bin:/usr/bin'; delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; # This sets the real to the effective ID, and prevents # an obscure error when starting apache/mod_perl $< = $>; # WORKAROUND $( = $) = 0; # set the group to root too # Do different things depending on our name my $name = $0; $name =~ m|([^/]+)$|; if ($name eq 'start_httpd') { system $HTTPD and die "Unable to start HTTPD"; print "HTTP started.\n"; exit 0; } # extract the process id and confirm that it is numeric my $pid = `cat $PID_FILE`; $pid =~ /^(\d+)$/ or die "PID $pid not numeric or not found"; $pid = $1; if ($name eq 'stop_httpd') { kill 'TERM', $pid or die "Unable to signal HTTPD"; print "HTTP stopped.\n"; exit 0; } if ($name eq 'restart_httpd') { kill 'HUP', $pid or die "Unable to signal HTTPD"; print "HTTP restarted.\n"; exit 0; } # script is named differently die "Script must be named start_httpd, stop_httpd, or restart_httpd.\n";
 
Continue to: