内核sys_call_table地址与system.map中指定的地址不匹配 [英] Kernel sys_call_table address does not match address specified in system.map

查看:237
本文介绍了内核sys_call_table地址与system.map中指定的地址不匹配的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用C语言,因此我一直在研究linux内核的系统调用表(在3.13.0-32-generic上).我在线找到了一个资源,该资源使用以下函数搜索系统调用表,并将其加载到LKM的内核中:

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). 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:

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;
}

该功能有效.我能够使用它返回的地址来操纵系统调用表.我不明白的是为什么此函数返回的地址与/boot/System.map-(KERNEL)中的地址不匹配

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)

函数打印内容如下:

sys_call_table found at address: 0xffff880001801400

这是我搜索system.map时得到的内容

Here is what I get when I search 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.

来自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

我们知道虚拟地址空间ffff880000000000-ffffc7ffffffffff是所有物理内存的直接映射.当内核要访问所有物理内存时,它使用直接映射.这也是您用于搜索的内容.

we know the virtual address space ffff880000000000-ffffc7ffffffffff is direct mapping of all physical memory. When the kernel wants to access all physical memory, it uses direct mapping. It's also what you use for searching.

ffffffff80000000-ffffffffa0000000是内核文本映射.当执行内核代码时,rip寄存器将使用内核文本映射.

And the ffffffff80000000-ffffffffa0000000 is kernel text mapping. When the kernel code executed, rip register uses the kernel text mapping.

arch/x86/include/asm/page_64.h中,我们可以获得虚拟地址和物理地址的关系.

In arch/x86/include/asm/page_64.h, we can get the relation of virtual address and physical address.

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;
}

// 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:

函数显示的内容,

sys_call_table found at address: 0xffff880001801400

system.map提供的内容,

what system.map gives,

$ 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转换的发生方式是,直接"映射区域和内核文本"映射区域中的对应地址解析为相同的物理地址.

virt->phys conversion happens in such way that corresponding addresses in 'direct' mapping region and 'kernel text' mapping region resolve to same physical address.

这篇关于内核sys_call_table地址与system.map中指定的地址不匹配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆