I have been trying to put postgres into its own changed root (chroot) environment 
for security purposes.  However, it has been fighting me tooth and nail over this.  I 
would be curious to know if such a move is actually possible, since I have had no 
trouble getting most other applications to run in such a situation.

   I first compiled postgres into /usr/local/pgsql on the main filesystem.  I then 
copied this directory to /jail1/usr/local/pgsql.  My intentions were to use chroot so 
anything started via it in /jail1 can not leave this directory.   This is done my 
making /jail1 the root directory, so /jail1/usr becomes /usr, etc.   I did some work 
with ldconfig and strace to hunt down all the needed libraries, set up the base 
directories (/usr, /etc, /lib, /tmp, /var, etc.) and I thought this would be it.   
/dev/zero,null, and log were provided in case postgres wanted them.   For most 
applications, this would be all I needed.   Unfortunately, luck would not make things 
this easy.

   First, I tried creating the initial database using the initdb command.   This was 
found to be a shell script, so I copied in the shell and its support utilities 
(really, all the things you do not want in a chroot environment), su'ed to postgres 
and made the database.   I then tried starting up postmaster from the shell I did not 
want to have in that environment once postgres was formally running.   Postgres worked 
fine.   So I shut down postmaster, and tried starting it up via the chroot command.  
Postgres muttered (and rightfully so) that I should not run it as root, but the chroot 
command needs root access, so this startup attempt failed.

   I wrote a shell script that temporarily set postmaster to be a set uid/gid program 
owned by the postgres user, set PGDATA, PATH, etc., appropriately, and ran postmaster 
in the chroot environment, but postgres still thought it was run root.   This kind of 
made sense (it was checking its real uid as opposed to the effective one).   It also 
meant I could not write another setuid program that called postgres, since it would 
still think it was run as root.    For lack of another option, I decided to let su 
function in the chrooted area.   However, it only can start an executable without 
giving it parameters (if you give it a -c, it tries to run "/bin/sh -c", and that is 
what we're trying to avoid having nearby postgres - a shell).    

   So I wrote a short c program to start postgres and hand it all of its parameters 
(see below).   This would be called as the "shell" via su in the chroot environment.   
I know I'm getting technical here - basically, I ran "chroot /jail1 su postgres -s 
/bin/postgres_start" where /jail1 is the directory I'm setting as root, and 
/jail1/bin/postgres_start (no, that's not a typo - that's its full path) is the 
program I wrote to start the postmaster.   This led to an error message that said that 
postmaster could not access the database postgres.   This seemed strange, as using the 
non chrooted postgres (/usr/local/pgsql/bin/postmaster -D /jail1/home/postgres/data ) 
worked to start the postmaster, as well as using a postmaster started from a chrooted 
shell ("chroot /jail1 su postgres -s /bin/sh" then "/usr/local/pgsql/bin/postmaster -D 
/home/postgres/data").   Starting up a shell in the chroot environment, su'ing to 
postgres, and starting up postmaster (which worked, but required!
 the unwanted shell), I ran createdb to make a database called postgres just to see 
what would happen.    

   Low and behold, using chroot, su, and my calling program, postgres dumped me to a 
backend prompt (see capture below).   This prompt does not seem to be the same as the 
normal SQL one.   It did not seem to know the help commands.   I do not see it 
documented anywhere, so I am quite confused as to what I found.   

   I apologize for the long email, but I would like to run postgres in an environment 
where it is isolated from the other programs on the system.   I intended to use the 
"-i" option so programs outside of its jail could access it But right now I just need 
a good way to get it started on its own where it is restricted to the /jail1 directory.

   So, short of hacking out the security checks in postgres so chroot will run 
properly, does anyone have a good idea how to do this?   I know most administrators do 
not bother to use the chroot command, but that is standard practice here.

   Sincerely,
   Samuel Greenfeld


postgres_start.c: (see "man 2 execve" if you have it)
#include<unistd.h>

int main() {

  char *envr[3];
  char *argv[2];

  envr[0]= "PATH=/usr/bin:/bin:/usr/local/pgsql/bin:."; 
  envr[1]= "PGDATA=/home/postgres/data";
  envr[2]= NULL;  

  argv[0]= "-i"; 
  argv[1]= NULL; 

  execve ("/usr/local/pgsql/bin/postmaster", argv, envr);
  return 0;

}


Command run: "chroot /jail1 su postgres -s /bin/postgres_start"
The result:
DEBUG:  Data Base System is starting up at Mon Jul 10 21:58:14 2000
DEBUG:  Data Base System was shut down at Mon Jul 10 20:55:01 2000
DEBUG:  Data Base System is in production state at Mon Jul 10 21:58:14 2000

POSTGRES backend interactive interface 
$Revision: 1.155 $ $Date: 2000/05/21 02:23:30 $

backend> \h
ERROR:  parser: parse error at or near "\"
ERROR:  parser: parse error at or near "\"
backend> 

/etc/passwd and /jail/etc/passwd line for postgres:
postgres:x:70:70:Postgres Daemon:/home/postgres:/bin/postgres_start
(account is disabled in /etc/shadow)

Reply via email to