From 703195acc2157969e66cb07946522b918dfd7dea Mon Sep 17 00:00:00 2001 From: wang di Date: Fri, 4 Sep 2015 01:48:32 -0700 Subject: [PATCH] LU-7093 mdt: Remote operation permission check Only do permission check for migrate, create striped (remote) directory, and set default LMV stripeEA for directory. For non-administrators, only if their gid match enable_remote_dir_gid (under /proc) or enable_remote_dir_gid = -1, then they can do these above 3 operations. Signed-off-by: wang di Change-Id: Id103ddd4dbf4a1901a32b599639037de8ce58e4a Reviewed-on: http://review.whamcloud.com/16286 Tested-by: Jenkins Tested-by: Maloo Reviewed-by: Lai Siyao Reviewed-by: Andreas Dilger Reviewed-by: Oleg Drokin --- lustre/mdt/mdt_reint.c | 97 ++++++++++++++++++++++++++++---------------------- lustre/tests/sanity.sh | 46 ++++++++++++++++++++++++ 2 files changed, 101 insertions(+), 42 deletions(-) diff --git a/lustre/mdt/mdt_reint.c b/lustre/mdt/mdt_reint.c index defdb39..6480510 100644 --- a/lustre/mdt/mdt_reint.c +++ b/lustre/mdt/mdt_reint.c @@ -220,64 +220,73 @@ static int mdt_lookup_version_check(struct mdt_thread_info *info, } +static inline int mdt_remote_permission_check(struct mdt_thread_info *info) +{ + struct lu_ucred *uc = mdt_ucred(info); + struct mdt_device *mdt = info->mti_mdt; + + if (!md_capable(uc, CFS_CAP_SYS_ADMIN)) { + if (uc->uc_gid != mdt->mdt_enable_remote_dir_gid && + mdt->mdt_enable_remote_dir_gid != -1) + return -EPERM; + } + + return 0; +} + /** * mdt_remote_permission: Check whether the remote operation is permitted, * - * Before we implement async cross-MDT updates (DNE phase 2). There are a few - * limitations here: - * - * 1.Only sysadmin can create remote directory and striped directory and - * migrate directory now, unless - * lctl set_param mdt.*.enable_remote_dir_gid=allow_gid. - * 2.Remote directory can only be created on MDT0, unless - * lctl set_param mdt.*.enable_remote_dir = 1 - * 3.Only new clients can access remote dir( >= 2.4) and striped dir(>= 2.6), - * old client will return -ENOTSUPP. + * Only sysadmin can create remote directory / striped directory, + * migrate directory and set default stripedEA on directory, unless * - * XXX these check are only needed for remote synchronization, once async - * update is supported, these check will be removed. + * lctl set_param mdt.*.enable_remote_dir_gid=allow_gid. * - * param[in]info: execution environment. - * param[in]parent: the directory of this operation. - * param[in]child: the child of this operation. + * param[in] info: mdt_thread_info. * * retval = 0 remote operation is allowed. * < 0 remote operation is denied. */ -static int mdt_remote_permission(struct mdt_thread_info *info, - struct mdt_object *parent, - struct mdt_object *child) +static int mdt_remote_permission(struct mdt_thread_info *info) { - struct mdt_device *mdt = info->mti_mdt; - struct lu_ucred *uc = mdt_ucred(info); - struct md_op_spec *spec = &info->mti_spec; - struct lu_attr *attr = &info->mti_attr.ma_attr; - struct obd_export *exp = mdt_info_req(info)->rq_export; - - /* Only check create remote directory, striped directory and - * migration */ - if (mdt_object_remote(parent) == 0 && mdt_object_remote(child) == 0 && - !(S_ISDIR(attr->la_mode) && spec->u.sp_ea.eadata != NULL && - spec->u.sp_ea.eadatalen != 0) && - info->mti_rr.rr_opcode != REINT_MIGRATE) - return 0; + struct md_op_spec *spec = &info->mti_spec; + struct lu_attr *attr = &info->mti_attr.ma_attr; + struct obd_export *exp = mdt_info_req(info)->rq_export; + int rc; - if (!md_capable(uc, CFS_CAP_SYS_ADMIN)) { - if (uc->uc_gid != mdt->mdt_enable_remote_dir_gid && - mdt->mdt_enable_remote_dir_gid != -1) - return -EPERM; + if (info->mti_rr.rr_opcode == REINT_MIGRATE) { + rc = mdt_remote_permission_check(info); + if (rc != 0) + return rc; } - if (!mdt_is_dne_client(exp)) - return -ENOTSUPP; - - if (S_ISDIR(attr->la_mode) && spec->u.sp_ea.eadata != NULL && - spec->u.sp_ea.eadatalen != 0) { + if (info->mti_rr.rr_opcode == REINT_CREATE && + (S_ISDIR(attr->la_mode) && spec->u.sp_ea.eadata != NULL && + spec->u.sp_ea.eadatalen != 0)) { const struct lmv_user_md *lum = spec->u.sp_ea.eadata; + /* Only new clients can create remote dir( >= 2.4) and + * striped dir(>= 2.6), old client will return -ENOTSUPP */ + if (!mdt_is_dne_client(exp)) + return -ENOTSUPP; + if (le32_to_cpu(lum->lum_stripe_count) > 1 && !mdt_is_striped_client(exp)) return -ENOTSUPP; + + rc = mdt_remote_permission_check(info); + if (rc != 0) + return rc; + } + + if (info->mti_rr.rr_opcode == REINT_SETATTR) { + struct md_attr *ma = &info->mti_attr; + + if ((ma->ma_valid & MA_LMV)) { + rc = mdt_remote_permission_check(info); + if (rc != 0) + return rc; + } } return 0; @@ -351,7 +360,7 @@ static int mdt_md_create(struct mdt_thread_info *info) if (likely(!IS_ERR(child))) { struct md_object *next = mdt_object_child(parent); - rc = mdt_remote_permission(info, parent, child); + rc = mdt_remote_permission(info); if (rc != 0) GOTO(out_put_child, rc); @@ -668,6 +677,10 @@ static int mdt_reint_setattr(struct mdt_thread_info *info, struct lu_buf *buf = &info->mti_buf; struct mdt_lock_handle *lh; + rc = mdt_remote_permission(info); + if (rc < 0) + GOTO(out_put, rc); + if (ma->ma_attr.la_valid != 0) GOTO(out_put, rc = -EPROTO); @@ -1414,7 +1427,7 @@ static int mdt_reint_migrate_internal(struct mdt_thread_info *info, GOTO(out_put_child, rc = -EPERM); } - rc = mdt_remote_permission(info, msrcdir, mold); + rc = mdt_remote_permission(info); if (rc != 0) GOTO(out_put_child, rc); diff --git a/lustre/tests/sanity.sh b/lustre/tests/sanity.sh index e546fa3..4f78323 100644 --- a/lustre/tests/sanity.sh +++ b/lustre/tests/sanity.sh @@ -13841,6 +13841,52 @@ test_300m() { } run_test 300m "setstriped directory on single MDT FS" +cleanup_300n() { + local list=$(comma_list $(mdts_nodes)) + + trap 0 + do_nodes $list $LCTL set_param -n mdt.*.enable_remote_dir_gid=0 +} + +test_300n() { + [ $PARALLEL == "yes" ] && skip "skip parallel run" && return + [ $MDSCOUNT -lt 2 ] && skip "needs >= 2 MDTs" && return + local stripe_index + local list=$(comma_list $(mdts_nodes)) + + trap cleanup_300n RETURN EXIT + mkdir -p $DIR/$tdir + chmod 777 $DIR/$tdir + $RUNAS $LFS setdirstripe -i0 -c$MDSCOUNT \ + $DIR/$tdir/striped_dir > /dev/null 2>&1 && + error "create striped dir succeeds with gid=0" + + do_nodes $list $LCTL set_param -n mdt.*.enable_remote_dir_gid=-1 + $RUNAS $LFS setdirstripe -i0 -c$MDSCOUNT $DIR/$tdir/striped_dir || + error "create striped dir fails with gid=-1" + + do_nodes $list $LCTL set_param -n mdt.*.enable_remote_dir_gid=0 + $RUNAS $LFS setdirstripe -i 1 -c$MDSCOUNT -D \ + $DIR/$tdir/striped_dir > /dev/null 2>&1 && + error "set default striped dir succeeds with gid=0" + + + do_nodes $list $LCTL set_param -n mdt.*.enable_remote_dir_gid=-1 + $RUNAS $LFS setdirstripe -i 1 -c$MDSCOUNT -D $DIR/$tdir/striped_dir || + error "set default striped dir fails with gid=-1" + + + do_nodes $list $LCTL set_param -n mdt.*.enable_remote_dir_gid=0 + $RUNAS mkdir $DIR/$tdir/striped_dir/test_dir || + error "create test_dir fails" + $RUNAS mkdir $DIR/$tdir/striped_dir/test_dir1 || + error "create test_dir1 fails" + $RUNAS mkdir $DIR/$tdir/striped_dir/test_dir2 || + error "create test_dir2 fails" + cleanup_300n +} +run_test 300n "non-root user to create dir under striped dir with default EA" + prepare_remote_file() { mkdir $DIR/$tdir/src_dir || error "create remote source failed" -- 1.8.3.1