在Linux系统中,无特权的用户启动程序。创建的流程具有CAP_NET_RAW,CAP_NET_ADMIN
功能,模式为effective,permitted,inheritable
。
然后,此过程通过调用fork
和execv
来调用另一个程序 udhcpc 来创建子进程,但子进程不会按预期继承功能CAP_NET_RAW,CAP_NET_ADMIN
。即使在设置功能之前,我也调用了prctl(PR_SET_KEEPCAPS, 1)
。
关于如何在fork
后跟execve
继承无特权的父进程功能的任何建议?
答案 0 :(得分:12)
在execve()
上,检查正在执行的文件(在本例中为udhcpc
)的文件功能集,并与线程的功能集合并。特别是,文件的Inheritable
集合为AND
- 设置了线程的Inheritable
以确定新的Permitted
集合,文件的Effective
位必须为设置是为了从Effective
集合中复制新的Permitted
集。
这意味着在您的情况下,您必须使用setcap cap_net_raw,cap_net_admin=ei /path/to/udhcpc
来获得所需的效果(除了在父进程中设置功能外 - 不需要prctl()
)。
答案 1 :(得分:2)
根据Michael Kerrisk撰写的“Linux编程接口”(No Starch Press,2010):
从内核2.6.24开始,可以将功能附加到文件。 在内核2.6.25和2.6.26中添加了各种其他功能 为了完成功能实施。
工具sucap
和execcap
是您应该查找的内容。但是,如果我记得仅限于限制,而不是授予能力。看看:
http://www.linuxjournal.com/article/5737
和
http://lkml.indiana.edu/hypermail/linux/kernel/0503.1/2540.html
答案 2 :(得分:1)
从手册中摘录,有一些变化。根据它fork
不会改变能力。现在有一个环境设置,似乎这是你想要做的。
Ambient (since Linux 4.3):
This is a set of capabilities that are preserved across an execve(2) of a program that is not privileged. The ambient capability set obeys the invariant that no capability can ever
be ambient if it is not both permitted and inheritable.
The ambient capability set can be directly modified using
prctl(2). Ambient capabilities are automatically lowered if
either of the corresponding permitted or inheritable
capabilities is lowered.
Executing a program that changes UID or GID due to the set-
user-ID or set-group-ID bits or executing a program that has
any file capabilities set will clear the ambient set. Ambient
capabilities are added to the permitted set and assigned to
the effective set when execve(2) is called.
A child created via fork(2) inherits copies of its parent's
capability sets. See below for a discussion of the treatment of
capabilities during execve(2).
...
P'(ambient) = (file is privileged) ? 0 : P(ambient)
P'(permitted) = (P(inheritable) & F(inheritable)) |
(F(permitted) & cap_bset) | P'(ambient)
P'(effective) = F(effective) ? P'(permitted) : P'(ambient)
P'(inheritable) = P(inheritable) [i.e., unchanged]
where:
P denotes the value of a thread capability set before the
execve(2)
P' denotes the value of a thread capability set after the
execve(2)
F denotes a file capability set
cap_bset is the value of the capability bounding set (described
below).
答案 3 :(得分:0)
有一个包装程序可以执行具有特定功能的任何程序,而不必在目标程序上设置功能,这很有用。这种包装对于从构建目录运行软件(在setcap
会很麻烦)或运行类似Python的解释器(在不合适的情况下)特别有用。
如其他答案所述,环境功能可以解决此问题,但仅从内核4.3起可用。通过使包装程序直接加载目标程序而不是使用exec
,可以解决此问题。我的意思是打开可执行文件,映射相关部分,设置堆栈等,然后跳转到其代码。这是一项非常复杂的任务,但是幸运的是,Wine项目中的 wine-preloader 程序确实做到了这一点(以及与此目的无关的其他事情)。
以root用户身份运行类似这样的内容以设置包装器:
cp /usr/bin/wine-preloader /path/to/wrapper
setcap cap_net_raw+ep /path/to/wrapper # set whatever capabilities you need
现在我们有一个wine-preloader
的副本,它可以运行具有这些功能的任何程序:
/path/to/wrapper /path/to/executable arguments...
这可行,但有一些陷阱:
PATH
中找到程序。#!
)的脚本,则不起作用。wine-preloader
会显示一条消息,提示找不到内容(但仍可以正常运行该程序)。