After playing around with this for a couple more weeks, we found a way to make the sandbox work as expected.
The issue seems to involve SELinux stopping libuv (the underpinnings of Node) from reading and writing a UNIX stream socket, which of course is required for Node's non-blocking I/O. One reason this took so long to find was that this error was being hidden from SELinux's audit by dontaudit rules.
We started by doing the following:
# semodule -DB ## turns off dontaudit rules
# tail -f /var/log/audit/audit.log
Then in a different terminal, run the application. A bunch of SELinux audits appear, but most significantly, one that says:
type=AVC msg=audit(1370065734.791:5038): avc: denied { read write } for pid=8887 comm="my_command" path="socket:[1258916]" dev=sockfs ino=1258916 scontext=unconfined_u:unconfined_r:sandbox_t:s0:c98,c807 tcontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tclass=unix_stream_socket
To make this into a policy, we did the following:
# grep "type=AVC msg=audit(1370065734.791:5038)" /var/log/audit/audit.log | audit2allow -M unixsocketsandbox
# semodule -i unixsocketsandbox.pp
where unixsocketsandbox
is a unique name for the policy. The policy (via cat unixsocketsandbox.te
) reads as follows:
allow sandbox_t unconfined_t:unix_stream_socket { read write };
After this, the application works as expected, within the limitations of a sandbox.