赞
踩
在对内核vfs层函数进行hook的时候,需要对struct pt_regs相关数据进行处理,插桩vfs_read/vfs_write时需要得到被读写文件的全路径或者文件名。
根据拿到的struct file来获得文件名和对应的全路径。
//hook vfs_write struct file *filep = NULL; char *full_path, *temp; char file_name = NULL; filep = (struct file *)regs->di; full_path = (char *)kmalloc(PATH_MAX, GFP_KERNEL); if (full_path == NULL) { printk("%s: malloc memory failed\n", __func__); return -1; } memset(full_path, 0, PATH_MAX); //Get file name filename = filep->f_path.dentry->d_iname; //Get full path temp = dentry_path_raw(filep->f_path.dentry, full_path, PATH_MAX); printk("%s\n", temp); //根据file指针获取文件全路径 char *file_path(struct file *filep, char *buf, int buflen) { return d_path(&filep->f_path, buf, buflen); } //最后要记得释放申请的内存
dentry_path_raw()函数只能获取到挂载点之后的路径!!!d_path()才能获取全路径!!!
需要特别注意的是,d_path函数有可能返回error code,需要对返回的指针做判断,不然有可能发生非法地址访问导致内核OOPS。
//函数原型,为内核导出函数,放心使用 /** * d_path - return the path of a dentry * @path: path to report * @buf: buffer to return value in * @buflen: buffer length * * Convert a dentry into an ASCII path name. If the entry has been deleted * the string " (deleted)" is appended. Note that this is ambiguous. * * Returns a pointer into the buffer or an error code if the path was * too long. Note: Callers should use the returned pointer, not the passed * in buffer, to use the name! The implementation often starts at an offset * into the buffer, and may leave 0 bytes at the start. * * "buflen" should be positive. */ char *d_path(const struct path *path, char *buf, int buflen) { char *res = buf + buflen; struct path root; int error; /* * We have various synthetic filesystems that never get mounted. On * these filesystems dentries are never used for lookup purposes, and * thus don't need to be hashed. They also don't need a name until a * user wants to identify the object in /proc/pid/fd/. The little hack * below allows us to generate a name for these objects on demand: * * Some pseudo inodes are mountable. When they are mounted * path->dentry == path->mnt->mnt_root. In that case don't call d_dname * and instead have d_path return the mounted path. */ if (path->dentry->d_op && path->dentry->d_op->d_dname && (!IS_ROOT(path->dentry) || path->dentry != path->mnt->mnt_root)) return path->dentry->d_op->d_dname(path->dentry, buf, buflen); rcu_read_lock(); get_fs_root_rcu(current->fs, &root); error = path_with_deleted(path, &root, &res, &buflen); rcu_read_unlock(); if (error < 0) res = ERR_PTR(error); return res; } EXPORT_SYMBOL(d_path); //内核函数使用实例 static int do_proc_readlink(struct path *path, char __user *buffer, int buflen) { char *tmp = (char *)__get_free_page(GFP_KERNEL); char *pathname; int len; if (!tmp) return -ENOMEM; pathname = d_path(path, tmp, PAGE_SIZE); len = PTR_ERR(pathname); if (IS_ERR(pathname)) goto out; len = tmp + PAGE_SIZE - 1 - pathname; if (len > buflen) len = buflen; if (copy_to_user(buffer, pathname, len)) len = -EFAULT; out: free_page((unsigned long)tmp); return len; }
char *ret_path = NULL;
char buff[256] = {0};
ret_path = d_path(path, buff, sizeof(buff));
if (IE_ERR(ret_path) {
pr_err("Get path failed\n");
return -1;
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。