Search code examples
hookinotifyinoderootkit

Is it possible to dump inode information from the inotify subsystem?


I am trying to figure out what files my editor is watching on. I have learnt that count the number of inotify fds from /proc/${PID}/fd is possible, and my question is: Is it possible to dump the list of watched inodes by one process?

UPDATE: I have updated one working solution, and thanks for a helpful reference here.

UPDATE 2: well, recently I found kallsyms_lookup_name (and more symbols) not export since Linux Kernel v5.7, so I decide to update my own solution if anyone else cares.


Solution

  • Solved. With the help of kprobe mechanism used in khook , I just simply hook the __x64_sys_inotify_add_watch and use user_path_at to steal the dentry.

    The code snippet is listed below, and my working solution is provided here.

    #define IN_ONLYDIR          0x01000000  /* only watch the path if it is a directory */
    #define IN_DONT_FOLLOW      0x02000000  /* don't follow a sym link */
    
    
    //regs->(di, si, dx, r10), reference: arch/x86/include/asm/syscall_wrapper.h#L125
    //SYSCALL_DEFINE3(inotify_add_watch, int, fd, const char __user *, pathname, u32, mask)
    KHOOK_EXT(long, __x64_sys_inotify_add_watch, const struct pt_regs *);
    static long khook___x64_sysinotify_add_watch(const struct pt_regs *regs)
    {
        int wd;
        struct path path;
        unsigned int flags = 0;
        char buf[PATH_MAX];
        char *pname;
        // decode the registers
        int fd = (int) regs->di;
        const char __user *pathname = (char __user *) regs->si;
        u32 mask = (u32) regs->dx;
    
        // do the original syscall
        wd = KHOOK_ORIGIN(__x64_sys_inotify_add_watch, regs);
        // get the pathname
        if (!(mask & IN_DONT_FOLLOW))
            flags |= LOOKUP_FOLLOW;
        if (mask & IN_ONLYDIR)
            flags |= LOOKUP_DIRECTORY;
        if ( wd>=0 && (user_path_at(AT_FDCWD, pathname, flags, &path)==0) )
        {
            pname = dentry_path_raw(path.dentry, buf, PATH_MAX); //"pname" points to "buf[PATH_MAX]"
            path_put(&path);
            printk("%s, PID %d add (%d,%d): %s\n", current->comm, task_pid_nr(current), fd, wd, pname);
        }
        return wd;
    }