Thread: Running Postgres 7.0.2 in a chroot environment, Linux 2.2 series, glibc

Running Postgres 7.0.2 in a chroot environment, Linux 2.2 series, glibc

From
"Samuel Greenfeld"
Date:
   I have been trying to put postgres into its own changed root (chroot) environment for security purposes.  However,
ithas been fighting me tooth and nail over this.  I would be curious to know if such a move is actually possible, since
Ihave 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
ldconfigand 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
copiedin the shell and its support utilities (really, all the things you do not want in a chroot environment), su'ed to
postgresand made the database.   I then tried starting up postmaster from the shell I did not want to have in that
environmentonce postgres was formally running.   Postgres worked fine.   So I shut down postmaster, and tried starting
itup via the chroot command.  Postgres muttered (and rightfully so) that I should not run it as root, but the chroot
commandneeds 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
notwrite another setuid program that called postgres, since it would still think it was run as root.    For lack of
anotheroption, I decided to let su function in the chrooted area.   However, it only can start an executable without
givingit parameters (if you give it a -c, it tries to run "/bin/sh -c", and that is what we're trying to avoid having
nearbypostgres - 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
asthe "shell" via su in the chroot environment.   I know I'm getting technical here - basically, I ran "chroot /jail1
supostgres -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
messagethat said that postmaster could not access the database postgres.   This seemed strange, as using the non
chrootedpostgres (/usr/local/pgsql/bin/postmaster -D /jail1/home/postgres/data ) worked to start the postmaster, as
wellas 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
calledpostgres 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.
Ido 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
otherprograms on the system.   I intended to use the "-i" option so programs outside of its jail could access it But
rightnow 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
howto 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)