git - 使用只读用户运行 git 守护进程给出 "fatal: cannot drop privileges"

标签 git git-daemon

我不确定这是否是发布的正确部分,如果不是,请告诉我应该在哪里发布以下问题:

我所在的 LAN 上有两台机器:一台装有 OS X Yosemite,充当 Git 服务器,另一台运行 Ubuntu 的笔记本电脑,充当 Git 客户端,通过 git:// 访问只读存储库。 .

我正在阅读 Git 书籍。这里https://git-scm.com/book/it/v2/Git-on-the-Server-Git-Daemon ,斯科特查康说:

For security reasons, it is strongly encouraged to have this daemon run as a user with read-only permissions to the repositories – you can easily do this by creating a new user git-ro and running the daemon as them. For the sake of simplicity we’ll simply run it as the same git user that Gitosis is running as.

运行 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

我正在 OS X 的 Terminal.app 上运行命令,我还没有设置 git 守护进程在启动时启动,因为我只是想在设置之前看看它是如何工作的。 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#d1365658927000-296看来问题与执行命令的主目录有关,不是吗?如果是这样,我应该如何处理?

编辑 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 持有两行具有相同的pid?这怎么可能?哪里有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)

最佳答案

该消息来自 git 的 daemon.c 中的函数 drop_privileges:

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");
}

请注意,如果credNULL,则此函数相当于一个大的无操作。如果cred不是NULL,则程序必须以 super 用户身份运行,并且 initgroups、setgid 和 setuid 序列旨在(正如函数名称所暗示的那样)放弃其 super 用户权限并继续以提供的用户和组身份运行。

此函数从同一文件中的 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 将不执行任何操作,并且该命令将以调用它的人(即您自己,而不是提供的用户名)的身份运行。

简而言之,除非您以 super 用户身份运行它(例如,使用 sudo),不要给它一个 --user = 选项,因为所做的就是让它在启动时失败,就像这样。

这和 $HOME 的问题都在 the manual page 中提到。同样(尽管下面的格式来 self 本地的 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>.

关于git - 使用只读用户运行 git 守护进程给出 "fatal: cannot drop privileges",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32034920/

相关文章:

git - 无法推送到 git 存储库。它卡在 "Writing Objects: 100%"之后

Git 'pre-receive' 钩子(Hook)和 'git-clang-format' 脚本可靠地拒绝违反代码风格约定的推送

git - 什么是 git 守护进程?

windows - git 如何在 Windows 上检测修改过的文件?

Git - 在 pull 请求之前修复主分支和功能分支之间的冲突

git - 在 git 中忽略文件的正确方法是什么?

git - 通过 Android Studio 提交的 Git 作者日期不正确

python - 使用 virtualenv 时在 pythonpath 中包含 Git 子模块