Skip to content

Commit 09f6b0c

Browse files
committed
Merge tag 'linux_kselftest-fixes-6.12-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest
Pull kselftest fixes from Shuah Khan: "Fixes for build, run-time errors, and reporting errors: - ftrace: regression test for a kernel crash when running function graph tracing and then enabling function profiler. - rseq: fix for mm_cid test failure. - vDSO: - fixes to reporting skip and other error conditions - changes unconditionally build chacha and getrandom tests on all architectures to make it easier for them to run in CIs - build error when sched.h to bring in CLONE_NEWTIME define" * tag 'linux_kselftest-fixes-6.12-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest: ftrace/selftest: Test combination of function_graph tracer and function profiler selftests/rseq: Fix mm_cid test failure selftests: vDSO: Explicitly include sched.h selftests: vDSO: improve getrandom and chacha error messages selftests: vDSO: unconditionally build getrandom test selftests: vDSO: unconditionally build chacha test
2 parents 974099e + 4ee5ca9 commit 09f6b0c

File tree

12 files changed

+183
-109
lines changed

12 files changed

+183
-109
lines changed

tools/arch/arm64/vdso

Lines changed: 0 additions & 1 deletion
This file was deleted.

tools/arch/loongarch/vdso

Lines changed: 0 additions & 1 deletion
This file was deleted.

tools/arch/powerpc/vdso

Lines changed: 0 additions & 1 deletion
This file was deleted.

tools/arch/s390/vdso

Lines changed: 0 additions & 1 deletion
This file was deleted.

tools/arch/x86/vdso

Lines changed: 0 additions & 1 deletion
This file was deleted.
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#!/bin/sh
2+
# SPDX-License-Identifier: GPL-2.0
3+
# description: ftrace - function profiler with function graph tracing
4+
# requires: function_profile_enabled set_ftrace_filter function_graph:tracer
5+
6+
# The function graph tracer can now be run along side of the function
7+
# profiler. But there was a bug that caused the combination of the two
8+
# to crash. It also required the function graph tracer to be started
9+
# first.
10+
#
11+
# This test triggers that bug
12+
#
13+
# We need both function_graph and profiling to run this test
14+
15+
fail() { # mesg
16+
echo $1
17+
exit_fail
18+
}
19+
20+
echo "Enabling function graph tracer:"
21+
echo function_graph > current_tracer
22+
echo "enable profiler"
23+
24+
# Older kernels do not allow function_profile to be enabled with
25+
# function graph tracer. If the below fails, mark it as unsupported
26+
echo 1 > function_profile_enabled || exit_unsupported
27+
28+
# Let it run for a bit to make sure nothing explodes
29+
sleep 1
30+
31+
exit 0

tools/testing/selftests/rseq/rseq.c

Lines changed: 75 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,6 @@ unsigned int rseq_size = -1U;
6060
/* Flags used during rseq registration. */
6161
unsigned int rseq_flags;
6262

63-
/*
64-
* rseq feature size supported by the kernel. 0 if the registration was
65-
* unsuccessful.
66-
*/
67-
unsigned int rseq_feature_size = -1U;
68-
6963
static int rseq_ownership;
7064
static int rseq_reg_success; /* At least one rseq registration has succeded. */
7165

@@ -111,6 +105,43 @@ int rseq_available(void)
111105
}
112106
}
113107

108+
/* The rseq areas need to be at least 32 bytes. */
109+
static
110+
unsigned int get_rseq_min_alloc_size(void)
111+
{
112+
unsigned int alloc_size = rseq_size;
113+
114+
if (alloc_size < ORIG_RSEQ_ALLOC_SIZE)
115+
alloc_size = ORIG_RSEQ_ALLOC_SIZE;
116+
return alloc_size;
117+
}
118+
119+
/*
120+
* Return the feature size supported by the kernel.
121+
*
122+
* Depending on the value returned by getauxval(AT_RSEQ_FEATURE_SIZE):
123+
*
124+
* 0: Return ORIG_RSEQ_FEATURE_SIZE (20)
125+
* > 0: Return the value from getauxval(AT_RSEQ_FEATURE_SIZE).
126+
*
127+
* It should never return a value below ORIG_RSEQ_FEATURE_SIZE.
128+
*/
129+
static
130+
unsigned int get_rseq_kernel_feature_size(void)
131+
{
132+
unsigned long auxv_rseq_feature_size, auxv_rseq_align;
133+
134+
auxv_rseq_align = getauxval(AT_RSEQ_ALIGN);
135+
assert(!auxv_rseq_align || auxv_rseq_align <= RSEQ_THREAD_AREA_ALLOC_SIZE);
136+
137+
auxv_rseq_feature_size = getauxval(AT_RSEQ_FEATURE_SIZE);
138+
assert(!auxv_rseq_feature_size || auxv_rseq_feature_size <= RSEQ_THREAD_AREA_ALLOC_SIZE);
139+
if (auxv_rseq_feature_size)
140+
return auxv_rseq_feature_size;
141+
else
142+
return ORIG_RSEQ_FEATURE_SIZE;
143+
}
144+
114145
int rseq_register_current_thread(void)
115146
{
116147
int rc;
@@ -119,7 +150,7 @@ int rseq_register_current_thread(void)
119150
/* Treat libc's ownership as a successful registration. */
120151
return 0;
121152
}
122-
rc = sys_rseq(&__rseq_abi, rseq_size, 0, RSEQ_SIG);
153+
rc = sys_rseq(&__rseq_abi, get_rseq_min_alloc_size(), 0, RSEQ_SIG);
123154
if (rc) {
124155
if (RSEQ_READ_ONCE(rseq_reg_success)) {
125156
/* Incoherent success/failure within process. */
@@ -140,28 +171,12 @@ int rseq_unregister_current_thread(void)
140171
/* Treat libc's ownership as a successful unregistration. */
141172
return 0;
142173
}
143-
rc = sys_rseq(&__rseq_abi, rseq_size, RSEQ_ABI_FLAG_UNREGISTER, RSEQ_SIG);
174+
rc = sys_rseq(&__rseq_abi, get_rseq_min_alloc_size(), RSEQ_ABI_FLAG_UNREGISTER, RSEQ_SIG);
144175
if (rc)
145176
return -1;
146177
return 0;
147178
}
148179

149-
static
150-
unsigned int get_rseq_feature_size(void)
151-
{
152-
unsigned long auxv_rseq_feature_size, auxv_rseq_align;
153-
154-
auxv_rseq_align = getauxval(AT_RSEQ_ALIGN);
155-
assert(!auxv_rseq_align || auxv_rseq_align <= RSEQ_THREAD_AREA_ALLOC_SIZE);
156-
157-
auxv_rseq_feature_size = getauxval(AT_RSEQ_FEATURE_SIZE);
158-
assert(!auxv_rseq_feature_size || auxv_rseq_feature_size <= RSEQ_THREAD_AREA_ALLOC_SIZE);
159-
if (auxv_rseq_feature_size)
160-
return auxv_rseq_feature_size;
161-
else
162-
return ORIG_RSEQ_FEATURE_SIZE;
163-
}
164-
165180
static __attribute__((constructor))
166181
void rseq_init(void)
167182
{
@@ -178,28 +193,54 @@ void rseq_init(void)
178193
}
179194
if (libc_rseq_size_p && libc_rseq_offset_p && libc_rseq_flags_p &&
180195
*libc_rseq_size_p != 0) {
196+
unsigned int libc_rseq_size;
197+
181198
/* rseq registration owned by glibc */
182199
rseq_offset = *libc_rseq_offset_p;
183-
rseq_size = *libc_rseq_size_p;
200+
libc_rseq_size = *libc_rseq_size_p;
184201
rseq_flags = *libc_rseq_flags_p;
185-
rseq_feature_size = get_rseq_feature_size();
186-
if (rseq_feature_size > rseq_size)
187-
rseq_feature_size = rseq_size;
202+
203+
/*
204+
* Previous versions of glibc expose the value
205+
* 32 even though the kernel only supported 20
206+
* bytes initially. Therefore treat 32 as a
207+
* special-case. glibc 2.40 exposes a 20 bytes
208+
* __rseq_size without using getauxval(3) to
209+
* query the supported size, while still allocating a 32
210+
* bytes area. Also treat 20 as a special-case.
211+
*
212+
* Special-cases are handled by using the following
213+
* value as active feature set size:
214+
*
215+
* rseq_size = min(32, get_rseq_kernel_feature_size())
216+
*/
217+
switch (libc_rseq_size) {
218+
case ORIG_RSEQ_FEATURE_SIZE:
219+
fallthrough;
220+
case ORIG_RSEQ_ALLOC_SIZE:
221+
{
222+
unsigned int rseq_kernel_feature_size = get_rseq_kernel_feature_size();
223+
224+
if (rseq_kernel_feature_size < ORIG_RSEQ_ALLOC_SIZE)
225+
rseq_size = rseq_kernel_feature_size;
226+
else
227+
rseq_size = ORIG_RSEQ_ALLOC_SIZE;
228+
break;
229+
}
230+
default:
231+
/* Otherwise just use the __rseq_size from libc as rseq_size. */
232+
rseq_size = libc_rseq_size;
233+
break;
234+
}
188235
return;
189236
}
190237
rseq_ownership = 1;
191238
if (!rseq_available()) {
192239
rseq_size = 0;
193-
rseq_feature_size = 0;
194240
return;
195241
}
196242
rseq_offset = (void *)&__rseq_abi - rseq_thread_pointer();
197243
rseq_flags = 0;
198-
rseq_feature_size = get_rseq_feature_size();
199-
if (rseq_feature_size == ORIG_RSEQ_FEATURE_SIZE)
200-
rseq_size = ORIG_RSEQ_ALLOC_SIZE;
201-
else
202-
rseq_size = RSEQ_THREAD_AREA_ALLOC_SIZE;
203244
}
204245

205246
static __attribute__((destructor))
@@ -209,7 +250,6 @@ void rseq_exit(void)
209250
return;
210251
rseq_offset = 0;
211252
rseq_size = -1U;
212-
rseq_feature_size = -1U;
213253
rseq_ownership = 0;
214254
}
215255

tools/testing/selftests/rseq/rseq.h

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,6 @@ extern unsigned int rseq_size;
6868
/* Flags used during rseq registration. */
6969
extern unsigned int rseq_flags;
7070

71-
/*
72-
* rseq feature size supported by the kernel. 0 if the registration was
73-
* unsuccessful.
74-
*/
75-
extern unsigned int rseq_feature_size;
76-
7771
enum rseq_mo {
7872
RSEQ_MO_RELAXED = 0,
7973
RSEQ_MO_CONSUME = 1, /* Unused */
@@ -193,7 +187,7 @@ static inline uint32_t rseq_current_cpu(void)
193187

194188
static inline bool rseq_node_id_available(void)
195189
{
196-
return (int) rseq_feature_size >= rseq_offsetofend(struct rseq_abi, node_id);
190+
return (int) rseq_size >= rseq_offsetofend(struct rseq_abi, node_id);
197191
}
198192

199193
/*
@@ -207,7 +201,7 @@ static inline uint32_t rseq_current_node_id(void)
207201

208202
static inline bool rseq_mm_cid_available(void)
209203
{
210-
return (int) rseq_feature_size >= rseq_offsetofend(struct rseq_abi, mm_cid);
204+
return (int) rseq_size >= rseq_offsetofend(struct rseq_abi, mm_cid);
211205
}
212206

213207
static inline uint32_t rseq_current_mm_cid(void)

tools/testing/selftests/vDSO/Makefile

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,8 @@ ifeq ($(ARCH),$(filter $(ARCH),x86 x86_64))
99
TEST_GEN_PROGS += vdso_standalone_test_x86
1010
endif
1111
TEST_GEN_PROGS += vdso_test_correctness
12-
ifeq ($(ARCH)$(CONFIG_X86_32),$(filter $(ARCH)$(CONFIG_X86_32),x86 x86_64 loongarch arm64 powerpc s390))
1312
TEST_GEN_PROGS += vdso_test_getrandom
1413
TEST_GEN_PROGS += vdso_test_chacha
15-
endif
1614

1715
CFLAGS := -std=gnu99 -O2
1816

@@ -37,9 +35,9 @@ $(OUTPUT)/vdso_test_getrandom: CFLAGS += -isystem $(top_srcdir)/tools/include \
3735
$(KHDR_INCLUDES) \
3836
-isystem $(top_srcdir)/include/uapi
3937

40-
$(OUTPUT)/vdso_test_chacha: $(top_srcdir)/tools/arch/$(SRCARCH)/vdso/vgetrandom-chacha.S
38+
$(OUTPUT)/vdso_test_chacha: vgetrandom-chacha.S
4139
$(OUTPUT)/vdso_test_chacha: CFLAGS += -idirafter $(top_srcdir)/tools/include \
4240
-idirafter $(top_srcdir)/tools/include/generated \
4341
-idirafter $(top_srcdir)/arch/$(SRCARCH)/include \
4442
-idirafter $(top_srcdir)/include \
45-
-D__ASSEMBLY__ -Wa,--noexecstack
43+
-Wa,--noexecstack

tools/testing/selftests/vDSO/vdso_test_chacha.c

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* Copyright (C) 2022-2024 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
44
*/
55

6+
#include <linux/compiler.h>
67
#include <tools/le_byteshift.h>
78
#include <sys/random.h>
89
#include <sys/auxv.h>
@@ -73,10 +74,10 @@ static void reference_chacha20_blocks(uint8_t *dst_bytes, const uint32_t *key, u
7374
counter[1] = s[13];
7475
}
7576

76-
typedef uint8_t u8;
77-
typedef uint32_t u32;
78-
typedef uint64_t u64;
79-
#include <vdso/getrandom.h>
77+
void __weak __arch_chacha20_blocks_nostack(uint8_t *dst_bytes, const uint32_t *key, uint32_t *counter, size_t nblocks)
78+
{
79+
ksft_exit_skip("Not implemented on architecture\n");
80+
}
8081

8182
int main(int argc, char *argv[])
8283
{
@@ -90,10 +91,8 @@ int main(int argc, char *argv[])
9091
ksft_set_plan(1);
9192

9293
for (unsigned int trial = 0; trial < TRIALS; ++trial) {
93-
if (getrandom(key, sizeof(key), 0) != sizeof(key)) {
94-
printf("getrandom() failed!\n");
95-
return KSFT_SKIP;
96-
}
94+
if (getrandom(key, sizeof(key), 0) != sizeof(key))
95+
ksft_exit_skip("getrandom() failed unexpectedly\n");
9796
memset(counter1, 0, sizeof(counter1));
9897
reference_chacha20_blocks(output1, key, counter1, BLOCKS);
9998
for (unsigned int split = 0; split < BLOCKS; ++split) {
@@ -102,8 +101,10 @@ int main(int argc, char *argv[])
102101
if (split)
103102
__arch_chacha20_blocks_nostack(output2, key, counter2, split);
104103
__arch_chacha20_blocks_nostack(output2 + split * BLOCK_SIZE, key, counter2, BLOCKS - split);
105-
if (memcmp(output1, output2, sizeof(output1)) || memcmp(counter1, counter2, sizeof(counter1)))
106-
return KSFT_FAIL;
104+
if (memcmp(output1, output2, sizeof(output1)))
105+
ksft_exit_fail_msg("Main loop outputs do not match on trial %u, split %u\n", trial, split);
106+
if (memcmp(counter1, counter2, sizeof(counter1)))
107+
ksft_exit_fail_msg("Main loop counters do not match on trial %u, split %u\n", trial, split);
107108
}
108109
}
109110
memset(counter1, 0, sizeof(counter1));
@@ -113,14 +114,19 @@ int main(int argc, char *argv[])
113114

114115
reference_chacha20_blocks(output1, key, counter1, BLOCKS);
115116
__arch_chacha20_blocks_nostack(output2, key, counter2, BLOCKS);
116-
if (memcmp(output1, output2, sizeof(output1)) || memcmp(counter1, counter2, sizeof(counter1)))
117-
return KSFT_FAIL;
117+
if (memcmp(output1, output2, sizeof(output1)))
118+
ksft_exit_fail_msg("Block limit outputs do not match after first round\n");
119+
if (memcmp(counter1, counter2, sizeof(counter1)))
120+
ksft_exit_fail_msg("Block limit counters do not match after first round\n");
118121

119122
reference_chacha20_blocks(output1, key, counter1, BLOCKS);
120123
__arch_chacha20_blocks_nostack(output2, key, counter2, BLOCKS);
121-
if (memcmp(output1, output2, sizeof(output1)) || memcmp(counter1, counter2, sizeof(counter1)))
122-
return KSFT_FAIL;
124+
if (memcmp(output1, output2, sizeof(output1)))
125+
ksft_exit_fail_msg("Block limit outputs do not match after second round\n");
126+
if (memcmp(counter1, counter2, sizeof(counter1)))
127+
ksft_exit_fail_msg("Block limit counters do not match after second round\n");
123128

124129
ksft_test_result_pass("chacha: PASS\n");
125-
return KSFT_PASS;
130+
ksft_exit_pass();
131+
return 0;
126132
}

0 commit comments

Comments
 (0)