kmalloc 分配实际上不是连续的吗? [英] Is kmalloc allocation not virtually contiguous?

查看:17
本文介绍了kmalloc 分配实际上不是连续的吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发现 kmalloc 返回物理上和虚拟上连续的内存.

我写了一些代码来观察行为,但似乎只有物理内存是连续的,而不是虚拟内存.我有没有搞错?

#include #include #include #include MODULE_LICENSE("GPL");静态字符 *ptr;int alloc_size = 1024;模块参数(alloc_size,int,0);静态 int test_hello_init(void){ptr = kmalloc(alloc_size,GFP_ATOMIC);如果(!ptr){/* 处理错误 */pr_err("内存分配失败
");返回-ENOMEM;} 别的 {pr_info("内存分配成功:%p	%p
", ptr, ptr+100);pr_info("物理地址:%llx	 %llx
", virt_to_phys(ptr), virt_to_phys(ptr+100));}返回0;}静态无效 test_hello_exit(void){kfree(ptr);pr_info("内存释放
");}模块初始化(test_hello_init);模块退出(test_hello_exit);

dmesg 输出:

内存分配成功:0000000083318b28 000000001fba1614物理地址:1d5d09c00 1d5d09c64

解决方案

打印内核指针通常是一个坏主意,因为它基本上意味着将内核地址泄漏到用户空间,所以当使用 %pprintk()(或类似的宏,如 pr_info() 等)中,内核试图保护自己并且不打印真实地址.相反,它会为该地址打印一个不同的散列唯一标识符.

如果你真的想打印那个地址,你可以使用%px.


来自如何获取printk格式说明符正确 (web)Documentation/core-api/printk-formats.rst (git):

<块引用>

指针类型

不带说明符扩展的指针打印(即未修饰的%p)是散列以提供唯一标识符而不会将内核地址泄漏给用户空间.在 64 位机器上,前 32 位被清零.如果你真的想要地址见下面的%px.

%p abcdef12 或 00000000abcdef12

然后,稍后:

<块引用>

未修改的地址

%px 01234567 或 0123456789abcdef

用于在您确实想要打印地址时打印指针.请考虑您是否正在泄露有关使用 %px 打印指针之前内存中的内核布局.%px 是在功能上等同于 %lx.%px%lx 更受欢迎,因为它更多独特的grep'able.如果将来我们需要修改 Kernel 的方式处理打印指针很高兴能够找到调用网站.

I found that kmalloc returns physically and virtually contiguous memory.

I wrote some code to observe the behavior, but only the physical memory seems to be contiguous and not the virtual. Am I making any mistake?

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/moduleparam.h>

MODULE_LICENSE("GPL");

static char *ptr;
int alloc_size = 1024;

module_param(alloc_size, int, 0);

static int test_hello_init(void)
{
    ptr = kmalloc(alloc_size,GFP_ATOMIC);
    if(!ptr) {
        /* handle error */
        pr_err("memory allocation failed
");
        return -ENOMEM;
    } else {
        pr_info("Memory allocated successfully:%p	%p
", ptr, ptr+100);
        pr_info("Physical address:%llx	 %llx
", virt_to_phys(ptr), virt_to_phys(ptr+100));
    }

    return 0;
}

static void test_hello_exit(void)
{
    kfree(ptr);
    pr_info("Memory freed
");

}

module_init(test_hello_init);
module_exit(test_hello_exit);

dmesg output:

Memory allocated successfully:0000000083318b28  000000001fba1614
Physical address:1d5d09c00   1d5d09c64

解决方案

Printing kernel pointers is in general a bad idea, because it basically means leaking kernel addresses to user space, so when using %p in printk() (or similar macros like pr_info() etc.), the kernel tries to protect itself and does not print the real address. Instead, it prints a different hashed unique identifier for that address.

If you really want to print that address, you can use %px.


From How to get printk format specifiers right (web) or Documentation/core-api/printk-formats.rst (git):

Pointer Types

Pointers printed without a specifier extension (i.e unadorned %p) are hashed to give a unique identifier without leaking kernel addresses to user space. On 64 bit machines the first 32 bits are zeroed. If you really want the address see %px below.

%p    abcdef12 or 00000000abcdef12

Then, later below:

Unmodified Addresses

%px   01234567 or 0123456789abcdef

For printing pointers when you really want to print the address. Please consider whether or not you are leaking sensitive information about the Kernel layout in memory before printing pointers with %px. %px is functionally equivalent to %lx. %px is preferred to %lx because it is more uniquely grep'able. If, in the future, we need to modify the way the Kernel handles printing pointers it will be nice to be able to find the call sites.

这篇关于kmalloc 分配实际上不是连续的吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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