1 /*
2 * Check poke injection.
3 *
4 * Copyright (c) 2021 The strace developers.
5 * All rights reserved.
6 *
7 * SPDX-License-Identifier: GPL-2.0-or-later
8 */
9
10 #include "tests.h"
11 #include "scno.h"
12
13 #include <limits.h>
14 #include <stdio.h>
15 #include <string.h>
16 #include <unistd.h>
17
18 int
19 main(int argc, char *argv[])
20 {
21 FILE *exp_err = NULL;
22
23 if (argc > 1) {
24 exp_err = fopen(argv[1], "w");
25 if (!exp_err)
26 perror_msg_and_fail("fopen: %s", argv[1]);
27 setvbuf(exp_err, NULL, _IONBF, 0);
28 }
29
30 pid_t pid = getpid();
31 char *const chdir_buf = tail_alloc(PATH_MAX);
32 char *const getcwd_buf = tail_alloc(PATH_MAX);
33 char *p;
34
35 /*
36 * regular poke at a properly aligned address on entering syscall
37 */
38 memset(chdir_buf, '/', PATH_MAX);
39 p = chdir_buf;
40 printf("chdir(\"%.*s\") = %s (INJECTED: args)\n",
41 PATH_MAX - 1, p, sprintrc(chdir(p)));
42
43 /*
44 * regular poke at an unaligned address on entering syscall
45 */
46 memset(chdir_buf, '/', PATH_MAX);
47 chdir_buf[PATH_MAX - 1] = '\0';
48 p = chdir_buf + 1;
49 printf("chdir(\"%.*s\") = %s (INJECTED: args)\n",
50 PATH_MAX - 2, p, sprintrc(chdir(p)));
51 if (chdir_buf[0] != '/')
52 error_msg_and_fail("failed to poke at unaligned address"
53 " %p properly", p);
54
55 /*
56 * poke at an inaccessible but properly aligned address
57 */
58 p = chdir_buf + PATH_MAX;
59 printf("chdir(%p) = %s\n", p, sprintrc(chdir(p)));
60 if (exp_err) {
61 fprintf(exp_err,
62 ".*: Failed to tamper with process %d: couldn't poke\n",
63 pid);
64 }
65
66 /*
67 * poke at an inaccessible unaligned address
68 */
69 ++p;
70 printf("chdir(%p) = %s\n", p, sprintrc(chdir(p)));
71 if (exp_err) {
72 fprintf(exp_err,
73 ".*: Failed to tamper with process %d: couldn't poke\n",
74 pid);
75 }
76
77 /*
78 * poke at a partially accessible unaligned address
79 */
80 memset(chdir_buf, '/', PATH_MAX);
81 p = chdir_buf + PATH_MAX - 1;
82 printf("chdir(%p) = %s (INJECTED: args)\n", p, sprintrc(chdir(p)));
83 if (exp_err) {
84 fprintf(exp_err,
85 ".*: pid:%d short write"
86 " \\(1 < [[:digit:]]+\\) @%p(: .*)?\n",
87 pid, p);
88 fprintf(exp_err,
89 ".*: short read \\(1 < [[:digit:]]+\\) @%p: .*\n", p);
90 }
91
92 /*
93 * poke at a partially accessible properly aligned address
94 */
95 memset(chdir_buf, '/', PATH_MAX);
96 p -= 7;
97 printf("chdir(%p) = %s (INJECTED: args)\n", p, sprintrc(chdir(p)));
98 if (exp_err) {
99 fprintf(exp_err,
100 ".*: pid:%d short write"
101 " \\(8 < [[:digit:]]+\\) @%p(: .*)?\n",
102 pid, p);
103 fprintf(exp_err,
104 ".*: short read \\(8 < [[:digit:]]+\\) @%p: .*\n", p);
105 }
106
107 /*
108 * regular poke on exiting syscall
109 */
110 p = getcwd_buf;
111 long res = syscall(__NR_getcwd, p, PATH_MAX);
112 if (res <= 0)
113 perror_msg_and_fail("getcwd");
114
115 printf("getcwd(");
116 print_quoted_string(p);
117 printf(", %u) = %ld (INJECTED: args)\n", PATH_MAX, res);
118
119 if (exp_err)
120 fclose(exp_err);
121
122 puts("+++ exited with 0 +++");
123 return 0;
124 }