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 17static 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 36static 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)); 53out: 54 sharefs_put_lower_path(dentry, &lower_path); 55 return err; 56} 57 58static 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 80static 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 109out: 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 116static 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 147out: 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 154static 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 176out: 177 unlock_dir(lower_dir_dentry); 178 dput(lower_dentry); 179 sharefs_put_lower_path(dentry, &lower_path); 180 return err; 181} 182 183static 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 204out: 205 unlock_dir(lower_dir_dentry); 206 sharefs_put_lower_path(dentry, &lower_path); 207 return err; 208} 209 210static 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 258out: 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 267static 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 341out: 342 sharefs_put_lower_path(dentry, &lower_path); 343out_err: 344 return err; 345} 346#endif 347 348const struct inode_operations sharefs_symlink_iops = { 349 .permission = sharefs_permission, 350 .getattr = sharefs_getattr, 351 .get_link = NULL, 352 .listxattr = sharefs_listxattr, 353}; 354 355const 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 370const 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