In the context of security integration, a sandbox is a mechanism for constraining code with virtual walls to protect it from being damaged by malicious code. You can also use a sandbox to limit the damage done if the code it contains is co-opted by an attacker.
Best practices for security integrators include protecting mountpoints from client access by sandboxing them. Application sandboxing (including third-party applications) can reduce vulnerability to malware. Sandboxes are also a convenient, isolated space for testing your code. Use the procmgr ability _PROCMGR_AID_SANDBOX to create and delete sandboxes, attach a process to a sandbox, and detach a process from a sandbox.
To learn more about procmgr abilities, see the Procmgr abilities chapter of the QNX Neutrino Programmer's Guide.
The following example shows how to use procmgr abilities to create a sandbox, attach a process to the sandbox, and then delete the sandbox:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sandbox.h>
#include <signal.h>
#include <fcntl.h>
#include <errno.h>
#include <pthread.h>
#include <sys/neutrino.h>
#include <sys/iomsg.h>
#include <sys/procmsg.h>
static const char sandbox_config[] =
"[version=1]\n"
"/proc/boot\n"
"/dev/tty*\n"
"/tmp\n"
"/root\n"
"/usr/lib\n"
"!*";
int main(int argc, char *argv[])
{
proc_sandbox_create_t msg;
iov_t iov[2];
int r;
int sbid;
fprintf(stderr, "Initializing sandbox configuration\n");
r = sandbox_parse_config(sandbox_config, sizeof(sandbox_config), &iov[1], &msg.i.version);
if (r > 0) {
fprintf(stderr, "Parse error on line %d\n", r);
return 1;
} else if (r < 0) {
errno = r;
perror("sandbox_parse_config");
return 1;
} else {
fprintf(stderr, "%s:%d - Creating sandbox...\n", __FUNCTION__, __LINE__);
msg.i.type = _PROC_SANDBOX;
msg.i.subtype = _PROC_SANDBOX_CREATE;
msg.i.datalen = iov[1].iov_len;
iov[0].iov_base = &msg;
iov[0].iov_len = sizeof(msg);
if (MsgSendv(PROCMGR_COID, iov, 2, iov, 1) != 0) {
perror("MsgSendv(_PROC_SANDBOX_CREATE)");
return 1;
}
sbid = msg.o.sbid;
sandbox_done_config(&iov[1]);
}
// Start the child process.
pid_t pid = fork();
if (pid < 0) {
perror("fork");
return 1;
}
if (pid == 0) {
delay(1000); // wait for parent to attach child to sandbox
if (execl("/proc/boot/sh", "proc/boot/sh", NULL) < 0) { /* execute the command */
printf("*** ERROR: exec failed errno:%d\n", errno);
exit(1);
}
fprintf(stderr, "%s:%d - execl exitting\n", __FUNCTION__, __LINE__);
}
fprintf(stderr, "%s:%d\n", __FUNCTION__, __LINE__);
r = sandbox_attach(sbid, pid);
if (r < 0) {
fprintf(stderr, "sandbox_attach: %s\n", strerror(-r));
goto done;
}
fprintf(stderr, "%s:%d pid=%d r=%d\n", __FUNCTION__, __LINE__, pid, r);
waitpid(pid, &r, 0);
fprintf(stderr, "%s:%d\n", __FUNCTION__, __LINE__);
pid = 0;
done:
if (sbid != -1) {
sandbox_delete(sbid);
}
return r;
}