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 sharefs_put_lower_path(path->dentry, &lower_path);
71
72 return ret;
73 }
74
75 static ssize_t
sharefs_listxattr(struct dentry * dentry,char * buffer,size_t buffer_size)76 sharefs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
77 {
78 int err;
79 struct dentry *lower_dentry;
80 struct path lower_path;
81
82 sharefs_get_lower_path(dentry, &lower_path);
83 lower_dentry = lower_path.dentry;
84 if (!(d_inode(lower_dentry)->i_opflags & IOP_XATTR)) {
85 err = -EOPNOTSUPP;
86 goto out;
87 }
88 err = vfs_listxattr(lower_dentry, buffer, buffer_size);
89 if (err)
90 goto out;
91 fsstack_copy_attr_atime(d_inode(dentry),
92 d_inode(lower_path.dentry));
93 out:
94 sharefs_put_lower_path(dentry, &lower_path);
95 return err;
96 }
97
sharefs_permission(struct inode * inode,int mask)98 static int sharefs_permission(struct inode *inode, int mask)
99 {
100 unsigned short mode = inode->i_mode;
101 kuid_t cur_uid = current_fsuid();
102 if (uid_eq(cur_uid, ROOT_UID))
103 return 0;
104 if (uid_eq(cur_uid, inode->i_uid)) {
105 mode >>= 6;
106 } else if (in_group_p(inode->i_gid)) {
107 mode >>= 3;
108 }
109
110 if ((mask & ~mode & (MAY_READ | MAY_WRITE | MAY_EXEC)) == 0)
111 return 0;
112
113 return -EACCES;
114 }
115
116 const struct inode_operations sharefs_symlink_iops = {
117 .permission = sharefs_permission,
118 .getattr = sharefs_getattr,
119 .get_link = sharefs_get_link,
120 .listxattr = sharefs_listxattr,
121 };
122
123 const struct inode_operations sharefs_dir_iops = {
124 .lookup = sharefs_lookup,
125 .permission = sharefs_permission,
126 .getattr = sharefs_getattr,
127 .listxattr = sharefs_listxattr,
128 };
129
130 const struct inode_operations sharefs_main_iops = {
131 .permission = sharefs_permission,
132 .getattr = sharefs_getattr,
133 .listxattr = sharefs_listxattr,
134 };
135