添加一个特殊的部分到一个 Linux 内核模块

huangapple go评论58阅读模式
英文:

adding a special section to a linux kernel module

问题

以下是您要翻译的部分:

当在内核模块中使用正常的 `attribute section` 语法时,此部分不会自动生成。

我正在尝试在源代码的不同位置在编译时将数据放入特殊部分,然后在运行时使用部分的 `start` 和 `end` 符号来检索该部分中的所有数据。

将符号放入 `foo` 部分:
```C
...
int var_on_foo __attribute__((section("foo"))) = 10;
...

然后尝试访问 foo 部分:

int* first_foo = __start_foo;
....

在用户空间中使用这些代码是完全正常的,因为编译器会将所有部分编译到 ELF 中。但是在内核模块中使用这些代码会导致错误:

[  192.586590] simple_test: Unknown symbol __start_foo (err -2)

我该如何告诉 kbuild 编译所有我的特殊部分?


<details>
<summary>英文:</summary>

when using the normal `attribute section` syntax in a kernel module this section is not auto generated.

i am trying to put data on a special section from different places in the source code at compile-time, and then use the section `start` and `end` symbols to retrieve all the data in that section during runtime. 

placing symbol in section `foo`:
```C
...
int var_on_foo __attribute__((section(&quot;foo&quot;))) = 10;
...

and then trying to access section foo:

int* first_foo = __start_foo;
....

using this in userspace works totally fine as the compiler just compiles in all the sections into the elf. but using this in a kernel module results in an error:

[  192.586590] simple_test: Unknown symbol __start_foo (err -2) 

How can i tell kbuild to compile in all my special sections?

答案1

得分: 0

以下是您要翻译的内容:

  1. 解决方案:(极端)

极端的解决方案将是修改load_module函数以获取对mod_info结构的访问,其中解析了各个部分和符号的偏移量。

  1. 解决方案:

如果您使用部分的目标是能够从模块的各个地方收集数据并将其存储在一个地方,更简单的方法可能是这样的:

#include &lt;linux/elf.h&gt;
#include &lt;linux/kallsyms.h&gt;
#include &lt;linux/module.h&gt;

__attribute__((used)) static void barA(void)
{
    static char my_value[] = "我想自由";
    static char *_magic_meta_string_my_value __attribute__((used)) = my_value;
}

__attribute__((used)) static void barB(void)
{
    static char my_value[] = "我想解脱";
    static char *_magic_meta_string_my_value_foo_bar_baz __attribute__((used)) = my_value;
}

static int __init init_magic_meta_section(void)
{
    const struct mod_kallsyms *const kallsyms = THIS_MODULE->kallsyms;
    for (unsigned int i = 0; i < kallsyms->num_symtab; i++) {

        const Elf_Sym *const ksym = &kallsyms->symtab[i];
        const char *const name = &kallsyms->strtab[ksym->st_name];
        static const char ref_name[] = "_magic_meta_string";
        static const unsigned int ref_name_length = sizeof((ref_name)) - 1;

        if (strncmp(name, ref_name, ref_name_length) == 0) {
            const char *const section_name = name + ref_name_length + 1;
            const char *const first_dot = strchr(section_name, '.');
            const long section_name_length = (long)first_dot - (long)section_name;

            printk(KERN_INFO "符号 %u:%lx %lu %s 用于部分 %.*s\n", i, (uintptr_t)ksym->st_value,
                   (uintptr_t)ksym->st_size, name, section_name_length, section_name);

            const char **magic_ptr = (char **)ksym->st_value;

            printk(KERN_INFO "这就是魔法:(%s)\n", *magic_ptr);
        }
    }

    return 0;
}

在这种情况下,_magic_meta_string 是我们添加到所有要再次查找的符号的字符串。然后,我们遍历所有模块符号,搜索以此字符串开头的所有符号。不完全等同于用户空间的sections_startsections_end符号,但我想在大多数情况下足够了。

特别感谢@jo5ta为我找到这个解决方案 添加一个特殊的部分到一个 Linux 内核模块

英文:

so here half an answer that might be enough for most people:

the sections are compiled in and the section will in most cases not be striped out (as striping kernel modules is considered a bad thing).

BUT accessing the data as in userland with the section start end symbols is not possible as the kernel ko elf loader (modules.c - load_module ...) will not take care to set this symbols.

1. Solution: (hardcore)

The hardcore solution would be to modify the load_module function to get access to the mod_info struct where the offsets to the sections and symbols are parsed.

2. Solution:

If your goal of using sections is to be able to collect data from various places of your module within one place, the easier way might be this:

#include &lt;linux/elf.h&gt;
#include &lt;linux/kallsyms.h&gt;
#include &lt;linux/module.h&gt;

__attribute__((used)) static void barA(void)
{
    static char my_value[] = &quot;i want to be free&quot;;
    static char *_magic_meta_string_my_value __attribute__((used)) = my_value;
}

__attribute__((used)) static void barB(void)
{
    static char my_value[] = &quot;i want to break free&quot;;
    static char *_magic_meta_string_my_value_foo_bar_baz __attribute__((used)) = my_value;
}

static int __init init_magic_meta_section(void)
{
    const struct mod_kallsyms *const kallsyms = THIS_MODULE-&gt;kallsyms;
    for (unsigned int i = 0; i &lt; kallsyms-&gt;num_symtab; i++) {

        const Elf_Sym *const ksym = &amp;kallsyms-&gt;symtab[i];
        const char *const name = &amp;kallsyms-&gt;strtab[ksym-&gt;st_name];
        static const char ref_name[] = &quot;_magic_meta_string&quot;;
        static const unsigned int ref_name_length = sizeof((ref_name)) - 1;

        if (strncmp(name, ref_name, ref_name_length) == 0) {
            const char *const section_name = name + ref_name_length + 1;
            const char *const first_dot = strchr(section_name, &#39;.&#39;);
            const long section_name_length = (long)first_dot - (long)section_name;

            printk(KERN_INFO &quot;symbol %u: %lx %lu %s for section %.*s\n&quot;, i, (uintptr_t)ksym-&gt;st_value,
                   (uintptr_t)ksym-&gt;st_size, name, section_name_length, section_name);

            const char **magic_ptr = (char **)ksym-&gt;st_value;

            printk(KERN_INFO &quot;and here the magic: (%s)\n&quot;, *magic_ptr);
        }
    }

    return 0;
}

in this case _magic_meta_string is a string we add to all symbols that we want to find again. and then we iterate about all module symbols and search for all symbols that start with this string.

not exactly the same thing as the sections_start and end symbols in userland but i guess in most cases enough.

Special thanks to @jo5ta for finding this out for me 添加一个特殊的部分到一个 Linux 内核模块

huangapple
  • 本文由 发表于 2023年4月4日 16:43:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/75927270.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定