不一致的 seccomp 行为
Inconsistent seccomp behavior
我正在使用 Linux 的 seccomp 包含不同的应用程序,我遇到了一个我无法解释的不一致。
我已尝试为您提供足够清晰的示例以重现该问题。
我正在创建一个 "protector module",它不允许进程调用 set_robust_list
(为了演示问题)。然后我 运行 使用 LD_PRELOAD 注入这个 "protector module" 的过程,并期望在进行这个系统调用时进程停止。
我正在基于这段代码创建一个共享对象:
#include <seccomp.h>
#include <sys/prctl.h>
static void __attribute__((constructor)) Initialization(void) {
scmp_filter_ctx ctx;
prctl(PR_SET_NO_NEW_PRIVS, 1);
ctx = seccomp_init(SCMP_ACT_ALLOW);
seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(set_robust_list), 0);
seccomp_load(ctx);
}
我正在用 gcc -shared seccompdemo.c -lseccomp -o libseccompdemo.so
构建它。
然后为了测试它,我正在构建这个可执行文件:
#define _GNU_SOURCE
#include <unistd.h>
#include <sys/syscall.h>
int main() {
syscall(SYS_set_robust_list,0,0);
return 0;
}
我正在用 gcc set_robust_list.c -o set_robust_list
构建它。
然后正如预期的那样我运行用上面的命令ninig这个可执行文件所以它被一个信号杀死:
$ LD_PRELOAD=./libseccompdemo.so ./set_robust_list
Bad system call (core dumped)
问题是当我试图用 Java 做同样的事情时。
我在 java 上调用相同的 "protector module" 它 似乎不起作用 尽管我知道 Java 正在调用 set_robust_list
来自 strace:
$ LD_PRELOAD=./libseccompdemo.so java FileWriterTest /tmp/hosts < /etc/hosts
$ echo $?
0
查看 strace 输出证明 java 正在调用 'set_robust_list':
$ strace -f java FileWriterTest /tmp/hosts < /etc/hosts 2>&1 | grep set_robust_list
set_robust_list(0x7f0b168af660, 24) = 0
[pid 12847] set_robust_list(0x7f0b168ad9e0, 24 <unfinished ...>
[pid 12847] <... set_robust_list resumed> ) = 0
[pid 12848] set_robust_list(0x7f0b12b259e0, 24) = 0
我确实看到 java 调用 clone
系统调用主要是为了创建线程。我想也许 seccomp 过滤器不是继承的,但根据文档它们是。
如果有人能向我解释为什么这不起作用,我将非常高兴。
此处供参考的是 Java 代码:
import java.io.FileOutputStream;
import java.io.IOException;
public class FileWriterTest {
public static void main(String[] args) {
try {
FileOutputStream f = new FileOutputStream(args[0]);
f.write(System.in.readAllBytes());
}
catch (IOException e) {
System.out.format("Caught exception: "+e.toString());
}
}
}
Bad system call (core dumped)
消息是您的 shell 告诉您子进程因 SIGSYS
信号而退出。但是,如果 SIGSYS
被阻塞,系统调用只会 return 一个错误,将以 application-specific 方式处理。
我猜 pthread_create
在执行时会阻塞信号,因此 set_robust_list
只会在 SIGSYS
被阻塞的情况下被调用,这与您的示例代码不同,它不修改信号掩码。
无论如何,它不应该真正影响你想要完成的事情:添加一个 System.out.println("Hello from Java!");
到你的 java main
你会看到它不会打印如果您预加载了 segcomp 过滤器,因为 main
从未按预期调用。
我正在使用 Linux 的 seccomp 包含不同的应用程序,我遇到了一个我无法解释的不一致。
我已尝试为您提供足够清晰的示例以重现该问题。
我正在创建一个 "protector module",它不允许进程调用 set_robust_list
(为了演示问题)。然后我 运行 使用 LD_PRELOAD 注入这个 "protector module" 的过程,并期望在进行这个系统调用时进程停止。
我正在基于这段代码创建一个共享对象:
#include <seccomp.h>
#include <sys/prctl.h>
static void __attribute__((constructor)) Initialization(void) {
scmp_filter_ctx ctx;
prctl(PR_SET_NO_NEW_PRIVS, 1);
ctx = seccomp_init(SCMP_ACT_ALLOW);
seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(set_robust_list), 0);
seccomp_load(ctx);
}
我正在用 gcc -shared seccompdemo.c -lseccomp -o libseccompdemo.so
构建它。
然后为了测试它,我正在构建这个可执行文件:
#define _GNU_SOURCE
#include <unistd.h>
#include <sys/syscall.h>
int main() {
syscall(SYS_set_robust_list,0,0);
return 0;
}
我正在用 gcc set_robust_list.c -o set_robust_list
构建它。
然后正如预期的那样我运行用上面的命令ninig这个可执行文件所以它被一个信号杀死:
$ LD_PRELOAD=./libseccompdemo.so ./set_robust_list
Bad system call (core dumped)
问题是当我试图用 Java 做同样的事情时。
我在 java 上调用相同的 "protector module" 它 似乎不起作用 尽管我知道 Java 正在调用 set_robust_list
来自 strace:
$ LD_PRELOAD=./libseccompdemo.so java FileWriterTest /tmp/hosts < /etc/hosts
$ echo $?
0
查看 strace 输出证明 java 正在调用 'set_robust_list':
$ strace -f java FileWriterTest /tmp/hosts < /etc/hosts 2>&1 | grep set_robust_list
set_robust_list(0x7f0b168af660, 24) = 0
[pid 12847] set_robust_list(0x7f0b168ad9e0, 24 <unfinished ...>
[pid 12847] <... set_robust_list resumed> ) = 0
[pid 12848] set_robust_list(0x7f0b12b259e0, 24) = 0
我确实看到 java 调用 clone
系统调用主要是为了创建线程。我想也许 seccomp 过滤器不是继承的,但根据文档它们是。
如果有人能向我解释为什么这不起作用,我将非常高兴。
此处供参考的是 Java 代码:
import java.io.FileOutputStream;
import java.io.IOException;
public class FileWriterTest {
public static void main(String[] args) {
try {
FileOutputStream f = new FileOutputStream(args[0]);
f.write(System.in.readAllBytes());
}
catch (IOException e) {
System.out.format("Caught exception: "+e.toString());
}
}
}
Bad system call (core dumped)
消息是您的 shell 告诉您子进程因 SIGSYS
信号而退出。但是,如果 SIGSYS
被阻塞,系统调用只会 return 一个错误,将以 application-specific 方式处理。
我猜 pthread_create
在执行时会阻塞信号,因此 set_robust_list
只会在 SIGSYS
被阻塞的情况下被调用,这与您的示例代码不同,它不修改信号掩码。
无论如何,它不应该真正影响你想要完成的事情:添加一个 System.out.println("Hello from Java!");
到你的 java main
你会看到它不会打印如果您预加载了 segcomp 过滤器,因为 main
从未按预期调用。