运行 git 具有只读用户的守护程序提供 "fatal: cannot drop privileges"

Running git daemon with read only user gives "fatal: cannot drop privileges"

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

我在局域网上有两台机器:一台有 OS X Yosemite 作为 Git 服务器,另一台笔记本电脑 运行ning Ubuntu 作为 Git 客户端通过 git://.

访问只读存储库

我正在阅读 Git 这本书。这里 https://git-scm.com/book/it/v2/Git-on-the-Server-Git-Daemon,Scott Chacon 说:

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 读取的命令没有任何问题只有守护进程启动,但是一旦我尝试 运行 它作为一个非特权用户,它对 repo 具有只读访问权限(在我的例子中,用户 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 问题似乎与执行命令的HOME 目录有关,不是吗?如果是这样,我应该如何处理?

编辑 2:这里是带有 sudo 的命令 运行:

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

守护进程启动,但是我有它的三个进程 运行ning,其中两个作为 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 程序必须 运行ning 作为超级用户,并且 initgroups、setgid 和 setuid 序列是有意的(正如函数名称所暗示的那样)放弃其超级用户权限并继续 运行ning 而不是作为提供的用户和组。

此函数在同一文件中从 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在哪里设置and/or修改:

        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 的问题也在 the manual page 中提到(尽管下面的格式来自我的本地 git help daemon 输出而不是 kernel.org link):

   --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>.