This question does not appear to be about a specific programming problem, a software algorithm, or software tools primarily used by programmers. If you believe the question would be on-topic on another Stack Exchange site, you can leave a comment to explain where the question may be able to be answered.
Closed 8 years ago.
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(4)
它可以通过 libcap 来完成 - 它提供了一个 PAM 模块 pam_cap.so。
然而,事情并没有那么简单:)
每个进程都具有三个功能集:
每个文件都有相同的功能集。当新的二进制文件被 exec()'d 时,进程的能力根据以下规则发生变化,其中:
|代表工会
(从 http://www.friedhoff.org/posixfilecaps.html 简化而来)
在大多数情况下场景中,pE'是我们唯一关心的结果。与 libcap 链接的程序可以调用 setcap() 来更改其有效上限(只要它们尝试请求的上限位于允许集中),但绝大多数程序不会显式触及其上限,因此我们必须安排上限在 exec() 后生效。
有一个具体的例子将有助于理解这里...我厌倦了必须“su”才能运行 openvpn,所以我想授予自己 CAP_NET_ADMIN 功能以允许设置路由等。
查看最后一条规则 (
pE' = fE & pP'
),很明显,要将 CAP_NET_ADMIN 包含在进程的有效集中,CAP_NET_ADMIN 必须位于文件中的有效集。因此,功能系统不允许我们简单地说“将 CAP_NET_ADMIN 授予用户 sqweek” - 程序的功能始终很重要。不过,仅位于文件的有效集中还不够,上限还需要位于进程的新许可集中。让我们看看这个规则:pP' = fP | (pI 和 fI)。因此,我们可以通过两种方法获取
pP'
中的上限,要么将 CAP_NET_ADMIN 添加到文件的 Permissible 集中,要么将其添加到文件的 Inheritable 集中并确保它位于进程的 Inheritable 集中。如果我们将其添加到文件的允许集中,则进程的初始功能变得无关紧要 - openvpn 每次运行时都会获得 CAP_NET_ADMIN,无论谁运行它。这与 setuid 类似,但提供了更细粒度的方法。不过,它不是每个用户的粒度,所以让我们看看另一个选项。
请注意第一条规则,
pI' = pI
。进程的可继承功能不受 exec() 影响。这意味着,我们只需要一个 libcap 感知程序将 CAP_NET_ADMIN 设置为可继承上限,并且从那里生成的每个进程也将具有 CAP_NET_ADMIN 可继承属性。这就是 pam 模块扮演的角色 - 它在登录期间修改可继承集,然后该集将被该用户的所有进程继承。总结一下:
cap_net_admin sqweek
行添加到/etc/security/capability.conf
中。如果该文件以前不存在,请添加另一行none *
auth required pam_cap.so
添加到/etc/pam.d/login
在进行 PAM 更改时,请确保在注销之前在单独的终端中测试您的登录,这样您就不会将自己锁定!setcap )。 cap_net_admin+ie /usr/sbin/openvpn
)openvpn
调用ip
来更改路由表等,因此需要相同的处理(setcap cap_net_admin+ie /sbin/ip
)请注意,
/etc/pam.d/login
仅管理本地登录 - 您可能需要提供/etc/pam.d。 /sshd
类似的处理。此外,当您的包管理器安装新版本的目标二进制文件时,您通过 setcap 添加的任何功能都将消失,因此您必须重新添加它们。 。It can sort of be done with libcap - it provides a PAM module pam_cap.so.
However it's not quite that simple :)
Each process has three capability sets:
Each file has the same capability sets. When a new binary is exec()'d, the capabilities of the process change according to the following rules, where:
| represents union
(simplified from http://www.friedhoff.org/posixfilecaps.html)
In most scenarios, pE' is the only result we care about. Programs that are linked against libcap can call setcap() to change their Effective caps (as long as the caps they try to request are in the Permitted set), but the vast majority of programs don't explicitly touch their caps so we have to arrange for the cap to be effective post-exec().
Having a concrete example will help understanding here... I got fed up with having to 'su' to run openvpn, so I wanted to grant myself the CAP_NET_ADMIN capability to allow the setting of routes and such.
Looking at the last rule (
pE' = fE & pP'
) it's clear that to have CAP_NET_ADMIN in the process's Effective set, CAP_NET_ADMIN must be in the file's Effective set. So, the capabilities system doesn't allow us to simply say "grant CAP_NET_ADMIN to user sqweek" - the program's capabilities are always important.Being in the file's Effective set isn't enough though, the cap also needs to be in the process's new Permitted set. Lets look at that rule:
pP' = fP | (pI & fI)
. So there's two ways we can get the cap inpP'
, either we add CAP_NET_ADMIN to the file's Permitted set, or we add it to the file's Inheritable set and make sure it is in the process's Inheritable set.If we add it to the file's Permitted set, then the process's initial capabilities become irrelevant - openvpn will get CAP_NET_ADMIN every time it runs, regardless of who runs it. This is similar to setuid, but provides a more fine-grained approach. Still, it is not a per-user granularity, so lets look at the other option.
Note the first rule,
pI' = pI
. The process's Inheritable capabilities are unaffected by exec(). What this means is, all we need is a single libcap aware program to set CAP_NET_ADMIN as an Inheritable cap, and every process spawned from there will also have CAP_NET_ADMIN Inheritable. This is the role the pam module plays - it modifies the Inheritable set during login, which is then inherited for all of that user's processes.To summarise:
cap_net_admin sqweek
to/etc/security/capability.conf
. If the file did not previously exist, add another linenone *
for a sensible default.auth required pam_cap.so
to/etc/pam.d/login
). Make sure to test your login in a separate terminal BEFORE logging out when making PAM changes so you don't lock yourself out!setcap cap_net_admin+ie /usr/sbin/openvpn
)openvpn
callsip
to change the routing table and such, so that needs the same treatment (setcap cap_net_admin+ie /sbin/ip
)Note that
/etc/pam.d/login
only governs local logins - you might want to give eg./etc/pam.d/sshd
similar treatment. Also, any capabilities you add viasetcap
will be blown away when your package manager installs a new version of the target binary so you'll have to re-add them.是的,您可以使用
setcap
为可执行文件指定功能集,这可以在运行该可执行文件时授予特定功能。来自 功能(7)手册页:
为每个用户(甚至每个组)授予功能的方法是使用 PAM 模块。 sqweek 的回答展示了如何使用
pam_cap
执行此操作。Yes, you can use
setcap
to specify a capability set for an executable, which can grant specific capabilities when that executable is run.From the capabilities(7) man page:
The way to grant capabilities per-user (or even per-group) would be with a PAM module. sqweek's answer shows how to do this using
pam_cap
.我还没有确认,但我认为 SELinux 的这个方面可能是您的答案:
http://www.lurking-grue.org/writingselinuxpolicyHOWTO.html#userpol5.1
I've not confirmed, but I think that this aspect of SELinux may be your answer:
http://www.lurking-grue.org/writingselinuxpolicyHOWTO.html#userpol5.1
看看 CapOver - 它应该可以满足您的需求。
注意:我还没有使用过它,因为它还没有被移植到 2.6.30ish 内核 API。
Have a look at CapOver - it should do what you want.
Note: I haven't used this as it's not (yet?) been ported to the 2.6.30ish kernel API.