Запуск git daemon с правами только для чтения дает "fatal: не может отбросить привилегии"

Я не уверен, если это правильный раздел, где размещать сообщения, если это не так, пожалуйста, скажите мне, где я должен опубликовать следующую проблему:

Я нахожусь в локальной сети с двумя компьютерами: один с OS X Yosemite на нем, который действует как сервер Git, и другой ноутбук с Ubuntu, который действует как клиент Git, получающий доступ к репозиторию только для чтения через git://,

Я читаю Git Book. Здесь https://git-scm.com/book/it/v2/Git-on-the-Server-Git-Daemon Скотт Чакон говорит:

По соображениям безопасности настоятельно рекомендуется, чтобы этот демон запускался как пользователь с правами доступа только для чтения к репозиториям - это можно легко сделать, создав нового пользователя git-ro и запустив демона под ним. Для простоты мы просто запустим его как того же пользователя git, что и Gitosis.

Команда для запуска демона git:

/usr/bin/git daemon --base-path=/opt/git/ /opt/git/

Теперь я могу прекрасно выполнить команду без каких-либо проблем с моим текущим пользователем на компьютере с OS X (мой текущий пользователь также является администратором), и запускается демон только для чтения Git, но как только я пытаюсь запустить его как непривилегированный пользователь который имеет доступ только для чтения к репо (в моем случае пользователь git-ro, как предлагается в книге), git daemon жалуется и не запускается:

$ /usr/bin/git daemon \
    --user=git-ro --group=git-ro \
    --reuseaddr \
    --base-path=/opt/git/ \
    /opt/git/
fatal: cannot drop privileges

Я запускаю команды в Terminal.app OS X, я еще не настроил git daemon для запуска при запуске, потому что я просто хотел бы посмотреть, как он работает, прежде чем настраивать все. Что значит cannot drop privileges значит и как я могу разрешить и запустить демон с непривилегированным пользователем, у которого есть права только для чтения в хранилище?

Спасибо за внимание!

Изменить: здесь http://git.661346.n2.nabble.com/regression-quot-96b9e0e3-config-treat-user-and-xdg-config-permission-problems-as-errors-quot-busted-n-td7582202.html кажется, что проблема связана с каталогом HOME, который выполняет команду, не так ли? Если так, как я должен действовать в моем случае?

Редактировать 2: вот команда, запускаемая с sudo:

$ sudo git daemon --reuseaddr --user=git-ro --group=git-ro --base-path=/opt/git/ /opt/git/

Демон запускается, однако у меня запущены три процесса, два из которых от имени root:

$ ps aux | grep "git-ro"
git-ro           1477   0.0  0.0  2471332   1424 s000  S+    7:34PM   0:00.01 git-daemon --reuseaddr --user=git-ro --group=git-ro --base-path=/opt/git/ /opt/git/
root             1476   0.0  0.0  2464108   1608 s000  S+    7:34PM   0:00.01 git daemon daemon --reuseaddr --user=git-ro --group=git-ro --base-path=/opt/git/ /opt/git/
root             1475   0.0  0.1  2452612   2612 s000  S+    7:34PM   0:00.01 sudo git daemon --reuseaddr --user=git-ro --group=git-ro --base-path=/opt/git/ /opt/git/

Почему демон по-прежнему работает как root с двумя процессами? Это ожидаемое поведение или я должен улучшить?

Редактировать 3: Далее, почему, если вместо этого я бегу lsof и проверить, что слушает на порту 9418, я вижу две строки, проведенные git-ro с таким же пидом? Как это возможно? Где есть git daemon процессы запускались как root ушли?

$ sudo lsof -i :9418
COMMAND    PID   USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
git-daemo 1477 git-ro    5u  IPv4 0xce9b2f57e8d5af93      0t0  TCP *:git (LISTEN)
git-daemo 1477 git-ro    6u  IPv6 0xce9b2f57e60cacc3      0t0  TCP *:git (LISTEN)

1 ответ

Решение

Сообщение приходит от функции drop_privileges в Git's daemon.c:

static void drop_privileges(struct credentials *cred)
{
        if (cred && (initgroups(cred->pass->pw_name, cred->gid) ||
            setgid (cred->gid) || setuid(cred->pass->pw_uid)))
                die("cannot drop privileges");
}

Обратите внимание, что если cred является NULLэта функция представляет собой большой запрет. Если cred не NULL программа должна быть запущена от имени суперпользователя, а последовательность initgroups, setgid и setuid предназначена (как следует из названия функции), чтобы отбросить свои привилегии суперпользователя и продолжить работу вместо нее как предоставленный пользователь и группа.

Эта функция вызывается из serve в том же файле, который вызывается из main когда демон запускается:

int main(int argc, char **argv)
{
...
        return serve(&listen_addr, listen_port, cred);

cred аргумент здесь передается через serve в drop_privileges и, следовательно, представляет прямой интерес. Так где же cred приготовься? Давайте посмотрим немного больше на main, где cred инициализируется, а затем модифицируется:

        struct credentials *cred = NULL;
...
        if (user_name)
                cred = prepare_credentials(user_name, group_name);

Так что теперь нам нужно найти где user_name установлен и / или изменен:

        const char *pid_file = NULL, *user_name = NULL, *group_name = NULL;
...
                if (skip_prefix(arg, "--user=", &v)) {
                        user_name = v;
                        continue;
                }

На данный момент, даже не глядя на skip_prefixдолжно быть довольно очевидно, что это исходит от --user=... параметр, который вы предоставляете, и если вы не предоставите один, user_name останется NULL чтобы cred останется NULL чтобы drop_privileges ничего не будет делать, и команда будет выполняться так же, как и тот, кто ее вызывал (т. е. вы сами, а не предоставленное имя пользователя).

Короче говоря, если вы не используете это как суперпользователь (например, с sudoне давай --user= вариант, так как все, что будет делать, это сделать его при запуске, как это.

Это и проблема с $HOME оба упомянуты на странице руководства (хотя форматирование ниже от моего местного git help daemon вывод, а не ссылка на kernel.org):

   --user=<user>, --group=<group>
       Change daemon's uid and gid before entering the service loop. When
       only --user is given without --group, the primary group ID for the
       user is used. The values of the option are given to getpwnam(3) and
       getgrnam(3) and numeric IDs are not supported.

       Giving these options is an error when used with --inetd; use the
       facility of inet daemon to achieve the same before spawning git
       daemon if needed.

       Like many programs that switch user id, the daemon does not reset
       environment variables such as $HOME when it runs git programs, e.g.
       upload-pack and receive-pack. When using this option, you may also
       want to set and export HOME to point at the home directory of
       <user> before starting the daemon, and make sure any Git
       configuration files in that directory are readable by <user>.
Другие вопросы по тегам