[LTP] [PATCH] kallsyms: skip user-space mapped addresses
Jan Stancek
jstancek@redhat.com
Tue Jul 9 14:41:19 CEST 2024
On Tue, Jul 9, 2024 at 2:35 PM Li Wang <liwan@redhat.com> wrote:
>
>
>
> On Tue, Jul 9, 2024 at 8:18 PM Jan Stancek <jstancek@redhat.com> wrote:
>>
>> RHEL9 s390x with KPTI enabled has been observed to sporadically
>> use same address ranges for user-space libraries as the ones
>> occupied by kallsyms while in kernel-space.
>
>
> Thanks for the proposal fix, do you think we need to add
> a check to see if KPTI is explicitly enabled before doing that
> is_address_mapped?
> (or, check the configuration for CONFIG_PAGE_TABLE_ISOLATION)
It shouldn't be needed. It's a small optimization, but the test run looks
fast enough (at least on s390x I tried).
>
>
>>
>> The test currently (wrongly) assumes, that a write to kallsym
>> address should fail and doesn't take into account that same
>> memory ranges could be mapped differently in user vs. kernel-space.
>>
>> Add a check to see if a kallsym address is already mapped by user-space,
>> and if it is, skip it to avoid false positives.
>>
>>
>> Before:
>> 13 kallsyms.c:115: TFAIL: Successfully accessed kernel addr 0x3ff8060787d (r) (__kstrtabns_nfs3_set_ds_client)
>> 14 kallsyms.c:115: TFAIL: Successfully accessed kernel addr 0x3ff806007a0 (t) (nfs_init_server_aclclient)
>> 15 kallsyms.c:115: TFAIL: Successfully accessed kernel addr 0x3ff8060a058 (d) (nfsacl_version)
>> 16 kallsyms.c:115: TFAIL: Successfully accessed kernel addr 0x3ff8060a078 (d) (nfsacl_rpcstat)
>> ...
>> kallsyms.c:130: TFAIL: Caught 103102 SIGSEGV but expected 153738
>>
>> After:
>> kallsyms.c:175: TDEBUG: Skipping userspace mapped address 0x3ff80220024
>> kallsyms.c:175: TDEBUG: Skipping userspace mapped address 0x3ff8022003c
>> kallsyms.c:175: TDEBUG: Skipping userspace mapped address 0x3ff80213b20
>> ...
>> kallsyms.c:184: TPASS: Caught 103473 SIGSEGV in access ksymbols addr, skipped 27234
>>
>> Signed-off-by: Jan Stancek <jstancek@redhat.com>
>> ---
>> testcases/kernel/security/kallsyms/kallsyms.c | 68 +++++++++++++++++--
>> 1 file changed, 63 insertions(+), 5 deletions(-)
>>
>> diff --git a/testcases/kernel/security/kallsyms/kallsyms.c b/testcases/kernel/security/kallsyms/kallsyms.c
>> index 2a5cbaa325ea..b07cb9cda268 100644
>> --- a/testcases/kernel/security/kallsyms/kallsyms.c
>> +++ b/testcases/kernel/security/kallsyms/kallsyms.c
>> @@ -54,6 +54,8 @@ static struct kallsym *sym_table;
>> static unsigned int nr_symbols;
>> static sigjmp_buf jmpbuf;
>> volatile sig_atomic_t segv_caught;
>> +static unsigned long *ranges;
>> +static int ranges_size, ranges_len;
>>
>> static void segv_handler(int sig)
>> {
>> @@ -89,6 +91,49 @@ static unsigned int read_kallsyms(struct kallsym *table, unsigned int table_size
>> return nr_syms;
>> }
>>
>> +static void read_proc_self_maps(void)
>> +{
>> + FILE *fp;
>> +
>> + ranges_len = 0;
>> + fp = fopen("/proc/self/maps", "r");
>> + if (fp == NULL)
>> + tst_brk(TBROK | TERRNO, "Failed to open /proc/self/maps.");
>> +
>> + while (!feof(fp)) {
>> + unsigned long start, end;
>> + int ret;
>> +
>> + ret = fscanf(fp, "%lx-%lx %*[^\n]\n", &start, &end);
>> + if (ret != 2) {
>> + fclose(fp);
>> + tst_brk(TBROK | TERRNO, "Couldn't parse /proc/self/maps line.");
>> + }
>> +
>> + if (ranges_size < ranges_len + 1) {
>> + ranges_size += 128;
>> + ranges = realloc(ranges, 2*ranges_size*sizeof(unsigned long));
>> + }
>> + ranges[ranges_len*2] = start;
>> + ranges[ranges_len*2 + 1] = end;
>> +
>> + ranges_len++;
>> + }
>> +
>> + fclose(fp);
>> +}
>> +
>> +static int is_address_mapped(unsigned long addr)
>> +{
>> + int i;
>> +
>> + for (i = 0; i < ranges_len; i++) {
>> + if (ranges[i*2] <= addr && addr < ranges[i*2 + 1])
>> + return 1;
>> + }
>> + return 0;
>> +}
>> +
>> static void setup(void)
>> {
>> struct sigaction sa;
>> @@ -117,17 +162,30 @@ static void access_ksymbols_address(struct kallsym *table)
>> }
>> }
>>
>> +
>> static void test_access_kernel_address(void)
>> {
>> - segv_caught = 0;
>> + int skipped = 0;
>>
>> - for (unsigned int i = 0; i < nr_symbols; i++)
>> + segv_caught = 0;
>> + read_proc_self_maps();
>> +
>> + for (unsigned int i = 0; i < nr_symbols; i++) {
>> + if (is_address_mapped(sym_table[i].addr)) {
>> + tst_res(TDEBUG, "Skipping userspace mapped address 0x%lx",
>> + sym_table[i].addr);
>> + skipped++;
>> + continue;
>> + }
>> access_ksymbols_address(&sym_table[i]);
>> + }
>>
>> - if (segv_caught == (sig_atomic_t)nr_symbols)
>> - tst_res(TPASS, "Caught %d SIGSEGV in access ksymbols addr", segv_caught);
>> + if (segv_caught == (sig_atomic_t)nr_symbols - skipped)
>> + tst_res(TPASS, "Caught %d SIGSEGV in access ksymbols addr, skipped %d",
>> + segv_caught, skipped);
>> else
>> - tst_res(TFAIL, "Caught %d SIGSEGV but expected %d", segv_caught, nr_symbols);
>> + tst_res(TFAIL, "Caught %d SIGSEGV but expected %d, skipped %d",
>> + segv_caught, nr_symbols-skipped, skipped);
>> }
>>
>> static void cleanup(void)
>> --
>> 2.39.3
>>
More information about the ltp
mailing list