简体   繁体   English

内核 sys_call_table 地址与 system.map 中指定的地址不匹配

[英]Kernel sys_call_table address does not match address specified in system.map

I am trying to brush up on C so I have been playing around with the linux kernel's system call table (on 3.13.0-32-generic).我正在尝试复习 C,所以我一直在玩 linux 内核的系统调用表(在 3.13.0-32-generic 上)。 I found a resource online that searches for the system call table with the following function which I load into the kernel in an LKM:我在网上找到了一个资源,它使用以下函数搜索系统调用表,我将其加载到 LKM 中的内核中:

static uint64_t **aquire_sys_call_table(void)
{
    uint64_t offset = PAGE_OFFSET;
    uint64_t **sct;

    while (offset < ULLONG_MAX) {
        sct = (uint64_t **)offset;

        if (sct[__NR_close] == (uint64_t *) sys_close) {
            printk("\nsys_call_table found at address: 0x%p\n", sys_call_table);
            return sct;
        }

        offset += sizeof(void *);
    }

    return NULL;
}

The function works.该功能有效。 I am able to use the address it returns to manipulate the system call table.我可以使用它返回的地址来操作系统调用表。 What I don't understand is why the address returned by this function doesn't match the address in /boot/System.map-(KERNEL)我不明白的是为什么这个函数返回的地址与 /boot/System.map-(KERNEL) 中的地址不匹配

Here is what the function prints:这是函数打印的内容:

sys_call_table found at address: 0xffff880001801400

Here is what I get when I search system.map这是我搜索 system.map 时得到的

$ sudo cat /boot/System.map-3.13.0-32-generic | grep sys_call_table 
  ffffffff81801400 R sys_call_table
  ffffffff81809cc0 R ia32_sys_call_table

Why don't the two addresses match?为什么两个地址不匹配? Its my understanding that the module runs in the kernel's address space, so the address of the system call table should be the same.我的理解是模块运行在内核的地址空间,所以系统调用表的地址应该是一样的。

The two virtual addresses have the same physical address.这两个虚拟地址具有相同的物理地址。

From Documentation/x86/x86_64/mm.txt来自Documentation/x86/x86_64/mm.txt

<previous description obsolete, deleted>

Virtual memory map with 4 level page tables:

0000000000000000 - 00007fffffffffff (=47 bits) user space, different per mm
hole caused by [48:63] sign extension
ffff800000000000 - ffff87ffffffffff (=43 bits) guard hole, reserved for hypervisor
ffff880000000000 - ffffc7ffffffffff (=64 TB) direct mapping of all phys. memory
ffffc80000000000 - ffffc8ffffffffff (=40 bits) hole
ffffc90000000000 - ffffe8ffffffffff (=45 bits) vmalloc/ioremap space
ffffe90000000000 - ffffe9ffffffffff (=40 bits) hole
ffffea0000000000 - ffffeaffffffffff (=40 bits) virtual memory map (1TB)
... unused hole ...
ffffec0000000000 - fffffc0000000000 (=44 bits) kasan shadow memory (16TB)
... unused hole ...
ffffff0000000000 - ffffff7fffffffff (=39 bits) %esp fixup stacks
... unused hole ...
ffffffff80000000 - ffffffffa0000000 (=512 MB)  kernel text mapping, from phys 0
ffffffffa0000000 - ffffffffff5fffff (=1525 MB) module mapping space
ffffffffff600000 - ffffffffffdfffff (=8 MB) vsyscalls
ffffffffffe00000 - ffffffffffffffff (=2 MB) unused hole

The direct mapping covers all memory in the system up to the highest
memory address (this means in some cases it can also include PCI memory
holes).

vmalloc space is lazily synchronized into the different PML4 pages of
the processes using the page fault handler, with init_level4_pgt as
reference.

Current X86-64 implementations only support 40 bits of address space,
but we support up to 46 bits. This expands into MBZ space in the page tables.

->trampoline_pgd:

We map EFI runtime services in the aforementioned PGD in the virtual
range of 64Gb (arbitrarily set, can be raised if needed)

0xffffffef00000000 - 0xffffffff00000000

-Andi Kleen, Jul 2004

we know the virtual address space ffff880000000000 - ffffc7ffffffffff is direct mapping of all physical memory.我们知道虚拟地址空间ffff880000000000 - ffffc7ffffffffff是所有物理内存的直接映射。 When the kernel wants to access all physical memory, it uses direct mapping.当内核想要访问所有物理内存时,它使用直接映射。 It's also what you use for searching.这也是您用于搜索的内容。

And the ffffffff80000000 - ffffffffa0000000 is kernel text mapping.ffffffff80000000 - ffffffffa0000000是内核文本映射。 When the kernel code executed, rip register uses the kernel text mapping.当内核代码执行时, rip register 使用内核文本映射。

In arch/x86/include/asm/page_64.h , we can get the relation of virtual address and physical address.arch/x86/include/asm/page_64.h ,我们可以得到虚拟地址和物理地址的关系。

static inline unsigned long __phys_addr_nodebug(unsigned long x)
{
    unsigned long y = x - __START_KERNEL_map;

    /* use the carry flag to determine if x was < __START_KERNEL_map */
    x = y + ((x > y) ? phys_base : (__START_KERNEL_map - PAGE_OFFSET));

    return x;
}

and

// arch/x86/include/asm/page_types.h
#define PAGE_OFFSET     ((unsigned long)__PAGE_OFFSET)
// arch/x86/include/asm/page_64_types.h
#define __START_KERNEL_map  _AC(0xffffffff80000000, UL)
#define __PAGE_OFFSET           _AC(0xffff880000000000, UL)


As for the addresses mentioned in the question above: 至于上面问题中提到的地址:

what the function prints,函数打印什么,

$ sudo cat /boot/System.map-3.13.0-32-generic | grep sys_call_table 
  ffffffff81801400 R sys_call_table
  ffffffff81809cc0 R ia32_sys_call_table

what system.map gives, system.map 给出了什么,

 $ sudo cat /boot/System.map-3.13.0-32-generic | grep sys_call_table ffffffff81801400 R sys_call_table ffffffff81809cc0 R ia32_sys_call_table

both of them resolve to same physical address.它们都解析为相同的物理地址。

virt->phys conversion happens in such way that corresponding addresses in 'direct' mapping region and 'kernel text' mapping region resolve to same physical address. virt->phys 转换以这样的方式发生,即“直接”映射区域和“内核文本”映射区域中的相应地址解析为相同的物理地址。

Through the magic of virtual memory mapping, the address you use depends on where you are.通过虚拟内存映射的魔力,您使用的地址取决于您所在的位置。 The symbol table file System.map is to help attaching a gdb or crash utility to the running system.符号表文件 System.map 用于帮助将 gdb 或崩溃实用程序附加到正在运行的系统。 Inside the kernel, well, is inside the kernel.内核内部,嗯,就是内核内部。

You may also have a /proc/kallsym file for even more values :)您可能还有一个 /proc/kallsym 文件以获得更多值:)

Only root can show the addresses in the /proc/kallsyms file!只有 root 才能显示/proc/kallsyms文件中的地址! It is rarely disabled but you can enable it if it's disabled.它很少被禁用,但如果它被禁用,您可以启用它。 But the addresses in the System.map and kallsyms file for the same sys_call are different.但是同一个sys_callSystem.mapkallsyms文件中的地址是不同的。

If a person is using a kernel built by himself, then System.map is preferable but if you are using a pre-built kernel (like we mostly do), then kallsyms is the right place for you!如果一个人使用自己构建的内核,那么System.map更可取,但如果您使用预构建的内核(就像我们通常所做的那样),那么kallsyms是适合您的地方!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么不能使用System.map 中的system_wq 导出sys_call_table 的地址? - Why can't the address of sys_call_table be derived using that of system_wq in System.map? 在现代内核上查找没有符号的 sys_call_table 的地址 - Find the address of the sys_call_table without symbols on a modern kernel 访问内核2.6+中的sys_call_table - access to the sys_call_table in kernel 2.6+ Linux内核 - 为什么System.map中的函数地址是实时看到的地址之前的一个字节? - Linux Kernel - why a function's address in System.map is one byte preceding its address as seen in real time? Linux Kernel 4.2.x:为什么检查时预期的系统调用地址与实际地址不匹配? - Linux Kernel 4.2.x: Why does the expected system call address not match the actual address when checked? 在Linux内核中重写sys_call_table时自定义文件打开函数的奇怪行为 - Weird behavior of custom file open function on overriding sys_call_table in Linux Kernel Kernel模块在读取系统调用表function地址时崩溃 - Kernel module crash when reading system call table function address kernel怎么知道进程文件表的地址呢? - How does the kernel know the address of a process file table? awatch不会在指定地址停止 - awatch does not stop on specified address 内核中的地址 - The address in Kernel
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM