Reputation: 3602
I'm trying to create a sandbox to run untrusted user code and I would like to allow users to listen on a network socket (on Linux). But I would like to limit what ports they can listen on. I have tried apparmor, but apparmor only provides an option to completely disable tcp connections. I need a more fine grained policy.
I have also tried ptrace, but was only able to intercept the sys_socketcall syscall but was not able to get the port number. Besides, I know ptrace is not entirely secure so that would not be a proper solution.
Here is the code that I have been trying to use to intercept the port number supplied to bind:
params[0] = ptrace(PTRACE_PEEKUSER,
child, 4 * EBX,
NULL);
params[1] = ptrace(PTRACE_PEEKUSER,
child, 4 * ECX,
NULL);
params[2] = ptrace(PTRACE_PEEKUSER,
child, 4 * EDX,
NULL);
printf("SYS_socketcall called with %u\n", (int)params[0]);
if(params[0] == 2){ // SYS_BIND
int call = params[0];
int *args = (intptr_t*)params[1];
int socket = args[0];
struct sockaddr_in *addr = (struct sockaddr_in*)args[1];
int len = args[2];
//struct sockaddr_in *addr = (struct sockaddr_in*)args[1];
printf("BIND CALLED WITH call: %d, fd: %d, addr: %p\n", call, socket, addr);
}
but it segfaults because I must be doing something wrong when getting the pointer to the sockaddr struct that is passed to the syscall. According to http://docs.cs.up.ac.za/programming/asm/derick_tut/syscalls.html the second parameter in ECX is a pointer to argument list where arguments are [socket_fd, sockaddr*]. But it doesn't work. why?
Is there a better way to do this than with ptrace?
Upvotes: 2
Views: 1274
Reputation: 799190
SELinux will allow you to restrict processes very tightly, including port access. It even comes with a sandbox
command that can run a process in a very restricted sandbox domain, to which you can then replace with a customized domain in order to provide access to files and ports as appropriate.
Upvotes: 1