Issue
I am working on containing different applications using Linux's seccomp and I got to an inconsistency I cannot explain.
I have tried to give you examples clear enough to reproduce the problem.
I am creating a "protector module" which disallows process calling set_robust_list
(for the sake of demoing the problem). Then I run processes where I inject this "protector module" using LD_PRELOAD and expect the process to stop when this system call is made.
I am making a shared object based on this code:
#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);
}
I am building it with gcc -shared seccompdemo.c -lseccomp -o libseccompdemo.so
.
Then to test it I'm building this executable:
#define _GNU_SOURCE
#include <unistd.h>
#include <sys/syscall.h>
int main() {
syscall(SYS_set_robust_list,0,0);
return 0;
}
I'm building this with gcc set_robust_list.c -o set_robust_list
.
Then as expected I'm runninig this executable with the above so and it gets killed with a signal:
$ LD_PRELOAD=./libseccompdemo.so ./set_robust_list
Bad system call (core dumped)
The problem is when I'm trying to do the same trick with Java.
I'm invoking the same "protector module" on java it does not seem to work despite I know Java is calling set_robust_list
from strace:
$ LD_PRELOAD=./libseccompdemo.so java FileWriterTest /tmp/hosts < /etc/hosts
$ echo $?
0
See the strace output proves that java is calling '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
I do see that java calls clone
system call essentially for creating threads. I thought maybe seccomp filters are not inherited, but according to the documentation they are.
I'd be very glad if someone could explain me why this is not working.
For reference here is the Java code:
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());
}
}
}
Solution
That Bad system call (core dumped)
message is your shell telling you that the child process exited due to a SIGSYS
signal. But if SIGSYS
is blocked, the system call would just return an error, which would be handled in an application-specific manner.
I guess that pthread_create
blocks signals while executing and therefore set_robust_list
is only called with SIGSYS
blocked, unlike your example code which doesn't modify the signal mask.
Anyways, it shouldn't really affect what you're trying to accomplish: Add a System.out.println("Hello from Java!");
to your java main
and you will see it won't print if you preload the segcomp filters, because main
is never called as expected.
Answered By - a3f Answer Checked By - Willingham (WPSolving Volunteer)