3 # Copyright (C) 2016 Julien Desfossez <jdesfossez@efficios.com>
5 # SPDX-License-Identifier: GPL-2.0-only
8 TEST_DESC
="Kernel tracer - select, poll and epoll payload extraction"
12 VALIDATE_SCRIPT
="$CURDIR/validate_select_poll_epoll.py"
15 # Only run this test on x86 and arm
16 uname
-m |
grep -E "x86|i686|arm|aarch64" >/dev
/null
2>&1
22 # Babeltrace python bindings are required for the validation, but
23 # it is not a mandatory dependancy of the project, so fail run the
24 # without the content validation, at least we test that we are not
25 # crashing the kernel.
26 $VALIDATE_SCRIPT --help >/dev
/null
2>&1
28 echo "# Failed to run the validation script, Babeltrace Python bindings might be missing"
32 LAST_WARNING
=$
(dmesg |
grep " WARNING:" | cut
-d' ' -f1 |
tail -1)
33 LAST_OOPS
=$
(dmesg |
grep " OOPS:" | cut
-d' ' -f1 |
tail -1)
34 LAST_BUG
=$
(dmesg |
grep " BUG:" | cut
-d' ' -f1 |
tail -1)
36 source $TESTDIR/utils
/utils.sh
38 function check_trace_content
()
40 if test $DISABLE_VALIDATE == 1; then
41 ok
0 "Validation skipped"
47 ok
0 "Validation success"
53 function test_working_cases
()
55 TRACE_PATH
=$
(mktemp
--tmpdir -d "tmp.${FUNCNAME[0]}_trace_path.XXXXXX")
56 SESSION_NAME
="syscall_payload"
58 # arm64 does not have epoll_wait
59 uname
-m |
grep -E "aarch64" >/dev
/null
2>&1
61 SYSCALL_LIST
="select,pselect6,poll,ppoll,epoll_ctl,epoll_pwait"
63 SYSCALL_LIST
="select,pselect6,poll,ppoll,epoll_ctl,epoll_wait,epoll_pwait"
66 diag
"Working cases for select, pselect6, poll, ppoll and epoll, waiting for input"
68 create_lttng_session_ok
$SESSION_NAME $TRACE_PATH
70 lttng_enable_kernel_syscall_ok
$SESSION_NAME $SYSCALL_LIST
71 add_context_kernel_ok
$SESSION_NAME channel0 pid
73 start_lttng_tracing_ok
74 { out
=$
(yes |
$CURDIR/select_poll_epoll
-t 1); } 2>/dev
/null
76 pid
=$
(echo $out | cut
-d' ' -f1)
78 validate_trace
"$SYSCALL_LIST" $TRACE_PATH
79 check_trace_content
-t 1 -p $pid $TRACE_PATH
81 destroy_lttng_session_ok
$SESSION_NAME
86 function test_timeout_cases
()
88 TRACE_PATH
=$
(mktemp
--tmpdir -d "tmp.${FUNCNAME[0]}_trace_path.XXXXXX")
89 SESSION_NAME
="syscall_payload"
91 # arm64 does not have epoll_wait
92 uname
-m |
grep -E "aarch64" >/dev
/null
2>&1
94 SYSCALL_LIST
="select,pselect6,poll,ppoll,epoll_ctl,epoll_pwait"
96 SYSCALL_LIST
="select,pselect6,poll,ppoll,epoll_ctl,epoll_wait,epoll_pwait"
99 diag
"Timeout cases (1ms) for select, pselect6, poll, ppoll and epoll"
101 create_lttng_session_ok
$SESSION_NAME $TRACE_PATH
103 lttng_enable_kernel_syscall_ok
$SESSION_NAME "$SYSCALL_LIST"
104 add_context_kernel_ok
$SESSION_NAME channel0 pid
106 start_lttng_tracing_ok
107 { out
=$
($CURDIR/select_poll_epoll
-t 2); } 2>/dev
/null
108 stop_lttng_tracing_ok
109 pid
=$
(echo $out | cut
-d' ' -f1)
111 validate_trace
"$SYSCALL_LIST" $TRACE_PATH
112 check_trace_content
-t 2 -p $pid $TRACE_PATH 2>/dev
/null
114 destroy_lttng_session_ok
$SESSION_NAME
119 function test_pselect_invalid_fd
()
121 TRACE_PATH
=$
(mktemp
--tmpdir -d "tmp.${FUNCNAME[0]}_trace_path.XXXXXX")
122 SESSION_NAME
="syscall_payload"
123 SYSCALL_LIST
="pselect6"
125 diag
"pselect with invalid FD"
127 create_lttng_session_ok
$SESSION_NAME $TRACE_PATH
129 lttng_enable_kernel_syscall_ok
$SESSION_NAME $SYSCALL_LIST
130 add_context_kernel_ok
$SESSION_NAME channel0 pid
132 start_lttng_tracing_ok
133 { out
=$
($CURDIR/select_poll_epoll
-t 3); } 2>/dev
/null
134 stop_lttng_tracing_ok
135 pid
=$
(echo $out | cut
-d' ' -f1)
137 validate_trace
"$SYSCALL_LIST" $TRACE_PATH
138 check_trace_content
-t 3 -p $pid $TRACE_PATH 2>/dev
/null
140 destroy_lttng_session_ok
$SESSION_NAME
145 function test_big_ppoll
()
147 TRACE_PATH
=$
(mktemp
--tmpdir -d "tmp.${FUNCNAME[0]}_trace_path.XXXXXX")
148 SESSION_NAME
="syscall_payload"
151 diag
"ppoll with 2047 FDs"
153 create_lttng_session_ok
$SESSION_NAME $TRACE_PATH
155 lttng_enable_kernel_syscall_ok
$SESSION_NAME $SYSCALL_LIST
156 add_context_kernel_ok
$SESSION_NAME channel0 pid
158 start_lttng_tracing_ok
159 { out
=$
(yes |
$CURDIR/select_poll_epoll
-t 4); } 2>/dev
/null
160 stop_lttng_tracing_ok
161 pid
=$
(echo $out | cut
-d' ' -f1)
163 validate_trace
"$SYSCALL_LIST" $TRACE_PATH
164 check_trace_content
-t 4 -p $pid $TRACE_PATH 2>/dev
/null
166 destroy_lttng_session_ok
$SESSION_NAME
171 function test_ppoll_overflow
()
173 TRACE_PATH
=$
(mktemp
--tmpdir -d "tmp.${FUNCNAME[0]}_trace_path.XXXXXX")
174 SESSION_NAME
="syscall_payload"
177 diag
"ppoll buffer overflow, should segfault, waits for input"
179 create_lttng_session_ok
$SESSION_NAME $TRACE_PATH
181 lttng_enable_kernel_syscall_ok
$SESSION_NAME $SYSCALL_LIST
182 add_context_kernel_ok
$SESSION_NAME channel0 pid
184 start_lttng_tracing_ok
185 diag
"Expect segfaults"
186 { out
=$
(yes |
$CURDIR/select_poll_epoll
-t 5); } 2>/dev
/null
187 stop_lttng_tracing_ok
189 pid
=$
(echo $out | cut
-d' ' -f1)
191 validate_trace
"$SYSCALL_LIST" $TRACE_PATH
193 check_trace_content
-t 5 -p $pid $TRACE_PATH 2>/dev
/null
195 destroy_lttng_session_ok
$SESSION_NAME
200 function test_pselect_invalid_ptr
()
202 TRACE_PATH
=$
(mktemp
--tmpdir -d "tmp.${FUNCNAME[0]}_trace_path.XXXXXX")
203 SESSION_NAME
="syscall_payload"
204 SYSCALL_LIST
="pselect6"
206 diag
"pselect with invalid pointer, waits for input"
208 create_lttng_session_ok
$SESSION_NAME $TRACE_PATH
210 lttng_enable_kernel_syscall_ok
$SESSION_NAME $SYSCALL_LIST
211 add_context_kernel_ok
$SESSION_NAME channel0 pid
213 start_lttng_tracing_ok
214 { out
=$
(yes |
$CURDIR/select_poll_epoll
-t 6); } 2>/dev
/null
215 stop_lttng_tracing_ok
216 pid
=$
(echo $out | cut
-d' ' -f1)
218 validate_trace
"$SYSCALL_LIST" $TRACE_PATH
219 check_trace_content
-t 6 -p $pid $TRACE_PATH 2>/dev
/null
221 destroy_lttng_session_ok
$SESSION_NAME
226 function test_ppoll_ulong_max
()
228 TRACE_PATH
=$
(mktemp
--tmpdir -d "tmp.${FUNCNAME[0]}_trace_path.XXXXXX")
229 SESSION_NAME
="syscall_payload"
232 diag
"ppoll with ulong_max fds, waits for input"
234 create_lttng_session_ok
$SESSION_NAME $TRACE_PATH
236 lttng_enable_kernel_syscall_ok
$SESSION_NAME $SYSCALL_LIST
237 add_context_kernel_ok
$SESSION_NAME channel0 pid
239 start_lttng_tracing_ok
240 { out
=$
(yes |
$CURDIR/select_poll_epoll
-t 7); } 2>/dev
/null
241 stop_lttng_tracing_ok
242 pid
=$
(echo $out | cut
-d' ' -f1)
244 validate_trace
"$SYSCALL_LIST" $TRACE_PATH
245 check_trace_content
-t 7 -p $pid $TRACE_PATH 2>/dev
/null
247 destroy_lttng_session_ok
$SESSION_NAME
252 function test_epoll_pwait_invalid_ptr
()
254 TRACE_PATH
=$
(mktemp
--tmpdir -d "tmp.${FUNCNAME[0]}_trace_path.XXXXXX")
255 SESSION_NAME
="syscall_payload"
256 SYSCALL_LIST
="epoll_pwait"
258 diag
"epoll_pwait with invalid pointer, waits for input"
260 create_lttng_session_ok
$SESSION_NAME $TRACE_PATH
262 lttng_enable_kernel_syscall_ok
$SESSION_NAME $SYSCALL_LIST
263 add_context_kernel_ok
$SESSION_NAME channel0 pid
265 start_lttng_tracing_ok
266 { out
=$
(yes |
$CURDIR/select_poll_epoll
-t 8); } 2>/dev
/null
267 stop_lttng_tracing_ok
268 pid
=$
(echo $out | cut
-d' ' -f1)
270 validate_trace
"$SYSCALL_LIST" $TRACE_PATH
271 check_trace_content
-t 8 -p $pid $TRACE_PATH 2>/dev
/null
273 destroy_lttng_session_ok
$SESSION_NAME
278 function test_epoll_pwait_int_max
()
280 TRACE_PATH
=$
(mktemp
--tmpdir -d "tmp.${FUNCNAME[0]}_trace_path.XXXXXX")
281 SESSION_NAME
="syscall_payload"
282 SYSCALL_LIST
="epoll_pwait"
284 diag
"epoll_pwait with maxevents set to INT_MAX, waits for input"
286 create_lttng_session_ok
$SESSION_NAME $TRACE_PATH
288 lttng_enable_kernel_syscall_ok
$SESSION_NAME $SYSCALL_LIST
289 add_context_kernel_ok
$SESSION_NAME channel0 pid
291 start_lttng_tracing_ok
292 { out
=$
(yes |
$CURDIR/select_poll_epoll
-t 9); } 2>/dev
/null
293 stop_lttng_tracing_ok
294 pid
=$
(echo $out | cut
-d' ' -f1)
296 validate_trace
"$SYSCALL_LIST" $TRACE_PATH
297 check_trace_content
-t 9 -p $pid $TRACE_PATH 2>/dev
/null
299 destroy_lttng_session_ok
$SESSION_NAME
304 function test_ppoll_concurrent
()
306 TRACE_PATH
=$
(mktemp
--tmpdir -d "tmp.${FUNCNAME[0]}_trace_path.XXXXXX")
307 SESSION_NAME
="syscall_payload"
310 diag
"ppoll with concurrent updates of the structure from user-space, stress test (3000 iterations), waits for input + timeout 1ms"
312 create_lttng_session_ok
$SESSION_NAME $TRACE_PATH
314 lttng_enable_kernel_syscall_ok
$SESSION_NAME $SYSCALL_LIST
315 add_context_kernel_ok
$SESSION_NAME channel0 pid
317 start_lttng_tracing_ok
318 { out
=$
(yes |
$CURDIR/select_poll_epoll
-t 10); } 2>/dev
/null
319 stop_lttng_tracing_ok
320 pid
=$
(echo $out | cut
-d' ' -f1)
322 validate_trace
"$SYSCALL_LIST" $TRACE_PATH
323 check_trace_content
-t 10 -p $pid $TRACE_PATH 2>/dev
/null
325 destroy_lttng_session_ok
$SESSION_NAME
330 function test_epoll_pwait_concurrent
()
332 TRACE_PATH
=$
(mktemp
--tmpdir -d "tmp.${FUNCNAME[0]}_trace_path.XXXXXX")
333 SESSION_NAME
="syscall_payload"
334 SYSCALL_LIST
="epoll_ctl,epoll_pwait"
336 diag
"epoll_pwait with concurrent munmap of the buffer from user-space, should randomly segfault, run multiple times, waits for input + timeout 1ms"
338 create_lttng_session_ok
$SESSION_NAME $TRACE_PATH
340 lttng_enable_kernel_syscall_ok
$SESSION_NAME $SYSCALL_LIST
341 add_context_kernel_ok
$SESSION_NAME channel0 pid
343 start_lttng_tracing_ok
344 diag
"Expect segfaults"
345 for i
in $
(seq 1 100); do
346 { out
=$
($CURDIR/select_poll_epoll
-t 11); } 2>/dev
/null
348 pid
=$
(echo $out | cut
-d' ' -f1)
349 stop_lttng_tracing_ok
351 # epoll_wait is not always generated in the trace (stress test)
352 validate_trace
"epoll_ctl" $TRACE_PATH
353 check_trace_content
-t 11 -p $pid $TRACE_PATH 2>/dev
/null
355 destroy_lttng_session_ok
$SESSION_NAME
360 # MUST set TESTDIR before calling those functions
361 plan_tests
$NUM_TESTS
363 print_test_banner
"$TEST_DESC"
365 if [ "$(id -u)" == "0" ]; then
371 skip
$isroot "Root access is needed. Skipping all tests." $NUM_TESTS ||
377 test_pselect_invalid_fd
380 test_pselect_invalid_ptr
382 test_epoll_pwait_invalid_ptr
383 test_epoll_pwait_int_max
384 test_ppoll_concurrent
385 test_epoll_pwait_concurrent
389 NEW_WARNING
=$
(dmesg |
grep " WARNING:" | cut
-d' ' -f1 |
tail -1)
390 NEW_OOPS
=$
(dmesg |
grep " OOPS:" | cut
-d' ' -f1 |
tail -1)
391 NEW_BUG
=$
(dmesg |
grep " BUG:" | cut
-d' ' -f1 |
tail -1)
393 if test "$LAST_WARNING" != "$NEW_WARNING"; then
394 fail
"New WARNING generated"
396 if test "$LAST_OOPS" != "$NEW_OOPS"; then
397 fail
"New OOPS generated"
399 if test "$LAST_BUG" != "$NEW_BUG"; then
400 fail
"New BUG generated"