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(&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 inode *dir, struct dentry *dentry, umode_t mode, bool want_excl)80 static int sharefs_create(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(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 inode *dir, struct dentry *dentry, umode_t mode)116 static int sharefs_mkdir(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(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(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(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 inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry, unsigned int flags)210 static int sharefs_rename(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
222 if (flags)
223 return -EINVAL;
224
225 sharefs_get_lower_path(old_dentry, &lower_old_path);
226 sharefs_get_lower_path(new_dentry, &lower_new_path);
227 lower_old_dentry = lower_old_path.dentry;
228 lower_new_dentry = lower_new_path.dentry;
229 lower_old_dir_dentry = dget_parent(lower_old_dentry);
230 lower_new_dir_dentry = dget_parent(lower_new_dentry);
231 trap = lock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
232 /* source should not be ancestor of target */
233 if (trap == lower_old_dentry) {
234 err = -EINVAL;
235 goto out;
236 }
237 /* target should not be ancestor of source */
238 if (trap == lower_new_dentry) {
239 err = -ENOTEMPTY;
240 goto out;
241 }
242
243 err = vfs_rename(lower_old_dir_dentry->d_inode, lower_old_dentry,
244 lower_new_dir_dentry->d_inode, lower_new_dentry,
245 NULL, 0);
246 if (err)
247 goto out;
248
249 fsstack_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode);
250 fsstack_copy_inode_size(new_dir, lower_new_dir_dentry->d_inode);
251 if (new_dir != old_dir) {
252 fsstack_copy_attr_all(old_dir,
253 lower_old_dir_dentry->d_inode);
254 fsstack_copy_inode_size(old_dir,
255 lower_old_dir_dentry->d_inode);
256 }
257
258 out:
259 unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
260 dput(lower_old_dir_dentry);
261 dput(lower_new_dir_dentry);
262 sharefs_put_lower_path(old_dentry, &lower_old_path);
263 sharefs_put_lower_path(new_dentry, &lower_new_path);
264 return err;
265 }
266
sharefs_setattr(struct dentry *dentry, struct iattr *ia)267 static int sharefs_setattr(struct dentry *dentry, struct iattr *ia)
268 {
269 int err;
270 struct dentry *lower_dentry;
271 struct inode *inode;
272 struct inode *lower_inode;
273 struct path lower_path;
274 struct iattr lower_ia;
275
276 inode = dentry->d_inode;
277 /*
278 * Check if user has permission to change inode. We don't check if
279 * this user can change the lower inode: that should happen when
280 * calling notify_change on the lower inode.
281 */
282
283 err = setattr_prepare(dentry, ia);
284 if (err)
285 goto out_err;
286
287 sharefs_get_lower_path(dentry, &lower_path);
288 lower_dentry = lower_path.dentry;
289 lower_inode = sharefs_lower_inode(inode);
290
291 /* prepare our own lower struct iattr (with the lower file) */
292 memcpy(&lower_ia, ia, sizeof(lower_ia));
293 if (ia->ia_valid & ATTR_FILE)
294 lower_ia.ia_file = sharefs_lower_file(ia->ia_file);
295
296 /*
297 * If shrinking, first truncate upper level to cancel writing dirty
298 * pages beyond the new eof; and also if its' maxbytes is more
299 * limiting (fail with -EFBIG before making any change to the lower
300 * level). There is no need to vmtruncate the upper level
301 * afterwards in the other cases: we fsstack_copy_inode_size from
302 * the lower level.
303 */
304 if (ia->ia_valid & ATTR_SIZE) {
305 err = inode_newsize_ok(inode, ia->ia_size);
306 if (err)
307 goto out;
308 truncate_setsize(inode, ia->ia_size);
309 }
310
311 /*
312 * mode change is for clearing setuid/setgid bits. Allow lower fs
313 * to interpret this in its own way.
314 */
315 if (lower_ia.ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID))
316 lower_ia.ia_valid &= ~ATTR_MODE;
317
318 /* notify the (possibly copied-up) lower inode */
319 /*
320 * Note: we use lower_dentry->d_inode, because lower_inode may be
321 * unlinked (no inode->i_sb and i_ino==0. This happens if someone
322 * tries to open(), unlink(), then ftruncate() a file.
323 */
324
325 inode_lock(d_inode(lower_dentry));
326 err = notify_change(lower_dentry, &lower_ia, /* note: lower_ia */
327 NULL);
328 inode_unlock(d_inode(lower_dentry));
329
330 if (err)
331 goto out;
332
333 /* get attributes from the lower inode */
334 fsstack_copy_attr_all(inode, lower_inode);
335 /*
336 * Not running fsstack_copy_inode_size(inode, lower_inode), because
337 * VFS should update our inode size, and notify_change on
338 * lower_inode should update its size.
339 */
340
341 out:
342 sharefs_put_lower_path(dentry, &lower_path);
343 out_err:
344 return err;
345 }
346 #endif
347
348 const struct inode_operations sharefs_symlink_iops = {
349 .permission = sharefs_permission,
350 .getattr = sharefs_getattr,
351 .get_link = NULL,
352 .listxattr = sharefs_listxattr,
353 };
354
355 const struct inode_operations sharefs_dir_iops = {
356 .lookup = sharefs_lookup,
357 .permission = sharefs_permission,
358 .getattr = sharefs_getattr,
359 .listxattr = sharefs_listxattr,
360 #ifdef CONFIG_SHAREFS_SUPPORT_WRITE
361 .unlink = sharefs_unlink,
362 .rmdir = sharefs_rmdir,
363 .rename = sharefs_rename,
364 .create = sharefs_create,
365 .mkdir = sharefs_mkdir,
366 .setattr = sharefs_setattr,
367 #endif
368 };
369
370 const struct inode_operations sharefs_main_iops = {
371 .permission = sharefs_permission,
372 .getattr = sharefs_getattr,
373 .listxattr = sharefs_listxattr,
374 #ifdef CONFIG_SHAREFS_SUPPORT_WRITE
375 .setattr = sharefs_setattr,
376 #endif
377 };
378