• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) 2008 Analog Devices Inc.
4  * Copyright (c) Linux Test Project, 2008-2023
5  * Copyright (c) 2025 Wei Gao <wegao@suse.com>
6  */
7 
8 /*\
9  * [Description]
10  *
11  * Check out-of-bound/unaligned addresses given to
12  *
13  *  - {PEEK,POKE}{DATA,TEXT,USER}
14  *  - {GET,SET}{,FG}REGS
15  *  - {GET,SET}SIGINFO
16  */
17 
18 #include <stdlib.h>
19 #include <sys/ptrace.h>
20 #include "tst_test.h"
21 
22 /* this should be sizeof(struct user), but that info is only found
23  * in the kernel asm/user.h which is not exported to userspace.
24  */
25 
26 #if defined(__i386__)
27 # define SIZEOF_USER 284
28 #elif defined(__x86_64__)
29 # define SIZEOF_USER 928
30 #else
31 # define SIZEOF_USER 0x1000	/* just pick a big number */
32 #endif
33 
34 static struct test_case_t {
35 	int request;
36 	long addr;
37 	long data;
38 } test_cases[] = {
39 	{PTRACE_PEEKDATA, .addr = 0},
40 	{PTRACE_PEEKDATA, .addr = 1},
41 	{PTRACE_PEEKDATA, .addr = 2},
42 	{PTRACE_PEEKDATA, .addr = 3},
43 	{PTRACE_PEEKDATA, .addr = -1},
44 	{PTRACE_PEEKDATA, .addr = -2},
45 	{PTRACE_PEEKDATA, .addr = -3},
46 	{PTRACE_PEEKDATA, .addr = -4},
47 	{PTRACE_PEEKTEXT, .addr = 0},
48 	{PTRACE_PEEKTEXT, .addr = 1},
49 	{PTRACE_PEEKTEXT, .addr = 2},
50 	{PTRACE_PEEKTEXT, .addr = 3},
51 	{PTRACE_PEEKTEXT, .addr = -1},
52 	{PTRACE_PEEKTEXT, .addr = -2},
53 	{PTRACE_PEEKTEXT, .addr = -3},
54 	{PTRACE_PEEKTEXT, .addr = -4},
55 	{PTRACE_PEEKUSER, .addr = SIZEOF_USER + 1},
56 	{PTRACE_PEEKUSER, .addr = SIZEOF_USER + 2},
57 	{PTRACE_PEEKUSER, .addr = SIZEOF_USER + 3},
58 	{PTRACE_PEEKUSER, .addr = SIZEOF_USER + 4},
59 	{PTRACE_PEEKUSER, .addr = -1},
60 	{PTRACE_PEEKUSER, .addr = -2},
61 	{PTRACE_PEEKUSER, .addr = -3},
62 	{PTRACE_PEEKUSER, .addr = -4},
63 	{PTRACE_POKEDATA, .addr = 0},
64 	{PTRACE_POKEDATA, .addr = 1},
65 	{PTRACE_POKEDATA, .addr = 2},
66 	{PTRACE_POKEDATA, .addr = 3},
67 	{PTRACE_POKEDATA, .addr = -1},
68 	{PTRACE_POKEDATA, .addr = -2},
69 	{PTRACE_POKEDATA, .addr = -3},
70 	{PTRACE_POKEDATA, .addr = -4},
71 	{PTRACE_POKETEXT, .addr = 0},
72 	{PTRACE_POKETEXT, .addr = 1},
73 	{PTRACE_POKETEXT, .addr = 2},
74 	{PTRACE_POKETEXT, .addr = 3},
75 	{PTRACE_POKETEXT, .addr = -1},
76 	{PTRACE_POKETEXT, .addr = -2},
77 	{PTRACE_POKETEXT, .addr = -3},
78 	{PTRACE_POKETEXT, .addr = -4},
79 	{PTRACE_POKEUSER, .addr = SIZEOF_USER + 1},
80 	{PTRACE_POKEUSER, .addr = SIZEOF_USER + 2},
81 	{PTRACE_POKEUSER, .addr = SIZEOF_USER + 3},
82 	{PTRACE_POKEUSER, .addr = SIZEOF_USER + 4},
83 	{PTRACE_POKEUSER, .addr = -1},
84 	{PTRACE_POKEUSER, .addr = -2},
85 	{PTRACE_POKEUSER, .addr = -3},
86 	{PTRACE_POKEUSER, .addr = -4},
87 #ifdef PTRACE_GETREGS
88 	{PTRACE_GETREGS, .data = 0},
89 	{PTRACE_GETREGS, .data = 1},
90 	{PTRACE_GETREGS, .data = 2},
91 	{PTRACE_GETREGS, .data = 3},
92 	{PTRACE_GETREGS, .data = -1},
93 	{PTRACE_GETREGS, .data = -2},
94 	{PTRACE_GETREGS, .data = -3},
95 	{PTRACE_GETREGS, .data = -4},
96 #endif
97 #ifdef PTRACE_GETFGREGS
98 	{PTRACE_GETFGREGS, .data = 0},
99 	{PTRACE_GETFGREGS, .data = 1},
100 	{PTRACE_GETFGREGS, .data = 2},
101 	{PTRACE_GETFGREGS, .data = 3},
102 	{PTRACE_GETFGREGS, .data = -1},
103 	{PTRACE_GETFGREGS, .data = -2},
104 	{PTRACE_GETFGREGS, .data = -3},
105 	{PTRACE_GETFGREGS, .data = -4},
106 #endif
107 #ifdef PTRACE_SETREGS
108 	{PTRACE_SETREGS, .data = 0},
109 	{PTRACE_SETREGS, .data = 1},
110 	{PTRACE_SETREGS, .data = 2},
111 	{PTRACE_SETREGS, .data = 3},
112 	{PTRACE_SETREGS, .data = -1},
113 	{PTRACE_SETREGS, .data = -2},
114 	{PTRACE_SETREGS, .data = -3},
115 	{PTRACE_SETREGS, .data = -4},
116 #endif
117 #ifdef PTRACE_SETFGREGS
118 	{PTRACE_SETFGREGS, .data = 0},
119 	{PTRACE_SETFGREGS, .data = 1},
120 	{PTRACE_SETFGREGS, .data = 2},
121 	{PTRACE_SETFGREGS, .data = 3},
122 	{PTRACE_SETFGREGS, .data = -1},
123 	{PTRACE_SETFGREGS, .data = -2},
124 	{PTRACE_SETFGREGS, .data = -3},
125 	{PTRACE_SETFGREGS, .data = -4},
126 #endif
127 #if HAVE_DECL_PTRACE_GETSIGINFO
128 	{PTRACE_GETSIGINFO, .data = 0},
129 	{PTRACE_GETSIGINFO, .data = 1},
130 	{PTRACE_GETSIGINFO, .data = 2},
131 	{PTRACE_GETSIGINFO, .data = 3},
132 	{PTRACE_GETSIGINFO, .data = -1},
133 	{PTRACE_GETSIGINFO, .data = -2},
134 	{PTRACE_GETSIGINFO, .data = -3},
135 	{PTRACE_GETSIGINFO, .data = -4},
136 #endif
137 #if HAVE_DECL_PTRACE_SETSIGINFO
138 	{PTRACE_SETSIGINFO, .data = 0},
139 	{PTRACE_SETSIGINFO, .data = 1},
140 	{PTRACE_SETSIGINFO, .data = 2},
141 	{PTRACE_SETSIGINFO, .data = 3},
142 	{PTRACE_SETSIGINFO, .data = -1},
143 	{PTRACE_SETSIGINFO, .data = -2},
144 	{PTRACE_SETSIGINFO, .data = -3},
145 	{PTRACE_SETSIGINFO, .data = -4},
146 #endif
147 };
148 
149 #define SPT(x)[PTRACE_##x] = #x,
150 static char *strings[] = {
151 	SPT(TRACEME)
152 	SPT(PEEKTEXT)
153 	SPT(PEEKDATA)
154 	SPT(PEEKUSER)
155 	SPT(POKETEXT)
156 	SPT(POKEDATA)
157 	SPT(POKEUSER)
158 #ifdef PTRACE_GETREGS
159 	SPT(GETREGS)
160 #endif
161 #ifdef PTRACE_SETREGS
162 	SPT(SETREGS)
163 #endif
164 #ifdef PTRACE_GETSIGINFO
165 	SPT(GETSIGINFO)
166 #endif
167 #ifdef PTRACE_SETSIGINFO
168 	SPT(SETSIGINFO)
169 #endif
170 #ifdef PTRACE_GETFGREGS
171 	SPT(GETFGREGS)
172 #endif
173 #ifdef PTRACE_SETFGREGS
174 	SPT(SETFGREGS)
175 #endif
176 	SPT(KILL)
177 	SPT(SINGLESTEP)
178 };
179 
child(void)180 static void child(void)
181 {
182 	SAFE_PTRACE(PTRACE_TRACEME, 0, NULL, NULL);
183 	raise(SIGSTOP);
184 	exit(0);
185 }
186 
run(void)187 static void run(void)
188 {
189 	size_t i;
190 	int pid;
191 	int status;
192 	int exp_errnos[] = {EIO, EFAULT};
193 
194 	pid = SAFE_FORK();
195 
196 	if (!pid)
197 		child();
198 
199 	SAFE_WAIT(&status);
200 
201 	if (!WIFSTOPPED(status))
202 		tst_brk(TBROK, "child %d was not stopped", pid);
203 
204 	for (i = 0; i < ARRAY_SIZE(test_cases); ++i) {
205 		struct test_case_t *tc = &test_cases[i];
206 
207 		TST_EXP_FAIL_ARR(ptrace(tc->request, pid, (void *)tc->addr,
208 					(void *)tc->data), exp_errnos, ARRAY_SIZE(exp_errnos),
209 					"ptrace(%s, ..., %li, %li) failed as expected",
210 					 strings[tc->request], tc->addr, tc->data);
211 	}
212 
213 	SAFE_PTRACE(PTRACE_CONT, pid, NULL, NULL);
214 
215 }
216 
217 static struct tst_test test = {
218 	.test_all = run,
219 	.forks_child = 1,
220 };
221