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