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) 51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "sandbox/linux/seccomp-bpf/die.h" 61320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <errno.h> 81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include <signal.h> 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <stdio.h> 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <sys/prctl.h> 111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include <sys/syscall.h> 121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include <unistd.h> 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/logging.h" 17f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/posix/eintr_wrapper.h" 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sandbox/linux/seccomp-bpf/syscall.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace sandbox { 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Die::ExitGroup() { 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // exit_group() should exit our program. After all, it is defined as a 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // function that doesn't return. But things can theoretically go wrong. 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Especially, since we are dealing with system call filters. Continuing 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // execution would be very bad in most cases where ExitGroup() gets called. 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // So, we'll try a few other strategies too. 28f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Syscall::Call(__NR_exit_group, 1); 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We have no idea what our run-time environment looks like. So, signal 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // handlers might or might not do the right thing. Try to reset settings 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to a defined state; but we have not way to verify whether we actually 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // succeeded in doing so. Nonetheless, triggering a fatal signal could help 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // us terminate. 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) signal(SIGSEGV, SIG_DFL); 36f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Syscall::Call(__NR_prctl, PR_SET_DUMPABLE, (void*)0, (void*)0, (void*)0); 37f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (*(volatile char*)0) { 38f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If there is no way for us to ask for the program to exit, the next 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // best thing we can do is to loop indefinitely. Maybe, somebody will notice 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and file a bug... 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We in fact retry the system call inside of our loop so that it will 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // stand out when somebody tries to diagnose the problem by using "strace". 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (;;) { 46f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Syscall::Call(__NR_exit_group, 1); 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 50f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void Die::SandboxDie(const char* msg, const char* file, int line) { 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (simple_exit_) { 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogToStderr(msg, file, line); 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 54f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) logging::LogMessage(file, line, logging::LOG_FATAL).stream() << msg; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExitGroup(); 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 59f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void Die::RawSandboxDie(const char* msg) { 6058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (!msg) 6158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) msg = ""; 6258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) RAW_LOG(FATAL, msg); 6358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) ExitGroup(); 6458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 6558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void Die::SandboxInfo(const char* msg, const char* file, int line) { 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!suppress_info_) { 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) logging::LogMessage(file, line, logging::LOG_INFO).stream() << msg; 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void Die::LogToStderr(const char* msg, const char* file, int line) { 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (msg) { 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char buf[40]; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) snprintf(buf, sizeof(buf), "%d", line); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string s = std::string(file) + ":" + buf + ":" + msg + "\n"; 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No need to loop. Short write()s are unlikely and if they happen we 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // probably prefer them over a loop that blocks. 80f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ignore_result( 81f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) HANDLE_EINTR(Syscall::Call(__NR_write, 2, s.c_str(), s.length()))); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool Die::simple_exit_ = false; 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool Die::suppress_info_ = false; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 88a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} // namespace sandbox 89