Я работаю над модулем ядра для отслеживания операций, выполняемых клиентами NFS на моем сервере. Я могу перехватить файловые операции, используя хакерский способ (перехват уровня vfs), но не могу получить IP-адрес клиента.
Существует ли какая-либо информация, которая может быть сохранена в задаче current
, которая Я могу использовать, чтобы получить IP-адрес клиента NFS, выполняющего операцию?
Я знаю, что, покопавшись в исходном коде, nfsd сохраняет struct nfsd_net
в struct super_block
поле s_fs_info
, но Я могу получить его только как указатель struct net
. И в реализации nfsd net_generic
метод используется для получения указателя struct nfsd_net
(используя nfsd_net_id
, который является pernet_operations
s id
).
Могу ли я получить этот идентификатор как-нибудь? и если да, могу ли я использовать struct nfsd_net
в моем модуле ядра? Он определен где-то, кроме fs/nfsd/netns.h
?
Редактировать
Я использую этот подход для захвата функции открытия. Я пишу это для версии ядра 4.15.0. Вот код модуля ядра:
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/kobject.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/version.h>
#include <linux/proc_fs.h>
#include <linux/cred.h>
#include <linux/sched.h>
#include <linux/preempt.h>
#include <linux/uaccess.h>
#include <linux/xattr.h>
MODULE_LICENSE("GPL");
#if defined(__i386__)
#define POFF 1
#define CSIZE 6
// push address, addr, ret
char *jmp_code="\x68\x00\x00\x00\x00\xc3";
typedef unsigned int PSIZE;
#else
#define POFF 2
#define CSIZE 12
// mov address to register rax, jmp rax. for normal x64 convention
char *jmp_code="\x48\xb8\x00\x00\x00\x00\x00\x00\x00\x00\xff\xe0";
typedef unsigned long PSIZE;
#endif
DEFINE_SPINLOCK(root_open_lock);
int (*orig_root_open) (struct inode *, struct file *);
void *orig_root_open_code;
void hook(void *src_func,void *dst_addr){
barrier();
write_cr0(read_cr0() & (~0x10000));
memcpy(src_func,jmp_code,CSIZE);
*(PSIZE *)&(((unsigned char*)src_func)[POFF])=(PSIZE)dst_addr;
write_cr0(read_cr0() | 0x10000);
barrier();
}
void save_and_hook(void **p_reserve,void *src_func,void *dst_addr){
barrier();
write_cr0(read_cr0() & (~0x10000));
*p_reserve=kmalloc(CSIZE,GFP_KERNEL);
// save origin code
memcpy(*p_reserve,src_func,CSIZE);
hook(src_func,dst_addr);
write_cr0(read_cr0() | 0x10000);
barrier();
}
void fix(void **p_reserve,void *src_func){
barrier();
write_cr0(read_cr0() & (~0x10000));
memcpy(src_func,*p_reserve,CSIZE);
write_cr0(read_cr0() | 0x10000);
barrier();
}
int fake_root_open(struct inode *x, struct file *fp)
{
int ret;
printk("vfshijack: hijacked open\n"); // I need to find the client ip here.
barrier();
spin_lock(&root_open_lock);
fix(&orig_root_open_code, orig_root_open);
ret = orig_root_open(x, fp);
hook(orig_root_open, fake_root_open);
spin_unlock(&root_open_lock);
barrier();
return ret;
}
int vfs_init(void)
{
struct file *fp = filp_open("/", O_DIRECTORY|O_RDONLY, 0);
if (IS_ERR(fp))
return -1;
orig_root_open = fp->f_op->open;
if(orig_root_open)
{
save_and_hook(&orig_root_open_code, orig_root_open, fake_root_open);
}
filp_close(fp, NULL);
printk("vfshijack: vfshijack loaded\n");
return 0;
}
void vfs_exit(void)
{
if(orig_root_open)
{
fix(&orig_root_open_code, orig_root_open);
}
printk("vfshijack: vfshijack unloaded\n");
}
module_init(vfs_init);
module_exit(vfs_exit);