os.execve(pth,args,env) and os.chroot(pth) = problems

goodnamesalltaken at gmail.com goodnamesalltaken at gmail.com
Tue Mar 7 12:04:39 EST 2006


Hello fellow python users,

I've been working on a basic implementation of a privilege separated
web server, and I've goto the point of running a basic cgi script.
Basically when the execCGI function in my Unpriv.py program is called a
few things should happen, it should fork (which it does), the stdout of
the child should be redirected to a given pipe (which it does), and the
script should execute using execve(which is has problems with).  Also
before the execCGI() fucntion is executed, a few important things
happen in __init__: os.chroot('/var/www/webroot/') the path is web
server root and os.setuid(33) where 33 is the uid of a user on my
machine.  It seems me that the os.chroot() call is messing up the
os.execve() (which executes the cgi script).  os.execve(pth, args,
envVariables) is only executed if os.path.exists(pth) returns True.
But when I run a CGI script that os.path.exists(pth) returns True for,
then os.execve(pth) python throws back the error:

File "/***/***/***/Unpriv.py", line 201, in execCGI
OSError: [Errno 2] No such file or directory

However I don't see how this is possible if os.path.exists(pth) returns
True, why is it os.execve() has problems finding it.

I thought it might be a user permission problem, but I've run it
without the chroot and with the setuid and it works fine.  So I'm
pretty sure its something to do with the chroot conflicting with the
os.execve().  Also execution privileges for the script file are also
checked before execution.


Any insight would be greatly appreciated


Here are the relevant functions of Unpriv.py


class Unpriv(object):

    def __init__(self):
        pipes = sys.argv
        self.fromParent, self.toParent = os.pipe()
        # this is just how http requested are recieved from a privilege
part and sent back
        os.dup2(int(pipes[2]), self. toParent)       ##write
        os.dup2(int(pipes[1]), self.fromParent)   ##read

       os.chroot('/var/www/webroot/')     ##chrooting
       os.setuid(33)                                  ##setuid


    def checkFileExists(self, pth):    ## just calls os.path.exists()
        return os.path.exists(pth)


    def execCGI(self, pth):
        ##
        x = pth.rfind('?')
        if x  > -1:
            path = pth[:x]
            query = pth[x+1:]
            query = query.replace('+', ' ')
        else:
            path = pth
            query = ''

        ##populate enviroment variables, not yet implemented
        envVariables = {}

        readEnd, writeEnd = os.pipe()
        parentStout = sys.stdout.fileno()
        args = ['']
        args.append(query)

	pid = os.fork()

        if pid == 0:
            ##child

            os.dup2(writeEnd, sys.stdout.fileno())     ##this works

	    ## this is the problem!
            if self.checkFileExists(pth):
                       os.execve(pth , args, envVariables)
            else:
                 ## just some debug info for me.
                 ## in fact part of pth is there
                 ##however for some reason execve doesn't see
                 print 'the directory listing is:',
os.listdir(os.getcwd())

             os._exit(0)

        else:  #parent
            #read the output from the script
            scriptOutPut = os.read(readEnd, 100000)
            #just some debug info for me
            print 'OUTPUT FROM SCRIPT EXECUTION: ' , scriptOutPut
            return scriptOutPut

Please excuse any problems with the formatting.
Thanks in advance.




More information about the Python-list mailing list