| Index: sandbox/linux/seccomp/debug.cc
|
| ===================================================================
|
| --- sandbox/linux/seccomp/debug.cc (revision 57969)
|
| +++ sandbox/linux/seccomp/debug.cc (working copy)
|
| @@ -1,363 +0,0 @@
|
| -// 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.
|
| -
|
| -#ifndef NDEBUG
|
| -
|
| -#include "debug.h"
|
| -
|
| -namespace playground {
|
| -
|
| -bool Debug::enabled_;
|
| -int Debug::numSyscallNames_;
|
| -const char **Debug::syscallNames_;
|
| -std::map<int, std::string> Debug::syscallNamesMap_;
|
| -
|
| -Debug Debug::debug_;
|
| -
|
| -Debug::Debug() {
|
| - // Logging is disabled by default, but can be turned on by setting an
|
| - // appropriate environment variable. Initialize this code from a global
|
| - // constructor, so that it runs before the sandbox is turned on.
|
| - enabled_ = !!getenv("SECCOMP_SANDBOX_DEBUGGING");
|
| -
|
| - // Read names of system calls from header files, if available. Symbolic
|
| - // names make debugging so much nicer.
|
| - if (enabled_) {
|
| - static const char *filenames[] = {
|
| - #if __WORDSIZE == 64
|
| - "/usr/include/asm/unistd_64.h",
|
| - #elif __WORDSIZE == 32
|
| - "/usr/include/asm/unistd_32.h",
|
| - #endif
|
| - "/usr/include/asm/unistd.h",
|
| - NULL };
|
| - numSyscallNames_ = 0;
|
| - for (const char **fn = filenames; *fn; ++fn) {
|
| - FILE *fp = fopen(*fn, "r");
|
| - if (fp) {
|
| - std::string baseName;
|
| - int baseNum = -1;
|
| - char buf[80];
|
| - while (fgets(buf, sizeof(buf), fp)) {
|
| - // Check if the line starts with "#define"
|
| - static const char* whitespace = " \t\r\n";
|
| - char *token, *save;
|
| - token = strtok_r(buf, whitespace, &save);
|
| - if (token && !strcmp(token, "#define")) {
|
| -
|
| - // Only parse identifiers that start with "__NR_"
|
| - token = strtok_r(NULL, whitespace, &save);
|
| - if (token) {
|
| - if (strncmp(token, "__NR_", 5)) {
|
| - continue;
|
| - }
|
| - std::string syscallName(token + 5);
|
| -
|
| - // Parse the value of the symbol. Try to be forgiving in what
|
| - // we accept, as the file format might change over time.
|
| - token = strtok_r(NULL, "\r\n", &save);
|
| - if (token) {
|
| - // Some values are defined relative to previous values, we
|
| - // detect these examples by finding an earlier symbol name
|
| - // followed by a '+' plus character.
|
| - bool isRelative = false;
|
| - char *base = strstr(token, baseName.c_str());
|
| - if (baseNum >= 0 && base) {
|
| - base += baseName.length();
|
| - while (*base == ' ' || *base == '\t') {
|
| - ++base;
|
| - }
|
| - if (*base == '+') {
|
| - isRelative = true;
|
| - token = base;
|
| - }
|
| - }
|
| -
|
| - // Skip any characters that are not part of the syscall number.
|
| - while (*token < '0' || *token > '9') {
|
| - token++;
|
| - }
|
| -
|
| - // If we now have a valid datum, enter it into our map.
|
| - if (*token) {
|
| - int sysnum = atoi(token);
|
| -
|
| - // Deal with symbols that are defined relative to earlier
|
| - // ones.
|
| - if (isRelative) {
|
| - sysnum += baseNum;
|
| - } else {
|
| - baseNum = sysnum;
|
| - baseName = syscallName;
|
| - }
|
| -
|
| - // Keep track of the highest syscall number that we know
|
| - // about.
|
| - if (sysnum >= numSyscallNames_) {
|
| - numSyscallNames_ = sysnum + 1;
|
| - }
|
| -
|
| - syscallNamesMap_[sysnum] = syscallName;
|
| - }
|
| - }
|
| - }
|
| - }
|
| - }
|
| - fclose(fp);
|
| - break;
|
| - }
|
| - }
|
| - if (numSyscallNames_) {
|
| - // We cannot make system calls at the time, when we are looking up
|
| - // the names. So, copy them into a data structure that can be
|
| - // accessed without having to allocated memory (i.e. no more STL).
|
| - syscallNames_ = reinterpret_cast<const char **>(
|
| - calloc(sizeof(char *), numSyscallNames_));
|
| - for (std::map<int, std::string>::const_iterator iter =
|
| - syscallNamesMap_.begin();
|
| - iter != syscallNamesMap_.end();
|
| - ++iter) {
|
| - syscallNames_[iter->first] = iter->second.c_str();
|
| - }
|
| - }
|
| - }
|
| -}
|
| -
|
| -bool Debug::enter() {
|
| - // Increment the recursion level in TLS storage. This allows us to
|
| - // make system calls from within our debugging functions, without triggering
|
| - // additional debugging output.
|
| - //
|
| - // This function can be called from both the sandboxed process and from the
|
| - // trusted process. Only the sandboxed process needs to worry about
|
| - // recursively calling system calls. The trusted process doesn't intercept
|
| - // system calls and thus doesn't have this problem. It also doesn't have
|
| - // a TLS. We explicitly set the segment selector to zero, when in the
|
| - // trusted process, so that we can avoid tracking recursion levels.
|
| - int level;
|
| - #if defined(__x86_64__)
|
| - asm volatile("mov %%gs, %0\n"
|
| - "test %0, %0\n"
|
| - "jz 1f\n"
|
| - "movl %%gs:0x1050-0xE0, %0\n"
|
| - "incl %%gs:0x1050-0xE0\n"
|
| - "1:\n"
|
| - : "=r"(level)
|
| - :
|
| - : "memory");
|
| - #elif defined(__i386__)
|
| - asm volatile("mov %%fs, %0\n"
|
| - "test %0, %0\n"
|
| - "jz 1f\n"
|
| - "movl %%fs:0x1034-0x58, %0\n"
|
| - "incl %%fs:0x1034-0x58\n"
|
| - "1:\n"
|
| - : "=r"(level)
|
| - :
|
| - : "memory");
|
| - #else
|
| - #error "Unsupported target platform"
|
| - #endif
|
| - return !level;
|
| -}
|
| -
|
| -bool Debug::leave() {
|
| - // Decrement the recursion level in TLS storage. This allows us to
|
| - // make system calls from within our debugging functions, without triggering
|
| - // additional debugging output.
|
| - //
|
| - // This function can be called from both the sandboxed process and from the
|
| - // trusted process. Only the sandboxed process needs to worry about
|
| - // recursively calling system calls. The trusted process doesn't intercept
|
| - // system calls and thus doesn't have this problem. It also doesn't have
|
| - // a TLS. We explicitly set the segment selector to zero, when in the
|
| - // trusted process, so that we can avoid tracking recursion levels.
|
| - int level;
|
| - #if defined(__x86_64__)
|
| - asm volatile("mov %%gs, %0\n"
|
| - "test %0, %0\n"
|
| - "jz 1f\n"
|
| - "decl %%gs:0x1050-0xE0\n"
|
| - "movl %%gs:0x1050-0xE0, %0\n"
|
| - "1:\n"
|
| - : "=r"(level)
|
| - :
|
| - : "memory");
|
| - #elif defined(__i386__)
|
| - asm volatile("mov %%fs, %0\n"
|
| - "test %0, %0\n"
|
| - "jz 1f\n"
|
| - "decl %%fs:0x1034-0x58\n"
|
| - "movl %%fs:0x1034-0x58, %0\n"
|
| - "1:\n"
|
| - : "=r"(level)
|
| - :
|
| - : "memory");
|
| - #else
|
| - #error Unsupported target platform
|
| - #endif
|
| - return !level;
|
| -}
|
| -
|
| -void Debug::_message(const char* msg) {
|
| - if (enabled_) {
|
| - Sandbox::SysCalls sys;
|
| - size_t len = strlen(msg);
|
| - if (len && msg[len-1] != '\n') {
|
| - // Write operations should be atomic, so that we don't interleave
|
| - // messages from multiple threads. Append a newline, if it is not
|
| - // already there.
|
| - char copy[len + 1];
|
| - memcpy(copy, msg, len);
|
| - copy[len] = '\n';
|
| - Sandbox::write(sys, 2, copy, len + 1);
|
| - } else {
|
| - Sandbox::write(sys, 2, msg, len);
|
| - }
|
| - }
|
| -}
|
| -
|
| -void Debug::message(const char* msg) {
|
| - if (enabled_) {
|
| - if (enter()) {
|
| - _message(msg);
|
| - }
|
| - leave();
|
| - }
|
| -}
|
| -
|
| -void Debug::gettimeofday(long long* tm) {
|
| - if (tm) {
|
| - struct timeval tv;
|
| - #if defined(__i386__)
|
| - // Zero out the lastSyscallNum, so that we don't try to coalesce
|
| - // calls to gettimeofday(). For debugging purposes, we need the
|
| - // exact time.
|
| - asm volatile("movl $0, %fs:0x102C-0x58");
|
| - #elif !defined(__x86_64__)
|
| - #error Unsupported target platform
|
| - #endif
|
| - ::gettimeofday(&tv, NULL);
|
| - *tm = 1000ULL*1000ULL*static_cast<unsigned>(tv.tv_sec) +
|
| - static_cast<unsigned>(tv.tv_usec);
|
| - }
|
| -}
|
| -
|
| -void Debug::syscall(long long* tm, int sysnum, const char* msg, int call) {
|
| - // This function gets called from the system call wrapper. Avoid calling
|
| - // any library functions that themselves need system calls.
|
| - if (enabled_) {
|
| - if (enter() || !tm) {
|
| - gettimeofday(tm);
|
| -
|
| - const char *sysname = NULL;
|
| - if (sysnum >= 0 && sysnum < numSyscallNames_) {
|
| - sysname = syscallNames_[sysnum];
|
| - }
|
| - static const char kUnnamedMessage[] = "Unnamed syscall #";
|
| - char unnamed[40];
|
| - if (!sysname) {
|
| - memcpy(unnamed, kUnnamedMessage, sizeof(kUnnamedMessage) - 1);
|
| - itoa(unnamed + sizeof(kUnnamedMessage) - 1, sysnum);
|
| - sysname = unnamed;
|
| - }
|
| - #if defined(__NR_socketcall) || defined(__NR_ipc)
|
| - char extra[40];
|
| - *extra = '\000';
|
| - #if defined(__NR_socketcall)
|
| - if (sysnum == __NR_socketcall) {
|
| - static const char* socketcall_name[] = {
|
| - 0, "socket", "bind", "connect", "listen", "accept", "getsockname",
|
| - "getpeername", "socketpair", "send", "recv", "sendto","recvfrom",
|
| - "shutdown", "setsockopt", "getsockopt", "sendmsg", "recvmsg",
|
| - "accept4"
|
| - };
|
| - if (call >= 1 &&
|
| - call < (int)(sizeof(socketcall_name)/sizeof(char *))) {
|
| - strcat(strcpy(extra, " "), socketcall_name[call]);
|
| - } else {
|
| - itoa(strcpy(extra, " #") + 2, call);
|
| - }
|
| - }
|
| - #endif
|
| - #if defined(__NR_ipc)
|
| - if (sysnum == __NR_ipc) {
|
| - static const char* ipc_name[] = {
|
| - 0, "semop", "semget", "semctl", "semtimedop", 0, 0, 0, 0, 0, 0,
|
| - "msgsnd", "msgrcv", "msgget", "msgctl", 0, 0, 0, 0, 0, 0,
|
| - "shmat", "shmdt", "shmget", "shmctl" };
|
| - if (call >= 1 && call < (int)(sizeof(ipc_name)/sizeof(char *)) &&
|
| - ipc_name[call]) {
|
| - strcat(strcpy(extra, " "), ipc_name[call]);
|
| - } else {
|
| - itoa(strcpy(extra, " #") + 2, call);
|
| - }
|
| - }
|
| - #endif
|
| - #else
|
| - static const char extra[1] = { 0 };
|
| - #endif
|
| - char buf[strlen(sysname) + strlen(extra) + (msg ? strlen(msg) : 0) + 4];
|
| - strcat(strcat(strcat(strcat(strcpy(buf, sysname), extra), ": "),
|
| - msg ? msg : ""), "\n");
|
| - _message(buf);
|
| - }
|
| - leave();
|
| - }
|
| -}
|
| -
|
| -char* Debug::itoa(char* s, int n) {
|
| - // Remember return value
|
| - char *ret = s;
|
| -
|
| - // Insert sign for negative numbers
|
| - if (n < 0) {
|
| - *s++ = '-';
|
| - n = -n;
|
| - }
|
| -
|
| - // Convert to decimal (in reverse order)
|
| - char *start = s;
|
| - do {
|
| - *s++ = '0' + (n % 10);
|
| - n /= 10;
|
| - } while (n);
|
| - *s-- = '\000';
|
| -
|
| - // Reverse order of digits
|
| - while (start < s) {
|
| - char ch = *s;
|
| - *s-- = *start;
|
| - *start++ = ch;
|
| - }
|
| -
|
| - return ret;
|
| -}
|
| -
|
| -void Debug::elapsed(long long tm, int sysnum, int call) {
|
| - if (enabled_) {
|
| - if (enter()) {
|
| - // Compute the time that has passed since the system call started.
|
| - long long delta;
|
| - gettimeofday(&delta);
|
| - delta -= tm;
|
| -
|
| - // Format "Elapsed time: %d.%03dms" without using sprintf().
|
| - char buf[80];
|
| - itoa(strrchr(strcpy(buf, "Elapsed time: "), '\000'), delta/1000);
|
| - delta %= 1000;
|
| - strcat(buf, delta < 100 ? delta < 10 ? ".00" : ".0" : ".");
|
| - itoa(strrchr(buf, '\000'), delta);
|
| - strcat(buf, "ms");
|
| -
|
| - // Print system call name and elapsed time.
|
| - syscall(NULL, sysnum, buf, call);
|
| - }
|
| - leave();
|
| - }
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -#endif // NDEBUG
|
|
|