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