Linux 驱动根据struct file获取全路径和文件名

Linux 驱动根据struct file获取全路径和文件名
一、背景

在对内核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;
}

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值