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