无法使 upstart 服务满足功能要求(7)

无法使 upstart 服务满足功能要求(7)

我正在开发一个由 upstart(Ubuntu 14.04)启动的守护进程,它需要以非特权用户身份运行(为了安全),但绑定特权端口 443。

我用它setcap来设置CAP_NET_BIND_SERVICE可执行文件(不是脚本)的功能。我在允许、有效和继承集(setcap 'cap_net_bind_service+eip' EXEC)中设置它。

我可以su将其交给非特权用户,并直接运行它,它运行完美。它正确绑定了端口,并/proc/PID/status显示了设置了位的正确功能掩码0x400

但是当我通过 upstart 启动服务时,它无法使用为二进制文件指定的功能运行,并且bind()会失败(EPERM)。/proc/PID/status显示功能掩码全部为 0。

有任何想法吗?

答案1

我现在认为这是一个错误,与 upstart 使用“expect daemon”启动服务的方式有关(即启动时分叉两次的服务)。我注意到,如果我对使用 capabilities(7) 的进程使用 strace,功能也会被忽略。我怀疑 upstart 为了确定要等待的 PID,会跟踪使用“expect daemon”指定的服务足够长的时间以获取 PID,这会导致内核功能机制失败。因此,错误在于功能与进程跟踪交互的方式,以及 upstart 在用“expect daemon”启动服务时使用进程跟踪的事实(这是假设)。

作为一个简单的测试:

  1. 写一个小C程序绑定到端口 443(不能使用具有功能(7)的解释型语言,如 python)。
  2. 以非root身份运行它,并发现由于缺乏权限而绑定失败。
  3. 为您的程序(以 root 身份运行setcap 'cap_net_bind_service+epi' PROGRAM
  4. 以非root身份运行它,并看到它现在已成功。
  5. 现在用 strace 运行它,发现它现在失败了。

i(请注意,在步骤 3 中,严格来说,不需要为该测试修改继承的功能集(标志),但对于forks()诸如我的守护进程之类的进程则需要修改)。

此行为对于避免特权攻击是必要的,但会使 Upstart 行为与功能不兼容。

相关内容