From: Cyril Hrubis <chrubis@suse.cz>
To: Li Wang <liwang@redhat.com>
Cc: Rafael Aquini <aquini@redhat.com>, ltp@lists.linux.it
Subject: Re: [LTP] [PATCH v2 2/2] kallsyms01: Utilize ksymbol table for unauthorized address access
Date: Thu, 2 May 2024 12:29:22 +0200 [thread overview]
Message-ID: <ZjNrApqMiZ9bj0au@yuki> (raw)
In-Reply-To: <20240430052845.31039-2-liwang@redhat.com>
Hi!
> @@ -0,0 +1,141 @@
> +// SPDX-License-Identifier: GPL-2.0-only
Any reason this is GPL-2.0-only and not 2.0-or-later?
> +/*
> + * Copyright (C) 2024 Red Hat, Inc.
> + */
> +
> +/*\
> + * [Description]
> + *
> + * Utilize kernel's symbol table for unauthorized address access.
> + *
> + * Access the system symbols with root permission to test whether it's
> + * possible to read and write the memory addresses of kernel-space
> + * from user-space. This helps in identifying potential vulnerabilities
> + * where user-space processes can inappropriately access kernel memory.
> + *
> + * Steps:
> + * 1. Start a process that reads all symbols and their addresses from
> + * '/proc/kallsyms' and stores them in a linked list.
> + *
> + * 2. Attempt to write to each kernel address found in the linked list.
> + * The expectation is that each attempt will fail with a SIGSEGV
> + * (segmentation fault), indicating that the user-space process
> + * cannot write to kernel memory.
> + *
> + * 3. Handle each SIGSEGV using a signal handler that sets a flag and
> + * long jumps out of the faulting context.
> + *
> + * 4. If any write operation does not result in a SIGSEGV, log this as
> + * a potential security vulnerability.
> + *
> + * 5. Observe and log the behavior and any system responses to these
> + * unauthorized access attempts.
> + *
> + */
> +
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <assert.h>
> +#include <unistd.h>
> +#include <string.h>
> +#include <setjmp.h>
> +#include <signal.h>
> +
> +#include "tst_test.h"
> +#include "tst_safe_stdio.h"
> +
> +struct kallsym {
> + unsigned long addr;
> + char type;
> + char name[128];
> +};
> +
> +static struct kallsym *sym_table;
> +static unsigned int nr_symbols;
> +static sigjmp_buf jmpbuf;
> +volatile sig_atomic_t segv_caught = 0;
> +
> +static void segv_handler(int sig)
> +{
> + if (sig == SIGSEGV)
> + segv_caught++;
> + else
> + tst_res(TFAIL, "Unexpected signal %s", strsignal(sig));
> +
> + siglongjmp(jmpbuf, 1);
> +}
> +
> +static unsigned int read_kallsyms(struct kallsym *table, unsigned int table_size)
> +{
> + char *line = NULL;
> + size_t len = 0;
> + unsigned int nr_syms = 0;
> + FILE *stream = SAFE_FOPEN("/proc/kallsyms", "r");
> +
> + while (getline(&line, &len, stream) != -1) {
> +
> + if (table && nr_syms < table_size) {
> + sscanf(line, "%lx %c %s",
> + &table[nr_syms].addr,
> + &table[nr_syms].type,
> + table[nr_syms].name);
> + }
> +
> + nr_syms++;
> + }
> +
> + SAFE_FCLOSE(stream);
> +
> + return nr_syms;
> +}
> +
> +static void setup(void)
> +{
> + nr_symbols = read_kallsyms(NULL, 0);
> + sym_table = SAFE_CALLOC(nr_symbols, sizeof(*sym_table));
> + unsigned int read_symbols = read_kallsyms(sym_table, nr_symbols);
> +
> + if (nr_symbols != read_symbols)
> + tst_res(TWARN, "/proc/kallsyms changed size!?");
> +}
> +
> +static void access_ksymbols_address(struct kallsym *table)
> +{
> + tst_res(TDEBUG, "Access kernel addr: 0x%lx (%c) (%s)",
> + table->addr, table->type, table->name);
> +
> + if (sigsetjmp(jmpbuf, 1) == 0) {
> + *(volatile unsigned long *)table->addr = 0;
> +
> + tst_res(TFAIL, "Successfully accessed kernel addr 0x%lx (%c) (%s)",
> + table->addr, table->type, table->name);
> + }
> +}
> +
> +static void test_access_kernel_address(void)
> +{
> + struct sigaction sa;
> + memset(&sa, 0, sizeof(sa));
> + sa.sa_handler = segv_handler;
> + sigaction(SIGSEGV, &sa, NULL);
We can move the sigaction to the test setup.
> + for (unsigned int i = 0; i < nr_symbols; i++)
> + access_ksymbols_address(&sym_table[i]);
And we have to set the segv_caught to 0 before this loop, otherwise the
test does not work with -i 2
> + if (segv_caught == (sig_atomic_t)nr_symbols)
> + tst_res(TPASS, "Caught %d times SIGSEGV in access ksymbols addr", segv_caught);
And also in a case that we got wrong number on segfaults this does not
produce any results. I guess that we need to do:
if (...)
tst_res(TPASS, "...");
else
tst_res(TFAIL, "Caught %d SIGSEGV expected %d", ...);
> +}
> +
> +static void cleanup(void)
> +{
> + if (sym_table)
> + free(sym_table);
> +}
> +
> +static struct tst_test test = {
> + .needs_root = 1,
> + .setup = setup,
> + .cleanup = cleanup,
> + .max_runtime = 60,
> + .test_all = test_access_kernel_address,
> +};
> --
> 2.40.1
>
>
> --
> Mailing list info: https://lists.linux.it/listinfo/ltp
--
Cyril Hrubis
chrubis@suse.cz
--
Mailing list info: https://lists.linux.it/listinfo/ltp
next prev parent reply other threads:[~2024-05-02 10:30 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-04-30 5:28 [LTP] [PATCH v2 1/2] lib: add SAFE_CALLOC macro Li Wang
2024-04-30 5:28 ` [LTP] [PATCH v2 2/2] kallsyms01: Utilize ksymbol table for unauthorized address access Li Wang
2024-04-30 5:36 ` Li Wang
2024-05-02 10:29 ` Cyril Hrubis [this message]
2024-05-06 3:21 ` Li Wang
2024-05-02 10:31 ` [LTP] [PATCH v2 1/2] lib: add SAFE_CALLOC macro Cyril Hrubis
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=ZjNrApqMiZ9bj0au@yuki \
--to=chrubis@suse.cz \
--cc=aquini@redhat.com \
--cc=liwang@redhat.com \
--cc=ltp@lists.linux.it \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.