X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;ds=sidebyside;f=lustre%2Fmdt%2Fmdt_lib.c;h=d6dacde27f1dae9459aaf66f94052678c250902a;hb=49fd10ec8a2a85bbc56618d70f2f71d323d90a4c;hp=d212c5683349215d3c90f43675e5bb55ff23b85b;hpb=f4b93dff9a8f4a59976ea864c4e3c2c42faa5770;p=fs%2Flustre-release.git diff --git a/lustre/mdt/mdt_lib.c b/lustre/mdt/mdt_lib.c index d212c56..d6dacde 100644 --- a/lustre/mdt/mdt_lib.c +++ b/lustre/mdt/mdt_lib.c @@ -27,7 +27,7 @@ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. * Use is subject to license terms. * - * Copyright (c) 2011, 2014, Intel Corporation. + * Copyright (c) 2011, 2015, Intel Corporation. */ /* * This file is part of Lustre, http://www.lustre.org/ @@ -141,7 +141,7 @@ static void ucred_set_jobid(struct mdt_thread_info *info, struct lu_ucred *uc) } static int new_init_ucred(struct mdt_thread_info *info, ucred_init_type_t type, - void *buf) + void *buf, bool drop_fs_cap) { struct ptlrpc_request *req = mdt_info_req(info); struct mdt_device *mdt = info->mti_mdt; @@ -195,7 +195,8 @@ static int new_init_ucred(struct mdt_thread_info *info, ucred_init_type_t type, RETURN(-EACCES); } } else { - if (req->rq_auth_uid != pud->pud_uid) { + if (!flvr_is_rootonly(req->rq_flvr.sf_rpc) && + req->rq_auth_uid != pud->pud_uid) { CDEBUG(D_SEC, "local client %s: auth uid %u " "while client claims %u:%u/%u:%u\n", libcfs_nid2str(peernid), req->rq_auth_uid, @@ -294,7 +295,7 @@ static int new_init_ucred(struct mdt_thread_info *info, ucred_init_type_t type, mdt_root_squash(info, peernid); /* remove fs privilege for non-root user. */ - if (ucred->uc_fsuid) + if (ucred->uc_fsuid && drop_fs_cap) ucred->uc_cap = pud->pud_cap & ~CFS_CAP_FS_MASK; else ucred->uc_cap = pud->pud_cap; @@ -403,7 +404,8 @@ int mdt_check_ucred(struct mdt_thread_info *info) RETURN(-EACCES); } } else { - if (req->rq_auth_uid != pud->pud_uid) { + if (!flvr_is_rootonly(req->rq_flvr.sf_rpc) && + req->rq_auth_uid != pud->pud_uid) { CDEBUG(D_SEC, "local client %s: auth uid %u " "while client claims %u:%u/%u:%u\n", libcfs_nid2str(peernid), req->rq_auth_uid, @@ -463,29 +465,62 @@ out: return rc; } -static void mdt_squash_nodemap_id(struct lu_ucred *ucred, - struct lu_nodemap *nodemap) +static int old_init_ucred_common(struct mdt_thread_info *info, + struct lu_nodemap *nodemap, + bool drop_fs_cap) { - if (ucred->uc_o_uid == nodemap->nm_squash_uid) { - ucred->uc_fsuid = nodemap->nm_squash_uid; - ucred->uc_fsgid = nodemap->nm_squash_gid; - ucred->uc_cap = 0; - ucred->uc_suppgids[0] = -1; - ucred->uc_suppgids[1] = -1; + struct lu_ucred *uc = mdt_ucred(info); + struct mdt_device *mdt = info->mti_mdt; + struct md_identity *identity = NULL; + + if (!is_identity_get_disabled(mdt->mdt_identity_cache)) { + identity = mdt_identity_get(mdt->mdt_identity_cache, + uc->uc_fsuid); + if (IS_ERR(identity)) { + if (unlikely(PTR_ERR(identity) == -EREMCHG || + uc->uc_cap & CFS_CAP_FS_MASK)) { + identity = NULL; + } else { + CDEBUG(D_SEC, "Deny access without identity: " + "uid %u\n", uc->uc_fsuid); + RETURN(-EACCES); + } + } } -} + uc->uc_identity = identity; + + if (nodemap && uc->uc_o_uid == nodemap->nm_squash_uid) { + uc->uc_fsuid = nodemap->nm_squash_uid; + uc->uc_fsgid = nodemap->nm_squash_gid; + uc->uc_cap = 0; + uc->uc_suppgids[0] = -1; + uc->uc_suppgids[1] = -1; + } + + /* process root_squash here. */ + mdt_root_squash(info, mdt_info_req(info)->rq_peer.nid); + + /* remove fs privilege for non-root user. */ + if (uc->uc_fsuid && drop_fs_cap) + uc->uc_cap &= ~CFS_CAP_FS_MASK; + uc->uc_valid = UCRED_OLD; + ucred_set_jobid(info, uc); + return 0; +} static int old_init_ucred(struct mdt_thread_info *info, - struct mdt_body *body) + struct mdt_body *body, bool drop_fs_cap) { - struct lu_ucred *uc = mdt_ucred(info); - struct mdt_device *mdt = info->mti_mdt; - struct md_identity *identity = NULL; - struct lu_nodemap *nodemap = - info->mti_exp->exp_target_data.ted_nodemap; + struct lu_ucred *uc = mdt_ucred(info); + struct lu_nodemap *nodemap; + int rc; ENTRY; + nodemap = nodemap_get_from_exp(info->mti_exp); + if (IS_ERR(nodemap)) + RETURN(PTR_ERR(nodemap)); + body->mbo_uid = nodemap_map_id(nodemap, NODEMAP_UID, NODEMAP_CLIENT_TO_FS, body->mbo_uid); body->mbo_gid = nodemap_map_id(nodemap, NODEMAP_GID, @@ -504,46 +539,25 @@ static int old_init_ucred(struct mdt_thread_info *info, uc->uc_suppgids[0] = body->mbo_suppgid; uc->uc_suppgids[1] = -1; uc->uc_ginfo = NULL; - if (!is_identity_get_disabled(mdt->mdt_identity_cache)) { - identity = mdt_identity_get(mdt->mdt_identity_cache, - uc->uc_fsuid); - if (IS_ERR(identity)) { - if (unlikely(PTR_ERR(identity) == -EREMCHG)) { - identity = NULL; - } else { - CDEBUG(D_SEC, "Deny access without identity: " - "uid %u\n", uc->uc_fsuid); - RETURN(-EACCES); - } - } - } - uc->uc_identity = identity; + uc->uc_cap = body->mbo_capability; - mdt_squash_nodemap_id(uc, nodemap); + rc = old_init_ucred_common(info, nodemap, drop_fs_cap); + nodemap_putref(nodemap); - /* process root_squash here. */ - mdt_root_squash(info, mdt_info_req(info)->rq_peer.nid); - - /* remove fs privilege for non-root user. */ - if (uc->uc_fsuid) - uc->uc_cap = body->mbo_capability & ~CFS_CAP_FS_MASK; - else - uc->uc_cap = body->mbo_capability; - uc->uc_valid = UCRED_OLD; - ucred_set_jobid(info, uc); - - RETURN(0); + RETURN(rc); } static int old_init_ucred_reint(struct mdt_thread_info *info) { - struct lu_ucred *uc = mdt_ucred(info); - struct mdt_device *mdt = info->mti_mdt; - struct md_identity *identity = NULL; - struct lu_nodemap *nodemap = - info->mti_exp->exp_target_data.ted_nodemap; + struct lu_ucred *uc = mdt_ucred(info); + struct lu_nodemap *nodemap; + int rc; ENTRY; + nodemap = nodemap_get_from_exp(info->mti_exp); + if (IS_ERR(nodemap)) + RETURN(PTR_ERR(nodemap)); + LASSERT(uc != NULL); uc->uc_fsuid = nodemap_map_id(nodemap, NODEMAP_UID, @@ -556,65 +570,62 @@ static int old_init_ucred_reint(struct mdt_thread_info *info) uc->uc_o_gid = uc->uc_o_fsgid = uc->uc_gid = uc->uc_fsgid; uc->uc_ginfo = NULL; - if (!is_identity_get_disabled(mdt->mdt_identity_cache)) { - identity = mdt_identity_get(mdt->mdt_identity_cache, - uc->uc_fsuid); - if (IS_ERR(identity)) { - if (unlikely(PTR_ERR(identity) == -EREMCHG)) { - identity = NULL; - } else { - CDEBUG(D_SEC, "Deny access without identity: " - "uid %u\n", uc->uc_fsuid); - RETURN(-EACCES); - } - } - } - uc->uc_identity = identity; - - /* process root_squash here. */ - mdt_root_squash(info, mdt_info_req(info)->rq_peer.nid); + rc = old_init_ucred_common(info, nodemap, true); /* drop_fs_cap=true */ + nodemap_putref(nodemap); - /* remove fs privilege for non-root user. */ - if (uc->uc_fsuid) - uc->uc_cap &= ~CFS_CAP_FS_MASK; - uc->uc_valid = UCRED_OLD; - ucred_set_jobid(info, uc); - - RETURN(0); + RETURN(rc); } -int mdt_init_ucred(struct mdt_thread_info *info, struct mdt_body *body) +static inline int __mdt_init_ucred(struct mdt_thread_info *info, + struct mdt_body *body, + bool drop_fs_cap) { - struct ptlrpc_request *req = mdt_info_req(info); - struct lu_ucred *uc = mdt_ucred(info); + struct ptlrpc_request *req = mdt_info_req(info); + struct lu_ucred *uc = mdt_ucred(info); LASSERT(uc != NULL); if ((uc->uc_valid == UCRED_OLD) || (uc->uc_valid == UCRED_NEW)) return 0; - mdt_exit_ucred(info); + mdt_exit_ucred(info); - if (!req->rq_auth_gss || req->rq_auth_usr_mdt || !req->rq_user_desc) - return old_init_ucred(info, body); - else - return new_init_ucred(info, BODY_INIT, body); + if (!req->rq_auth_gss || req->rq_auth_usr_mdt || !req->rq_user_desc) + return old_init_ucred(info, body, drop_fs_cap); + else + return new_init_ucred(info, BODY_INIT, body, drop_fs_cap); +} + +int mdt_init_ucred(struct mdt_thread_info *info, struct mdt_body *body) +{ + return __mdt_init_ucred(info, body, true); +} + +/* LU-6528 when "no_subtree_check" is set for NFS export, nfsd_set_fh_dentry() + * doesn't set correct fsuid explicitely, but raise capability to allow + * exportfs_decode_fh() to reconnect disconnected dentry into dcache. So for + * lookup (i.e. intent_getattr), we should keep FS capability, otherwise it + * will fail permission check. */ +int mdt_init_ucred_intent_getattr(struct mdt_thread_info *info, + struct mdt_body *body) +{ + return __mdt_init_ucred(info, body, false); } int mdt_init_ucred_reint(struct mdt_thread_info *info) { - struct ptlrpc_request *req = mdt_info_req(info); + struct ptlrpc_request *req = mdt_info_req(info); struct lu_ucred *uc = mdt_ucred(info); LASSERT(uc != NULL); if ((uc->uc_valid == UCRED_OLD) || (uc->uc_valid == UCRED_NEW)) return 0; - mdt_exit_ucred(info); + mdt_exit_ucred(info); - if (!req->rq_auth_gss || req->rq_auth_usr_mdt || !req->rq_user_desc) - return old_init_ucred_reint(info); - else - return new_init_ucred(info, REC_INIT, NULL); + if (!req->rq_auth_gss || req->rq_auth_usr_mdt || !req->rq_user_desc) + return old_init_ucred_reint(info); + else + return new_init_ucred(info, REC_INIT, NULL, true); } /* copied from lov/lov_ea.c, just for debugging, will be removed later */ @@ -905,8 +916,7 @@ static int mdt_setattr_unpack_rec(struct mdt_thread_info *info) struct req_capsule *pill = info->mti_pill; struct mdt_reint_record *rr = &info->mti_rr; struct mdt_rec_setattr *rec; - struct lu_nodemap *nodemap = - info->mti_exp->exp_target_data.ted_nodemap; + struct lu_nodemap *nodemap; ENTRY; CLASSERT(sizeof(struct mdt_rec_setattr)== sizeof(struct mdt_rec_reint)); @@ -925,10 +935,17 @@ static int mdt_setattr_unpack_rec(struct mdt_thread_info *info) la->la_valid = mdt_attr_valid_xlate(rec->sa_valid, rr, ma); la->la_mode = rec->sa_mode; la->la_flags = rec->sa_attr_flags; + + nodemap = nodemap_get_from_exp(info->mti_exp); + if (IS_ERR(nodemap)) + RETURN(PTR_ERR(nodemap)); + la->la_uid = nodemap_map_id(nodemap, NODEMAP_UID, NODEMAP_CLIENT_TO_FS, rec->sa_uid); la->la_gid = nodemap_map_id(nodemap, NODEMAP_GID, NODEMAP_CLIENT_TO_FS, rec->sa_gid); + nodemap_putref(nodemap); + la->la_size = rec->sa_size; la->la_blocks = rec->sa_blocks; la->la_ctime = rec->sa_ctime; @@ -946,6 +963,11 @@ static int mdt_setattr_unpack_rec(struct mdt_thread_info *info) else ma->ma_attr_flags &= ~MDS_HSM_RELEASE; + if (rec->sa_bias & MDS_CLOSE_LAYOUT_SWAP) + ma->ma_attr_flags |= MDS_CLOSE_LAYOUT_SWAP; + else + ma->ma_attr_flags &= ~MDS_CLOSE_LAYOUT_SWAP; + RETURN(0); } @@ -963,7 +985,7 @@ static int mdt_close_handle_unpack(struct mdt_thread_info *info) if (ioepoch == NULL) RETURN(-EPROTO); - info->mti_close_handle = ioepoch->handle; + info->mti_close_handle = ioepoch->mio_handle; RETURN(0); } @@ -1018,16 +1040,16 @@ static int mdt_setattr_unpack(struct mdt_thread_info *info) RETURN(rc); } -static int mdt_hsm_release_unpack(struct mdt_thread_info *info) +static int mdt_intent_close_unpack(struct mdt_thread_info *info) { struct md_attr *ma = &info->mti_attr; - struct req_capsule *pill = info->mti_pill; + struct req_capsule *pill = info->mti_pill; ENTRY; - if (!(ma->ma_attr_flags & MDS_HSM_RELEASE)) + if (!(ma->ma_attr_flags & (MDS_HSM_RELEASE | MDS_CLOSE_LAYOUT_SWAP))) RETURN(0); - req_capsule_extend(pill, &RQF_MDS_RELEASE_CLOSE); + req_capsule_extend(pill, &RQF_MDS_INTENT_CLOSE); if (!(req_capsule_has_field(pill, &RMF_CLOSE_DATA, RCL_CLIENT) && req_capsule_field_present(pill, &RMF_CLOSE_DATA, RCL_CLIENT))) @@ -1049,7 +1071,7 @@ int mdt_close_unpack(struct mdt_thread_info *info) if (rc) RETURN(rc); - rc = mdt_hsm_release_unpack(info); + rc = mdt_intent_close_unpack(info); if (rc) RETURN(rc); @@ -1263,6 +1285,14 @@ static int mdt_rename_unpack(struct mdt_thread_info *info) else ma->ma_attr_flags &= ~MDS_VTX_BYPASS; + if (rec->rn_bias & MDS_RENAME_MIGRATE) { + req_capsule_extend(info->mti_pill, &RQF_MDS_REINT_MIGRATE); + rc = mdt_close_handle_unpack(info); + if (rc < 0) + RETURN(rc); + info->mti_spec.sp_migrate_close = 1; + } + info->mti_spec.no_create = !!req_is_replay(mdt_info_req(info));