无法让新贵服务兑现能力(7)

无法让新贵服务兑现能力(7)

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

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

作为一个简单的测试:

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

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

我将针对此问题向内核提交一个错误,因为功能(7)手册页上没有任何内容表明它不应该与进程跟踪一起使用。

答案2

一种解决方法是不使用expect fork 或expect daemon,而只是使您的守护进程成为前台进程。那么Upstart根本就不会追踪它。

相关内容