summaryrefslogtreecommitdiff
path: root/tools/testing/selftests
diff options
context:
space:
mode:
authorPark Tae-sun <ts930@dgu.ac.kr>2026-09-23 18:26:48 +0900
committerAndrew Morton <akpm@linux-foundation.org>2026-09-30 16:57:48 -0700
commit1cad68bc87c6f98e68b27e8589c1e9abc5835dbc (patch)
treefaa1713da6124c0fd2cd9a2d1db80356caeadc18 /tools/testing/selftests
parent33b6a821152ca43c74ad36b46fac22178499d27e (diff)
downloadlinux-next-1cad68bc87c6f98e68b27e8589c1e9abc5835dbc.tar.gz
linux-next-1cad68bc87c6f98e68b27e8589c1e9abc5835dbc.zip
selftests/mm: fix mlock2 errno handling and false PASS on ENOSYS
While inspecting selftests/mm syscall wrappers, I noticed that mlock2_() in mlock2.h handles the syscall return value differently from other wrappers: int ret = syscall(__NR_mlock2, start, len, flags); if (ret) { errno = ret; return -1; } Commit 1ddae9d67ee1 ("selftests/mm/mlock: print error on failure") introduced this intending to make mlock2_() behave like libc by setting errno and returning -1. However, glibc syscall(2) already returns -1 on failure and sets positive errno. Assigning "errno = ret;" overwrites errno with -1. To verify this, mlock2 was disabled in the kernel (via sys_ni_syscall) to return -ENOSYS. Testing revealed two interrelated defects: 1. In the unmodified test, mlock2_() clobbered errno to -1. The check "if (ret && errno == ENOSYS)" in main() was bypassed, resulting in an immediate crash in the first test: ~ # ./mlock2-tests TAP version 13 1..15 Bail out! mlock2(0): Unknown error -1 # Planned tests != run tests (15 != 0) # Totals: pass:0 fail:0 xfail:0 xpass:0 skip:0 error:0 (exit code: 1 - FAIL) 2. After restoring mlock2_() to directly return syscall(), errno correctly retained ENOSYS (38), entering the ENOSYS check in main(). However, it then called ksft_finished(): ~ # ./mlock2-tests TAP version 13 # Totals: pass:0 fail:0 xfail:0 xpass:0 skip:0 error:0 ~ # echo $? 0 Because ksft_set_plan() had not been called yet (ksft_plan == 0) and zero tests ran (ksft_pass == 0), ksft_finished() evaluated 0 == 0 as success and exited with KSFT_PASS (code 0) without any TAP skip header. Fix both issues by: 1. Returning the syscall() result directly in mlock2_() so that errno is preserved. 2. Calling ksft_exit_skip() on ENOSYS so unsupported kernels report a TAP skip ("1..0 # SKIP ...") and exit with KSFT_SKIP (code 4). Verification on the mlock2-disabled kernel: ~ # ./mlock2-tests TAP version 13 1..0 # SKIP mlock2() syscall is not supported ~ # echo $? 4 Re-enabling mlock2 in the kernel confirmed all 15 tests pass cleanly: ~ # ./mlock2-tests TAP version 13 1..15 ok 1 test_mlock_lock: Locked ... ok 15 test_mlockall_future_droppable: droppable memory not locked # Totals: pass:15 fail:0 xfail:0 xpass:0 skip:0 error:0 ~ # echo $? 0 Link: https://lore.kernel.org/20260923-selftests-mm-mlock2-fix-v1-1-750b627854c6@dgu.ac.kr Fixes: 1ddae9d67ee1 ("selftests/mm/mlock: print error on failure") Fixes: 65c89684896d ("selftests/mm: mlock2-tests: conform test to TAP format output") Signed-off-by: Park Tae-sun <ts930@dgu.ac.kr> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Reviewed-by: Gregory Price <gourry@gourry.net> Acked-by: David Hildenbrand (Arm) <david@kernel.org> Reviewed-by: Muhammad Usama Anjum <usama.anjum@arm.com> Cc: Lorenzo Stoakes <ljs@kernel.org> Cc: Liam R. Howlett <liam@infradead.org> Cc: Vlastimil Babka <vbabka@kernel.org> Cc: Mike Rapoport <rppt@kernel.org> Cc: Suren Baghdasaryan <surenb@google.com> Cc: Michal Hocko <mhocko@suse.com> Cc: Shuah Khan <shuah@kernel.org> Cc: Brendan Jackman <brendan.jackman@linux.dev>
Diffstat (limited to 'tools/testing/selftests')
-rw-r--r--tools/testing/selftests/mm/mlock2-tests.c2
-rw-r--r--tools/testing/selftests/mm/mlock2.h8
2 files changed, 2 insertions, 8 deletions
diff --git a/tools/testing/selftests/mm/mlock2-tests.c b/tools/testing/selftests/mm/mlock2-tests.c
index e16e288cc7c1..144b550813a6 100644
--- a/tools/testing/selftests/mm/mlock2-tests.c
+++ b/tools/testing/selftests/mm/mlock2-tests.c
@@ -502,7 +502,7 @@ int main(int argc, char **argv)
ret = mlock2_(map, size, MLOCK_ONFAULT);
if (ret && errno == ENOSYS)
- ksft_finished();
+ ksft_exit_skip("mlock2() syscall is not supported\n");
munmap(map, size);
diff --git a/tools/testing/selftests/mm/mlock2.h b/tools/testing/selftests/mm/mlock2.h
index 81e77fa41901..4417eaa5cfb7 100644
--- a/tools/testing/selftests/mm/mlock2.h
+++ b/tools/testing/selftests/mm/mlock2.h
@@ -6,13 +6,7 @@
static int mlock2_(void *start, size_t len, int flags)
{
- int ret = syscall(__NR_mlock2, start, len, flags);
-
- if (ret) {
- errno = ret;
- return -1;
- }
- return 0;
+ return syscall(__NR_mlock2, start, len, flags);
}
static FILE *seek_to_smaps_entry(unsigned long addr)