Home | History | Annotate | Download | only in crasher
      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