1// SPDX-License-Identifier: GPL-2.0 2/* 3 * fs/hmdfs/inode_local.c 4 * 5 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. 6 */ 7 8#include <linux/file.h> 9#include <linux/fs_stack.h> 10#include <linux/kernel.h> 11#include <linux/mount.h> 12#include <linux/namei.h> 13#include <linux/string.h> 14 15#include "authority/authentication.h" 16#include "comm/socket_adapter.h" 17#include "comm/transport.h" 18#include "hmdfs_client.h" 19#include "hmdfs_dentryfile.h" 20#include "hmdfs_device_view.h" 21#include "hmdfs_share.h" 22#include "hmdfs_trace.h" 23 24extern struct kmem_cache *hmdfs_dentry_cachep; 25 26struct hmdfs_name_data { 27 struct dir_context ctx; 28 const struct qstr *to_find; 29 char *name; 30 bool found; 31}; 32 33int init_hmdfs_dentry_info(struct hmdfs_sb_info *sbi, struct dentry *dentry, 34 int dentry_type) 35{ 36 struct hmdfs_dentry_info *info = 37 kmem_cache_zalloc(hmdfs_dentry_cachep, GFP_ATOMIC); 38 39 if (!info) 40 return -ENOMEM; 41 INIT_LIST_HEAD(&info->cache_list_head); 42 INIT_LIST_HEAD(&info->remote_cache_list_head); 43 spin_lock_init(&info->cache_list_lock); 44 mutex_init(&info->remote_cache_list_lock); 45 mutex_init(&info->cache_pull_lock); 46 spin_lock_init(&info->lock); 47 info->dentry_type = dentry_type; 48 info->device_id = 0; 49 dentry->d_fsdata = info; 50 if (dentry_type == HMDFS_LAYER_ZERO || 51 dentry_type == HMDFS_LAYER_FIRST_DEVICE || 52 dentry_type == HMDFS_LAYER_SECOND_LOCAL || 53 dentry_type == HMDFS_LAYER_SECOND_CLOUD || 54 dentry_type == HMDFS_LAYER_SECOND_REMOTE) 55 d_set_d_op(dentry, &hmdfs_dev_dops); 56 else 57 d_set_d_op(dentry, &hmdfs_dops); 58 return 0; 59} 60 61static inline void set_sharefile_flag(struct hmdfs_dentry_info *gdi) 62{ 63 gdi->file_type = HM_SHARE; 64} 65 66static void check_and_fixup_share_ops(struct inode *inode, 67 const char *name) 68{ 69 if (is_share_dir(inode, name)) { 70 inode->i_op = &hmdfs_dir_inode_ops_share; 71 inode->i_fop = &hmdfs_dir_ops_share; 72 } 73} 74 75struct inode *fill_inode_local(struct super_block *sb, 76 struct inode *lower_inode, const char *name) 77{ 78 int ret = 0; 79 struct inode *inode; 80 struct hmdfs_sb_info *sbi = hmdfs_sb(sb); 81 struct hmdfs_inode_info *info; 82 83 if (!igrab(lower_inode)) 84 return ERR_PTR(-ESTALE); 85 86 inode = hmdfs_iget5_locked_local(sb, lower_inode); 87 if (!inode) { 88 hmdfs_err("iget5_locked get inode NULL"); 89 iput(lower_inode); 90 return ERR_PTR(-ENOMEM); 91 } 92 if (!(inode->i_state & I_NEW)) { 93 iput(lower_inode); 94 return inode; 95 } 96 97 info = hmdfs_i(inode); 98#ifdef CONFIG_HMDFS_FS_PERMISSION 99 info->perm = hmdfs_read_perm(lower_inode); 100#endif 101 if (S_ISDIR(lower_inode->i_mode)) 102 inode->i_mode = (lower_inode->i_mode & S_IFMT) | S_IRWXU | 103 S_IRWXG | S_IXOTH; 104 else if (S_ISREG(lower_inode->i_mode)) 105 inode->i_mode = (lower_inode->i_mode & S_IFMT) | S_IRUSR | 106 S_IWUSR | S_IRGRP | S_IWGRP; 107 else if (S_ISLNK(lower_inode->i_mode)) 108 inode->i_mode = 109 S_IFREG | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP; 110 111#ifdef CONFIG_HMDFS_FS_PERMISSION 112 inode->i_uid = lower_inode->i_uid; 113 inode->i_gid = lower_inode->i_gid; 114#else 115 inode->i_uid = KUIDT_INIT((uid_t)1000); 116 inode->i_gid = KGIDT_INIT((gid_t)1000); 117#endif 118 inode->i_atime = lower_inode->i_atime; 119 inode->__i_ctime = lower_inode->__i_ctime; 120 inode->i_mtime = lower_inode->i_mtime; 121 inode->i_generation = lower_inode->i_generation; 122 123 info->inode_type = HMDFS_LAYER_OTHER_LOCAL; 124 if (S_ISDIR(lower_inode->i_mode)) { 125 inode->i_op = &hmdfs_dir_inode_ops_local; 126 inode->i_fop = &hmdfs_dir_ops_local; 127 inode->i_mode |= S_IXUGO; 128 } else if (S_ISREG(lower_inode->i_mode)) { 129 inode->i_op = &hmdfs_file_iops_local; 130 inode->i_fop = &hmdfs_file_fops_local; 131 } else if (S_ISLNK(lower_inode->i_mode)) { 132 inode->i_op = &hmdfs_symlink_iops_local; 133 inode->i_fop = &hmdfs_file_fops_local; 134 inode->i_size = i_size_read(lower_inode); 135 } else { 136 ret = -EIO; 137 goto bad_inode; 138 } 139 140 if (sbi->s_cloud_disk_switch) 141 inode->i_mapping->a_ops = &hmdfs_aops_cloud; 142 143 fsstack_copy_inode_size(inode, lower_inode); 144 check_and_fixup_share_ops(inode, name); 145 unlock_new_inode(inode); 146 return inode; 147bad_inode: 148 iget_failed(inode); 149 return ERR_PTR(ret); 150} 151 152/* hmdfs_convert_lookup_flags - covert hmdfs lookup flags to vfs lookup flags 153 * 154 * @hmdfs_flags: hmdfs lookup flags 155 * @vfs_flags: pointer to converted flags 156 * 157 * return 0 on success, or err code on failure. 158 */ 159int hmdfs_convert_lookup_flags(unsigned int hmdfs_flags, 160 unsigned int *vfs_flags) 161{ 162 *vfs_flags = 0; 163 164 /* currently only support HMDFS_LOOKUP_REVAL */ 165 if (hmdfs_flags & ~HMDFS_LOOKUP_REVAL) 166 return -EINVAL; 167 168 if (hmdfs_flags & HMDFS_LOOKUP_REVAL) 169 *vfs_flags |= LOOKUP_REVAL; 170 171 return 0; 172} 173 174static bool hmdfs_name_match(struct dir_context *ctx, const char *name, 175 int namelen, loff_t offset, u64 ino, 176 unsigned int d_type) 177{ 178 struct hmdfs_name_data *buf = 179 container_of(ctx, struct hmdfs_name_data, ctx); 180 struct qstr candidate = QSTR_INIT(name, namelen); 181 182 if (qstr_case_eq(buf->to_find, &candidate)) { 183 memcpy(buf->name, name, namelen); 184 buf->name[namelen] = 0; 185 buf->found = true; 186 return false; 187 } 188 return true; 189} 190 191static int __lookup_nosensitive(struct path *lower_parent_path, 192 struct dentry *child_dentry, unsigned int flags, 193 struct path *lower_path) 194{ 195 struct file *file; 196 const struct cred *cred = current_cred(); 197 const struct qstr *name = &child_dentry->d_name; 198 int err; 199 struct hmdfs_name_data buffer = { 200 .ctx.actor = hmdfs_name_match, 201 .to_find = name, 202 .name = __getname(), 203 .found = false, 204 }; 205 206 if (!buffer.name) { 207 err = -ENOMEM; 208 goto out; 209 } 210 file = dentry_open(lower_parent_path, O_RDONLY, cred); 211 if (IS_ERR(file)) { 212 err = PTR_ERR(file); 213 goto put_name; 214 } 215 err = iterate_dir(file, &buffer.ctx); 216 fput(file); 217 if (err) 218 goto put_name; 219 if (buffer.found) 220 err = vfs_path_lookup(lower_parent_path->dentry, 221 lower_parent_path->mnt, buffer.name, 222 flags, lower_path); 223 else 224 err = -ENOENT; 225put_name: 226 __putname(buffer.name); 227out: 228 return err; 229} 230 231static inline void set_symlink_flag(struct hmdfs_dentry_info *gdi) 232{ 233 gdi->file_type = HM_SYMLINK; 234} 235 236struct dentry *hmdfs_lookup_local(struct inode *parent_inode, 237 struct dentry *child_dentry, 238 unsigned int flags) 239{ 240 const char *d_name = child_dentry->d_name.name; 241 int err = 0; 242 struct path lower_path, lower_parent_path; 243 struct dentry *lower_dentry = NULL, *parent_dentry = NULL, *ret = NULL; 244 struct hmdfs_dentry_info *gdi = NULL; 245 struct inode *child_inode = NULL; 246 struct hmdfs_sb_info *sbi = hmdfs_sb(child_dentry->d_sb); 247 248 trace_hmdfs_lookup_local(parent_inode, child_dentry, flags); 249 if (child_dentry->d_name.len > NAME_MAX) { 250 ret = ERR_PTR(-ENAMETOOLONG); 251 goto out; 252 } 253 254 /* local device */ 255 parent_dentry = dget_parent(child_dentry); 256 hmdfs_get_lower_path(parent_dentry, &lower_parent_path); 257 err = init_hmdfs_dentry_info(sbi, child_dentry, 258 HMDFS_LAYER_OTHER_LOCAL); 259 if (err) { 260 ret = ERR_PTR(err); 261 goto out_err; 262 } 263 264 gdi = hmdfs_d(child_dentry); 265 266 flags &= ~LOOKUP_FOLLOW; 267 err = vfs_path_lookup(lower_parent_path.dentry, lower_parent_path.mnt, 268 (child_dentry->d_name.name), 0, &lower_path); 269 if (err && err != -ENOENT) { 270 ret = ERR_PTR(err); 271 goto out_err; 272 } else if (!err) { 273 hmdfs_set_lower_path(child_dentry, &lower_path); 274 child_inode = fill_inode_local(parent_inode->i_sb, 275 d_inode(lower_path.dentry), 276 child_dentry->d_name.name); 277 278 if (S_ISLNK(d_inode(lower_path.dentry)->i_mode)) 279 set_symlink_flag(gdi); 280 if (IS_ERR(child_inode)) { 281 err = PTR_ERR(child_inode); 282 ret = ERR_PTR(err); 283 hmdfs_put_reset_lower_path(child_dentry); 284 goto out_err; 285 } 286 ret = d_splice_alias(child_inode, child_dentry); 287 if (IS_ERR(ret)) { 288 err = PTR_ERR(ret); 289 hmdfs_put_reset_lower_path(child_dentry); 290 goto out_err; 291 } 292 293 check_and_fixup_ownership(parent_inode, child_inode); 294 goto out_err; 295 } 296 /* 297 * return 0 here, so that vfs can continue the process of making this 298 * negative dentry to a positive one while creating a new file. 299 */ 300 err = 0; 301 ret = 0; 302 303 lower_dentry = lookup_one_len_unlocked(d_name, lower_parent_path.dentry, 304 child_dentry->d_name.len); 305 if (IS_ERR(lower_dentry)) { 306 err = PTR_ERR(lower_dentry); 307 ret = lower_dentry; 308 goto out_err; 309 } 310 lower_path.dentry = lower_dentry; 311 lower_path.mnt = mntget(lower_parent_path.mnt); 312 hmdfs_set_lower_path(child_dentry, &lower_path); 313 314out_err: 315 if (!err) 316 hmdfs_set_time(child_dentry, jiffies); 317 hmdfs_put_lower_path(&lower_parent_path); 318 dput(parent_dentry); 319out: 320 trace_hmdfs_lookup_local_end(parent_inode, child_dentry, err); 321 return ret; 322} 323 324int hmdfs_mkdir_local_dentry(struct inode *dir, struct dentry *dentry, 325 umode_t mode) 326{ 327 struct inode *lower_dir = hmdfs_i(dir)->lower_inode; 328 struct dentry *lower_dir_dentry = NULL; 329 struct super_block *sb = dir->i_sb; 330 struct path lower_path; 331 struct dentry *lower_dentry = NULL; 332 int error = 0; 333 struct inode *lower_inode = NULL; 334 struct inode *child_inode = NULL; 335 bool local_res = false; 336 struct cache_fs_override or; 337 __u16 child_perm; 338 kuid_t tmp_uid; 339 340 error = hmdfs_override_dir_id_fs(&or, dir, dentry, &child_perm); 341 if (error) 342 goto cleanup; 343 344 hmdfs_get_lower_path(dentry, &lower_path); 345 lower_dentry = lower_path.dentry; 346 lower_dir_dentry = lock_parent(lower_dentry); 347 348 tmp_uid = hmdfs_override_inode_uid(lower_dir); 349 mode = (mode & S_IFMT) | 00771; 350 351 error = vfs_mkdir(&nop_mnt_idmap, lower_dir, lower_dentry, mode); 352 hmdfs_revert_inode_uid(lower_dir, tmp_uid); 353 if (error) { 354 hmdfs_err("vfs_mkdir() error:%d", error); 355 goto out; 356 } 357 local_res = true; 358 lower_inode = d_inode(lower_dentry); 359#ifdef CONFIG_HMDFS_FS_PERMISSION 360 error = hmdfs_persist_perm(lower_dentry, &child_perm); 361#endif 362 child_inode = fill_inode_local(sb, lower_inode, dentry->d_name.name); 363 if (IS_ERR(child_inode)) { 364 error = PTR_ERR(child_inode); 365 goto out; 366 } 367 d_add(dentry, child_inode); 368 set_nlink(dir, hmdfs_i(dir)->lower_inode->i_nlink); 369out: 370 unlock_dir(lower_dir_dentry); 371 if (local_res) 372 hmdfs_drop_remote_cache_dents(dentry->d_parent); 373 374 if (error) { 375 hmdfs_clear_drop_flag(dentry->d_parent); 376 d_drop(dentry); 377 } 378 hmdfs_put_lower_path(&lower_path); 379 hmdfs_revert_dir_id_fs(&or); 380cleanup: 381 return error; 382} 383 384int hmdfs_mkdir_local(struct mnt_idmap *idmap, struct inode *dir, struct dentry *dentry, umode_t mode) 385{ 386 int err = 0; 387 388 if (check_filename(dentry->d_name.name, dentry->d_name.len)) { 389 err = -EINVAL; 390 return err; 391 } 392 393 if (hmdfs_file_type(dentry->d_name.name) != HMDFS_TYPE_COMMON) { 394 err = -EACCES; 395 return err; 396 } 397 err = hmdfs_mkdir_local_dentry(dir, dentry, mode); 398 trace_hmdfs_mkdir_local(dir, dentry, err); 399 return err; 400} 401 402int hmdfs_create_local_dentry(struct inode *dir, struct dentry *dentry, 403 umode_t mode, bool want_excl) 404{ 405 struct inode *lower_dir = NULL; 406 struct dentry *lower_dir_dentry = NULL; 407 struct super_block *sb = dir->i_sb; 408 struct path lower_path; 409 struct dentry *lower_dentry = NULL; 410 int error = 0; 411 struct inode *lower_inode = NULL; 412 struct inode *child_inode = NULL; 413 kuid_t tmp_uid; 414#ifdef CONFIG_HMDFS_FS_PERMISSION 415 const struct cred *saved_cred = NULL; 416 struct fs_struct *saved_fs = NULL, *copied_fs = NULL; 417 __u16 child_perm; 418#endif 419 420#ifdef CONFIG_HMDFS_FS_PERMISSION 421 saved_cred = hmdfs_override_file_fsids(dir, &child_perm); 422 if (!saved_cred) { 423 error = -ENOMEM; 424 goto path_err; 425 } 426 427 saved_fs = current->fs; 428 copied_fs = hmdfs_override_fsstruct(saved_fs); 429 if (!copied_fs) { 430 error = -ENOMEM; 431 goto revert_fsids; 432 } 433#endif 434 hmdfs_get_lower_path(dentry, &lower_path); 435 lower_dentry = lower_path.dentry; 436 mode = (mode & S_IFMT) | 00660; 437 lower_dir_dentry = lock_parent(lower_dentry); 438 lower_dir = d_inode(lower_dir_dentry); 439 tmp_uid = hmdfs_override_inode_uid(lower_dir); 440 error = vfs_create(&nop_mnt_idmap, lower_dir, lower_dentry, mode, want_excl); 441 hmdfs_revert_inode_uid(lower_dir, tmp_uid); 442 unlock_dir(lower_dir_dentry); 443 if (error) 444 goto out; 445 446 lower_inode = d_inode(lower_dentry); 447#ifdef CONFIG_HMDFS_FS_PERMISSION 448 error = hmdfs_persist_perm(lower_dentry, &child_perm); 449#endif 450 child_inode = fill_inode_local(sb, lower_inode, dentry->d_name.name); 451 if (IS_ERR(child_inode)) { 452 error = PTR_ERR(child_inode); 453 goto out_created; 454 } 455 d_add(dentry, child_inode); 456 457out_created: 458 hmdfs_drop_remote_cache_dents(dentry->d_parent); 459out: 460 if (error) { 461 hmdfs_clear_drop_flag(dentry->d_parent); 462 d_drop(dentry); 463 } 464 hmdfs_put_lower_path(&lower_path); 465 466#ifdef CONFIG_HMDFS_FS_PERMISSION 467 hmdfs_revert_fsstruct(saved_fs, copied_fs); 468revert_fsids: 469 hmdfs_revert_fsids(saved_cred); 470#endif 471#ifdef CONFIG_HMDFS_FS_PERMISSION 472path_err: 473#endif 474 return error; 475} 476 477int hmdfs_create_local(struct mnt_idmap *idmap, struct inode *dir, struct dentry *child_dentry, 478 umode_t mode, bool want_excl) 479{ 480 int err = 0; 481 482 if (check_filename(child_dentry->d_name.name, 483 child_dentry->d_name.len)) { 484 err = -EINVAL; 485 return err; 486 } 487 488 if (hmdfs_file_type(child_dentry->d_name.name) != HMDFS_TYPE_COMMON) { 489 err = -EACCES; 490 return err; 491 } 492 493 err = hmdfs_create_local_dentry(dir, child_dentry, mode, want_excl); 494 trace_hmdfs_create_local(dir, child_dentry, err); 495 return err; 496} 497 498int hmdfs_rmdir_local_dentry(struct inode *dir, struct dentry *dentry) 499{ 500 struct inode *lower_dir = NULL; 501 struct dentry *lower_dir_dentry = NULL; 502 kuid_t tmp_uid; 503 struct path lower_path; 504 struct dentry *lower_dentry = NULL; 505 struct dentry *lookup_dentry = NULL; 506 int error = 0; 507 508 hmdfs_clear_cache_dents(dentry, true); 509 hmdfs_get_lower_path(dentry, &lower_path); 510 lower_dentry = lower_path.dentry; 511 lower_dir_dentry = lock_parent(lower_dentry); 512 lower_dir = d_inode(lower_dir_dentry); 513 514 lookup_dentry = lookup_one_len(lower_dentry->d_name.name, lower_dir_dentry, 515 lower_dentry->d_name.len); 516 if (IS_ERR(lookup_dentry)) { 517 error = PTR_ERR(lookup_dentry); 518 hmdfs_err("lookup_one_len failed, err = %d", error); 519 goto lookup_err; 520 } 521 tmp_uid = hmdfs_override_inode_uid(lower_dir); 522 523 error = vfs_rmdir(&nop_mnt_idmap, lower_dir, lookup_dentry); 524 hmdfs_revert_inode_uid(lower_dir, tmp_uid); 525 dput(lookup_dentry); 526lookup_err: 527 unlock_dir(lower_dir_dentry); 528 hmdfs_put_lower_path(&lower_path); 529 if (error) 530 goto path_err; 531 hmdfs_drop_remote_cache_dents(dentry->d_parent); 532path_err: 533 if (error) 534 hmdfs_clear_drop_flag(dentry->d_parent); 535 return error; 536} 537 538int hmdfs_rmdir_local(struct inode *dir, struct dentry *dentry) 539{ 540 int err = 0; 541 542 if (hmdfs_file_type(dentry->d_name.name) != HMDFS_TYPE_COMMON) { 543 err = -EACCES; 544 goto out; 545 } 546 547 err = hmdfs_rmdir_local_dentry(dir, dentry); 548 if (err != 0) { 549 hmdfs_err("rm dir failed:%d", err); 550 goto out; 551 } 552 553 /* drop dentry even remote failed 554 * it maybe cause that one remote devices disconnect 555 * when doing remote rmdir 556 */ 557 d_drop(dentry); 558out: 559 /* return connect device's errcode */ 560 trace_hmdfs_rmdir_local(dir, dentry, err); 561 return err; 562} 563 564int hmdfs_unlink_local_dentry(struct inode *dir, struct dentry *dentry) 565{ 566 struct dentry *lower_dir_dentry = NULL; 567 struct path lower_path; 568 struct inode *lower_dir = NULL; 569 struct dentry *lower_dentry = NULL; 570 struct dentry *lookup_dentry = NULL; 571 int error; 572 kuid_t tmp_uid; 573 574 hmdfs_get_lower_path(dentry, &lower_path); 575 lower_dentry = lower_path.dentry; 576 dget(lower_dentry); 577 lower_dir_dentry = lock_parent(lower_dentry); 578 lower_dir = d_inode(lower_dir_dentry); 579 lookup_dentry = lookup_one_len(lower_dentry->d_name.name, lower_dir_dentry, 580 lower_dentry->d_name.len); 581 if (IS_ERR(lookup_dentry)) { 582 error = PTR_ERR(lookup_dentry); 583 hmdfs_err("lookup_one_len failed, err = %d", error); 584 goto lookup_err; 585 } 586 587 tmp_uid = hmdfs_override_inode_uid(lower_dir); 588 error = vfs_unlink(&nop_mnt_idmap, lower_dir, lookup_dentry, NULL); 589 hmdfs_revert_inode_uid(lower_dir, tmp_uid); 590 set_nlink(d_inode(dentry), 591 hmdfs_i(d_inode(dentry))->lower_inode->i_nlink); 592 dput(lookup_dentry); 593lookup_err: 594 unlock_dir(lower_dir_dentry); 595 dput(lower_dentry); 596 if (error) 597 goto path_err; 598 599 hmdfs_drop_remote_cache_dents(dentry->d_parent); 600 d_drop(dentry); 601 602path_err: 603 hmdfs_put_lower_path(&lower_path); 604 if (error) 605 hmdfs_clear_drop_flag(dentry->d_parent); 606 return error; 607} 608 609int hmdfs_unlink_local(struct inode *dir, struct dentry *dentry) 610{ 611 if (hmdfs_file_type(dentry->d_name.name) != HMDFS_TYPE_COMMON) 612 return -EACCES; 613 614 return hmdfs_unlink_local_dentry(dir, dentry); 615} 616 617int hmdfs_rename_local_dentry(struct inode *old_dir, struct dentry *old_dentry, 618 struct inode *new_dir, struct dentry *new_dentry, 619 unsigned int flags) 620{ 621 struct path lower_old_path; 622 struct path lower_new_path; 623 struct dentry *lower_old_dentry = NULL; 624 struct dentry *lower_new_dentry = NULL; 625 struct dentry *lower_old_dir_dentry = NULL; 626 struct dentry *lower_new_dir_dentry = NULL; 627 struct dentry *trap = NULL; 628 struct renamedata rename_data; 629 int rc = 0; 630 kuid_t old_dir_uid, new_dir_uid; 631 632 if (flags) 633 return -EINVAL; 634 635 hmdfs_get_lower_path(old_dentry, &lower_old_path); 636 lower_old_dentry = lower_old_path.dentry; 637 if (!lower_old_dentry) { 638 hmdfs_err("lower_old_dentry as NULL"); 639 rc = -EACCES; 640 goto out_put_old_path; 641 } 642 643 hmdfs_get_lower_path(new_dentry, &lower_new_path); 644 lower_new_dentry = lower_new_path.dentry; 645 if (!lower_new_dentry) { 646 hmdfs_err("lower_new_dentry as NULL"); 647 rc = -EACCES; 648 goto out_put_new_path; 649 } 650 651 lower_old_dir_dentry = dget_parent(lower_old_dentry); 652 lower_new_dir_dentry = dget_parent(lower_new_dentry); 653 trap = lock_rename(lower_old_dir_dentry, lower_new_dir_dentry); 654 new_dir_uid = hmdfs_override_inode_uid(d_inode(lower_new_dir_dentry)); 655 old_dir_uid = hmdfs_override_inode_uid(d_inode(lower_old_dir_dentry)); 656 657 /* source should not be ancestor of target */ 658 if (trap == lower_old_dentry) { 659 rc = -EINVAL; 660 goto out_lock; 661 } 662 /* target should not be ancestor of source */ 663 if (trap == lower_new_dentry) { 664 rc = -ENOTEMPTY; 665 goto out_lock; 666 } 667 668 rename_data.old_mnt_idmap = &nop_mnt_idmap; 669 rename_data.old_dir = d_inode(lower_old_dir_dentry); 670 rename_data.old_dentry = lower_old_dentry; 671 rename_data.new_mnt_idmap = &nop_mnt_idmap; 672 rename_data.new_dir = d_inode(lower_new_dir_dentry); 673 rename_data.new_dentry = lower_new_dentry; 674 rename_data.flags = flags; 675 rc = vfs_rename(&rename_data); 676 677out_lock: 678 dget(old_dentry); 679 680 hmdfs_revert_inode_uid(d_inode(lower_old_dir_dentry), old_dir_uid); 681 hmdfs_revert_inode_uid(d_inode(lower_new_dir_dentry), new_dir_uid); 682 683 unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry); 684 if (rc == 0) { 685 hmdfs_drop_remote_cache_dents(old_dentry->d_parent); 686 if (old_dentry->d_parent != new_dentry->d_parent) 687 hmdfs_drop_remote_cache_dents(new_dentry->d_parent); 688 } else { 689 hmdfs_clear_drop_flag(old_dentry->d_parent); 690 if (old_dentry->d_parent != new_dentry->d_parent) 691 hmdfs_clear_drop_flag(old_dentry->d_parent); 692 d_drop(new_dentry); 693 } 694 695 dput(old_dentry); 696 dput(lower_old_dir_dentry); 697 dput(lower_new_dir_dentry); 698 699out_put_new_path: 700 hmdfs_put_lower_path(&lower_new_path); 701out_put_old_path: 702 hmdfs_put_lower_path(&lower_old_path); 703 return rc; 704} 705 706int hmdfs_rename_local(struct mnt_idmap *idmap, struct inode *old_dir, struct dentry *old_dentry, 707 struct inode *new_dir, struct dentry *new_dentry, 708 unsigned int flags) 709{ 710 int err = 0; 711 int ret = 0; 712 713 trace_hmdfs_rename_local(old_dir, old_dentry, new_dir, new_dentry, 714 flags); 715 if (hmdfs_file_type(old_dentry->d_name.name) != HMDFS_TYPE_COMMON || 716 hmdfs_file_type(new_dentry->d_name.name) != HMDFS_TYPE_COMMON) { 717 err = -EACCES; 718 goto rename_out; 719 } 720 721 if (hmdfs_i(old_dir)->inode_type != hmdfs_i(new_dir)->inode_type) { 722 hmdfs_err("in different view"); 723 err = -EPERM; 724 goto rename_out; 725 } 726 727 if (hmdfs_d(old_dentry)->device_id != hmdfs_d(new_dentry)->device_id) { 728 err = -EXDEV; 729 goto rename_out; 730 } 731 732 if (S_ISREG(old_dentry->d_inode->i_mode)) { 733 err = hmdfs_rename_local_dentry(old_dir, old_dentry, new_dir, 734 new_dentry, flags); 735 } else if (S_ISDIR(old_dentry->d_inode->i_mode)) { 736 ret = hmdfs_rename_local_dentry(old_dir, old_dentry, new_dir, 737 new_dentry, flags); 738 if (ret != 0) { 739 err = ret; 740 goto rename_out; 741 } 742 } 743 744 if (!err) 745 d_invalidate(old_dentry); 746 747rename_out: 748 return err; 749} 750 751static bool symname_is_allowed(const char *symname) 752{ 753 char *p = NULL; 754 size_t len; 755 756 len = strnlen(symname, PATH_MAX); 757 if (len >= PATH_MAX) 758 return false; 759 760 p = strstr(symname, "/../"); 761 if (p) 762 return false; 763 764 if (len == 2u && strncmp(symname, "..", 2u) == 0) 765 return false; 766 if (len >= 3u && strncmp(symname, "../", 3u) == 0) 767 return false; 768 if (len >= 3u && strncmp(symname + len - 3u, "/..", 3u) == 0) 769 return false; 770 return true; 771} 772 773int hmdfs_symlink_local(struct mnt_idmap *idmap, struct inode *dir, struct dentry *dentry, 774 const char *symname) 775{ 776 int err; 777 struct dentry *lower_dentry = NULL; 778 struct dentry *lower_parent_dentry = NULL; 779 struct path lower_path; 780 struct inode *child_inode = NULL; 781 struct inode *lower_dir_inode = hmdfs_i(dir)->lower_inode; 782 struct hmdfs_dentry_info *gdi = hmdfs_d(dentry); 783 kuid_t tmp_uid; 784#ifdef CONFIG_HMDFS_FS_PERMISSION 785 const struct cred *saved_cred = NULL; 786 struct fs_struct *saved_fs = NULL, *copied_fs = NULL; 787 __u16 child_perm; 788#endif 789 790 if (unlikely(!symname_is_allowed(symname))) { 791 err = -EPERM; 792 goto path_err; 793 } 794 795#ifdef CONFIG_HMDFS_FS_PERMISSION 796 saved_cred = hmdfs_override_file_fsids(dir, &child_perm); 797 if (!saved_cred) { 798 err = -ENOMEM; 799 goto path_err; 800 } 801 802 saved_fs = current->fs; 803 copied_fs = hmdfs_override_fsstruct(saved_fs); 804 if (!copied_fs) { 805 err = -ENOMEM; 806 goto revert_fsids; 807 } 808#endif 809 hmdfs_get_lower_path(dentry, &lower_path); 810 lower_dentry = lower_path.dentry; 811 lower_parent_dentry = lock_parent(lower_dentry); 812 tmp_uid = hmdfs_override_inode_uid(lower_dir_inode); 813 err = vfs_symlink(&nop_mnt_idmap, lower_dir_inode, lower_dentry, symname); 814 hmdfs_revert_inode_uid(lower_dir_inode, tmp_uid); 815 unlock_dir(lower_parent_dentry); 816 if (err) 817 goto out_err; 818 set_symlink_flag(gdi); 819#ifdef CONFIG_HMDFS_FS_PERMISSION 820 err = hmdfs_persist_perm(lower_dentry, &child_perm); 821#endif 822 child_inode = fill_inode_local(dir->i_sb, d_inode(lower_dentry), 823 dentry->d_name.name); 824 if (IS_ERR(child_inode)) { 825 err = PTR_ERR(child_inode); 826 goto out_err; 827 } 828 d_add(dentry, child_inode); 829 fsstack_copy_attr_times(dir, lower_dir_inode); 830 fsstack_copy_inode_size(dir, lower_dir_inode); 831 832out_err: 833 hmdfs_put_lower_path(&lower_path); 834#ifdef CONFIG_HMDFS_FS_PERMISSION 835 hmdfs_revert_fsstruct(saved_fs, copied_fs); 836revert_fsids: 837 hmdfs_revert_fsids(saved_cred); 838#endif 839path_err: 840 return err; 841} 842 843static const char *hmdfs_get_link_local(struct dentry *dentry, 844 struct inode *inode, 845 struct delayed_call *done) 846{ 847 const char *link = NULL; 848 struct dentry *lower_dentry = NULL; 849 struct inode *lower_inode = NULL; 850 struct path lower_path; 851 852 if(!dentry) { 853 hmdfs_err("dentry MULL"); 854 link = ERR_PTR(-ECHILD); 855 goto link_out; 856 } 857 858 hmdfs_get_lower_path(dentry, &lower_path); 859 lower_dentry = lower_path.dentry; 860 lower_inode = d_inode(lower_dentry); 861 if(!lower_inode->i_op || !lower_inode->i_op->get_link) { 862 hmdfs_err("The lower inode doesn't support get_link i_op"); 863 link = ERR_PTR(-EINVAL); 864 goto out; 865 } 866 867 link = lower_inode->i_op->get_link(lower_dentry, lower_inode, done); 868 if(IS_ERR_OR_NULL(link)) 869 goto out; 870 fsstack_copy_attr_atime(inode, lower_inode); 871out: 872 hmdfs_put_lower_path(&lower_path); 873link_out: 874 return link; 875} 876 877static int hmdfs_setattr_local(struct mnt_idmap *idmap, struct dentry *dentry, struct iattr *ia) 878{ 879 struct inode *inode = d_inode(dentry); 880 struct inode *lower_inode = hmdfs_i(inode)->lower_inode; 881 struct path lower_path; 882 struct dentry *lower_dentry = NULL; 883 struct iattr lower_ia; 884 unsigned int ia_valid = ia->ia_valid; 885 int err = 0; 886 kuid_t tmp_uid; 887 888 hmdfs_get_lower_path(dentry, &lower_path); 889 lower_dentry = lower_path.dentry; 890 memcpy(&lower_ia, ia, sizeof(lower_ia)); 891 if (ia_valid & ATTR_FILE) 892 lower_ia.ia_file = hmdfs_f(ia->ia_file)->lower_file; 893 lower_ia.ia_valid &= ~(ATTR_UID | ATTR_GID | ATTR_MODE); 894 if (ia_valid & ATTR_SIZE) { 895 err = inode_newsize_ok(inode, ia->ia_size); 896 if (err) 897 goto out; 898 truncate_setsize(inode, ia->ia_size); 899 } 900 inode_lock(lower_inode); 901 tmp_uid = hmdfs_override_inode_uid(lower_inode); 902 903 err = notify_change(&nop_mnt_idmap, lower_dentry, &lower_ia, NULL); 904 i_size_write(inode, i_size_read(lower_inode)); 905 inode->i_atime = lower_inode->i_atime; 906 inode->i_mtime = lower_inode->i_mtime; 907 inode->__i_ctime = lower_inode->__i_ctime; 908 err = update_inode_to_dentry(dentry, inode); 909 hmdfs_revert_inode_uid(lower_inode, tmp_uid); 910 911 inode_unlock(lower_inode); 912out: 913 hmdfs_put_lower_path(&lower_path); 914 return err; 915} 916 917static int hmdfs_getattr_local(struct mnt_idmap *idmap, const struct path *path, struct kstat *stat, 918 u32 request_mask, unsigned int flags) 919{ 920 struct path lower_path; 921 int ret; 922 923 if (path->dentry == NULL || hmdfs_d(path->dentry) == NULL) { 924 hmdfs_err("dentry is NULL"); 925 return -ENOENT; 926 } 927 928 hmdfs_get_lower_path(path->dentry, &lower_path); 929 ret = vfs_getattr(&lower_path, stat, request_mask, flags); 930 stat->ino = d_inode(path->dentry)->i_ino; 931 stat->uid = d_inode(path->dentry)->i_uid; 932 stat->gid = d_inode(path->dentry)->i_gid; 933 stat->dev = 0; 934 stat->rdev = 0; 935 hmdfs_put_lower_path(&lower_path); 936 937 return ret; 938} 939 940int hmdfs_permission(struct mnt_idmap *idmap, struct inode *inode, int mask) 941{ 942#ifdef CONFIG_HMDFS_FS_PERMISSION 943 unsigned int mode = inode->i_mode; 944 kuid_t cur_uid = current_fsuid(); 945 946 if (uid_eq(cur_uid, ROOT_UID) || uid_eq(cur_uid, SYSTEM_UID)) 947 return 0; 948 949 if (uid_eq(cur_uid, inode->i_uid)) { 950 mode >>= 6; 951 } else if (in_group_p(inode->i_gid)) { 952 mode >>= 3; 953 } 954 955 if ((mask & ~mode & (MAY_READ | MAY_WRITE | MAY_EXEC)) == 0) 956 return 0; 957 958 trace_hmdfs_permission(inode->i_ino); 959 return -EACCES; 960#else 961 962 return 0; 963#endif 964} 965 966static ssize_t hmdfs_local_listxattr(struct dentry *dentry, char *list, 967 size_t size) 968{ 969 struct path lower_path; 970 ssize_t res = 0; 971 size_t r_size = size; 972 973 if (!hmdfs_support_xattr(dentry)) 974 return -EOPNOTSUPP; 975 976 if (size > HMDFS_LISTXATTR_SIZE_MAX) 977 r_size = HMDFS_LISTXATTR_SIZE_MAX; 978 979 hmdfs_get_lower_path(dentry, &lower_path); 980 res = vfs_listxattr(lower_path.dentry, list, r_size); 981 hmdfs_put_lower_path(&lower_path); 982 983 if (res == -ERANGE && r_size != size) { 984 hmdfs_info("no support listxattr size over than %d", 985 HMDFS_LISTXATTR_SIZE_MAX); 986 res = -E2BIG; 987 } 988 989 return res; 990} 991struct dentry *hmdfs_lookup_share(struct inode *parent_inode, 992 struct dentry *child_dentry, unsigned int flags) 993{ 994 const struct qstr *d_name = &child_dentry->d_name; 995 int err = 0; 996 struct dentry *ret = NULL; 997 struct hmdfs_sb_info *sbi = hmdfs_sb(child_dentry->d_sb); 998 struct path src_path; 999 struct inode *child_inode = NULL; 1000 1001 trace_hmdfs_lookup_share(parent_inode, child_dentry, flags); 1002 if (d_name->len > NAME_MAX) { 1003 ret = ERR_PTR(-ENAMETOOLONG); 1004 goto err_out; 1005 } 1006 1007 err = init_hmdfs_dentry_info(sbi, child_dentry, HMDFS_LAYER_OTHER_LOCAL); 1008 if (err) { 1009 ret = ERR_PTR(err); 1010 goto err_out; 1011 } 1012 1013 err = get_path_from_share_table(sbi, child_dentry, &src_path); 1014 if (err) { 1015 ret = ERR_PTR(err); 1016 goto err_out; 1017 } 1018 1019 hmdfs_set_lower_path(child_dentry, &src_path); 1020 child_inode = fill_inode_local(parent_inode->i_sb, 1021 d_inode(src_path.dentry), d_name->name); 1022 1023 set_sharefile_flag(hmdfs_d(child_dentry)); 1024 1025 if (IS_ERR(child_inode)) { 1026 err = PTR_ERR(child_inode); 1027 ret = ERR_PTR(err); 1028 hmdfs_put_reset_lower_path(child_dentry); 1029 goto err_out; 1030 } 1031 ret = d_splice_alias(child_inode, child_dentry); 1032 if (IS_ERR(ret)) { 1033 err = PTR_ERR(ret); 1034 hmdfs_put_reset_lower_path(child_dentry); 1035 goto err_out; 1036 } 1037 1038 check_and_fixup_ownership(parent_inode, child_inode); 1039 1040err_out: 1041 trace_hmdfs_lookup_share_end(parent_inode, child_dentry, err); 1042 return ret; 1043} 1044 1045const struct inode_operations hmdfs_dir_inode_ops_local = { 1046 .lookup = hmdfs_lookup_local, 1047 .mkdir = hmdfs_mkdir_local, 1048 .create = hmdfs_create_local, 1049 .rmdir = hmdfs_rmdir_local, 1050 .unlink = hmdfs_unlink_local, 1051 .symlink = hmdfs_symlink_local, 1052 .rename = hmdfs_rename_local, 1053 .permission = hmdfs_permission, 1054 .setattr = hmdfs_setattr_local, 1055 .getattr = hmdfs_getattr_local, 1056}; 1057 1058const struct inode_operations hmdfs_symlink_iops_local = { 1059 .get_link = hmdfs_get_link_local, 1060 .permission = hmdfs_permission, 1061 .setattr = hmdfs_setattr_local, 1062}; 1063 1064const struct inode_operations hmdfs_dir_inode_ops_share = { 1065 .lookup = hmdfs_lookup_share, 1066 .permission = hmdfs_permission, 1067}; 1068 1069const struct inode_operations hmdfs_file_iops_local = { 1070 .setattr = hmdfs_setattr_local, 1071 .getattr = hmdfs_getattr_local, 1072 .permission = hmdfs_permission, 1073 .listxattr = hmdfs_local_listxattr, 1074}; 1075