All of lore.kernel.org
 help / color / mirror / Atom feed
From: Li Wang <liwang@redhat.com>
To: ltp@lists.linux.it
Cc: Rafael Aquini <aquini@redhat.com>
Subject: [LTP] [Patch v3 2/2] kallsyms01: Utilize ksymbol table for unauthorized address access
Date: Mon,  6 May 2024 13:32:07 +0800	[thread overview]
Message-ID: <20240506053207.12308-2-liwang@redhat.com> (raw)
In-Reply-To: <20240506053207.12308-1-liwang@redhat.com>

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.

Suggested-by: Rafael Aquini <aquini@redhat.com>
Suggested-by: Cyril Hrubis <chrubis@suse.cz>
Signed-off-by: Li Wang <liwang@redhat.com>
---

Notes:
    v2 --> v3
    	* update GPL lisence to 2.0-or-later
    	* move the sigaction to the test setup
    	* init segv_caught to 0 in the main
    	* add TFAIL print in report

 runtest/mm                                    |   2 +
 testcases/kernel/security/kallsyms/.gitignore |   1 +
 testcases/kernel/security/kallsyms/Makefile   |   6 +
 testcases/kernel/security/kallsyms/kallsyms.c | 145 ++++++++++++++++++
 4 files changed, 154 insertions(+)
 create mode 100644 testcases/kernel/security/kallsyms/.gitignore
 create mode 100644 testcases/kernel/security/kallsyms/Makefile
 create mode 100644 testcases/kernel/security/kallsyms/kallsyms.c

diff --git a/runtest/mm b/runtest/mm
index d859b331c..6a8cd0b9d 100644
--- a/runtest/mm
+++ b/runtest/mm
@@ -58,6 +58,8 @@ mmap10_2 mmap10 -s
 mmap10_3 mmap10 -a -s
 mmap10_4 mmap10 -a -s -i 60
 
+kallsyms kallsyms
+
 ksm01 ksm01
 ksm01_1 ksm01 -u 128
 ksm02 ksm02
diff --git a/testcases/kernel/security/kallsyms/.gitignore b/testcases/kernel/security/kallsyms/.gitignore
new file mode 100644
index 000000000..7074d4e24
--- /dev/null
+++ b/testcases/kernel/security/kallsyms/.gitignore
@@ -0,0 +1 @@
+kallsyms
diff --git a/testcases/kernel/security/kallsyms/Makefile b/testcases/kernel/security/kallsyms/Makefile
new file mode 100644
index 000000000..5ea7d67db
--- /dev/null
+++ b/testcases/kernel/security/kallsyms/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+top_srcdir		?= ../../../..
+
+include $(top_srcdir)/include/mk/testcases.mk
+include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/security/kallsyms/kallsyms.c b/testcases/kernel/security/kallsyms/kallsyms.c
new file mode 100644
index 000000000..818e8c471
--- /dev/null
+++ b/testcases/kernel/security/kallsyms/kallsyms.c
@@ -0,0 +1,145 @@
+// SPDX-License-Identifier: GPL-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;
+
+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)
+{
+	struct sigaction sa;
+	memset(&sa, 0, sizeof(sa));
+	sa.sa_handler = segv_handler;
+	sigaction(SIGSEGV, &sa, NULL);
+
+	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)
+{
+	segv_caught = 0;
+
+	for (unsigned int i = 0; i < nr_symbols; i++)
+		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);
+	else
+		tst_res(TFAIL, "Caught %d SIGSEGV but expected %d", segv_caught, nr_symbols);
+}
+
+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.44.0


-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

  reply	other threads:[~2024-05-06  5:32 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-05-06  5:32 [LTP] [Patch v3 1/2] lib: add SAFE_CALLOC macro Li Wang
2024-05-06  5:32 ` Li Wang [this message]
2024-05-06  9:30   ` [LTP] [Patch v3 2/2] kallsyms01: Utilize ksymbol table for unauthorized address access Cyril Hrubis
2024-05-06 11:15     ` Li Wang

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=20240506053207.12308-2-liwang@redhat.com \
    --to=liwang@redhat.com \
    --cc=aquini@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.