我有一个名为 的守护进程foo
。我的 init 脚本/etc/init.d/foo
启动foo
守护进程并将其 pidfile 存储在 中/var/run/foo.pid
,这似乎是标准位置。因为/etc/init.d/foo
必须以 root 身份运行,所以它可以毫无问题地在 中创建和删除 pidfile /var/run
。
守护进程foo
实际上是/usr/sbin/foo
由 init 脚本以 root 身份调用但随后立即将其权限放弃给非特权foo
用户的程序。但是,我还希望此/usr/sbin/foo
程序在因严重错误而退出时删除其 pidfile。但由于它已经放弃其权限,因此它不再具有从目录中删除文件的能力/var/run
。
我目前的方法是使用seteuid
而不是setuid
来放弃我的权限,然后在退出前立即重新提升权限,以便我可以正确地从 中删除 pidfile /var/run
。但是,我遇到了很多问题,各种库和外部程序在使用不同的 euid 而不是 uid 调用时都会出现问题。
还有其他方法可以实现这一点吗?我想另一种选择是将我的 pidfile 放在 root 和foo
用户都可以写入的目录中。但是我们所有其他 pidfile 都在 中,包括以非特权用户身份运行的其他程序的 pidfile,所以我也/var/run
想将文件放在那里。foo.pid
除了使用之外还有其他方法可以做到这一点吗seteuid
?
答案1
不要将 PID 文件放入/var/run/foo.pid
,而是将其放入/var/run/foo/foo.pid
并归用户和组/var/run/foo
所有。这样,您可以在退出之前删除 pid 文件,而不必提升您的权限级别。foo
foo
但请注意,这是一种不良的安全做法,因为允许非特权应用程序破坏其文件将打开一个安全漏洞:想象一下您的应用程序被劫持(毕竟,如果不预料到应用程序可能会受到攻击,放弃特权的意义何在?)——现在,攻击者更新 pid 文件并将 sshd 的 pid 编号放在那里。现在,当系统范围的脚本(以 root 身份运行)尝试使用该 pid 文件停止您的应用程序时,它们将关闭 sshd。这只是一个例子,还有更多方法可以滥用您的系统。总之,应该创建 pid 文件前删除权限和清理 pid 文件应该由系统范围的脚本执行。——Dmitry D. Khlebnikov
更好的想法是切换到不需要 PID 文件来管理服务的 init 系统(如 systemd 或 Upstart)。
答案2
您可以在运行守护进程之前派生一个新进程。父进程仍具有特权用户root
。子进程将其权限放弃给foo
用户。此进程执行真正的守护进程工作。
父进程将在分叉子进程后创建 PID 文件,并在子进程终止时将其删除。
答案3
查看我的 Ubuntu 系统时,我发现一些已安装的软件在 /var/run 下创建了由非 root 用户拥有的目录,正如 jcollie 所建议的那样。
另一个选择是让非 root 用户拥有 pidfile,并将该文件清零而不是删除它。