From: Lai Siyao Date: Fri, 29 May 2015 01:59:45 +0000 (+0800) Subject: LU-6528 mdt: keep FS capability for intent_getattr X-Git-Tag: 2.7.55~15 X-Git-Url: https://git.whamcloud.com/?a=commitdiff_plain;h=a55aebd70e9073ef1d1bd7de280c8393af0ea30d;p=fs%2Flustre-release.git LU-6528 mdt: keep FS capability for intent_getattr 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 on MDS, otherwise it will fail permission check. Signed-off-by: Lai Siyao Change-Id: I99e2caeec06239a1df39918cbd6e9213e37ec758 Reviewed-on: http://review.whamcloud.com/14978 Tested-by: Jenkins Tested-by: Maloo Reviewed-by: Niu Yawei Reviewed-by: Bobi Jam Reviewed-by: Oleg Drokin --- diff --git a/lustre/mdd/mdd_permission.c b/lustre/mdd/mdd_permission.c index 750df8d..f082d41 100644 --- a/lustre/mdd/mdd_permission.c +++ b/lustre/mdd/mdd_permission.c @@ -298,6 +298,9 @@ check_capabilities: if (md_capable(uc, CFS_CAP_DAC_READ_SEARCH)) RETURN(0); + CDEBUG(D_SEC, "permission denied, mode %x, fsuid %u, uid %u\n", + la->la_mode, uc->uc_fsuid, la->la_uid); + RETURN(-EACCES); } diff --git a/lustre/mdt/mdt_handler.c b/lustre/mdt/mdt_handler.c index a2cc964..381f056 100644 --- a/lustre/mdt/mdt_handler.c +++ b/lustre/mdt/mdt_handler.c @@ -3123,9 +3123,9 @@ static int mdt_intent_getattr(enum mdt_it_code opcode, GOTO(out_shrink, rc = -EINVAL); } - rc = mdt_init_ucred(info, reqbody); - if (rc) - GOTO(out_shrink, rc); + rc = mdt_init_ucred_intent_getattr(info, reqbody); + if (rc) + GOTO(out_shrink, rc); ldlm_rep = req_capsule_server_get(info->mti_pill, &RMF_DLM_REP); mdt_set_disposition(info, ldlm_rep, DISP_IT_EXECD); diff --git a/lustre/mdt/mdt_internal.h b/lustre/mdt/mdt_internal.h index 61816a0..042bc50 100644 --- a/lustre/mdt/mdt_internal.h +++ b/lustre/mdt/mdt_internal.h @@ -707,6 +707,7 @@ void mdt_dump_lmv(unsigned int level, const union lmv_mds_md *lmv); bool allow_client_chgrp(struct mdt_thread_info *info, struct lu_ucred *uc); int mdt_check_ucred(struct mdt_thread_info *); int mdt_init_ucred(struct mdt_thread_info *, struct mdt_body *); +int mdt_init_ucred_intent_getattr(struct mdt_thread_info *, struct mdt_body *); int mdt_init_ucred_reint(struct mdt_thread_info *); void mdt_exit_ucred(struct mdt_thread_info *); int mdt_version_get_check(struct mdt_thread_info *, struct mdt_object *, int); diff --git a/lustre/mdt/mdt_lib.c b/lustre/mdt/mdt_lib.c index a5cc692..984cfa2 100644 --- a/lustre/mdt/mdt_lib.c +++ b/lustre/mdt/mdt_lib.c @@ -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; @@ -294,7 +294,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; @@ -477,7 +477,7 @@ static void mdt_squash_nodemap_id(struct lu_ucred *ucred, 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; @@ -525,7 +525,7 @@ static int old_init_ucred(struct mdt_thread_info *info, mdt_root_squash(info, mdt_info_req(info)->rq_peer.nid); /* remove fs privilege for non-root user. */ - if (uc->uc_fsuid) + if (uc->uc_fsuid && drop_fs_cap) uc->uc_cap = body->mbo_capability & ~CFS_CAP_FS_MASK; else uc->uc_cap = body->mbo_capability; @@ -583,38 +583,56 @@ static int old_init_ucred_reint(struct mdt_thread_info *info) RETURN(0); } -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 */