]>
Commit | Line | Data |
---|---|---|
39037602 A |
1 | #include <darwintest.h> |
2 | #include <errno.h> | |
3 | #include <fcntl.h> | |
4 | #include <sys/types.h> | |
5 | #include <sys/sysctl.h> | |
6 | #include <sys/resource.h> | |
7 | #include <stdlib.h> | |
8 | #include <string.h> | |
9 | #include <stdio.h> | |
10 | #include <TargetConditionals.h> | |
11 | #include <unistd.h> | |
12 | ||
13 | #define BUFFLEN 2048 | |
14 | #define EVILLEN 19 | |
15 | ||
16 | static const char corefile_ctl[] = "kern.corefile"; | |
17 | static const char coredump_ctl[] = "kern.coredump"; | |
18 | /* The default coredump location if the kern.coredump ctl is invalid */ | |
19 | static const char default_dump_fmt[] = "/cores/core.%d"; | |
20 | /* The coredump location when we set kern.coredump ctl to something valid */ | |
21 | static const char valid_dump_fmt[] = "/cores/test-core.%d"; | |
22 | ||
23 | /* /cores/core.%(null), then BORK immediately after. */ | |
24 | static char evil[] = {'/', 'c', 'o', 'r', 'e', 's', '/', 'c', 'o', 'r', 'e', '.', '%', '\0', 'B', 'O', 'R', 'K', '\0'}; | |
25 | /* A valid coredump location to test. */ | |
26 | static char valid_dump_loc[] = "/cores/test-core.%P"; | |
27 | ||
28 | static const struct rlimit lim_infty = { | |
29 | RLIM_INFINITY, | |
30 | RLIM_INFINITY | |
31 | }; | |
32 | ||
33 | #if TARGET_OS_OSX | |
34 | static int fork_and_wait_for_segfault(void); | |
35 | ||
36 | static int fork_and_wait_for_segfault() { | |
37 | int pid, ret; | |
38 | pid = fork(); | |
39 | if (pid == 0) { | |
40 | unsigned int *ptr = NULL; /* Cause a segfault so that we get a coredump */ | |
41 | *ptr = 0xdeadd00d; | |
42 | T_FAIL("Expected segmentation fault on write to NULL pointer"); | |
43 | } | |
44 | T_ASSERT_TRUE(pid != -1, "Checking fork success in parent"); | |
45 | ||
46 | ret = wait(NULL); | |
47 | T_ASSERT_TRUE(ret != -1, "Waited for child to segfault and dump core"); | |
48 | return pid; | |
49 | } | |
50 | #endif | |
51 | ||
52 | T_DECL( | |
813fb2f6 A |
53 | proc_core_name_24152432, |
54 | "Tests behavior of core dump when kern.corefile ends in %, e.g., /cores/core.%", | |
55 | T_META_ASROOT(true)) | |
39037602 A |
56 | { |
57 | #if TARGET_OS_OSX | |
58 | int ret, pid; | |
59 | int enable_core_dump = 1; | |
60 | char buf[BUFFLEN]; | |
61 | memset(buf, 0, BUFFLEN); | |
62 | size_t oldlen = BUFFLEN; | |
63 | ||
64 | ret = sysctlbyname(coredump_ctl, buf, &oldlen, &enable_core_dump, sizeof(int)); | |
65 | T_ASSERT_POSIX_SUCCESS(ret, "sysctl: enable core dumps"); | |
66 | memset(buf, 0, BUFFLEN); | |
67 | oldlen = BUFFLEN; | |
68 | ||
69 | ret = setrlimit(RLIMIT_CORE, &lim_infty); | |
70 | T_ASSERT_POSIX_SUCCESS(ret, "setrlimit: remove limit on maximum coredump size"); | |
71 | ||
72 | ret = sysctlbyname(corefile_ctl, buf, &oldlen, evil, EVILLEN); | |
73 | T_ASSERT_POSIX_SUCCESS(ret, "sysctl: set bad core dump location, old value was %s", buf); | |
74 | memset(buf, 0, BUFFLEN); | |
75 | oldlen = BUFFLEN; | |
76 | ||
77 | pid = fork_and_wait_for_segfault(); | |
78 | ||
79 | snprintf(buf, BUFFLEN, default_dump_fmt, pid); | |
80 | ret = remove(buf); | |
81 | T_ASSERT_TRUE(ret != -1, "Removing coredump file (should be in fallback location)"); | |
82 | memset(buf, 0, BUFFLEN); | |
83 | ||
84 | ret = sysctlbyname(corefile_ctl, buf, &oldlen, valid_dump_loc, strlen(valid_dump_loc)); | |
85 | T_ASSERT_POSIX_SUCCESS(ret, "sysctl: set valid core dump location, old value was %s", buf); | |
86 | memset(buf, 0, BUFFLEN); | |
87 | ||
88 | pid = fork_and_wait_for_segfault(); | |
89 | ||
90 | snprintf(buf, BUFFLEN, valid_dump_fmt, pid); | |
91 | ret = remove(buf); | |
92 | T_ASSERT_TRUE(ret != -1, "Removing coredump file (should be in valid location)"); | |
93 | #else | |
94 | T_LOG("proc_core_name appears in OS X only, skipping test."); | |
95 | #endif | |
96 | T_PASS("proc_core_name_24152432 PASSED"); | |
97 | } |