15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <errno.h> 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <linux/unistd.h> 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <stdio.h> 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <sys/prctl.h> 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/logging.h" 13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/posix/eintr_wrapper.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sandbox/linux/seccomp-bpf/syscall.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace sandbox { 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Die::ExitGroup() { 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // exit_group() should exit our program. After all, it is defined as a 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // function that doesn't return. But things can theoretically go wrong. 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Especially, since we are dealing with system call filters. Continuing 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // execution would be very bad in most cases where ExitGroup() gets called. 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // So, we'll try a few other strategies too. 25f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Syscall::Call(__NR_exit_group, 1); 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We have no idea what our run-time environment looks like. So, signal 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // handlers might or might not do the right thing. Try to reset settings 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to a defined state; but we have not way to verify whether we actually 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // succeeded in doing so. Nonetheless, triggering a fatal signal could help 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // us terminate. 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) signal(SIGSEGV, SIG_DFL); 33f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Syscall::Call(__NR_prctl, PR_SET_DUMPABLE, (void*)0, (void*)0, (void*)0); 34f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (*(volatile char*)0) { 35f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If there is no way for us to ask for the program to exit, the next 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // best thing we can do is to loop indefinitely. Maybe, somebody will notice 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and file a bug... 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We in fact retry the system call inside of our loop so that it will 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // stand out when somebody tries to diagnose the problem by using "strace". 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (;;) { 43f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Syscall::Call(__NR_exit_group, 1); 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 47f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void Die::SandboxDie(const char* msg, const char* file, int line) { 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (simple_exit_) { 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogToStderr(msg, file, line); 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 51f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) logging::LogMessage(file, line, logging::LOG_FATAL).stream() << msg; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExitGroup(); 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 56f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void Die::RawSandboxDie(const char* msg) { 5758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (!msg) 5858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) msg = ""; 5958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) RAW_LOG(FATAL, msg); 6058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) ExitGroup(); 6158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 6258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 63f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void Die::SandboxInfo(const char* msg, const char* file, int line) { 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!suppress_info_) { 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) logging::LogMessage(file, line, logging::LOG_INFO).stream() << msg; 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 69f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void Die::LogToStderr(const char* msg, const char* file, int line) { 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (msg) { 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char buf[40]; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) snprintf(buf, sizeof(buf), "%d", line); 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string s = std::string(file) + ":" + buf + ":" + msg + "\n"; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No need to loop. Short write()s are unlikely and if they happen we 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // probably prefer them over a loop that blocks. 77f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ignore_result( 78f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) HANDLE_EINTR(Syscall::Call(__NR_write, 2, s.c_str(), s.length()))); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 82f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool Die::simple_exit_ = false; 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool Die::suppress_info_ = false; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} // namespace sandbox 86