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