1 // Copyright (c) 2012 The Chromium OS Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include <sys/socket.h> 6 #include <sys/un.h> 7 #include <unistd.h> 8 9 #include <cerrno> 10 #include <cstdlib> 11 #include <cstring> 12 #include <iostream> 13 14 int recbomb(int n); 15 void PrepareBelow(int argc, char *argv[]); 16 extern int DefeatTailOptimizationForCrasher(); 17 int DefeatTailOptimizationForBomb() { 18 return 0; 19 } 20 21 int main(int argc, char *argv[]) { 22 PrepareBelow(argc, argv); 23 return recbomb(16) + DefeatTailOptimizationForCrasher(); 24 } 25 26 bool SendPid(const char *socket_path); 27 28 using std::cerr; 29 30 // Prepare for doing the crash, but do it below main so that main's 31 // line numbers remain stable. 32 void PrepareBelow(int argc, char *argv[]) { 33 cerr << "pid=" << getpid() << '\n'; 34 if (argc == 2 && strcmp(argv[1], "--nocrash") == 0) { 35 cerr << "Doing normal exit\n"; 36 exit(0); 37 } 38 if (argc == 3 && strcmp(argv[1], "--sendpid") == 0) { 39 if (!SendPid(argv[2])) 40 exit(0); 41 } 42 cerr << "Crashing as requested.\n"; 43 } 44 45 // Used when the crasher runs in a different PID namespace than the test. A PID 46 // sent over a Unix domain socket to a process in a different PID namespace is 47 // converted to that PID namespace. 48 bool SendPid(const char *socket_path) { 49 struct Socket { 50 Socket(): fd(socket(AF_UNIX, SOCK_DGRAM, 0)) {} 51 ~Socket() { if (fd != -1) close(fd); } 52 int fd; 53 } sock; 54 55 if (sock.fd == -1) { 56 cerr << "socket() failed: " << strerror(errno) << '\n'; 57 return false; 58 } 59 60 sockaddr_un address = { AF_UNIX }; 61 strncpy(address.sun_path, socket_path, sizeof(address.sun_path) - 1); 62 sockaddr *address_ptr = reinterpret_cast<sockaddr *>(&address); 63 if (connect(sock.fd, address_ptr, sizeof(address)) == -1) { 64 cerr << "connect() failed: " << strerror(errno) << '\n'; 65 return false; 66 } 67 68 char zero = '\0'; 69 iovec data = { &zero, 1 }; 70 msghdr msg = { NULL, 0, &data, 1 }; 71 72 if (sendmsg(sock.fd, &msg, 0) == -1) { 73 cerr << "sendmsg() failed: " << strerror(errno) << '\n'; 74 return false; 75 } 76 77 return true; 78 } 79