I'm considering several options for sandboxing a Linux process. Using clone()
with CLONE_NEWNET
(etc.) is one of the options. CLONE_NEWNET
ensures that the sandboxed process cannot make or accept real network connections. But I'd like to disable sockets entirely for that process, even bind()
ing to any port on 0.0.0.0
, and binding to a Unix doman socket (even anonymous). I'd like to do this to prevent the process from using too much kernel resources by binding to thousands of ports. How do I do that?
In general, I'm interested in many sandboxing approaches (i.e. those provided by the Linux kernel 开发者_开发知识库and those enforced by ptrace()
), but in this question I'm only interested in the socket creation aspect of the sandboxing approaches (so if you suggest a sandboxing approach, please also explain how to prevent socket creation with it), and I'm not interested in approaches which need kernel patching or which involve loading a kernel module which is not part of the Ubuntu Lucid default binary kernel package, or which would affect every process on the system.
ptrace
seems to be the most obvious tool but aside from that…
util-linux[-ng] has a command unshare
, which uses the kernel's clone
/unshare
interfaces. If you run the new process throughunshare -n
(or clone(CLONE_NEWNET)
), any network sockets it creates are in a different namespace. That doesn't solve the kernel resource issue but it does sandbox the process.
The Linux kernel also supports seccomp, a mode entered with prctl(PR_SET_SECCOMP, 1)
which prevents the process (well, thread, really) from calling any syscalls other than read
, write
, exit
, and sigreturn
. It's a pretty effective sandbox but difficult to use with unmodified code.
You can define a SELinux domain which disallows socket
/bind
/etc. calls, and perform a dynamic transition into that type. This (obviously) requires a system with an actively enforcing SELinux policy. (Possibly similar things are possible with AppArmor and TOMOYO, but I'm not very familiar with any of them.)
Take a look at systrace - not limited to sockets, but a generic syscall policy generator/enforcer. Quote:
GNU/Linux port is finished and kernel patch is maintained actively by Marius Eriksen. Can be run without kernel changes using the ptrace backend.
Disclamer - I never tried it on Linux.
Try seccomp (see the prctl man page), it can confine your process to only accessing the sockets that were left open at the time the prctl call was made.
You might be interested with "sydbox" sandbox or "pinktrace" library :
http://www.diigo.com/user/wierzowiecki/sydbox
If your main goal is to limit the number of sockets that are opened by some benign process P applied to benign inputs, then setrlimit(RLIMIT_NOFILE, ...)
will do approximately what you want.
However, if P is assumed be to malicious rather than benign or if you're looking for strong assurance about how P will behave in the face of potentially malicious inputs, then you're probably out of luck: i.e., at best, with the tools available today, you can create an obstacle course for attackers.
(That being said, if an obstacle course works for you, then you might get some more good ideas by poking around over here at sandboxing.org or by sending your questions to the friendly folks on sandboxing-talk@lists.sandboxing.org
.)
精彩评论