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 <cstdint>
     11 #include <cstdlib>
     12 #include <cstring>
     13 #include <cstdio>
     14 
     15 int recbomb(int n);
     16 void PrepareBelow(int argc, char *argv[]);
     17 extern int DefeatTailOptimizationForCrasher();
     18 int DefeatTailOptimizationForBomb() {
     19   return 0;
     20 }
     21 
     22 int main(int argc, char *argv[]) {
     23   PrepareBelow(argc, argv);
     24   return recbomb(16) + DefeatTailOptimizationForCrasher();
     25 }
     26 
     27 bool SendPid(const char *socket_path);
     28 
     29 // Prepare for doing the crash, but do it below main so that main's
     30 // line numbers remain stable.
     31 void PrepareBelow(int argc, char *argv[]) {
     32   fprintf(stderr, "pid=%jd\n", (intmax_t) getpid());
     33   if (argc == 2 && strcmp(argv[1], "--nocrash") == 0) {
     34     fprintf(stderr, "Doing normal exit\n");
     35     exit(0);
     36   }
     37   if (argc == 3 && strcmp(argv[1], "--sendpid") == 0) {
     38     if (!SendPid(argv[2]))
     39       exit(0);
     40   }
     41   fprintf(stderr, "Crashing as requested.\n");
     42 }
     43 
     44 // Used when the crasher runs in a different PID namespace than the test. A PID
     45 // sent over a Unix domain socket to a process in a different PID namespace is
     46 // converted to that PID namespace.
     47 bool SendPid(const char *socket_path) {
     48   struct Socket {
     49     Socket(): fd(socket(AF_UNIX, SOCK_DGRAM, 0)) {}
     50     ~Socket() { if (fd != -1) close(fd); }
     51     int fd;
     52   } sock;
     53 
     54   if (sock.fd == -1) {
     55     fprintf(stderr,"socket() failed: %s\n", strerror(errno));
     56     return false;
     57   }
     58 
     59   sockaddr_un address = { AF_UNIX };
     60   strncpy(address.sun_path, socket_path, sizeof(address.sun_path) - 1);
     61   sockaddr *address_ptr = reinterpret_cast<sockaddr *>(&address);
     62   if (connect(sock.fd, address_ptr, sizeof(address)) == -1) {
     63     fprintf(stderr, "connect() failed: %s\n", strerror(errno));
     64     return false;
     65   }
     66 
     67   char zero = '\0';
     68   iovec data = { &zero, 1 };
     69   msghdr msg = { NULL, 0, &data, 1 };
     70 
     71   if (sendmsg(sock.fd, &msg, 0) == -1) {
     72     fprintf(stderr, "sendmsg() failed: %s\n", strerror(errno));
     73     return false;
     74   }
     75 
     76   return true;
     77 }
     78