Skip to content

Commit

Permalink
Kunit to check the longest symbol length
Browse files Browse the repository at this point in the history
The longest length of a symbol (KSYM_NAME_LEN) was increased to 512
in the reference [1]. This patch adds kunit test suite to check the longest
symbol length. These tests verify that the longest symbol length defined
is supported.

This test can also help other efforts for longer symbol length,
like [2].

The test suite defines one symbol with the longest possible length.

The first test verify that functions with names of the created
symbol, can be called or not.

The second test, verify that the symbols are created (or
not) in the kernel symbol table.

[1] https://lore.kernel.org/lkml/20220802015052.10452-6-ojeda@kernel.org/
[2] https://lore.kernel.org/lkml/20240605032120.3179157-1-song@kernel.org/

Link: https://lore.kernel.org/r/20250302221518.76874-1-sergio.collado@gmail.com
Tested-by: Martin Rodriguez Reboredo <yakoyoku@gmail.com>
Reviewed-by: Shuah Khan <skhan@linuxfoundation.org>
Reviewed-by: Rae Moar <rmoar@google.com>
Signed-off-by: Sergio González Collado <sergio.collado@gmail.com>
Link: https://github.com/Rust-for-Linux/linux/issues/504
Reviewed-by: Rae Moar <rmoar@google.com>
Acked-by: David Gow <davidgow@google.com>
Signed-off-by: Shuah Khan <shuah@kernel.org>
  • Loading branch information
Sergio González Collado authored and Shuah Khan committed Mar 16, 2025
1 parent 0619a48 commit c104c16
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 1 deletion.
3 changes: 2 additions & 1 deletion arch/x86/tools/insn_decoder_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <assert.h>
#include <unistd.h>
#include <stdarg.h>
#include <linux/kallsyms.h>

#define unlikely(cond) (cond)

Expand Down Expand Up @@ -106,7 +107,7 @@ static void parse_args(int argc, char **argv)
}
}

#define BUFSIZE 256
#define BUFSIZE (256 + KSYM_NAME_LEN)

int main(int argc, char **argv)
{
Expand Down
9 changes: 9 additions & 0 deletions lib/Kconfig.debug
Original file line number Diff line number Diff line change
Expand Up @@ -2838,6 +2838,15 @@ config FORTIFY_KUNIT_TEST
by the str*() and mem*() family of functions. For testing runtime
traps of FORTIFY_SOURCE, see LKDTM's "FORTIFY_*" tests.

config LONGEST_SYM_KUNIT_TEST
tristate "Test the longest symbol possible" if !KUNIT_ALL_TESTS
depends on KUNIT && KPROBES
default KUNIT_ALL_TESTS
help
Tests the longest symbol possible

If unsure, say N.

config HW_BREAKPOINT_KUNIT_TEST
bool "Test hw_breakpoint constraints accounting" if !KUNIT_ALL_TESTS
depends on HAVE_HW_BREAKPOINT
Expand Down
2 changes: 2 additions & 0 deletions lib/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,8 @@ obj-$(CONFIG_FORTIFY_KUNIT_TEST) += fortify_kunit.o
obj-$(CONFIG_CRC_KUNIT_TEST) += crc_kunit.o
obj-$(CONFIG_SIPHASH_KUNIT_TEST) += siphash_kunit.o
obj-$(CONFIG_USERCOPY_KUNIT_TEST) += usercopy_kunit.o
obj-$(CONFIG_LONGEST_SYM_KUNIT_TEST) += longest_symbol_kunit.o
CFLAGS_longest_symbol_kunit.o += $(call cc-disable-warning, missing-prototypes)

obj-$(CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED) += devmem_is_allowed.o

Expand Down
82 changes: 82 additions & 0 deletions lib/longest_symbol_kunit.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Test the longest symbol length. Execute with:
* ./tools/testing/kunit/kunit.py run longest-symbol
* --arch=x86_64 --kconfig_add CONFIG_KPROBES=y --kconfig_add CONFIG_MODULES=y
* --kconfig_add CONFIG_RETPOLINE=n --kconfig_add CONFIG_CFI_CLANG=n
* --kconfig_add CONFIG_MITIGATION_RETPOLINE=n
*/

#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

#include <kunit/test.h>
#include <linux/stringify.h>
#include <linux/kprobes.h>
#include <linux/kallsyms.h>

#define DI(name) s##name##name
#define DDI(name) DI(n##name##name)
#define DDDI(name) DDI(n##name##name)
#define DDDDI(name) DDDI(n##name##name)
#define DDDDDI(name) DDDDI(n##name##name)

/*Generate a symbol whose name length is 511 */
#define LONGEST_SYM_NAME DDDDDI(g1h2i3j4k5l6m7n)

#define RETURN_LONGEST_SYM 0xAAAAA

noinline int LONGEST_SYM_NAME(void);
noinline int LONGEST_SYM_NAME(void)
{
return RETURN_LONGEST_SYM;
}

_Static_assert(sizeof(__stringify(LONGEST_SYM_NAME)) == KSYM_NAME_LEN,
"Incorrect symbol length found. Expected KSYM_NAME_LEN: "
__stringify(KSYM_NAME_LEN) ", but found: "
__stringify(sizeof(LONGEST_SYM_NAME)));

static void test_longest_symbol(struct kunit *test)
{
KUNIT_EXPECT_EQ(test, RETURN_LONGEST_SYM, LONGEST_SYM_NAME());
};

static void test_longest_symbol_kallsyms(struct kunit *test)
{
unsigned long (*kallsyms_lookup_name)(const char *name);
static int (*longest_sym)(void);

struct kprobe kp = {
.symbol_name = "kallsyms_lookup_name",
};

if (register_kprobe(&kp) < 0) {
pr_info("%s: kprobe not registered", __func__);
KUNIT_FAIL(test, "test_longest_symbol kallsyms: kprobe not registered\n");
return;
}

kunit_warn(test, "test_longest_symbol kallsyms: kprobe registered\n");
kallsyms_lookup_name = (unsigned long (*)(const char *name))kp.addr;
unregister_kprobe(&kp);

longest_sym =
(void *) kallsyms_lookup_name(__stringify(LONGEST_SYM_NAME));
KUNIT_EXPECT_EQ(test, RETURN_LONGEST_SYM, longest_sym());
};

static struct kunit_case longest_symbol_test_cases[] = {
KUNIT_CASE(test_longest_symbol),
KUNIT_CASE(test_longest_symbol_kallsyms),
{}
};

static struct kunit_suite longest_symbol_test_suite = {
.name = "longest-symbol",
.test_cases = longest_symbol_test_cases,
};
kunit_test_suite(longest_symbol_test_suite);

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Test the longest symbol length");
MODULE_AUTHOR("Sergio González Collado");

0 comments on commit c104c16

Please sign in to comment.