Fix: futex wait: handle spurious futex wakeups
[lttng-tools.git] / tests / regression / kernel / test_select_poll_epoll
1 #!/bin/bash
2 #
3 # Copyright (C) 2016 Julien Desfossez <jdesfossez@efficios.com>
4 #
5 # SPDX-License-Identifier: GPL-2.0-only
6 #
7
8 TEST_DESC="Kernel tracer - select, poll and epoll payload extraction"
9
10 CURDIR=$(dirname "$0")/
11 TESTDIR=$CURDIR/../..
12 VALIDATE_SCRIPT="$CURDIR/validate_select_poll_epoll.py"
13 NUM_TESTS=102
14
15 DISABLE_VALIDATE=0
16 # Babeltrace python bindings are required for the validation, but
17 # it is not a mandatory dependancy of the project, so fail run the
18 # without the content validation, at least we test that we are not
19 # crashing the kernel.
20 $VALIDATE_SCRIPT --help >/dev/null 2>&1
21 if test $? != 0; then
22 echo "# Failed to run the validation script, Babeltrace Python bindings might be missing"
23 DISABLE_VALIDATE=1
24 fi
25
26 LAST_WARNING=$(dmesg | grep " WARNING:" | cut -d' ' -f1 | tail -1)
27 LAST_OOPS=$(dmesg | grep " OOPS:" | cut -d' ' -f1 | tail -1)
28 LAST_BUG=$(dmesg | grep " BUG:" | cut -d' ' -f1 | tail -1)
29
30 # shellcheck source=../../utils/utils.sh
31 source $TESTDIR/utils/utils.sh
32
33 function check_trace_content()
34 {
35 if test $DISABLE_VALIDATE == 1; then
36 ok 0 "Validation skipped"
37 return
38 fi
39
40 $VALIDATE_SCRIPT $@
41 if test $? = 0; then
42 ok 0 "Validation success"
43 else
44 fail "Validation"
45 fi
46 }
47
48 function test_working_cases()
49 {
50 SESSION_NAME="syscall_payload"
51 TRACE_PATH=$(mktemp --tmpdir -d "tmp.test_kernel_select_poll_epoll_${FUNCNAME[0]}_trace_path.XXXXXX")
52 TEST_VALIDATION_OUTPUT_PATH=$(mktemp --tmpdir -u "tmp.test_kernel_select_poll_epoll_${FUNCNAME[0]}_validation.XXXXXX")
53
54 # arm64 does not have epoll_wait
55 uname -m | grep -E "aarch64" >/dev/null 2>&1
56 if test $? = 0; then
57 SYSCALL_LIST="select,pselect6,poll,ppoll,epoll_ctl,epoll_pwait"
58 else
59 SYSCALL_LIST="select,pselect6,poll,ppoll,epoll_ctl,epoll_wait,epoll_pwait"
60 fi
61
62 diag "Working cases for select, pselect6, poll, ppoll and epoll, waiting for input"
63
64 create_lttng_session_ok $SESSION_NAME "$TRACE_PATH"
65
66 lttng_enable_kernel_syscall_ok $SESSION_NAME $SYSCALL_LIST
67 add_context_kernel_ok $SESSION_NAME channel0 pid
68
69 start_lttng_tracing_ok
70 yes | "$CURDIR"/select_poll_epoll --validation-file "$TEST_VALIDATION_OUTPUT_PATH" -t 1
71 stop_lttng_tracing_ok
72
73 validate_trace "$SYSCALL_LIST" "$TRACE_PATH"
74 check_trace_content -t 1 --validation-file "$TEST_VALIDATION_OUTPUT_PATH" "$TRACE_PATH"
75
76 destroy_lttng_session_ok $SESSION_NAME
77
78 rm -rf "$TRACE_PATH"
79 rm -f "$TEST_VALIDATION_OUTPUT_PATH"
80 }
81
82 function test_timeout_cases()
83 {
84 SESSION_NAME="syscall_payload"
85 TRACE_PATH=$(mktemp --tmpdir -d "tmp.test_kernel_select_poll_epoll_${FUNCNAME[0]}_trace_path.XXXXXX")
86 TEST_VALIDATION_OUTPUT_PATH=$(mktemp --tmpdir -u "tmp.test_kernel_select_poll_epoll_${FUNCNAME[0]}_validation.XXXXXX")
87
88 # arm64 does not have epoll_wait
89 uname -m | grep -E "aarch64" >/dev/null 2>&1
90 if test $? = 0; then
91 SYSCALL_LIST="select,pselect6,poll,ppoll,epoll_ctl,epoll_pwait"
92 else
93 SYSCALL_LIST="select,pselect6,poll,ppoll,epoll_ctl,epoll_wait,epoll_pwait"
94 fi
95
96 diag "Timeout cases (1ms) for select, pselect6, poll, ppoll and epoll"
97
98 create_lttng_session_ok $SESSION_NAME "$TRACE_PATH"
99
100 lttng_enable_kernel_syscall_ok $SESSION_NAME "$SYSCALL_LIST"
101 add_context_kernel_ok $SESSION_NAME channel0 pid
102
103 start_lttng_tracing_ok
104 yes | "$CURDIR"/select_poll_epoll --validation-file "$TEST_VALIDATION_OUTPUT_PATH" -t 2
105 stop_lttng_tracing_ok
106
107 validate_trace "$SYSCALL_LIST" "$TRACE_PATH"
108 check_trace_content -t 2 --validation-file "$TEST_VALIDATION_OUTPUT_PATH" "$TRACE_PATH" 2>/dev/null
109
110 destroy_lttng_session_ok $SESSION_NAME
111
112 rm -rf "$TRACE_PATH"
113 rm -f "$TEST_VALIDATION_OUTPUT_PATH"
114 }
115
116 function test_pselect_invalid_fd()
117 {
118 SESSION_NAME="syscall_payload"
119 SYSCALL_LIST="pselect6"
120 TRACE_PATH=$(mktemp --tmpdir -d "tmp.test_kernel_select_poll_epoll_${FUNCNAME[0]}_trace_path.XXXXXX")
121 TEST_VALIDATION_OUTPUT_PATH=$(mktemp --tmpdir -u "tmp.test_kernel_select_poll_epoll_${FUNCNAME[0]}_validation.XXXXXX")
122
123 diag "pselect with invalid FD"
124
125 create_lttng_session_ok $SESSION_NAME "$TRACE_PATH"
126
127 lttng_enable_kernel_syscall_ok $SESSION_NAME $SYSCALL_LIST
128 add_context_kernel_ok $SESSION_NAME channel0 pid
129
130 start_lttng_tracing_ok
131 yes | "$CURDIR"/select_poll_epoll --validation-file "$TEST_VALIDATION_OUTPUT_PATH" -t 3
132 stop_lttng_tracing_ok
133
134 validate_trace "$SYSCALL_LIST" "$TRACE_PATH"
135 check_trace_content -t 3 --validation-file "$TEST_VALIDATION_OUTPUT_PATH" "$TRACE_PATH" 2>/dev/null
136
137 destroy_lttng_session_ok $SESSION_NAME
138
139 rm -rf "$TRACE_PATH"
140 rm -f "$TEST_VALIDATION_OUTPUT_PATH"
141 }
142
143 function test_big_ppoll()
144 {
145 SESSION_NAME="syscall_payload"
146 SYSCALL_LIST="ppoll"
147 TRACE_PATH=$(mktemp --tmpdir -d "tmp.test_kernel_select_poll_epoll_${FUNCNAME[0]}_trace_path.XXXXXX")
148 TEST_VALIDATION_OUTPUT_PATH=$(mktemp --tmpdir -u "tmp.test_kernel_select_poll_epoll_${FUNCNAME[0]}_validation.XXXXXX")
149
150 diag "ppoll with 2047 FDs"
151
152 create_lttng_session_ok $SESSION_NAME "$TRACE_PATH"
153
154 lttng_enable_kernel_syscall_ok $SESSION_NAME $SYSCALL_LIST
155 add_context_kernel_ok $SESSION_NAME channel0 pid
156
157 start_lttng_tracing_ok
158 yes | "$CURDIR"/select_poll_epoll --validation-file "$TEST_VALIDATION_OUTPUT_PATH" -t 4
159 stop_lttng_tracing_ok
160
161 validate_trace "$SYSCALL_LIST" "$TRACE_PATH"
162 check_trace_content -t 4 --validation-file "$TEST_VALIDATION_OUTPUT_PATH" "$TRACE_PATH" 2>/dev/null
163
164 destroy_lttng_session_ok $SESSION_NAME
165
166 rm -rf "$TRACE_PATH"
167 rm -f "$TEST_VALIDATION_OUTPUT_PATH"
168 }
169
170 function test_ppoll_overflow()
171 {
172 SESSION_NAME="syscall_payload"
173 SYSCALL_LIST="ppoll"
174 TRACE_PATH=$(mktemp --tmpdir -d "tmp.test_kernel_select_poll_epoll_${FUNCNAME[0]}_trace_path.XXXXXX")
175 TEST_VALIDATION_OUTPUT_PATH=$(mktemp --tmpdir -u "tmp.test_kernel_select_poll_epoll_${FUNCNAME[0]}_validation.XXXXXX")
176
177 diag "ppoll buffer overflow, should segfault, waits for input"
178
179 create_lttng_session_ok $SESSION_NAME "$TRACE_PATH"
180
181 lttng_enable_kernel_syscall_ok $SESSION_NAME $SYSCALL_LIST
182 add_context_kernel_ok $SESSION_NAME channel0 pid
183
184 start_lttng_tracing_ok
185 diag "Expect segfaults"
186 yes | "$CURDIR"/select_poll_epoll --validation-file "$TEST_VALIDATION_OUTPUT_PATH" -t 5
187 stop_lttng_tracing_ok
188
189 validate_trace "$SYSCALL_LIST" "$TRACE_PATH"
190
191 check_trace_content -t 5 --validation-file "$TEST_VALIDATION_OUTPUT_PATH" "$TRACE_PATH" 2>/dev/null
192
193 destroy_lttng_session_ok $SESSION_NAME
194
195 rm -rf "$TRACE_PATH"
196 rm -f "$TEST_VALIDATION_OUTPUT_PATH"
197 }
198
199 function test_pselect_invalid_ptr()
200 {
201 SESSION_NAME="syscall_payload"
202 SYSCALL_LIST="pselect6"
203 TRACE_PATH=$(mktemp --tmpdir -d "tmp.test_kernel_select_poll_epoll_${FUNCNAME[0]}_trace_path.XXXXXX")
204 TEST_VALIDATION_OUTPUT_PATH=$(mktemp --tmpdir -u "tmp.test_kernel_select_poll_epoll_${FUNCNAME[0]}_validation.XXXXXX")
205
206 diag "pselect with invalid pointer, waits for input"
207
208 create_lttng_session_ok $SESSION_NAME "$TRACE_PATH"
209
210 lttng_enable_kernel_syscall_ok $SESSION_NAME $SYSCALL_LIST
211 add_context_kernel_ok $SESSION_NAME channel0 pid
212
213 start_lttng_tracing_ok
214 yes | "$CURDIR"/select_poll_epoll --validation-file "$TEST_VALIDATION_OUTPUT_PATH" -t 6
215 stop_lttng_tracing_ok
216
217 validate_trace "$SYSCALL_LIST" "$TRACE_PATH"
218 check_trace_content -t 6 --validation-file "$TEST_VALIDATION_OUTPUT_PATH" "$TRACE_PATH" 2>/dev/null
219
220 destroy_lttng_session_ok $SESSION_NAME
221
222 rm -rf "$TRACE_PATH"
223 rm -f "$TEST_VALIDATION_OUTPUT_PATH"
224 }
225
226 function test_ppoll_ulong_max()
227 {
228 SESSION_NAME="syscall_payload"
229 SYSCALL_LIST="ppoll"
230 TRACE_PATH=$(mktemp --tmpdir -d "tmp.test_kernel_select_poll_epoll_${FUNCNAME[0]}_trace_path.XXXXXX")
231 TEST_VALIDATION_OUTPUT_PATH=$(mktemp --tmpdir -u "tmp.test_kernel_select_poll_epoll_${FUNCNAME[0]}_validation.XXXXXX")
232
233 diag "ppoll with ulong_max fds, waits for input"
234
235 create_lttng_session_ok $SESSION_NAME "$TRACE_PATH"
236
237 lttng_enable_kernel_syscall_ok $SESSION_NAME $SYSCALL_LIST
238 add_context_kernel_ok $SESSION_NAME channel0 pid
239
240 start_lttng_tracing_ok
241 yes | "$CURDIR"/select_poll_epoll --validation-file "$TEST_VALIDATION_OUTPUT_PATH" -t 7
242 stop_lttng_tracing_ok
243
244 validate_trace "$SYSCALL_LIST" "$TRACE_PATH"
245 check_trace_content -t 7 --validation-file "$TEST_VALIDATION_OUTPUT_PATH" "$TRACE_PATH" 2>/dev/null
246
247 destroy_lttng_session_ok $SESSION_NAME
248
249 rm -rf "$TRACE_PATH"
250 rm -f "$TEST_VALIDATION_OUTPUT_PATH"
251 }
252
253 function test_epoll_pwait_invalid_ptr()
254 {
255 SESSION_NAME="syscall_payload"
256 SYSCALL_LIST="epoll_pwait"
257 TRACE_PATH=$(mktemp --tmpdir -d "tmp.test_kernel_select_poll_epoll_${FUNCNAME[0]}_trace_path.XXXXXX")
258 TEST_VALIDATION_OUTPUT_PATH=$(mktemp --tmpdir -u "tmp.test_kernel_select_poll_epoll_${FUNCNAME[0]}_validation.XXXXXX")
259
260 diag "epoll_pwait with invalid pointer, waits for input"
261
262 create_lttng_session_ok $SESSION_NAME "$TRACE_PATH"
263
264 lttng_enable_kernel_syscall_ok $SESSION_NAME $SYSCALL_LIST
265 add_context_kernel_ok $SESSION_NAME channel0 pid
266
267 start_lttng_tracing_ok
268 yes | "$CURDIR"/select_poll_epoll --validation-file "$TEST_VALIDATION_OUTPUT_PATH" -t 8
269 stop_lttng_tracing_ok
270
271 validate_trace "$SYSCALL_LIST" "$TRACE_PATH"
272 check_trace_content -t 8 --validation-file "$TEST_VALIDATION_OUTPUT_PATH" "$TRACE_PATH" 2>/dev/null
273
274 destroy_lttng_session_ok $SESSION_NAME
275
276 rm -rf "$TRACE_PATH"
277 rm -f "$TEST_VALIDATION_OUTPUT_PATH"
278 }
279
280 function test_epoll_pwait_int_max()
281 {
282 SESSION_NAME="syscall_payload"
283 SYSCALL_LIST="epoll_pwait"
284 TRACE_PATH=$(mktemp --tmpdir -d "tmp.test_kernel_select_poll_epoll_${FUNCNAME[0]}_trace_path.XXXXXX")
285 TEST_VALIDATION_OUTPUT_PATH=$(mktemp --tmpdir -u "tmp.test_kernel_select_poll_epoll_${FUNCNAME[0]}_validation.XXXXXX")
286
287 diag "epoll_pwait with maxevents set to INT_MAX, waits for input"
288
289 create_lttng_session_ok $SESSION_NAME "$TRACE_PATH"
290
291 lttng_enable_kernel_syscall_ok $SESSION_NAME $SYSCALL_LIST
292 add_context_kernel_ok $SESSION_NAME channel0 pid
293
294 start_lttng_tracing_ok
295 yes | "$CURDIR"/select_poll_epoll --validation-file "$TEST_VALIDATION_OUTPUT_PATH" -t 9
296 stop_lttng_tracing_ok
297
298 validate_trace "$SYSCALL_LIST" "$TRACE_PATH"
299 check_trace_content -t 9 --validation-file "$TEST_VALIDATION_OUTPUT_PATH" "$TRACE_PATH" 2>/dev/null
300
301 destroy_lttng_session_ok $SESSION_NAME
302
303 rm -rf "$TRACE_PATH"
304 rm -f "$TEST_VALIDATION_OUTPUT_PATH"
305 }
306
307 function test_ppoll_concurrent()
308 {
309 SESSION_NAME="syscall_payload"
310 SYSCALL_LIST="ppoll"
311 TRACE_PATH=$(mktemp --tmpdir -d "tmp.test_kernel_select_poll_epoll_${FUNCNAME[0]}_trace_path.XXXXXX")
312 TEST_VALIDATION_OUTPUT_PATH=$(mktemp --tmpdir -u "tmp.test_kernel_select_poll_epoll_${FUNCNAME[0]}_validation.XXXXXX")
313
314 diag "ppoll with concurrent updates of the structure from user-space, stress test (3000 iterations), waits for input + timeout 1ms"
315
316 create_lttng_session_ok $SESSION_NAME "$TRACE_PATH"
317
318 lttng_enable_kernel_syscall_ok $SESSION_NAME $SYSCALL_LIST
319 add_context_kernel_ok $SESSION_NAME channel0 pid
320
321 start_lttng_tracing_ok
322 yes | "$CURDIR"/select_poll_epoll --validation-file "$TEST_VALIDATION_OUTPUT_PATH" -t 10
323 stop_lttng_tracing_ok
324
325 validate_trace "$SYSCALL_LIST" "$TRACE_PATH"
326 check_trace_content -t 10 --validation-file "$TEST_VALIDATION_OUTPUT_PATH" "$TRACE_PATH" 2>/dev/null
327
328 destroy_lttng_session_ok $SESSION_NAME
329
330 rm -rf "$TRACE_PATH"
331 rm -f "$TEST_VALIDATION_OUTPUT_PATH"
332 }
333
334 function test_epoll_pwait_concurrent()
335 {
336 SESSION_NAME="syscall_payload"
337 SYSCALL_LIST="epoll_ctl,epoll_pwait"
338 TRACE_PATH=$(mktemp --tmpdir -d "tmp.test_kernel_select_poll_epoll_${FUNCNAME[0]}_trace_path.XXXXXX")
339 TEST_VALIDATION_OUTPUT_PATH=$(mktemp --tmpdir -u "tmp.test_kernel_select_poll_epoll_${FUNCNAME[0]}_validation.XXXXXX")
340
341 diag "epoll_pwait with concurrent munmap of the buffer from user-space, should randomly segfault, run multiple times, waits for input + timeout 1ms"
342
343 create_lttng_session_ok $SESSION_NAME "$TRACE_PATH"
344
345 lttng_enable_kernel_syscall_ok $SESSION_NAME $SYSCALL_LIST
346 add_context_kernel_ok $SESSION_NAME channel0 pid
347
348 start_lttng_tracing_ok
349 diag "Expect segfaults"
350 for i in $(seq 1 100); do
351 yes | "$CURDIR"/select_poll_epoll --validation-file "$TEST_VALIDATION_OUTPUT_PATH" -t 11
352 done
353 stop_lttng_tracing_ok
354
355 # epoll_wait is not always generated in the trace (stress test)
356 validate_trace "epoll_ctl" "$TRACE_PATH"
357 check_trace_content -t 11 --validation-file "$TEST_VALIDATION_OUTPUT_PATH" "$TRACE_PATH" 2>/dev/null
358
359 destroy_lttng_session_ok $SESSION_NAME
360
361 rm -rf "$TRACE_PATH"
362 rm -f "$TEST_VALIDATION_OUTPUT_PATH"
363 }
364
365 # MUST set TESTDIR before calling those functions
366 plan_tests $NUM_TESTS
367
368 print_test_banner "$TEST_DESC"
369
370 # Only run this test on x86 and arm
371 uname -m | grep -E "x86|i686|arm|aarch64" >/dev/null 2>&1
372 if test $? != 0; then
373 skip 0 "Run only on x86 and arm. Skipping all tests." $NUM_TESTS
374 exit 0
375 fi
376
377 if [ "$(id -u)" == "0" ]; then
378 isroot=1
379 else
380 isroot=0
381 fi
382
383 skip $isroot "Root access is needed. Skipping all tests." $NUM_TESTS ||
384 {
385 validate_lttng_modules_present
386
387 start_lttng_sessiond
388
389 test_working_cases
390 test_timeout_cases
391 test_pselect_invalid_fd
392 test_big_ppoll
393 test_ppoll_overflow
394 test_pselect_invalid_ptr
395 test_ppoll_ulong_max
396 test_epoll_pwait_invalid_ptr
397 test_epoll_pwait_int_max
398 test_ppoll_concurrent
399 test_epoll_pwait_concurrent
400
401 stop_lttng_sessiond
402
403 NEW_WARNING=$(dmesg | grep " WARNING:" | cut -d' ' -f1 | tail -1)
404 NEW_OOPS=$(dmesg | grep " OOPS:" | cut -d' ' -f1 | tail -1)
405 NEW_BUG=$(dmesg | grep " BUG:" | cut -d' ' -f1 | tail -1)
406
407 if test "$LAST_WARNING" != "$NEW_WARNING"; then
408 fail "New WARNING generated"
409 fi
410 if test "$LAST_OOPS" != "$NEW_OOPS"; then
411 fail "New OOPS generated"
412 fi
413 if test "$LAST_BUG" != "$NEW_BUG"; then
414 fail "New BUG generated"
415 fi
416 }
This page took 0.037975 seconds and 4 git commands to generate.