我正在尝试找出编辑器正在监视的文件。我已经知道我们可以从/proc/${PID}/fd
中计算inodify fds的数量,我的问题是:是否可以进一步确定哪个pathname是对应的notify_fd,即dump已注册的索引节点索引?
[借助提供的here跟踪调试方法和inotify(inotify_user.c)的源代码,我认为至少有一个肮脏的hack可以起作用(从未尝试过:]
sys_inotify_add_watch(fd:..., pathname: ..., mask: ...)
;/proc/${PID}/mem
中查找pathname字符串。更新:我已经更新了一个可行的解决方案,并感谢您提供有用的参考资料here。
已解决。我只是从内核代码复制了user_path_at
,而不是使用copy_from_user
。仍然感到困惑,为什么无法直接检索路径名。
工作代码粘贴如下。
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/version.h>
#include <linux/kallsyms.h>
#include <asm/tlbflush.h>
#include <linux/sched.h>
#include <linux/uaccess.h>
#include <linux/syscalls.h>
#include <linux/namei.h>
#define IN_ONLYDIR 0x01000000 /* only watch the path if it is a directory */
#define IN_DONT_FOLLOW 0x02000000 /* don't follow a sym link */
#define KERN_LOG KERN_NOTICE "[printk]"
#define printh(...) printk(KERN_LOG __VA_ARGS__)
/************************* PROTOTYPE DECLARATION *************************/
void **p_sys_call_table;
static void set_addr_rw(const unsigned long);
static void set_addr_ro(const unsigned long);
asmlinkage long (*ori_inotify_add_watch) (int, const char __user *, u32);
asmlinkage long mod_inotify_add_watch(int, const char __user *, u32);
static int __init inotify_hook_init(void);
static void __exit inotify_hook_fini(void);
static void set_addr_rw(const unsigned long addr)
{
unsigned int level;
pte_t *pte;
pte = lookup_address(addr, &level);
if (pte->pte &~ _PAGE_RW)
pte->pte |= _PAGE_RW;
local_flush_tlb();
}
static void set_addr_ro(const unsigned long address){
unsigned int level;
pte_t *pte = lookup_address(address, &level);
pte->pte = pte->pte &~_PAGE_RW;
}
/*************************** INOTIFY_ADD_WATCH ***************************/
asmlinkage long mod_inotify_add_watch(int fd, const char __user *pathname, u32 mask)
{
long ret;
struct path path;
unsigned int flags = 0;
char *pname = NULL;
char buf[PATH_MAX];
pid_t usr_pid = task_pid_nr(current);
ret = ori_inotify_add_watch(fd, pathname, mask);
if (!(mask & IN_DONT_FOLLOW))
flags |= LOOKUP_FOLLOW;
if (mask & IN_ONLYDIR)
flags |= LOOKUP_DIRECTORY;
if (user_path_at(AT_FDCWD, pathname, flags, &path) == 0)
{
pname = dentry_path_raw(path.dentry, buf, PATH_MAX); //->d_iname
printh("%d, %s\n", usr_pid, pname);
}
return ret;
}
/****************************** MAIN_ENTRY ******************************/
static int __init inotify_hook_init(void)
{
/* get sys_call_table pointer */
p_sys_call_table = (void **) kallsyms_lookup_name("sys_call_table");
if (!p_sys_call_table)
{
printh("Cannot find sys_call_table address\n");
return -EINVAL;
}
else
{
printh("Find sys_call_table at 0x%16lx\n", (unsigned long)p_sys_call_table);
}
/* syscall replacement */
set_addr_rw((unsigned long)p_sys_call_table);
ori_inotify_add_watch = p_sys_call_table[__NR_inotify_add_watch];
p_sys_call_table[__NR_inotify_add_watch] = mod_inotify_add_watch;
set_addr_ro((unsigned long)p_sys_call_table);
printh("Replace inotify_add_watch (0x%16lx) with modified (0x%16lx)\n", \
(unsigned long)ori_inotify_add_watch, (unsigned long)mod_inotify_add_watch);
return 0;
}
static void __exit inotify_hook_fini(void)
{
set_addr_rw((unsigned long)p_sys_call_table);
p_sys_call_table[__NR_inotify_add_watch] = ori_inotify_add_watch;
set_addr_ro((unsigned long)p_sys_call_table);
printh("inotify module exit.\n\n");
}
module_init(inotify_hook_init);
module_exit(inotify_hook_fini);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("VDM");