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