我的自定义程序使用非root权限执行,用户ID为:uid: 1000 euid: 0在fork()之后,在子进程execv()中调用以运行SSH客户端服务.由于我在非特权用户下启动程序,当尝试将套接字绑定到设备时,Linux内核执行所有权限检查,导致子程序sock_setbindtodevice()在检查CAP_NET_RAW功能时出现故障,如下所示.
我正在考虑的解决方案是首先获得子进程中的root权限,执行特权操作,例如设置所需的功能,然后回退到非root用户.
这里的一个问题是,下拉到非root用户需要什么,因为当执行ssh命令时,我希望生成的DSA/RSA密钥存储在$HOME/.ssh/known_hosts而不是root/.ssh/known_hosts.
请在下面找到以下代码段:
void
global_exec_func (const char *proc_name, const char *proc_path, char **arg_list)
{
pid_t pid;
int status, euid;
struct __user_cap_header_struct cap_header_data;
cap_user_header_t cap_header = &cap_header_data;
struct __user_cap_data_struct cap_data_data;
cap_user_data_t cap_data = &cap_data_data;
pid = fork();
if (pid < 0) {
printf("%% can't fork process %s", proc_name);
return;
}
/*
* Child process.
*/
if (pid == 0) {
euid = geteuid(); /* Storing …Run Code Online (Sandbox Code Playgroud) PodSecurityPolicy 文档中的第二个示例策略包含以下 PodSecurityPolicy 片段
...
spec:
privileged: false
# Required to prevent escalations to root.
allowPrivilegeEscalation: false
# This is redundant with non-root + disallow privilege escalation,
# but we can provide it for defense in depth.
requiredDropCapabilities:
- ALL
...
Run Code Online (Sandbox Code Playgroud)
为什么删除非 root 用户的所有功能是多余的 + 禁止权限提升?您可以拥有一个没有权限提升的容器进程,它是非 root 但具有有效功能,对吗?
Docker 似乎无法做到这一点:
$ docker run --cap-add SYS_ADMIN --user 1000 ubuntu grep Cap /proc/self/status
CapInh: 00000000a82425fb
CapPrm: 0000000000000000
CapEff: 0000000000000000
CapBnd: 00000000a82425fb
CapAmb: 0000000000000000
Run Code Online (Sandbox Code Playgroud)
即使在尝试明确添加它们时,所有有效功能也已被删除。但是其他容器运行时可以实现它,所以这个评论只是 Docker 特定的吗?
的搬运工撰写文件参考描述cap_add和cap_drop在一个相当简洁时尚元素:
添加或删除容器功能。有关完整列表,请参阅 man 7 功能。
这些元素是否有顺序,即先添加后删除?或者顺序是否重要(这在 YAML 中是否完全支持字典?)?
当其中之一cap_add或cap_drop包含时会发生什么ALL?
我知道 Docker Linux 默认功能集,在https://github.com/moby/moby/blob/master/oci/caps/defaults.go#L4 中定义。
我有以下简单的测试程序来创建一个UDP套接字并将其绑定到一个特定的接口,SO_BINDTODEVICE这样我就可以bind()这么INADDR_ANY来收到UDP该接口上专门播放。
//filename: bindtest.c
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#define MY_PORT (333)
#define MY_DEVICE "enp0s3"
#define BUFFERSIZE (1000)
/* global variables */
int sock;
struct sockaddr_in sa;
struct sockaddr_in my_addr;
char buffer[BUFFERSIZE];
int main(int argc, char *argv[])
{
unsigned int echolen, clientlen;
int rc, n;
char opt_buffer[1000];
struct protoent *udp_protoent;
struct timeval receive_timeout;
int optval;
socklen_t opt_length;
sleep(1);
/* Create the UDP socket */
if ((sock …Run Code Online (Sandbox Code Playgroud) 我正在尝试为脚本提供 cap_net_bind_service Linux 功能。但是使用 setcap 似乎不起作用。
$ cat listen.sh
#!/bin/bash
python -m SimpleHTTPServer 80
$ getcap listen.sh
listen.sh =
$ sudo setcap cap_net_bind_service=+eip ./listen.sh
$ getcap listen.sh
listen.sh = cap_net_bind_service+eip
$ ls -al listen.sh
-rwxrwxr-x. 1 eric eric 43 Jul 11 23:01 listen.sh
$ ./listen.sh
Traceback (most recent call last):
File "/usr/lib64/python2.7/runpy.py", line 162, in _run_module_as_main
"__main__", fname, loader, pkg_name)
...
File "/usr/lib64/python2.7/SocketServer.py", line 434, in server_bind
self.socket.bind(self.server_address)
File "/usr/lib64/python2.7/socket.py", line 228, in meth
return getattr(self._sock,name)(*args)
socket.error: [Errno 13] …Run Code Online (Sandbox Code Playgroud) 我有一个Qt项目,它使用一个插件接口,可以很好地编译我的系统.但是,当在docker中编译同一个项目时,它停止使用Qt 5.10.1,给出了消息Error: Undefined interface.一些经过strace荷兰国际集团的moc运行,事实证明,它定义接口的头文件没有找到,因为statx在包括的文件路径调用总是返回EPERM.文档甚至没有提到如何生成此错误.
docker run --privileged 解决了这个问题,但我想避免过多的权限,所以我只想设置必要的权限.
到目前为止,我试图添加所有这些功能(即使在同一时间)但没有成功:
我在这里错过了什么吗?
UPDATE
对此的拉取请求正在等待中.
我认为我已经掌握了文件权限和功能的基础知识。但现在——那是什么?
1. 验证是否没有设置 SETUID 位:
$ ll /bin/ping
-rwxr-xr-x 1 root root 72776 Jan 31 00:11 /bin/ping*
Run Code Online (Sandbox Code Playgroud)
2. 验证是否没有设置任何功能:
$ getcap /bin/ping
/bin/ping =
Run Code Online (Sandbox Code Playgroud)
3.使用ping
$ /bin/ping google.com
PING google.com(qro01s18-in-x0e.1e100.net (2607:f8b0:4012:80a::200e)) 56 data bytes
64 bytes from qro01s18-in-x0e.1e100.net (2607:f8b0:4012:80a::200e): icmp_seq=2 ttl=120 time=418 ms
64 bytes from qro01s18-in-x0e.1e100.net (2607:f8b0:4012:80a::200e): icmp_seq=3 ttl=120 time=102 ms
Run Code Online (Sandbox Code Playgroud)
4. 验证原始套接字是否已打开:
$ strace -e socket ping google.com
socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP) = 3
socket(AF_INET6, SOCK_DGRAM, IPPROTO_ICMPV6) = 4
socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0) = 5
socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0) = 5 …Run Code Online (Sandbox Code Playgroud) 我有一个程序(https://github.com/raboof/connbeat),它依赖于/proc/[pid]/fd/*查找给定(网络)inode 的进程。
/proc/[pid]/fd只能由 root 读取,但为了安全起见,我想尽可能地放弃权限。
有没有什么方法可以(有效地)获得进程和索引节点之间的关系,而不需要完全的 root 权限?也许我可以有选择地授予某些系统调用使用功能的访问权限?
在玩弄user_namespaces(7)的示例时,我遇到了一种奇怪的行为。
应用程序user-ns-ex使用 CLONE_NEWUSER 调用clone(2),从而在新的用户命名空间中创建一个新进程。父进程将映射 ( 0 1000 1) 写入 /proc//uid_map 文件并告诉(通过管道)子进程可以继续。然后子进程执行bash。
我在这里复制了源代码。
如果我不设置任何功能或设置所有功能,应用程序将打开 /proc//uid_map 进行写入。
当我仅设置 set_capuid、set_capgid 和可选的 cap_sys_admin 时,对 open(2) 的调用失败:
设置上限:
arksnote linux-namespaces # setcap 'cap_setuid,cap_setgid,cap_sys_admin=epi' ./user-ns-ex
arksnote linux-namespaces # getcap ./user-ns-ex
./user-ns-ex = cap_setgid,cap_setuid,cap_sys_admin+eip
Run Code Online (Sandbox Code Playgroud)
尝试运行:
kamyshev@arksnote ~/workspace/personal/linux-kernel/linux-namespaces $ ./user-ns-ex -v -U -M '0 1000 1' bash
./user-ns-ex: PID of child created by clone() is 19666
ERROR: open /proc/19666/uid_map: Permission denied
About to exec bash
Run Code Online (Sandbox Code Playgroud)
无能力:
arksnote …Run Code Online (Sandbox Code Playgroud) 我们在旨在监控网络接口流量的服务器上安装了 Java 11。
初始安装 ( yum install java-11-openjdk-devel.x86_64) 后,该java命令对root和普通用户都可以正常工作。
但是,我们的 Java 应用程序不会以 root 身份运行。然后我们运行:
setcap cap_net_raw,cap_net_admin=eip /path/to/java
Run Code Online (Sandbox Code Playgroud)
它设置了功能,并且java -version以root身份运行可以正常工作。
但是在运行 setcap 之后,当我尝试以java -version普通用户身份运行时,我看到:
java: symbol lookup error: java: undefined symbol: JLI_InitArgProcessing
Run Code Online (Sandbox Code Playgroud)
这似乎是此处讨论的预期安全保护:Linux 功能 (setcap) 似乎禁用 LD_LIBRARY_PATH
但我的问题是:如何允许java在普通用户帐户下使用这些功能(网络数据包捕获)?
注意:通过取消设置功能setcap -r /path/to/java允许普通用户java再次运行- 因此问题与功能无关。
我有两个代码示例:
第一,正确运行:
#include <sys/capability.h>
#include <unistd.h>
#include <cstdio>
int main()
{
__user_cap_header_struct *hdr = new __user_cap_header_struct;
__user_cap_data_struct *data = new __user_cap_data_struct;
hdr->pid = getpid();
hdr->version = _LINUX_CAPABILITY_VERSION;
data->effective &= ~CAP_TO_MASK(CAP_IPC_LOCK);
data->permitted &= ~CAP_TO_MASK(CAP_IPC_LOCK);
data->inheritable = 0;
if (capset(hdr, data) < 0)
printf("capset failed: %m");
return 0
}
Run Code Online (Sandbox Code Playgroud)
第二,fail: Operation not permitted:
#include <sys/capability.h>
#include <unistd.h>
#include <cstdio>
int main()
{
struct __user_cap_header_struct hdr;
hdr.pid = getpid();
hdr.version = _LINUX_CAPABILITY_VERSION;
struct __user_cap_data_struct data;
data.effective &= ~CAP_TO_MASK(CAP_IPC_LOCK);
data.permitted &= ~CAP_TO_MASK(CAP_IPC_LOCK); …Run Code Online (Sandbox Code Playgroud) 我正在将我们的 yocto 从 fido 更新为 morty,并且一直在迁移食谱等以使用它,但现在我没有达到getcap目标。
我检查了 PATH 是否正确设置:
echo $PATH
/usr/sbin:/usr/bin...
Run Code Online (Sandbox Code Playgroud)
并没有getcap在/usr/bin/为应该有。
我知道 libcap 应该提供这些,并且我将 libcap 作为对多个配方的依赖,这些配方构建得很好,所以我不明白为什么它们没有安装在目标上。
我不知道从哪里开始寻找问题,因此感谢您的帮助!
我正在用 C 开发一个程序,需要临时使用一些需要提升才能获取的功能,并且不希望用户只发出 sudo,因为这将是一次性设置。
我将如何授予诸如 CAP_CHOWN 之类的功能来启用更改文件所有权或由功能保护的类似操作?
当我之前问这个问题时,它被作为重复项关闭了。被引用为原始问题的问题与我发布的问题不同。我想要一组非常具体的功能,而不是根访问权限。
linux ×8
c ×3
docker ×3
acl ×1
containers ×1
java ×1
kubernetes ×1
linux-kernel ×1
openembedded ×1
permissions ×1
ping ×1
procfs ×1
root ×1
security ×1
sockets ×1
ssh ×1
struct ×1
unix ×1
yocto ×1