Index: sandbox/linux/seccomp_bpf/demo.cc |
=================================================================== |
--- sandbox/linux/seccomp_bpf/demo.cc (revision 0) |
+++ sandbox/linux/seccomp_bpf/demo.cc (revision 0) |
@@ -0,0 +1,175 @@ |
+#include <errno.h> |
+#include <fcntl.h> |
+#include <linux/unistd.h> |
+#include <netinet/in.h> |
+#include <netinet/tcp.h> |
+#include <netinet/udp.h> |
+#include <pthread.h> |
+#include <signal.h> |
+#include <stdio.h> |
+#include <stdlib.h> |
+#include <string.h> |
+#include <sys/ioctl.h> |
+#include <sys/ipc.h> |
+#include <sys/mman.h> |
+#include <sys/prctl.h> |
+#include <sys/resource.h> |
+#include <sys/shm.h> |
+#include <sys/socket.h> |
+#include <sys/time.h> |
+#include <sys/types.h> |
+#include <time.h> |
+#include <unistd.h> |
+ |
+#include "sandbox.h" |
+#include "util.h" |
+ |
+#define ERR EPERM |
+ |
+ |
+static void *threadFnc(void *arg) { |
+ return arg; |
+} |
+ |
+static void *sendmsgStressThreadFnc(void *arg) { |
+ static const int repetitions = 100; |
+ static const int numFds = 3; |
+ for (int rep = 0; rep < repetitions; ++rep) { |
+ int fds[2 + numFds]; |
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds)) { |
+ perror("socketpair()"); |
+ _exit(1); |
+ } |
+ size_t len = 4; |
+ char buf[4]; |
+ if (!playground2::Util::sendFds(fds[0], "test", 4, |
+ fds[1], fds[1], fds[1], -1) || |
+ !playground2::Util::getFds(fds[1], buf, &len, |
+ fds+2, fds+3, fds+4, NULL) || |
+ len != 4 || |
+ memcmp(buf, "test", len) || |
+ write(fds[2], "demo", 4) != 4 || |
+ read(fds[0], buf, 4) != 4 || |
+ memcmp(buf, "demo", 4)) { |
+ perror("sending/receiving of fds"); |
+ _exit(1); |
+ } |
+ for (int i = 0; i < 2+numFds; ++i) { |
+ if (close(fds[i])) { |
+ perror("close"); |
+ _exit(1); |
+ } |
+ } |
+ } |
+ return NULL; |
+} |
+ |
+int main(int argc, char *argv[]) { |
+ int proc_fd = open("/proc", O_RDONLY|O_DIRECTORY); |
+ if (!SupportsSeccomp2Sandbox(proc_fd)) { |
+ perror("sandbox"); |
+ _exit(1); |
+ } |
+ Seccomp2SandboxSetProcFd(proc_fd); |
+ StartSeccomp2Sandbox(); |
+ |
+ // Check that we can create threads |
+ pthread_t thr; |
+ if (!pthread_create(&thr, NULL, threadFnc, (void *)0x1234)) { |
+ void *ret; |
+ pthread_join(thr, &ret); |
+ if (ret != (void *)0x1234) { |
+ perror("clone() failed"); |
+ _exit(1); |
+ } |
+ } else { |
+ perror("clone() failed"); |
+ _exit(1); |
+ } |
+ |
+ // Check that we handle restart_syscall() without dieing. This is a little |
+ // tricky to trigger. And I can't think of a good way to verify whether it |
+ // actually executed. |
+ signal(SIGALRM, SIG_IGN); |
+ const struct itimerval tv = { { 0, 0 }, { 0, 5*1000 } }; |
+ const struct timespec tmo = { 0, 100*1000*1000 }; |
+ setitimer(ITIMER_REAL, &tv, NULL); |
+ nanosleep(&tmo, NULL); |
+ |
+ // Check that we can query the size of the stack, but that all other |
+ // calls to getrlimit() fail. |
+ if (((errno = 0), !getrlimit(RLIMIT_STACK, NULL)) || errno != EFAULT || |
+ ((errno = 0), !getrlimit(RLIMIT_CORE, NULL)) || errno != ERR) { |
+ perror("getrlimit()"); |
+ _exit(1); |
+ } |
+ |
+ // Check that we can query TCGETS and TIOCGWINSZ, but no other ioctls(). |
+ if (((errno = 0), !ioctl(2, TCGETS, NULL)) || errno != EFAULT || |
+ ((errno = 0), !ioctl(2, TIOCGWINSZ, NULL)) || errno != EFAULT || |
+ ((errno = 0), !ioctl(2, TCSETS, NULL)) || errno != ERR) { |
+ perror("ioctl()"); |
+ _exit(1); |
+ } |
+ |
+ // Check that prctl() can manipulate the dumpable flag, but nothing else. |
+ if (((errno = 0), !prctl(PR_GET_DUMPABLE)) || errno || |
+ ((errno = 0), prctl(PR_SET_DUMPABLE, 1)) || errno || |
+ ((errno = 0), !prctl(PR_SET_SECCOMP, 0)) || errno != ERR) { |
+ perror("prctl()"); |
+ _exit(1); |
+ } |
+ |
+ // Check that we can send and receive file handles. |
+ int fds[3]; |
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds)) { |
+ perror("socketpair()"); |
+ _exit(1); |
+ } |
+ size_t len = 4; |
+ char buf[4]; |
+ if (!playground2::Util::sendFds(fds[0], "test", 4, fds[1], -1) || |
+ !playground2::Util::getFds(fds[1], buf, &len, fds+2, NULL) || |
+ len != 4 || |
+ memcmp(buf, "test", len) || |
+ write(fds[2], "demo", 4) != 4 || |
+ read(fds[0], buf, 4) != 4 || |
+ memcmp(buf, "demo", 4) || |
+ close(fds[0]) || |
+ close(fds[1]) || |
+ close(fds[2])) { |
+ perror("sending/receiving of fds"); |
+ _exit(1); |
+ } |
+ |
+ // Check whether SysV IPC works. |
+ int shmid; |
+ void *addr; |
+ if ((shmid = shmget(IPC_PRIVATE, 4096, IPC_CREAT|0600)) < 0 || |
+ (addr = shmat(shmid, NULL, 0)) == (void *)-1 || |
+ shmdt(addr) || |
+ shmctl(shmid, IPC_RMID, NULL)) { |
+ perror("sysv IPC"); |
+ _exit(1); |
+ } |
+ |
+ // Print a message so that the user can see the sandbox is activated. |
+ time_t tm = time(NULL); |
+ printf("Sandbox has been started at %s", ctime(&tm)); |
+ |
+ // Stress-test the sendmsg() code |
+ static const int sendmsgStressNumThreads = 10; |
+ pthread_t sendmsgStressThreads[sendmsgStressNumThreads]; |
+ for (int i = 0; i < sendmsgStressNumThreads; ++i) { |
+ if (pthread_create(sendmsgStressThreads + i, NULL, |
+ sendmsgStressThreadFnc, NULL)) { |
+ perror("pthread_create"); |
+ _exit(1); |
+ } |
+ } |
+ for (int i = 0; i < sendmsgStressNumThreads; ++i) { |
+ pthread_join(sendmsgStressThreads[i], NULL); |
+ } |
+ |
+ return 0; |
+} |
Property changes on: sandbox/linux/seccomp_bpf/demo.cc |
___________________________________________________________________ |
Added: svn:eol-style |
+ LF |