• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * fs/sharefs/inode.c
4  *
5  * Copyright (c) 1998-2022 Erez Zadok
6  * Copyright (c) 2009	   Shrikar Archak
7  * Copyright (c) 2003-2022 Stony Brook University
8  * Copyright (c) 2003-2022 The Research Foundation of SUNY
9  * Copyright (c) 2023 Huawei Device Co., Ltd.
10  */
11 
12 #include "sharefs.h"
13 
sharefs_get_link(struct dentry * dentry,struct inode * inode,struct delayed_call * done)14 static const char *sharefs_get_link(struct dentry *dentry, struct inode *inode,
15 				   struct delayed_call *done)
16 {
17 	DEFINE_DELAYED_CALL(lower_done);
18 	struct dentry *lower_dentry;
19 	struct path lower_path;
20 	char *buf;
21 	const char *lower_link;
22 
23 	if (!dentry)
24 		return ERR_PTR(-ECHILD);
25 
26 	sharefs_get_lower_path(dentry, &lower_path);
27 	lower_dentry = lower_path.dentry;
28 
29 	/*
30 	 * get link from lower file system, but use a separate
31 	 * delayed_call callback.
32 	 */
33 	lower_link = vfs_get_link(lower_dentry, &lower_done);
34 	if (IS_ERR(lower_link)) {
35 		buf = ERR_CAST(lower_link);
36 		goto out;
37 	}
38 
39 	/*
40 	 * we can't pass lower link up: have to make private copy and
41 	 * pass that.
42 	 */
43 	buf = kstrdup(lower_link, GFP_KERNEL);
44 	do_delayed_call(&lower_done);
45 	if (!buf) {
46 		buf = ERR_PTR(-ENOMEM);
47 		goto out;
48 	}
49 
50 	fsstack_copy_attr_atime(d_inode(dentry), d_inode(lower_dentry));
51 
52 	set_delayed_call(done, kfree_link, buf);
53 out:
54 	sharefs_put_lower_path(dentry, &lower_path);
55 	return buf;
56 }
57 
sharefs_getattr(const struct path * path,struct kstat * stat,u32 request_mask,unsigned int flags)58 static int sharefs_getattr(const struct path *path, struct kstat *stat,
59 			   u32 request_mask, unsigned int flags)
60 {
61 	struct path lower_path;
62 	int ret;
63 
64 	sharefs_get_lower_path(path->dentry, &lower_path);
65 	ret = vfs_getattr(&lower_path, stat, request_mask, flags);
66 	stat->ino = d_inode(path->dentry)->i_ino;
67 	stat->uid = d_inode(path->dentry)->i_uid;
68 	stat->gid = d_inode(path->dentry)->i_gid;
69 	stat->mode = d_inode(path->dentry)->i_mode;
70 	stat->dev = 0;
71 	stat->rdev = 0;
72 	sharefs_put_lower_path(path->dentry, &lower_path);
73 
74 	return ret;
75 }
76 
77 static ssize_t
sharefs_listxattr(struct dentry * dentry,char * buffer,size_t buffer_size)78 sharefs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
79 {
80 	int err;
81 	struct dentry *lower_dentry;
82 	struct path lower_path;
83 
84 	sharefs_get_lower_path(dentry, &lower_path);
85 	lower_dentry = lower_path.dentry;
86 	if (!(d_inode(lower_dentry)->i_opflags & IOP_XATTR)) {
87 		err = -EOPNOTSUPP;
88 		goto out;
89 	}
90 	err = vfs_listxattr(lower_dentry, buffer, buffer_size);
91 	if (err)
92 		goto out;
93 	fsstack_copy_attr_atime(d_inode(dentry),
94 				d_inode(lower_path.dentry));
95 out:
96 	sharefs_put_lower_path(dentry, &lower_path);
97 	return err;
98 }
99 
sharefs_permission(struct inode * inode,int mask)100 static int sharefs_permission(struct inode *inode, int mask)
101 {
102 	unsigned short mode = inode->i_mode;
103 	kuid_t cur_uid = current_fsuid();
104 	if (uid_eq(cur_uid, ROOT_UID))
105 		return 0;
106 	if (uid_eq(cur_uid, inode->i_uid)) {
107 		mode >>= 6;
108 	} else if (in_group_p(inode->i_gid)) {
109 		mode >>= 3;
110 	}
111 
112 	if ((mask & ~mode & (MAY_READ | MAY_WRITE | MAY_EXEC)) == 0)
113 		return 0;
114 
115 	return -EACCES;
116 }
117 
118 const struct inode_operations sharefs_symlink_iops = {
119 	.permission	= sharefs_permission,
120 	.getattr	= sharefs_getattr,
121 	.get_link	= sharefs_get_link,
122 	.listxattr	= sharefs_listxattr,
123 };
124 
125 const struct inode_operations sharefs_dir_iops = {
126 	.lookup		= sharefs_lookup,
127 	.permission	= sharefs_permission,
128 	.getattr	= sharefs_getattr,
129 	.listxattr	= sharefs_listxattr,
130 };
131 
132 const struct inode_operations sharefs_main_iops = {
133 	.permission	= sharefs_permission,
134 	.getattr	= sharefs_getattr,
135 	.listxattr	= sharefs_listxattr,
136 };
137