1*43a90889SApple OSS Distributions #include <TargetConditionals.h>
2*43a90889SApple OSS Distributions #include <errno.h>
3*43a90889SApple OSS Distributions #include <stdio.h>
4*43a90889SApple OSS Distributions #include <stdlib.h>
5*43a90889SApple OSS Distributions #include <string.h>
6*43a90889SApple OSS Distributions #include <unistd.h>
7*43a90889SApple OSS Distributions
8*43a90889SApple OSS Distributions #if __has_include(<ptrauth.h>)
9*43a90889SApple OSS Distributions #include <ptrauth.h>
10*43a90889SApple OSS Distributions #endif
11*43a90889SApple OSS Distributions
12*43a90889SApple OSS Distributions #include <sys/mman.h>
13*43a90889SApple OSS Distributions #include <sys/syslimits.h>
14*43a90889SApple OSS Distributions
15*43a90889SApple OSS Distributions char *cmdname;
16*43a90889SApple OSS Distributions
17*43a90889SApple OSS Distributions int
main(int argc,char * argv[])18*43a90889SApple OSS Distributions main(
19*43a90889SApple OSS Distributions int argc,
20*43a90889SApple OSS Distributions char *argv[])
21*43a90889SApple OSS Distributions {
22*43a90889SApple OSS Distributions uint32_t page_size;
23*43a90889SApple OSS Distributions void *page;
24*43a90889SApple OSS Distributions int ch;
25*43a90889SApple OSS Distributions int opt_interactive;
26*43a90889SApple OSS Distributions
27*43a90889SApple OSS Distributions cmdname = argv[0];
28*43a90889SApple OSS Distributions
29*43a90889SApple OSS Distributions opt_interactive = 0;
30*43a90889SApple OSS Distributions while ((ch = getopt(argc, argv, "i")) != -1) {
31*43a90889SApple OSS Distributions switch (ch) {
32*43a90889SApple OSS Distributions case 'i':
33*43a90889SApple OSS Distributions opt_interactive = 1;
34*43a90889SApple OSS Distributions break;
35*43a90889SApple OSS Distributions case '?':
36*43a90889SApple OSS Distributions default:
37*43a90889SApple OSS Distributions fprintf(stdout,
38*43a90889SApple OSS Distributions "Usage: %s [-i]\n"
39*43a90889SApple OSS Distributions "\t-i: interactive\n",
40*43a90889SApple OSS Distributions cmdname);
41*43a90889SApple OSS Distributions exit(1);
42*43a90889SApple OSS Distributions }
43*43a90889SApple OSS Distributions }
44*43a90889SApple OSS Distributions
45*43a90889SApple OSS Distributions page_size = getpagesize();
46*43a90889SApple OSS Distributions page = mmap(NULL, page_size, PROT_READ | PROT_EXEC, MAP_ANON | MAP_SHARED, -1, 0);
47*43a90889SApple OSS Distributions if (!page) {
48*43a90889SApple OSS Distributions fprintf(stderr, "%s:%d mmap() error %d (%s)\n",
49*43a90889SApple OSS Distributions cmdname, __LINE__,
50*43a90889SApple OSS Distributions errno, strerror(errno));
51*43a90889SApple OSS Distributions exit(1);
52*43a90889SApple OSS Distributions }
53*43a90889SApple OSS Distributions if (opt_interactive) {
54*43a90889SApple OSS Distributions fprintf(stdout, "allocated page at %p\n",
55*43a90889SApple OSS Distributions page);
56*43a90889SApple OSS Distributions }
57*43a90889SApple OSS Distributions
58*43a90889SApple OSS Distributions if (mprotect(page, page_size, PROT_READ | PROT_WRITE) != 0) {
59*43a90889SApple OSS Distributions fprintf(stderr, "%s:%d mprotect(RW) error %d (%s)\n",
60*43a90889SApple OSS Distributions cmdname, __LINE__,
61*43a90889SApple OSS Distributions errno, strerror(errno));
62*43a90889SApple OSS Distributions exit(1);
63*43a90889SApple OSS Distributions }
64*43a90889SApple OSS Distributions
65*43a90889SApple OSS Distributions #if __arm64__
66*43a90889SApple OSS Distributions // arm64 chdir() syscall
67*43a90889SApple OSS Distributions char chdir_code[] = {
68*43a90889SApple OSS Distributions 0x90, 0x01, 0x80, 0xd2, // movz x16, #0xc
69*43a90889SApple OSS Distributions 0x01, 0x10, 0x00, 0xd4, // svc #0x80
70*43a90889SApple OSS Distributions 0xc0, 0x03, 0x5f, 0xd6, // ret
71*43a90889SApple OSS Distributions };
72*43a90889SApple OSS Distributions #elif __x86_64__
73*43a90889SApple OSS Distributions // x86_64 chdir() syscall
74*43a90889SApple OSS Distributions char chdir_code[] = {
75*43a90889SApple OSS Distributions 0xb8, 0x0c, 0x00, 0x00, 0x02, // movl $0x200000c, %eax
76*43a90889SApple OSS Distributions 0x49, 0x89, 0xca, // movq %rcx, %r10
77*43a90889SApple OSS Distributions 0x0f, 0x05, // syscall
78*43a90889SApple OSS Distributions 0xc3, // retq
79*43a90889SApple OSS Distributions };
80*43a90889SApple OSS Distributions #elif __i386__
81*43a90889SApple OSS Distributions // i386 chdir() syscall
82*43a90889SApple OSS Distributions char chdir_code[] = {
83*43a90889SApple OSS Distributions 0x90, // nop
84*43a90889SApple OSS Distributions 0xc3, // retq
85*43a90889SApple OSS Distributions };
86*43a90889SApple OSS Distributions #endif
87*43a90889SApple OSS Distributions memcpy(page, chdir_code, sizeof chdir_code);
88*43a90889SApple OSS Distributions
89*43a90889SApple OSS Distributions if (opt_interactive) {
90*43a90889SApple OSS Distributions fprintf(stdout,
91*43a90889SApple OSS Distributions "changed page protection to r/w and copied code at %p\n",
92*43a90889SApple OSS Distributions page);
93*43a90889SApple OSS Distributions fprintf(stdout, "pausing...\n");
94*43a90889SApple OSS Distributions fflush(stdout);
95*43a90889SApple OSS Distributions getchar();
96*43a90889SApple OSS Distributions }
97*43a90889SApple OSS Distributions
98*43a90889SApple OSS Distributions if (mprotect(page, page_size, PROT_READ | PROT_EXEC) != 0) {
99*43a90889SApple OSS Distributions fprintf(stderr, "%s:%d mprotect(RX) error %d (%s)\n",
100*43a90889SApple OSS Distributions cmdname, __LINE__,
101*43a90889SApple OSS Distributions errno, strerror(errno));
102*43a90889SApple OSS Distributions exit(1);
103*43a90889SApple OSS Distributions }
104*43a90889SApple OSS Distributions
105*43a90889SApple OSS Distributions if (opt_interactive) {
106*43a90889SApple OSS Distributions fprintf(stdout,
107*43a90889SApple OSS Distributions "changed page protection to r/x at %p\n",
108*43a90889SApple OSS Distributions page);
109*43a90889SApple OSS Distributions fprintf(stdout, "pausing...\n");
110*43a90889SApple OSS Distributions fflush(stdout);
111*43a90889SApple OSS Distributions getchar();
112*43a90889SApple OSS Distributions }
113*43a90889SApple OSS Distributions
114*43a90889SApple OSS Distributions char origdir[PATH_MAX];
115*43a90889SApple OSS Distributions getcwd(origdir, sizeof(origdir) - 1);
116*43a90889SApple OSS Distributions
117*43a90889SApple OSS Distributions chdir("/");
118*43a90889SApple OSS Distributions if (opt_interactive) {
119*43a90889SApple OSS Distributions fprintf(stdout, "cwd before = %s\n", getwd(NULL));
120*43a90889SApple OSS Distributions }
121*43a90889SApple OSS Distributions
122*43a90889SApple OSS Distributions void (*mychdir)(char *) = page;
123*43a90889SApple OSS Distributions #if __has_feature(ptrauth_calls)
124*43a90889SApple OSS Distributions mychdir = ptrauth_sign_unauthenticated(mychdir, ptrauth_key_function_pointer, 0);
125*43a90889SApple OSS Distributions #endif
126*43a90889SApple OSS Distributions mychdir(getenv("HOME"));
127*43a90889SApple OSS Distributions if (opt_interactive) {
128*43a90889SApple OSS Distributions fprintf(stdout, "cwd after = %s\n", getwd(NULL));
129*43a90889SApple OSS Distributions fprintf(stdout, "pausing...\n");
130*43a90889SApple OSS Distributions fflush(stdout);
131*43a90889SApple OSS Distributions getchar();
132*43a90889SApple OSS Distributions }
133*43a90889SApple OSS Distributions
134*43a90889SApple OSS Distributions fprintf(stdout, "%s: WARNING: unsigned code was executed\n",
135*43a90889SApple OSS Distributions cmdname);
136*43a90889SApple OSS Distributions
137*43a90889SApple OSS Distributions /* fail: unsigned code was executed */
138*43a90889SApple OSS Distributions fprintf(stdout, "%s: FAIL\n", cmdname);
139*43a90889SApple OSS Distributions exit(1);
140*43a90889SApple OSS Distributions }
141