Запуск 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>.