Project

General

Profile

Actions

suEXEC alternative: ExecWrap

ExecWrap

This rest of this page deals specifically with the suEXEC code distributed with the Apache web server, and with PHP: we want PHP executed as the target user.

Apache suEXEC

See the documentation of suEXEC
In a nutshell, suEXEC will take care that all things are fine, cleanup the environment and be sure some conditions are met, and then setuid. Among the things suEXEC checks are that:
  • the script you will execute belongs to the target user/group and that nobody else can modify it;
  • the directory where this script is belongs to the target user/group, and that nobody can write anything there;
  • suEXEC is launched from this target directory.

As a consequence, there's quite a bit of wrapping involved: at some point you need to change your current directory to the target directory to launch suEXEC, and it's simpler to launch a script (belonging to the target) user that will eventually launch the php executable.

So there are two script in the way, which is rather clumsy. On the bright side it's quite flexible.

Lighttpd Configuration

lighttpd.conf contains this piece:

$HTTP["host"] =~ "^mywebsite.org$" {
   fastcgi.server = ( ".php" =>
      ( "localhost" =>
         ( "socket" => "/var/run/fastcgi/myuser.socket",
           "bin-path" => "/usr/local/etc/suexec/myuser.sh",
           "idle-timeout" => 30,
           "min-procs" => 3,
           "max-procs" => 10,
           "max-load-per-proc" => 4
        ) ) )
}

/usr/local/etc/suexec/myuser.sh is the script that will launch suEXEC (see bellow). /var/run/fastcgi/ is the directory what will contains the UNIX sockets used by lighttpd to communicate with the FastCGI backends. It is important that only the www user can write in that directory.

Wrapping suEXEC

So, lighttpd runs /usr/local/etc/suexec/myuser.sh every now and then. lighttpd must be able to execute this script. This script takes care of what's needed to launch suEXEC: cd'ing to the target directory.

/usr/local/etc/suexec/myuser.sh:

#!/bin/sh

user=myuser
group=mygroup

cd /usr/local/www/data/$user
/usr/local/sbin/suexec $user $group php.sh

Please note: /usr/local/www/data/ is not chosen at random - suEXEC will only accept to run scripts in a specific directory that is configured at run time. Depending on the distribution you run, it may be something different. Run suexec -V as root to be sure:

$ sudo suexec -V
 -D DOC_ROOT="/usr/local/www/data" 
 -D GID_MIN=1000
 -D HTTPD_USER="www" 
 -D LOG_EXEC="/var/log/httpd-suexec.log" 
 -D LOGIN_CAP
 -D SAFE_PATH="/bin:/usr/bin:/usr/local/bin" 
 -D UID_MIN=1000
 -D USERDIR_SUFFIX="public_html" 

The script must be in the DOC_ROOT directory you see here.

The user's script: php.sh

This script and the directory it's in must belong to the target user/group (here,
myuser and mygroup).

/usr/local/www/data/myuser/php.sh:

#!/bin/sh

exec /usr/local/bin/php

To be on the safe side, you probably want to:

chown -R myuser:mygroup /usr/local/www/data/myuser/

Troubleshooting

Apart from the lighttpd log files, pieces of information about what's going on are available in the /var/log/httpd-suexec.log file (see the output of suexec -V, it may be different for you). Usually problems are related to permissions and ownership of the files.

Updated by gstrauss over 3 years ago · 10 revisions