首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >作为赋值的左操作数所需的l值.函数指针

作为赋值的左操作数所需的l值.函数指针
EN

Stack Overflow用户
提问于 2019-10-31 12:02:31
回答 1查看 165关注 0票数 0

我正在为内核编程和内存管理课程做作业。我需要动态获取sys_call_table地址并安装一个简单的钩子,它在打印一些文本之后调用原始的sys_call (在本例中是sys_read)。

首先,我对使用grep和/boot/System.map获得的sys_call_table地址进行了硬编码,并遵循了我在网上找到的一些代码示例:

  1. https://gajastechnologies.blogspot.com/2016/12/basics-of-making-rootkit-from-syscall.html
  2. https://syprog.blogspot.com/2011/10/hijack-linux-system-calls-part-iii.html

这些帖子对sys_call_table地址提供了不同的处理方式,即一个使用单个指针,另一个使用双指针。但是,在这两种情况下,我都得到了赋值lvalue required as left operand of assignment的错误original_read = table[__NR_read];

  • 我的错在哪里?更新的kernels?
  • You'll有什么变化吗?我留下了两种禁用内存只读保护的方法,它们都适合于更新的5.X 32位内核吗?
  • 将如何在代码中动态地获得sys_call_table,将用作参考?我还没有找到新版本导出的sys_calls的信息。我发现sys_close经常被使用,但是编译器没有识别它,而是建议使用ksys_close

代码:

代码语言:javascript
复制
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/printk.h>
#include <linux/fs.h>
#include <linux/syscalls.h>
#include <linux/kallsyms.h>
#include <linux/compat.h>
#include <asm/uaccess.h>
#include <uapi/asm/unistd.h>

#include <asm/cacheflush.h>
#include <linux/highmem.h>
#include <asm/pgtable_types.h>

#define DISABLE_W_PROTECTED_MEMORY \
    preempt_disable(); \
    barrier(); \
    write_cr0(read_cr0() & (~ 0x00010000));

#define ENABLE_W_PROTECTED_MEMORY \
    write_cr0(read_cr0() | 0x00010000); \
    barrier(); \
    preempt_enable();

MODULE_LICENSE("GPL");

asmlinkage long *original_read(unsigned int fd, char __user *buf, size_t count);
asmlinkage long modified_read(unsigned int fd, char __user *buf, size_t count) {
    pr_info("sys_read\n");
    return original_read(fd, buf, count);
}

void **table = (void *)0xc16e7180;

/*Make page writeable*/

int make_rw(unsigned long address){
    unsigned int level;
    pte_t *pte = lookup_address(address, &level);
    if(pte->pte &~_PAGE_RW){
        pte->pte |=_PAGE_RW;
    }
    return 0;
}

/* Make the page write protected */

int make_ro(unsigned long address){
    unsigned int level;
    pte_t *pte = lookup_address(address, &level);
    pte->pte = pte->pte &~_PAGE_RW;
    return 0;
}

static int __init mod_init(void)
{
    make_rw((unsigned long)table);
    original_read = table[__NR_read];
    table[__NR_read] = modified_read;
    return 0;
}
static void __exit mod_exit(void)
{
    table[__NR_read] = original_read;
    make_ro((unsigned long)table);
}

module_init(mod_init);
module_exit(mod_exit);

编辑:

我将修复应用于函数指针,并编辑代码以匹配第二个链接中显示的代码。尽管使用modified_read运行了一些示例C代码,但dmesg中从未出现来自read()内部的打印。另外,如果删除用于写保护内存的宏(并保留make_romake_rw),代码就会崩溃。我把两个都留在那里了,供你参考。有什么建议吗?

代码语言:javascript
复制
#define DISABLE_W_PROTECTED_MEMORY \
    preempt_disable(); \
    barrier(); \
    write_cr0(read_cr0() & (~ 0x00010000));

#define ENABLE_W_PROTECTED_MEMORY \
    write_cr0(read_cr0() | 0x00010000); \
    barrier(); \
    preempt_enable();

asmlinkage long (*original_read)(unsigned int fd, char __user *buf, size_t count);
asmlinkage long modified_read(unsigned int fd, char __user *buf, size_t count) {
    pr_info("sys_read\n");
    return original_read(fd, buf, count);
}

unsigned long *table = (unsigned long*)0xc16e7180;

int make_rw(unsigned long address){
    unsigned int level;
    pte_t *pte = lookup_address(address, &level);
    if(pte->pte &~_PAGE_RW){
        pte->pte |=_PAGE_RW;
    }
    return 0;
}

int make_ro(unsigned long address){
    unsigned int level;
    pte_t *pte = lookup_address(address, &level);
    pte->pte = pte->pte &~_PAGE_RW;
    return 0;
}

static int __init mod_init(void)
{
    DISABLE_W_PROTECTED_MEMORY
    make_rw((unsigned long)table);
    original_read = (void*)*(table + __NR_read);
    *(table + __NR_read) = (unsigned long) modified_read;
    make_ro((unsigned long)table);
    ENABLE_W_PROTECTED_MEMORY
    return 0;
}
static void __exit mod_exit(void)
{
    DISABLE_W_PROTECTED_MEMORY
    make_rw((unsigned long)table);
    *(table + __NR_read) = (unsigned long) original_read;
    make_ro((unsigned long)table);
    ENABLE_W_PROTECTED_MEMORY
}

module_init(mod_init);
module_exit(mod_exit);
EN

回答 1

Stack Overflow用户

发布于 2019-10-31 12:07:18

original_read是一个函数。不能将函数分配给函数。例如,你不能做printf = something;

似乎您想让original_read成为一个函数指针。要声明函数指针,需要一组额外的括号:

代码语言:javascript
复制
    asmlinkage long (*original_read)(unsigned int fd, char __user *buf, size_t count);
                    ^              ^
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58642957

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档