我在用Rust写一个tun/tap程序。由于我不希望它以root的形式运行,所以我将CAP_NET_ADMIN添加到二进制的功能中:
$sudo setcap cap_net_admin=eip target/release/tunnel
$getcap target/release/tunnel
target/release/tunnel = cap_net_admin+eip
然而,这是行不通的。我所读到的一切都表明,这是创建调谐器所需的唯一功能,但是程序在ioctl上得到了一个EPERM。在strace中,我看到了这个错误:
openat(AT_FDCWD, "/dev/net/tun", O_RDWR|O_CLOEXEC) = 3
fcntl(3, F_GETFD) = 0x1 (flags FD_CLOEXEC)
ioctl(3, TUNSETIFF, 0x7ffcdac7c7c0) = -1 EPERM (Operation not permitted)
我已经验证了二进制文件在完全根权限下成功运行,但我不希望这需要sudo来运行。为什么CAP_NET_ADMIN在这里还不够?
作为参考,我在Linux version 4.15.0-45
上只有几种方法,我看到这个ioctl可以在内核(https://elixir.bootlin.com/linux/v4.15/source/drivers/net/tun.c#L2194)中返回EPERM,而且其中至少有一种似乎是满意的。我不知道怎么去探测其他人:
if (!capable(CAP_NET_ADMIN))
return -EPERM;
...
if (tun_not_capable(tun))
return -EPERM;
...
if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
return -EPERM;
发布于 2023-02-14 19:43:30
我在编写一个Rust程序时也遇到了同样的问题,这个程序产生了一个用于创建和管理TUN/TAP接口的tunctl
过程。
例如:
let tunctl_status = Command::new("tunctl")
.args(&["-u", "user", "-t", "tap0"])
.stdout(Stdio::null())
.status()?;
失败:
$ ./target/debug/nio
TUNSETIFF: Operation not permitted
tunctl failed to create tap network device.
即使设置了NET_ADMIN
文件功能:
$ sudo setcap cap_net_admin=+ep ./target/debug/nio
$ getcap ./target/debug/nio
./target/debug/nio cap_net_admin=ep
手册规定:
由于当作为非根用户运行时,可继承功能通常不会在execve(2)中保留,因此希望运行功能提升的助手程序的应用程序应该考虑使用环境功能,如下所述。
为了涵盖execve()
系统调用的情况,我使用了环境功能。
Ambient (因为Linux4.3)这是一组功能,在没有特权的程序的execve(2)中保留。环境能力集遵循不变条件,即如果能力既不允许也不可继承,则任何能力都不可能是环境能力。
Example解决方案:为了方便起见,我使用caps-rs
库。
// Check if `NET_ADMIN` is in permitted set.
let perm_net_admin = caps::has_cap(None, CapSet::Permitted, Capability::CAP_NET_ADMIN);
match perm_net_admin {
Ok(is_in_perm) => {
if !is_in_perm {
eprintln!("Error: The capability 'NET_ADMIN' is not in the permitted set!");
std::process::exit(1)
}
}
Err(e) => {
eprintln!("Error: {:?}", e);
std::process::exit(1)
}
}
// Note: The ambient capability set obeys the invariant that no capability can ever be ambient if it is not both permitted and inheritable.
caps::raise(
None,
caps::CapSet::Inheritable,
caps::Capability::CAP_NET_ADMIN,
)
.unwrap_or_else(fail_due_to_caps_err);
caps::raise(None, caps::CapSet::Ambient, caps::Capability::CAP_NET_ADMIN)
.unwrap_or_else(fail_due_to_caps_err);
最后,设置NET_ADMIN
文件功能就足够了:
$ sudo setcap cap_net_admin=+ep ./target/debug/nio
发布于 2019-03-17 06:41:21
我猜您的target/release/tunnel
二进制文件系统是用nosuid
选项挂载的。这也将影响文件功能,而不仅仅是setuid位。
此外,您将无法像您所做的那样占用setuid二进制或setuid二进制文件,内核在从execve()
d进程调用ptrace
时将忽略文件功能:
$ getcap tapy
tapy = cap_net_admin+eip
$ ./tapy
tapy: {tap1}
^C
$ strace -e trace=ioctl ./tapy
ioctl(3, TUNSETIFF, 0x7ffdc5b2fef0) = -1 EPERM (Operation not permitted)
tapy: ioctl TUNSETIFF: Operation not permitted
+++ exited with 1 +++
发布于 2022-11-24 21:53:57
虽然CAP_NET_ADMIN
允许您修改网络配置(如iptables
、接口等)以进行实际的攻入和网络i/o读取,但除了CAP_NET_ADMIN
之外,您还必须添加CAP_NET_RAW
功能。
他们将共同给予你你所寻求的能力。
https://unix.stackexchange.com/questions/506766
复制相似问题