8

在 Linux 系统中,非特权用户启动程序。创建的进程CAP_NET_RAW,CAP_NET_ADMIN具有模式为的功能effective,permitted,inheritable。然后,该进程通过调用forkexecv调用另一个程序udhcpc创建一个子进程,但该子进程没有CAP_NET_RAW,CAP_NET_ADMIN按预期继承这些功能。即使在设置我调用的功能之前prctl(PR_SET_KEEPCAPS, 1)

关于如何继承非特权父进程的能力的任何fork建议execve

4

4 回答 4

13

在 上execve(),正在执行的文件的文件能力集(在本例中为udhcpc)被检查并与线程的能力集相结合。特别是,文件的Inheritable集合AND与线程的Inheritable集合一起确定新集合,并且必须设置Permitted文件的位以便从集合中复制新集合。EffectiveEffectivePermitted

这意味着在您的情况下,您必须使用setcap cap_net_raw,cap_net_admin=ei /path/to/udhcpc才能获得所需的效果(除了在父进程中设置功能 -prctl()不是必需的)。

于 2011-05-30T06:44:45.313 回答
2

根据 Michael Kerrisk 的“Linux 编程接口”(No Starch Press,2010):

从内核 2.6.24 开始,可以将功能附加到文件。为了完成功能实现,内核 2.6.25 和 2.6.26 中添加了各种其他功能。

这些工具 是您应该查找的sucapexeccap但是,如果我记得它们仅限于限制,而不是授予功能。看着 :

http://www.linuxjournal.com/article/5737

http://lkml.indiana.edu/hypermail/linux/kernel/0503.1/2540.html

于 2011-08-25T12:48:34.750 回答
2

摘自手册,有一些改动。据它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>

       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).
于 2016-06-04T08:25:32.693 回答
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打印一条关于无法找到某些东西的消息(但它仍然可以正常运行程序)。
于 2019-06-24T21:49:34.333 回答