web-dev-qa-db-ja.com

システムコールフッキングの例の引数が正しくない

Linuxカーネルモジュールからフックするシステムコールの例を書きました。

システムコールテーブルのオープンシステムコールを更新して、デフォルトではなくエントリポイントを使用するようにしました。

#include <linux/module.h>
#include <linux/kallsyms.h>

MODULE_LICENSE("GPL");
char *sym_name = "sys_call_table";

typedef asmlinkage long (*sys_call_ptr_t)(const struct pt_regs *);
static sys_call_ptr_t *sys_call_table;
typedef asmlinkage long (*custom_open) (const char __user *filename, int flags, umode_t mode);


custom_open old_open;

static asmlinkage long my_open(const char __user *filename, int flags, umode_t mode)
{
    char user_msg[256];
    pr_info("%s\n",__func__);
    memset(user_msg, 0, sizeof(user_msg));
    long copied = strncpy_from_user(user_msg, filename, sizeof(user_msg));
    pr_info("copied:%ld\n", copied);
    pr_info("%s\n",user_msg);

    return old_open(filename, flags, mode);
}



static int __init hello_init(void)
{
    sys_call_table = (sys_call_ptr_t *)kallsyms_lookup_name(sym_name);
    old_open = (custom_open)sys_call_table[__NR_open];
    // Temporarily disable write protection
    write_cr0(read_cr0() & (~0x10000));
    sys_call_table[__NR_open] = (sys_call_ptr_t)my_open;
    // Re-enable write protection
    write_cr0(read_cr0() | 0x10000);

    return 0;
}

static void __exit hello_exit(void)
{
    // Temporarily disable write protection
    write_cr0(read_cr0() & (~0x10000));
    sys_call_table[__NR_open] = (sys_call_ptr_t)old_open;
    // Re-enable write protection
    write_cr0(read_cr0() | 0x10000);

}

module_init(hello_init);
module_exit(hello_exit);

確認する簡単なユーザープログラムを作成しました。

#define _GNU_SOURCE
#include <sys/syscall.h>
#include <sys/time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>

int main(int argc, char *argv[])
{
    int fd = syscall(__NR_open, "hello.txt", O_RDWR|O_CREAT, 0777);

    exit(EXIT_SUCCESS);
}

ファイルは私のフォルダーに作成されますが、strncpy_userは不正なアドレスで失敗します

[  927.415905] my_open
[  927.415906] copied:-14

上記のコードの誤りは何ですか?

5
md.jamal

更新:以下は作業コードです。入力を提供してくださった皆さんに感謝します

    #include <linux/module.h>
    #include <linux/kallsyms.h>

    MODULE_LICENSE("GPL");
    char *sym_name = "sys_call_table";

    typedef asmlinkage long (*sys_call_ptr_t)(const struct pt_regs *);
    static sys_call_ptr_t *sys_call_table;


    sys_call_ptr_t old_open;

    static asmlinkage long my_open(const struct pt_regs *regs)
    {
        char __user *filename = (char *)regs->di;
            char user_filename[256] = {0};
        long copied = strncpy_from_user(user_filename, filename, sizeof(user_filename));
        if (copied > 0)
            pr_info("%s filename:%s\n",__func__, user_filename);
        return old_open(regs);
    }



    static int __init hello_init(void)
    {
        sys_call_table = (sys_call_ptr_t *)kallsyms_lookup_name(sym_name);
        old_open = sys_call_table[__NR_open];
        // Temporarily disable write protection
        write_cr0(read_cr0() & (~0x10000));
        sys_call_table[__NR_open] = my_open;
        // Re-enable write protection
        write_cr0(read_cr0() | 0x10000);

        return 0;
    }

    static void __exit hello_exit(void)
    {
        // Temporarily disable write protection
        write_cr0(read_cr0() & (~0x10000));
        sys_call_table[__NR_open] = old_open;
        // Re-enable write protection
        write_cr0(read_cr0() | 0x10000);

    }

    module_init(hello_init);
    module_exit(hello_exit);
1
md.jamal