blob: 84471658779b0890fa91de5ecb4dc9bf835bd5b8 [file] [log] [blame]
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#define SYS_SYSCALL_ENTRYPOINT "playground$syscallEntryPoint"
#include "linux_syscall_support.h"
#include "sandbox_impl.h"
#include <dirent.h>
#include <dlfcn.h>
#include <pthread.h>
#include <stdio.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include <signal.h>
// #define THREADS 1000
// #define ITER 100
#define THREADS 2
#define ITER 2
static long long tsc() {
long long rc;
asm volatile(
"rdtsc\n"
"mov %%eax, (%0)\n"
"mov %%edx, 4(%0)\n"
:
: "c"(&rc), "a"(-1), "d"(-1));
return rc;
}
#ifdef THREADS
static void *empty(void *arg) {
return mmap(0, 4096, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
}
static void *fnc(void *arg) {
struct timeval tv;
if (gettimeofday(&tv, 0)) {
printf("In thread:\ngettimeofday() failed\n");
} else {
printf("In thread: usec: %1.0f\n", 1.0*tv.tv_usec);
}
printf("In thread: TSC: %llx\n", tsc());
for (int i = 0; i < ITER; i++) {
pthread_t t;
if (!pthread_create(&t, NULL, empty, NULL)) {
pthread_join(t, NULL);
}
}
return 0;
}
#endif
static void triggerSEGV(void) {
asm volatile("int $1");
}
static void caughtSEGV(void *addr) asm("caughtSEGV") __attribute__((used));
static void caughtSEGV(void *addr) {
printf("Caught SIGSEGV at %p\n", addr);
}
static void (*segvHandler(void))(int signo, siginfo_t *info, void *context) {
void (*hdl)(int, siginfo_t *, void *);
asm volatile(
"lea 0f, %0\n"
"jmp 999f\n"
"0:\n"
#if defined(__x86_64__)
"mov 0xB0(%%rsp), %%rdi\n" // Pass original %rip to signal handler
"addq $2, 0xB0(%%rsp)\n" // Adjust %rip past failing instruction
"call caughtSEGV\n" // Call actual signal handler
#elif defined(__i386__)
"cmpw $0, 0xA(%%esp)\n"
"lea 0x40(%%esp), %%eax\n" // %eip at time of exception
"jz 1f\n"
"add $0x9C, %%eax\n" // %eip at time of exception
"1:mov 0(%%eax), %%ecx\n" // Pass original %eip to signal handler
"addl $2, 0(%%eax)\n" // Adjust %eip past failing instruction
"push %%ecx\n"
"call caughtSEGV\n" // Call actual signal handler
"pop %%eax\n"
#else
#error Unsupported target platform
#endif
"ret\n"
"999:\n"
: "=r"(hdl));
return hdl;
}
static void testSignals(sigset_t *orig_sigmask) {
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
int flags[4] = { 0, SA_NODEFER, SA_SIGINFO, SA_SIGINFO | SA_NODEFER };
for (int i = 0; i < 4; ++i) {
sa.sa_sigaction = segvHandler();
sa.sa_flags = flags[i];
sigaction(SIGSEGV, &sa, NULL);
triggerSEGV();
}
sigset_t sigmask = { { 0 } }, old_sigmask = { { 0 } };
sigemptyset(&sigmask);
sigemptyset(&old_sigmask);
sigaddset(&sigmask, SIGALRM);
sigprocmask(SIG_SETMASK, &sigmask, &old_sigmask);
printf("Original signal mask: 0x%llX, old mask: 0x%llX, new mask: 0x%llX, ",
*(unsigned long long *)orig_sigmask,
*(unsigned long long *)&old_sigmask,
*(unsigned long long *)&sigmask);
sigprocmask(SIG_SETMASK, &old_sigmask, &old_sigmask);
printf("cur mask: 0x%llX, restored mask: 0x%llX\n",
*(unsigned long long *)&old_sigmask,
*(unsigned long long *)orig_sigmask);
}
int main(int argc, char *argv[]) {
//{ char buf[128]; sprintf(buf, "cat /proc/%d/maps", getpid()); system(buf); }
if (SupportsSeccompSandbox(-1)) {
puts("Sandbox is supported. Enabling it now...");
} else {
puts("There is insufficient support for the seccomp sandbox. Exiting...");
return 1;
}
sigset_t orig_sigmask = { { 0 } };
sigemptyset(&orig_sigmask);
sigprocmask(-1, NULL, &orig_sigmask);
struct timeval tv, tv0;
gettimeofday(&tv0, 0);
StartSeccompSandbox();
write(2, "In secure mode, now!\n", 21);
gettimeofday(&tv, 0);
printf("It takes %fms to start the sandbox\n",
tv.tv_sec * 1000.0 + tv.tv_usec / 1000.0 -
tv0.tv_sec * 1000.0 - tv0.tv_usec / 1000.0);
sys_gettid();
testSignals(&orig_sigmask);
gettimeofday(&tv, 0);
gettimeofday(&tv, 0);
gettimeofday(&tv, 0);
gettimeofday(&tv, 0);
printf("TSC: %llx\n", tsc());
printf("TSC: %llx\n", tsc());
#if defined(__x86_64__)
asm volatile("mov $2, %%edi\n"
"lea 100f(%%rip), %%rsi\n"
"mov $101f-100f, %%edx\n"
"mov $1, %%eax\n"
"int $0\n"
"jmp 101f\n"
"100:.ascii \"Hello world (INT $0 worked)\\n\"\n"
"101:\n"
:
:
: "rax", "rdi", "rsi", "rdx");
#elif defined(__i386__)
asm volatile("push %%ebx\n"
"mov $2, %%ebx\n"
"lea 100f, %%ecx\n"
"mov $101f-100f, %%edx\n"
"mov $4, %%eax\n"
"int $0\n"
"jmp 101f\n"
"100:.ascii \"Hello world (INT $0 worked)\\n\"\n"
"101:pop %%ebx\n"
:
:
: "eax", "ecx", "edx");
#endif
int pair[2];
socketpair(AF_UNIX, SOCK_STREAM, 0, pair);
printf("uid: %d\n", getuid());
dlopen("libncurses.so.5", RTLD_LAZY);
if (gettimeofday(&tv, 0)) {
printf("gettimeofday() failed\n");
} else {
printf("usec: %ld\n", (long)tv.tv_usec);
}
fflush(stdout);
fopen("/usr/share/doc", "r");
fopen("/usr/share/doc", "r");
isatty(0);
#ifdef THREADS
pthread_t threads[THREADS];
for (int i = 0; i < THREADS; ++i) {
if (pthread_create(&threads[i], NULL, fnc, NULL)) {
threads[i] = (pthread_t)0;
}
}
#endif
for (int i = 0; i < 10; i++) {
mmap(0, 4096, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
}
printf("Hello %s\n", "world");
if (gettimeofday(&tv, 0)) {
printf("gettimeofday() failed\n");
} else {
printf("usec: %ld\n", (long)tv.tv_usec);
}
struct stat sb;
stat("/", &sb);
DIR *dirp = opendir("/");
if (dirp) {
readdir(dirp);
closedir(dirp);
}
#ifdef THREADS
for (int i = 0; i < THREADS; ++i) {
if (threads[i]) {
pthread_join(threads[i], NULL);
}
}
if (!pthread_create(&threads[0], NULL, fnc, NULL)) {
pthread_join(threads[0], NULL);
}
#endif
puts("Done");
exit(0);
return 0;
}