我想以非特权用户身份运行一项服务,但它需要绑定到系统端口号(即小于 1024),所以我给它setcap 'cap_net_bind_service=+ep' <path for service>
,一切顺利。
问题是,在启动时,服务会读取环境变量,但由于某种原因,当它有 时无法执行此操作cap_net_bind_service
。因此,如果有两个可执行文件副本,一个有cap_net_bind_service
,一个没有 ,则只有没有 的那个可以读取环境变量。
就好像有一组默认的功能允许读取环境变量,但是当我赋予它时,exe 会失去该功能cap_net_bind_service
。是这样吗,还是有其他原因?我可能需要为服务提供哪些额外的功能,以便它可以读取环境变量?能力.h弹出的是“允许环境变量读取”?
答案1
我找到了问题的根源。简而言之,该二进制文件正在使用secure_getenv
访问环境变量。
当二进制文件在“安全执行”模式 ( ) 下运行时,这将返回null
,而不是访问变量AT_SECURE=1
。设置任何功能都会导致它在此模式下运行。
确认二进制文件正在secure_getenv
使用readelf
:
readelf -a <path for service> | grep getenv
00000040ac28 004b00000007 R_X86_64_JUMP_SLO 0000000000000000 secure_getenv@GLIBC_2.17 + 0
00000040ad90 007a00000007 R_X86_64_JUMP_SLO 0000000000000000 getenv@GLIBC_2.2.5 + 0
75: 0000000000000000 0 FUNC GLOBAL DEFAULT UND secure_getenv@GLIBC_2.17 (6)
122: 0000000000000000 0 FUNC GLOBAL DEFAULT UND getenv@GLIBC_2.2.5 (2)
确认它正在使用环境变量在安全执行模式下运行(多么讽刺!)LD_DEBUG=all
和/或LD_SHOW_AUXV
(参见man ld.so
)。
如果不是,则LD_SHOW_AUXV
产生设置为 0 的输出。在安全执行模式下运行时AT_SECURE
没有输出。LD_SHOW_AUXV
通常,当它在安全执行模式下运行时,也会有输出,LD_DEBUG
当不在安全执行模式下运行时,也不会有输出。但是,如果/etc/suid-debug
存在(空文件,使用触摸创建),则LD_DEBUG
在安全执行模式下运行时会产生输出。
看man getauxval
有关AT_SECURE
安全执行模式的更多信息。