Linux内核 probe_kernel_read()

函数:probe_kernel_read( )

文件包含:

#include<linux/uaccess.h>

函数定义:

在内核源码中的位置:linux-3.19.3/mm/maccess.c

函数定义格式:

long __weak probe_kernel_read(void *dst, const void *src, size_t size)
__attribute__((alias(“__probe_kernel_read”)));

函数功能描述:

probe_kernel_read( )函数通过函数__probe_kernel_read( )安全地尝试将用户空间地址src开始的大小为size的数据块拷贝到内核空间地址dst开始的目标地址空间中。

输入参数说明:

  • src:指源起始地址,它指向某一用户空间的地址。

  • dst:指目标起始地址,它指向某一内核空间的地址。

  • size:指从src到dst要拷贝的数据块大小,它以字节为单位。

返回值说明:

  • 该函数返回一个长整型:如果操作成功,函数返回0,即该长整型值为0;如果操作失败(或发生内核错误),函数返回-EFAULT,其值为-14。

实例解析:

编写测试文件:probe_kernel_read.c

头文件及全局变量声明如下:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/security.h>
#include <linux/uaccess.h>
#include <linux/mm_types.h>
#include <linux/mm.h>
#include <linux/sched.h>

MODULE_LICENSE("GPL");
static int __init probe_kernel_read_init(void);
static void __exit probe_kernel_read_exit(void);

模块初始化函数:

int __init probe_kernel_read_init(void)
{
    struct mm_struct *mm = current->mm;         //mm指向当前进程的地址空间
    unsigned long mm_start = mm->mmap->vm_start; //mm_start指当前进程地址空间的起始地址
    unsigned long * src = NULL;
    src = (unsigned long *)mm_start;            //将源地址设置为用户空间的起始地址
    printk("mm_start = 0x%lx\n", mm_start);
    printk("*src = %lx\n", *src);

    unsigned long * dst = NULL;
    dst = (unsigned long *)kmalloc(sizeof(unsigned long), GFP_KERNEL);
                                          // 目标地址为内核空间的地址
    *dst = 5;
    printk("*dst = %ld\n", *dst);
    long ret = probe_kernel_read(dst, src, sizeof(unsigned long));
                                          // 调用函数实现源地址到目标地址内容的拷贝
    printk("ret = %ld\n", ret);
    printk("after probe_kernel_read, *dst = %lx\n", *dst);
    kfree(dst);
    return 0;
}

模块退出函数:

void __exit probe_kernel_read_exit(void)
{
    printk("exit! \n");
}

模块初始化及退出函数调用:

module_init(probe_kernel_read_init);
module_exit(probe_kernel_read_exit);

实例运行结果及分析:

首先编译模块,执行命令insmod probe_kernel_read.ko插入模块,然后执行命令dmesg-c,会出现如图所示的结果。

Linux内核 probe_kernel_read()

结果分析:

该测试程序中先获取用户空间的某一地址当作待拷贝的源地址src,这里取当前进程首地址,由输出结果可知为0x7fa3dc336000,输出其内容为*src = 0x10102464c457f。然后开辟一个内核地址dst,将该地址开始的一个字节内容设置为5(*dst=5)。为了使程序简单,测试时令参数size=sizeof(unsigned long),即拷贝一定字节内容,调用函数probe_kernel_read(dst, src, sizeof(unsigned long)),由输出结果可知返回值ret = 0(即拷贝成功),并且*dst =0x10102464c457f = *src

酷客网相关文章:

赞(0)

评论 抢沙发

评论前必须登录!