libgit2 / pygit2

Python bindings for libgit2
https://www.pygit2.org/
Other
1.62k stars 387 forks source link

apache fork user: Error stat'ing config file '/root/.gitconfig' #339

Closed kocian closed 10 years ago

kocian commented 10 years ago

running apache fork under the different user using mod_python

import pygit2 pygit2.Repository("path/to/repo.git")

ends up with exception "Error stat'ing config file '/root/.gitconfig'"

jdavid commented 10 years ago

Could you please provide an step-by-step procedure to reproduce the problem? I have never used mod_python. If you are able to isolate the problem so it is reproducible without Apache/mod_python that would speed up the problem resolution.

carlosmn commented 10 years ago

I suspect this comes from starting up as root and switching to a user like nobody or www-data, but leaving HOME=/root such that libgit2 tries to stat that file, but the program has no permissions anymore.

Git itself (git-daemon in particular) has changed a couple of times on what they want to do here.

kocian commented 10 years ago

Yes, thats it, apache itself starts as root and switch to different user (nobody:nogroup for example)

how to reproduce:

root@beruska:/tmp/pygit2# pwd
/tmp/pygit2
root@beruska:/tmp/pygit2# ls -la
total 16
drwxrwxrwx  2 root root 4096 Feb 12 10:22 .
drwxrwxrwt 21 root root 4096 Feb 12 10:20 ..
-rw-r--r--  1 root root  110 Feb 12 09:46 handler.py
-rw-r--r--  1 root root  608 Feb 12 09:50 http.conf
root@beruska:/tmp/pygit2# cat handler.py
import pygit2

def handler(request):
    pygit2.Repository('/path/to/repo.git')

root@beruska:/tmp/pygit2# cat http.conf
# run under nobody and nogroup
User nobody
Group nogroup

<IfModule prefork.c>
    StartServers         1
    MinSpareServers      1
    MaxSpareServers      1
    MaxClients           1
    MaxRequestsPerChild  2000
</IfModule>

ServerRoot "/tmp/pygit2"
DocumentRoot "/tmp/pygit2"

# port to listen on
Listen *:9999

# where to log
ErrorLog error_log
PidFile /tmp/pygit2/httpd.pid

LoadModule python_module /usr/lib/apache2/modules/mod_python.so

# Trac configuration
<LocationMatch /[^/]+/?>
    SetHandler mod_python
    PythonHandler handler
    PythonPath "['/tmp/pygit2'] + sys.path"
</LocationMatch>

start server:

root@beruska:/tmp/pygit2# apache2 -f /tmp/pygit2/http.conf

open in browser server-hostname:9999 (in my case beruska.dev:9999)

and check /tmp/pygit2/error_log for lines

[Wed Feb 12 10:27:00 2014] [error] [client 10.0.133.198]   File "/tmp/pygit2/handler.py", line 5, in handler\n    pygit2.Repository('/path/to/repo.git')
[Wed Feb 12 10:27:00 2014] [error] [client 10.0.133.198] GitError: /path/to/repo.git: Error stat'ing config file '/root/.gitconfig'
kocian commented 10 years ago

debian dependencies: apache2-mpm-prefork, libapache2-mod-python

jdavid commented 10 years ago

Okey I was able to reproduce the problem with the given instructions.

But this looks more like a libgit2 issue, right ?

kocian commented 10 years ago

seems to me it is.. but I did not go through libgit2 api and my example is in python so I wrote it here..

jdavid commented 10 years ago

Here a simple (Python) script to reproduce the problem without Apache:

import os
import _pygit2

if __name__ == '__main__':
    os.setuid(1000)
    _pygit2.Repository('/path/to/repo')

Its output:

# python test.py 
Traceback (most recent call last):
  File "test.py", line 6, in <module>
    _pygit2.Repository('path/to/repo')
_pygit2.GitError: /path/to/repo: Error stat'ing config file '/root/.gitconfig'

Now this should be rewritten to a C program, and then open a libgit2 issue.

jdavid commented 10 years ago

Here a C test program:

#include <git2.h>
#include <stdio.h>

int
main()
{
    git_repository *repo;
    int err;
    const git_error *error;

    setuid(1000);
    err = git_repository_open(&repo, "/path/to/repo");
    if (err < 0) {
        error = giterr_last();
        printf("Error %d: %s\n", err, error->message);
    }
    return err;
}

@kocian now you can open a libgit2 issue if you wish

Though the solution may be to switch the user environment in mod_python somehow..

kocian commented 10 years ago

thanks for c code @jdavid I opened new issue in libgit2 repo https://github.com/libgit2/libgit2/issues/2122

carlosmn commented 10 years ago

@kocian While we figure out how much we're willing to forgive in the library directly, you can use the options/settings which just went into pygit2 master, and change the search paths in your application, e.g.

>>> import pygit2 as g
>>> g.Repository('.')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
_pygit2.GitError: .: Error stat'ing config file '/root/.gitconfig'
>>> g.settings.search_path[g.GIT_CONFIG_LEVEL_GLOBAL] = '/var/lib/nobody'
>>> g.Repository('.')
<pygit2.repository.Repository object at 0x7ff9f6c40cb0>
kocian commented 10 years ago

thank u very much. I did not have much time so I switched to dulwich and finished my task with that.. by the way going throw the repo history with dulwich is huge pain in..

carlosmn commented 10 years ago

The policy from the libgit2 side is to set the search paths if you're not going to be running as a normal user, which the main bindings all support now, including pygit2.

Closing, as the upstream bugs have been closed with that resolution.