/** * This is the SIGSYS handler function. It is used to report to the user * which system call has been denied by Seccomp. * This function also makes the process exit as denying the system call * will otherwise generally lead to unexpected behavior from the process, * since we don't know if all functions will handle such denials gracefully. * * @see InstallSyscallReporter() function. */ static void Reporter(int nr, siginfo_t *info, void *void_context) { ucontext_t *ctx = static_cast<ucontext_t*>(void_context); unsigned long syscall_nr, args[6]; pid_t pid = getpid(); if (nr != SIGSYS) { return; } if (info->si_code != SYS_SECCOMP) { return; } if (!ctx) { return; } syscall_nr = SECCOMP_SYSCALL(ctx); args[0] = SECCOMP_PARM1(ctx); args[1] = SECCOMP_PARM2(ctx); args[2] = SECCOMP_PARM3(ctx); args[3] = SECCOMP_PARM4(ctx); args[4] = SECCOMP_PARM5(ctx); args[5] = SECCOMP_PARM6(ctx); #ifdef MOZ_GMP_SANDBOX if (syscall_nr == __NR_open && gMediaPluginFilePath) { const char *path = reinterpret_cast<const char*>(args[0]); int flags = int(args[1]); if ((flags & O_ACCMODE) != O_RDONLY) { SANDBOX_LOG_ERROR("non-read-only open of file %s attempted (flags=0%o)", path, flags); } else if (strcmp(path, gMediaPluginFilePath) != 0) { SANDBOX_LOG_ERROR("attempt to open file %s which is not the media plugin" " %s", path, gMediaPluginFilePath); } else if (gMediaPluginFileDesc == -1) { SANDBOX_LOG_ERROR("multiple opens of media plugin file unimplemented"); } else { SECCOMP_RESULT(ctx) = gMediaPluginFileDesc; gMediaPluginFileDesc = -1; return; } } #endif SANDBOX_LOG_ERROR("seccomp sandbox violation: pid %d, syscall %lu," " args %lu %lu %lu %lu %lu %lu. Killing process.", pid, syscall_nr, args[0], args[1], args[2], args[3], args[4], args[5]); // Bug 1017393: record syscall number somewhere useful. info->si_addr = reinterpret_cast<void*>(syscall_nr); gSandboxCrashFunc(nr, info, void_context); _exit(127); }
// Test whether a ucontext, interpreted as the state after a syscall, // indicates the given error. See also sandbox::Syscall::PutValueInUcontext. static bool ContextIsError(const ucontext_t *aContext, int aError) { // Avoid integer promotion warnings. (The unary addition makes // the decltype not evaluate to a reference type.) typedef decltype(+SECCOMP_RESULT(aContext)) reg_t; #ifdef __mips__ return SECCOMP_PARM4(aContext) != 0 && SECCOMP_RESULT(aContext) == static_cast<reg_t>(aError); #else return SECCOMP_RESULT(aContext) == static_cast<reg_t>(-aError); #endif }
static void Reporter(int nr, siginfo_t *info, void *void_context) { ucontext_t *ctx = static_cast<ucontext_t*>(void_context); unsigned long syscall_nr, args[6]; pid_t pid = getpid(), tid = syscall(__NR_gettid); if (nr != SIGSYS) { return; } if (info->si_code != SYS_SECCOMP) { return; } if (!ctx) { return; } syscall_nr = SECCOMP_SYSCALL(ctx); args[0] = SECCOMP_PARM1(ctx); args[1] = SECCOMP_PARM2(ctx); args[2] = SECCOMP_PARM3(ctx); args[3] = SECCOMP_PARM4(ctx); args[4] = SECCOMP_PARM5(ctx); args[5] = SECCOMP_PARM6(ctx); LOG_ERROR("seccomp sandbox violation: pid %d, syscall %lu, args %lu %lu %lu" " %lu %lu %lu. Killing process.", pid, syscall_nr, args[0], args[1], args[2], args[3], args[4], args[5]); #ifdef MOZ_CRASHREPORTER bool dumped = CrashReporter::WriteMinidumpForSigInfo(nr, info, void_context); if (!dumped) { LOG_ERROR("Failed to write minidump"); } #endif // Do this last, in case it crashes or deadlocks. SandboxLogJSStack(); // Try to reraise, so the parent sees that this process crashed. // (If tgkill is forbidden, then seccomp will raise SIGSYS, which // also accomplishes that goal.) signal(SIGSYS, SIG_DFL); syscall(__NR_tgkill, pid, tid, nr); _exit(127); }
/** * This is the SIGSYS handler function. It delegates to the Chromium * TrapRegistry handler (see InstallSigSysHandler, below) and, if the * trap handler installed by the policy would fail with ENOSYS, * crashes the process. This allows unintentional policy failures to * be reported as crash dumps and fixed. It also logs information * about the failed system call. * * Note that this could be invoked in parallel on multiple threads and * that it could be in async signal context (e.g., intercepting an * open() called from an async signal handler). */ static void SigSysHandler(int nr, siginfo_t *info, void *void_context) { ucontext_t *ctx = static_cast<ucontext_t*>(void_context); // This shouldn't ever be null, but the Chromium handler checks for // that and refrains from crashing, so let's not crash release builds: MOZ_DIAGNOSTIC_ASSERT(ctx); if (!ctx) { return; } // Save a copy of the context before invoking the trap handler, // which will overwrite one or more registers with the return value. ucontext_t savedCtx = *ctx; gChromiumSigSysHandler(nr, info, ctx); if (!ContextIsError(ctx, ENOSYS)) { return; } pid_t pid = getpid(); unsigned long syscall_nr = SECCOMP_SYSCALL(&savedCtx); unsigned long args[6]; args[0] = SECCOMP_PARM1(&savedCtx); args[1] = SECCOMP_PARM2(&savedCtx); args[2] = SECCOMP_PARM3(&savedCtx); args[3] = SECCOMP_PARM4(&savedCtx); args[4] = SECCOMP_PARM5(&savedCtx); args[5] = SECCOMP_PARM6(&savedCtx); // TODO, someday when this is enabled on MIPS: include the two extra // args in the error message. SANDBOX_LOG_ERROR("seccomp sandbox violation: pid %d, syscall %d," " args %d %d %d %d %d %d. Killing process.", pid, syscall_nr, args[0], args[1], args[2], args[3], args[4], args[5]); // Bug 1017393: record syscall number somewhere useful. info->si_addr = reinterpret_cast<void*>(syscall_nr); gSandboxCrashFunc(nr, info, &savedCtx); _exit(127); }
/** * This is the SIGSYS handler function. It is used to report to the user * which system call has been denied by Seccomp. * This function also makes the process exit as denying the system call * will otherwise generally lead to unexpected behavior from the process, * since we don't know if all functions will handle such denials gracefully. * * @see InstallSyscallReporter() function. */ static void Reporter(int nr, siginfo_t *info, void *void_context) { ucontext_t *ctx = static_cast<ucontext_t*>(void_context); unsigned long syscall_nr, args[6]; pid_t pid = getpid(), tid = syscall(__NR_gettid); if (nr != SIGSYS) { return; } if (info->si_code != SYS_SECCOMP) { return; } if (!ctx) { return; } syscall_nr = SECCOMP_SYSCALL(ctx); args[0] = SECCOMP_PARM1(ctx); args[1] = SECCOMP_PARM2(ctx); args[2] = SECCOMP_PARM3(ctx); args[3] = SECCOMP_PARM4(ctx); args[4] = SECCOMP_PARM5(ctx); args[5] = SECCOMP_PARM6(ctx); #ifdef MOZ_GMP_SANDBOX if (syscall_nr == __NR_open && gMediaPluginFilePath) { const char *path = reinterpret_cast<const char*>(args[0]); int flags = int(args[1]); if ((flags & O_ACCMODE) != O_RDONLY) { LOG_ERROR("non-read-only open of file %s attempted (flags=0%o)", path, flags); } else if (strcmp(path, gMediaPluginFilePath) != 0) { LOG_ERROR("attempt to open file %s which is not the media plugin %s", path, gMediaPluginFilePath); } else if (gMediaPluginFileDesc == -1) { LOG_ERROR("multiple opens of media plugin file unimplemented"); } else { SECCOMP_RESULT(ctx) = gMediaPluginFileDesc; gMediaPluginFileDesc = -1; return; } } #endif LOG_ERROR("seccomp sandbox violation: pid %d, syscall %lu, args %lu %lu %lu" " %lu %lu %lu. Killing process.", pid, syscall_nr, args[0], args[1], args[2], args[3], args[4], args[5]); #ifdef MOZ_CRASHREPORTER // Bug 1017393: record syscall number somewhere useful. info->si_addr = reinterpret_cast<void*>(syscall_nr); bool dumped = CrashReporter::WriteMinidumpForSigInfo(nr, info, void_context); if (!dumped) { LOG_ERROR("Failed to write minidump"); } #endif // Do this last, in case it crashes or deadlocks. SandboxLogJSStack(); // Try to reraise, so the parent sees that this process crashed. // (If tgkill is forbidden, then seccomp will raise SIGSYS, which // also accomplishes that goal.) signal(SIGSYS, SIG_DFL); syscall(__NR_tgkill, pid, tid, nr); _exit(127); }