* [LTP] [PATCH v2 1/2] lib: add SAFE_CALLOC macro
@ 2024-04-30 5:28 Li Wang
2024-04-30 5:28 ` [LTP] [PATCH v2 2/2] kallsyms01: Utilize ksymbol table for unauthorized address access Li Wang
2024-05-02 10:31 ` [LTP] [PATCH v2 1/2] lib: add SAFE_CALLOC macro Cyril Hrubis
0 siblings, 2 replies; 6+ messages in thread
From: Li Wang @ 2024-04-30 5:28 UTC (permalink / raw)
To: ltp
Signed-off-by: Li Wang <liwang@redhat.com>
---
include/tst_safe_macros.h | 5 +++++
lib/tst_safe_macros.c | 15 +++++++++++++++
2 files changed, 20 insertions(+)
diff --git a/include/tst_safe_macros.h b/include/tst_safe_macros.h
index 53aceb5ca..f228b99e1 100644
--- a/include/tst_safe_macros.h
+++ b/include/tst_safe_macros.h
@@ -75,6 +75,11 @@ int safe_dup2(const char *file, const int lineno, int oldfd, int newfd);
#define SAFE_MALLOC(size) \
safe_malloc(__FILE__, __LINE__, NULL, (size))
+void *safe_calloc(const char *file, const int lineno, size_t nmemb, size_t size);
+
+#define SAFE_CALLOC(nmemb, size) \
+ safe_calloc(__FILE__, __LINE__, (nmemb), (size))
+
void *safe_realloc(const char *file, const int lineno, void *ptr, size_t size);
#define SAFE_REALLOC(ptr, size) \
diff --git a/lib/tst_safe_macros.c b/lib/tst_safe_macros.c
index c6e6b15dc..40fdaca76 100644
--- a/lib/tst_safe_macros.c
+++ b/lib/tst_safe_macros.c
@@ -9,6 +9,7 @@
#include <stdlib.h>
#include <errno.h>
#include <sched.h>
+#include <malloc.h>
#include <sys/ptrace.h>
#include "config.h"
#ifdef HAVE_SYS_FANOTIFY_H
@@ -546,6 +547,20 @@ int safe_dup2(const char *file, const int lineno, int oldfd, int newfd)
return rval;
}
+void *safe_calloc(const char *file, const int lineno, size_t nmemb, size_t size)
+{
+ void *rval;
+
+ rval = calloc(nmemb, size);
+
+ if (rval == NULL) {
+ tst_brk_(file, lineno, TBROK | TERRNO,
+ "calloc(%zu, %zu) failed", nmemb, size);
+ }
+
+ return rval;
+}
+
void *safe_realloc(const char *file, const int lineno, void *ptr, size_t size)
{
void *ret;
--
2.40.1
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [LTP] [PATCH v2 2/2] kallsyms01: Utilize ksymbol table for unauthorized address access
2024-04-30 5:28 [LTP] [PATCH v2 1/2] lib: add SAFE_CALLOC macro Li Wang
@ 2024-04-30 5:28 ` Li Wang
2024-04-30 5:36 ` Li Wang
2024-05-02 10:29 ` Cyril Hrubis
2024-05-02 10:31 ` [LTP] [PATCH v2 1/2] lib: add SAFE_CALLOC macro Cyril Hrubis
1 sibling, 2 replies; 6+ messages in thread
From: Li Wang @ 2024-04-30 5:28 UTC (permalink / raw)
To: ltp; +Cc: Rafael Aquini
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>
Signed-off-by: Li Wang <liwang@redhat.com>
---
runtest/mm | 2 +
testcases/kernel/security/kallsyms/.gitignore | 1 +
testcases/kernel/security/kallsyms/Makefile | 6 +
testcases/kernel/security/kallsyms/kallsyms.c | 141 ++++++++++++++++++
4 files changed, 150 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..228d4d973
--- /dev/null
+++ b/testcases/kernel/security/kallsyms/kallsyms.c
@@ -0,0 +1,141 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * 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);
+
+ 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 times SIGSEGV in access ksymbols addr", segv_caught);
+}
+
+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
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [LTP] [PATCH v2 2/2] kallsyms01: Utilize ksymbol table for unauthorized address access
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
1 sibling, 0 replies; 6+ messages in thread
From: Li Wang @ 2024-04-30 5:36 UTC (permalink / raw)
To: ltp, Cyril Hrubis; +Cc: Rafael Aquini
Sorry forgot to attach the change from patch v1 to v2.
Notes:
V1 --> V2
* make use of SAFE_CALLOC macro
* drop the linked list to store the ksymbols table
* make use of onetime memory alloc to speed up test
* add TDEBUG to print ksymbols if needed
On Tue, Apr 30, 2024 at 1:29 PM Li Wang <liwang@redhat.com> wrote:
> 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>
> Signed-off-by: Li Wang <liwang@redhat.com>
> ---
> runtest/mm | 2 +
> testcases/kernel/security/kallsyms/.gitignore | 1 +
> testcases/kernel/security/kallsyms/Makefile | 6 +
> testcases/kernel/security/kallsyms/kallsyms.c | 141 ++++++++++++++++++
> 4 files changed, 150 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..228d4d973
> --- /dev/null
> +++ b/testcases/kernel/security/kallsyms/kallsyms.c
> @@ -0,0 +1,141 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * 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);
> +
> + 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 times SIGSEGV in access ksymbols
> addr", segv_caught);
> +}
> +
> +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
>
>
--
Regards,
Li Wang
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [LTP] [PATCH v2 2/2] kallsyms01: Utilize ksymbol table for unauthorized address access
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
2024-05-06 3:21 ` Li Wang
1 sibling, 1 reply; 6+ messages in thread
From: Cyril Hrubis @ 2024-05-02 10:29 UTC (permalink / raw)
To: Li Wang; +Cc: Rafael Aquini, ltp
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
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [LTP] [PATCH v2 1/2] lib: add SAFE_CALLOC macro
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-05-02 10:31 ` Cyril Hrubis
1 sibling, 0 replies; 6+ messages in thread
From: Cyril Hrubis @ 2024-05-02 10:31 UTC (permalink / raw)
To: Li Wang; +Cc: ltp
Hi!
> diff --git a/include/tst_safe_macros.h b/include/tst_safe_macros.h
> index 53aceb5ca..f228b99e1 100644
> --- a/include/tst_safe_macros.h
> +++ b/include/tst_safe_macros.h
> @@ -75,6 +75,11 @@ int safe_dup2(const char *file, const int lineno, int oldfd, int newfd);
> #define SAFE_MALLOC(size) \
> safe_malloc(__FILE__, __LINE__, NULL, (size))
>
> +void *safe_calloc(const char *file, const int lineno, size_t nmemb, size_t size);
> +
> +#define SAFE_CALLOC(nmemb, size) \
> + safe_calloc(__FILE__, __LINE__, (nmemb), (size))
> +
> void *safe_realloc(const char *file, const int lineno, void *ptr, size_t size);
>
> #define SAFE_REALLOC(ptr, size) \
> diff --git a/lib/tst_safe_macros.c b/lib/tst_safe_macros.c
> index c6e6b15dc..40fdaca76 100644
> --- a/lib/tst_safe_macros.c
> +++ b/lib/tst_safe_macros.c
> @@ -9,6 +9,7 @@
> #include <stdlib.h>
> #include <errno.h>
> #include <sched.h>
> +#include <malloc.h>
calloc() should be included from stdlib.h as far as I can tell malloc.h
is needed for mallopt() and such.
> #include <sys/ptrace.h>
> #include "config.h"
> #ifdef HAVE_SYS_FANOTIFY_H
> @@ -546,6 +547,20 @@ int safe_dup2(const char *file, const int lineno, int oldfd, int newfd)
> return rval;
> }
>
> +void *safe_calloc(const char *file, const int lineno, size_t nmemb, size_t size)
> +{
> + void *rval;
> +
> + rval = calloc(nmemb, size);
> +
> + if (rval == NULL) {
> + tst_brk_(file, lineno, TBROK | TERRNO,
> + "calloc(%zu, %zu) failed", nmemb, size);
> + }
> +
> + return rval;
> +}
Otherwise it looks good.
--
Cyril Hrubis
chrubis@suse.cz
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [LTP] [PATCH v2 2/2] kallsyms01: Utilize ksymbol table for unauthorized address access
2024-05-02 10:29 ` Cyril Hrubis
@ 2024-05-06 3:21 ` Li Wang
0 siblings, 0 replies; 6+ messages in thread
From: Li Wang @ 2024-05-06 3:21 UTC (permalink / raw)
To: Cyril Hrubis; +Cc: Rafael Aquini, ltp
Hi Cyril,
All comments make sense, patch v3 is coming.
On Thu, May 2, 2024 at 6:30 PM Cyril Hrubis <chrubis@suse.cz> wrote:
> 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
>
>
--
Regards,
Li Wang
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2024-05-06 3:21 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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
2024-05-06 3:21 ` Li Wang
2024-05-02 10:31 ` [LTP] [PATCH v2 1/2] lib: add SAFE_CALLOC macro Cyril Hrubis
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.