• 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 #ifdef CONFIG_SHAREFS_SUPPORT_WRITE
14 #include "authentication.h"
15 #endif
16 
sharefs_getattr(struct mnt_idmap * idmap,const struct path * path,struct kstat * stat,u32 request_mask,unsigned int flags)17 static int sharefs_getattr(struct mnt_idmap *idmap, const struct path *path, struct kstat *stat,
18                           u32 request_mask, unsigned int flags)
19 {
20 	struct path lower_path;
21 	int ret;
22 
23 	sharefs_get_lower_path(path->dentry, &lower_path);
24 	ret = vfs_getattr_nosec(&lower_path, stat, request_mask, flags);
25 	stat->ino = d_inode(path->dentry)->i_ino;
26 	stat->uid = d_inode(path->dentry)->i_uid;
27 	stat->gid = d_inode(path->dentry)->i_gid;
28 	stat->mode = d_inode(path->dentry)->i_mode;
29 	stat->dev = 0;
30 	stat->rdev = 0;
31 	sharefs_put_lower_path(path->dentry, &lower_path);
32 
33 	return ret;
34 }
35 
sharefs_listxattr(struct dentry * dentry,char * buffer,size_t buffer_size)36 static ssize_t sharefs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
37 {
38 	int err;
39 	struct dentry *lower_dentry;
40 	struct path lower_path;
41 
42 	sharefs_get_lower_path(dentry, &lower_path);
43 	lower_dentry = lower_path.dentry;
44 	if (!(d_inode(lower_dentry)->i_opflags & IOP_XATTR)) {
45 		err = -EOPNOTSUPP;
46 		goto out;
47 	}
48 	err = vfs_listxattr(lower_dentry, buffer, buffer_size);
49 	if (err)
50 		goto out;
51 	fsstack_copy_attr_atime(d_inode(dentry),
52 				d_inode(lower_path.dentry));
53 out:
54 	sharefs_put_lower_path(dentry, &lower_path);
55 	return err;
56 }
57 
sharefs_permission(struct mnt_idmap * idmap,struct inode * inode,int mask)58 static int sharefs_permission(struct mnt_idmap *idmap, struct inode *inode, int mask)
59 {
60 #ifdef CONFIG_SHAREFS_SUPPORT_OVERRIDE
61 	return 0;
62 #endif
63 	unsigned short mode = inode->i_mode;
64 	kuid_t cur_uid = current_fsuid();
65 	if (uid_eq(cur_uid, ROOT_UID))
66 		return 0;
67 	if (uid_eq(cur_uid, inode->i_uid)) {
68 		mode >>= 6;
69 	} else if (in_group_p(inode->i_gid)) {
70 		mode >>= 3;
71 	}
72 
73 	if ((mask & ~mode & (MAY_READ | MAY_WRITE | MAY_EXEC)) == 0)
74 		return 0;
75 
76 	return -EACCES;
77 }
78 
79 #ifdef CONFIG_SHAREFS_SUPPORT_WRITE
sharefs_create(struct mnt_idmap * idmap,struct inode * dir,struct dentry * dentry,umode_t mode,bool want_excl)80 static int sharefs_create(struct mnt_idmap *idmap, struct inode *dir, struct dentry *dentry,
81 			 umode_t mode, bool want_excl)
82 {
83 	int err;
84 	struct dentry *lower_dentry;
85 	struct dentry *lower_parent_dentry = NULL;
86 	struct path lower_path;
87 	const struct cred *saved_cred = NULL;
88 	__u16 child_perm;
89 
90 	saved_cred = sharefs_override_file_fsids(dir, &child_perm);
91 	if (!saved_cred) {
92 		err = -ENOMEM;
93 		return err;
94 	}
95 
96 	sharefs_get_lower_path(dentry, &lower_path);
97 	lower_dentry = lower_path.dentry;
98 	lower_parent_dentry = lock_parent(lower_dentry);
99 	err = vfs_create(&nop_mnt_idmap, d_inode(lower_parent_dentry), lower_dentry, mode,
100 			 want_excl);
101 	if (err)
102 		goto out;
103 	err = sharefs_interpose(dentry, dir->i_sb, &lower_path);
104 	if (err)
105 		goto out;
106 	fsstack_copy_attr_times(dir, sharefs_lower_inode(dir));
107 	fsstack_copy_inode_size(dir, d_inode(lower_parent_dentry));
108 
109 out:
110 	unlock_dir(lower_parent_dentry);
111 	sharefs_put_lower_path(dentry, &lower_path);
112 	sharefs_revert_fsids(saved_cred);
113 	return err;
114 }
115 
sharefs_mkdir(struct mnt_idmap * idmap,struct inode * dir,struct dentry * dentry,umode_t mode)116 static int sharefs_mkdir(struct mnt_idmap *idmap, struct inode *dir, struct dentry *dentry, umode_t mode)
117 {
118 	int err;
119 	struct dentry *lower_dentry;
120 	struct dentry *lower_parent_dentry = NULL;
121 	struct path lower_path;
122 	const struct cred *saved_cred = NULL;
123 	__u16 child_perm;
124 
125 	saved_cred = sharefs_override_file_fsids(dir, &child_perm);
126 	if (!saved_cred) {
127 		err = -ENOMEM;
128 		return err;
129 	}
130 
131 	sharefs_get_lower_path(dentry, &lower_path);
132 	lower_dentry = lower_path.dentry;
133 	lower_parent_dentry = lock_parent(lower_dentry);
134 	err = vfs_mkdir(&nop_mnt_idmap, d_inode(lower_parent_dentry), lower_dentry, mode);
135 	if (err)
136 		goto out;
137 
138 	err = sharefs_interpose(dentry, dir->i_sb, &lower_path);
139 	if (err)
140 		goto out;
141 
142 	fsstack_copy_attr_times(dir, sharefs_lower_inode(dir));
143 	fsstack_copy_inode_size(dir, d_inode(lower_parent_dentry));
144 	/* update number of links on parent directory */
145 	set_nlink(dir, sharefs_lower_inode(dir)->i_nlink);
146 
147 out:
148 	unlock_dir(lower_parent_dentry);
149 	sharefs_put_lower_path(dentry, &lower_path);
150 	sharefs_revert_fsids(saved_cred);
151 	return err;
152 }
153 
sharefs_unlink(struct inode * dir,struct dentry * dentry)154 static int sharefs_unlink(struct inode *dir, struct dentry *dentry)
155 {
156 	int err;
157 	struct dentry *lower_dentry = NULL;
158 	struct inode *lower_dir_inode = sharefs_lower_inode(dir);
159 	struct dentry *lower_dir_dentry = NULL;
160 	struct path lower_path;
161 
162 	sharefs_get_lower_path(dentry, &lower_path);
163 	lower_dentry = lower_path.dentry;
164 	dget(lower_dentry);
165 	lower_dir_dentry = lock_parent(lower_dentry);
166 	err = vfs_unlink(&nop_mnt_idmap, lower_dir_inode, lower_dentry, NULL);
167 	if (err)
168 		goto out;
169 	fsstack_copy_attr_times(dir, lower_dir_inode);
170 	fsstack_copy_inode_size(dir, lower_dir_inode);
171 	set_nlink(dentry->d_inode,
172 		  sharefs_lower_inode(dentry->d_inode)->i_nlink);
173 	dentry->d_inode->__i_ctime = dir->__i_ctime;
174 	d_drop(dentry);
175 
176 out:
177 	unlock_dir(lower_dir_dentry);
178 	dput(lower_dentry);
179 	sharefs_put_lower_path(dentry, &lower_path);
180 	return err;
181 }
182 
sharefs_rmdir(struct inode * dir,struct dentry * dentry)183 static int sharefs_rmdir(struct inode *dir, struct dentry *dentry)
184 {
185 	int err;
186 	struct dentry *lower_dentry;
187 	struct dentry *lower_dir_dentry;
188 	struct path lower_path;
189 
190 	sharefs_get_lower_path(dentry, &lower_path);
191 	lower_dentry = lower_path.dentry;
192 	lower_dir_dentry = lock_parent(lower_dentry);
193 	err = vfs_rmdir(&nop_mnt_idmap, lower_dir_dentry->d_inode, lower_dentry);
194 	if (err)
195 		goto out;
196 
197 	d_drop(dentry);
198 	if (dentry->d_inode)
199 		clear_nlink(dentry->d_inode);
200 	fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
201 	fsstack_copy_inode_size(dir, lower_dir_dentry->d_inode);
202 	set_nlink(dir, lower_dir_dentry->d_inode->i_nlink);
203 
204 out:
205 	unlock_dir(lower_dir_dentry);
206 	sharefs_put_lower_path(dentry, &lower_path);
207 	return err;
208 }
209 
sharefs_rename(struct mnt_idmap * idmap,struct inode * old_dir,struct dentry * old_dentry,struct inode * new_dir,struct dentry * new_dentry,unsigned int flags)210 static int sharefs_rename(struct mnt_idmap *idmap, struct inode *old_dir, struct dentry *old_dentry,
211 				struct inode *new_dir, struct dentry *new_dentry,
212 				unsigned int flags)
213 {
214 	int err;
215 	struct dentry *lower_old_dentry = NULL;
216 	struct dentry *lower_new_dentry = NULL;
217 	struct dentry *lower_old_dir_dentry = NULL;
218 	struct dentry *lower_new_dir_dentry = NULL;
219 	struct dentry *trap = NULL;
220 	struct path lower_old_path, lower_new_path;
221 	struct renamedata rename_data;
222 
223 	if (flags)
224 		return -EINVAL;
225 
226 	sharefs_get_lower_path(old_dentry, &lower_old_path);
227 	sharefs_get_lower_path(new_dentry, &lower_new_path);
228 	lower_old_dentry = lower_old_path.dentry;
229 	lower_new_dentry = lower_new_path.dentry;
230 	lower_old_dir_dentry = dget_parent(lower_old_dentry);
231 	lower_new_dir_dentry = dget_parent(lower_new_dentry);
232 	trap = lock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
233 	/* source should not be ancestor of target */
234 	if (trap == lower_old_dentry) {
235 		err = -EINVAL;
236 		goto out;
237 	}
238 	/* target should not be ancestor of source */
239 	if (trap == lower_new_dentry) {
240 		err = -ENOTEMPTY;
241 		goto out;
242 	}
243 
244 	rename_data.old_mnt_idmap  = &nop_mnt_idmap;
245 	rename_data.old_dir = lower_old_dir_dentry->d_inode;
246 	rename_data.old_dentry = lower_old_dentry;
247 	rename_data.new_mnt_idmap = &nop_mnt_idmap;
248 	rename_data.new_dir = lower_new_dir_dentry->d_inode;
249 	rename_data.new_dentry = lower_new_dentry;
250 	rename_data.flags = flags;
251 	err = vfs_rename(&rename_data);
252 	if (err)
253 		goto out;
254 
255 	fsstack_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode);
256 	fsstack_copy_inode_size(new_dir, lower_new_dir_dentry->d_inode);
257 	if (new_dir != old_dir) {
258 		fsstack_copy_attr_all(old_dir,
259 				    lower_old_dir_dentry->d_inode);
260 		fsstack_copy_inode_size(old_dir,
261 					lower_old_dir_dentry->d_inode);
262 	}
263 
264 out:
265 	unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
266 	dput(lower_old_dir_dentry);
267 	dput(lower_new_dir_dentry);
268 	sharefs_put_lower_path(old_dentry, &lower_old_path);
269 	sharefs_put_lower_path(new_dentry, &lower_new_path);
270 	return err;
271 }
272 #endif
273 
sharefs_setattr(struct mnt_idmap * idmap,struct dentry * dentry,struct iattr * ia)274 static int sharefs_setattr(struct mnt_idmap *idmap, struct dentry *dentry, struct iattr *ia)
275 {
276 	int err;
277 	struct dentry *lower_dentry;
278 	struct inode *inode;
279 	struct inode *lower_inode;
280 	struct path lower_path;
281 	struct iattr lower_ia;
282 
283 	inode = dentry->d_inode;
284 	/*
285 	 * Check if user has permission to change inode.  We don't check if
286 	 * this user can change the lower inode: that should happen when
287 	 * calling notify_change on the lower inode.
288 	 */
289 
290 	err = setattr_prepare(&nop_mnt_idmap, dentry, ia);
291 	if (err)
292 		goto out_err;
293 
294 	sharefs_get_lower_path(dentry, &lower_path);
295 	lower_dentry = lower_path.dentry;
296 	lower_inode = sharefs_lower_inode(inode);
297 
298 	/* prepare our own lower struct iattr (with the lower file) */
299 	memcpy(&lower_ia, ia, sizeof(lower_ia));
300 	if (ia->ia_valid & ATTR_FILE)
301 		lower_ia.ia_file = sharefs_lower_file(ia->ia_file);
302 
303 	/*
304 	 * If shrinking, first truncate upper level to cancel writing dirty
305 	 * pages beyond the new eof; and also if its' maxbytes is more
306 	 * limiting (fail with -EFBIG before making any change to the lower
307 	 * level).  There is no need to vmtruncate the upper level
308 	 * afterwards in the other cases: we fsstack_copy_inode_size from
309 	 * the lower level.
310 	 */
311 	if (ia->ia_valid & ATTR_SIZE) {
312 		err = inode_newsize_ok(inode, ia->ia_size);
313 		if (err)
314 			goto out;
315 		truncate_setsize(inode, ia->ia_size);
316 	}
317 
318 	lower_ia.ia_valid &= ~(ATTR_MODE|ATTR_UID|ATTR_GID);
319 
320 	/* notify the (possibly copied-up) lower inode */
321 	/*
322 	 * Note: we use lower_dentry->d_inode, because lower_inode may be
323 	 * unlinked (no inode->i_sb and i_ino==0.  This happens if someone
324 	 * tries to open(), unlink(), then ftruncate() a file.
325 	 */
326 
327 	inode_lock(d_inode(lower_dentry));
328 	err = notify_change(&nop_mnt_idmap, lower_dentry, &lower_ia, /* note: lower_ia */
329 			    NULL);
330 	inode_unlock(d_inode(lower_dentry));
331 
332 	if (err)
333 		goto out;
334 
335 	/* get attributes from the lower inode */
336 	fsstack_copy_attr_all(inode, lower_inode);
337 	/*
338 	 * Not running fsstack_copy_inode_size(inode, lower_inode), because
339 	 * VFS should update our inode size, and notify_change on
340 	 * lower_inode should update its size.
341 	 */
342 
343 out:
344 	sharefs_put_lower_path(dentry, &lower_path);
345 out_err:
346 	return err;
347 }
348 
349 const struct inode_operations sharefs_symlink_iops = {
350 	.permission	= sharefs_permission,
351 	.getattr	= sharefs_getattr,
352 	.get_link	= NULL,
353 	.listxattr	= sharefs_listxattr,
354 };
355 
356 const struct inode_operations sharefs_dir_iops = {
357 	.lookup		= sharefs_lookup,
358 	.permission	= sharefs_permission,
359 	.getattr	= sharefs_getattr,
360 	.listxattr	= sharefs_listxattr,
361 	.setattr	= sharefs_setattr,
362 #ifdef CONFIG_SHAREFS_SUPPORT_WRITE
363 	.unlink		= sharefs_unlink,
364 	.rmdir		= sharefs_rmdir,
365 	.rename		= sharefs_rename,
366 	.create		= sharefs_create,
367 	.mkdir		= sharefs_mkdir,
368 #endif
369 };
370 
371 const struct inode_operations sharefs_main_iops = {
372 	.permission	= sharefs_permission,
373 	.getattr	= sharefs_getattr,
374 	.listxattr	= sharefs_listxattr,
375 	.setattr        = sharefs_setattr,
376 };
377