xref: /aosp_15_r20/external/autotest/client/cros/crash/crasher/crasher.cc (revision 9c5db1993ded3edbeafc8092d69fe5de2ee02df7)
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();
DefeatTailOptimizationForBomb()18 int DefeatTailOptimizationForBomb() {
19   return 0;
20 }
21 
main(int argc,char * argv[])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.
PrepareBelow(int argc,char * argv[])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.
SendPid(const char * socket_path)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