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