From 031f1e8db5d31c6887b094ca8c2825620be34071 Mon Sep 17 00:00:00 2001 From: Etienne AUJAMES Date: Thu, 26 Oct 2023 21:28:55 +0200 Subject: [PATCH] LU-16566 sptlrpc: remove rq_sepol from ptlrpc_request This patch remove rq_sepol from ptlrpc_request to reduce the memory consumption on the servers. rq_sepol field is 327 bytes long allocated for each request and this is rarely used (it needs SELinux activated with the send_sepol feature). The patch store the SELinux policy status string in a separate object. The pointer is stored in ptlrpc_sec->ps_sepol and protected by RCU (mostly read-only, the SELinux policy should rarely change). When the policy status needs to be packed in a request, we take a reference to the current ps_sepol object and release it after the packing. If the policy has changed in the meantime, the object used will be free after. A read operation is added to srpc_sepol parameter to return the SELinux policy string cached in Lustre. Lustre-change: https://review.whamcloud.com/52845 Lustre-commit: 3f70481c93dcabbb30267608a0054f4d7092e0db Test-Parameters: testlist=sanity-selinux env=ONLY=21,ONLY_REPEAT=50 Test-Parameters: testlist=sanity-selinux env=ONLY=21,ONLY_REPEAT=50 Signed-off-by: Etienne AUJAMES Change-Id: I80fb76c97885c4b2987eb7f91a9bfe6e0e6e6c70 Reviewed-by: Sebastien Buisson Reviewed-by: Andreas Dilger Reviewed-on: https://review.whamcloud.com/c/ex/lustre-release/+/55211 Tested-by: jenkins Tested-by: Maloo --- lustre/include/lustre_net.h | 7 - lustre/include/lustre_sec.h | 36 +++-- lustre/mdc/mdc_internal.h | 18 ++- lustre/mdc/mdc_lib.c | 33 +++-- lustre/mdc/mdc_locks.c | 57 ++++---- lustre/mdc/mdc_reint.c | 297 ++++++++++++++++++++++------------------ lustre/mdc/mdc_request.c | 94 +++++++------ lustre/ptlrpc/gss/gss_keyring.c | 1 + lustre/ptlrpc/gss/sec_gss.c | 3 - lustre/ptlrpc/import.c | 14 +- lustre/ptlrpc/sec.c | 119 +++++++++++----- lustre/ptlrpc/sec_lproc.c | 108 +++++++++++++-- lustre/ptlrpc/sec_null.c | 18 ++- 13 files changed, 497 insertions(+), 308 deletions(-) diff --git a/lustre/include/lustre_net.h b/lustre/include/lustre_net.h index b306a44..ef3aec0 100644 --- a/lustre/include/lustre_net.h +++ b/lustre/include/lustre_net.h @@ -1061,13 +1061,6 @@ struct ptlrpc_request { /** description of flavors for client & server */ struct sptlrpc_flavor rq_flvr; - /** - * SELinux policy info at the time of the request - * sepol string format is: - * ::: - */ - char rq_sepol[LUSTRE_NODEMAP_SEPOL_LENGTH + 1]; - /* client/server security flags */ unsigned int rq_ctx_init:1, /* context initiation */ diff --git a/lustre/include/lustre_sec.h b/lustre/include/lustre_sec.h index 8b3118a..8c4d33e 100644 --- a/lustre/include/lustre_sec.h +++ b/lustre/include/lustre_sec.h @@ -849,6 +849,20 @@ struct ptlrpc_sec_policy { #define PTLRPC_SEC_FL_BULK 0x0008 /* intensive bulk i/o expected */ #define PTLRPC_SEC_FL_PAG 0x0010 /* PAG mode */ +struct sptlrpc_sepol { + struct rcu_head ssp_rcu; + struct kref ssp_ref; + /** mtime of SELinux policy file */ + ktime_t ssp_mtime; + /** + * SELinux policy info + * sepol string format is: + * ::: + */ + __u32 ssp_sepol_size; + char ssp_sepol[0]; +}; + /** * The ptlrpc_sec represents the client side ptlrpc security facilities, * each obd_import (both regular and reverse import) must associate with @@ -870,17 +884,10 @@ struct ptlrpc_sec { /** owning import */ struct obd_import *ps_import; spinlock_t ps_lock; - /** mtime of SELinux policy file */ - ktime_t ps_sepol_mtime; /** next check time of SELinux policy file */ ktime_t ps_sepol_checknext; - /** - * SELinux policy info - * sepol string format is: - * ::: - */ - char ps_sepol[LUSTRE_NODEMAP_SEPOL_LENGTH - + 1]; + /** SELinux policy file information */ + struct sptlrpc_sepol *ps_sepol; /* * garbage collection @@ -1098,9 +1105,16 @@ int sptlrpc_cli_enlarge_reqbuf(struct ptlrpc_request *req, int sptlrpc_cli_unwrap_early_reply(struct ptlrpc_request *req, struct ptlrpc_request **req_ret); void sptlrpc_cli_finish_early_reply(struct ptlrpc_request *early_req); - void sptlrpc_request_out_callback(struct ptlrpc_request *req); -int sptlrpc_get_sepol(struct ptlrpc_request *req); + +static inline size_t sptlrpc_sepol_size(struct sptlrpc_sepol *sepol) +{ + return sepol ? sepol->ssp_sepol_size : 0; +} + +void sptlrpc_sepol_put(struct sptlrpc_sepol *pol); +struct sptlrpc_sepol *sptlrpc_sepol_get_cached(struct ptlrpc_sec *imp_sec); +struct sptlrpc_sepol *sptlrpc_sepol_get(struct ptlrpc_request *req); /* * exported higher interface of import & request diff --git a/lustre/mdc/mdc_internal.h b/lustre/mdc/mdc_internal.h index 37033b5..2098d9f 100644 --- a/lustre/mdc/mdc_internal.h +++ b/lustre/mdc/mdc_internal.h @@ -49,22 +49,26 @@ void mdc_setattr_pack(struct req_capsule *pill, struct md_op_data *op_data, void *ea, size_t ealen); void mdc_create_pack(struct req_capsule *pill, struct md_op_data *op_data, const void *data, size_t datalen, umode_t mode, - uid_t uid, gid_t gid, kernel_cap_t capability, u64 rdev); + uid_t uid, gid_t gid, kernel_cap_t cap_effective, u64 rdev, + struct sptlrpc_sepol *sepol); void mdc_open_pack(struct req_capsule *pill, struct md_op_data *op_data, - umode_t mode, __u64 rdev, __u64 flags, - const void *data, size_t datalen); + umode_t mode, __u64 rdev, __u64 flags, const void *lmm, + size_t lmmlen, struct sptlrpc_sepol *sepol); void mdc_file_secctx_pack(struct req_capsule *pill, const char *secctx_name, const void *secctx, size_t secctx_size); void mdc_file_encctx_pack(struct req_capsule *pill, const void *encctx, size_t encctx_size); -void mdc_file_sepol_pack(struct req_capsule *pill); +void mdc_file_sepol_pack(struct req_capsule *pill, struct sptlrpc_sepol *p); -void mdc_unlink_pack(struct req_capsule *pill, struct md_op_data *op_data); -void mdc_link_pack(struct req_capsule *pill, struct md_op_data *op_data); +void mdc_unlink_pack(struct req_capsule *pill, struct md_op_data *op_data, + struct sptlrpc_sepol *sepol); +void mdc_link_pack(struct req_capsule *pill, struct md_op_data *op_data, + struct sptlrpc_sepol *sepol); void mdc_rename_pack(struct req_capsule *pill, struct md_op_data *op_data, const char *old, size_t oldlen, - const char *new, size_t newlen); + const char *new, size_t newlen, + struct sptlrpc_sepol *sepol); void mdc_migrate_pack(struct req_capsule *pill, struct md_op_data *op_data, const char *name, size_t namelen); void mdc_close_pack(struct req_capsule *pill, struct md_op_data *op_data); diff --git a/lustre/mdc/mdc_lib.c b/lustre/mdc/mdc_lib.c index 62b9bd0..05de8d0 100644 --- a/lustre/mdc/mdc_lib.c +++ b/lustre/mdc/mdc_lib.c @@ -163,21 +163,20 @@ void mdc_file_encctx_pack(struct req_capsule *pill, memcpy(buf, encctx, buf_size); } -void mdc_file_sepol_pack(struct req_capsule *pill) +void mdc_file_sepol_pack(struct req_capsule *pill, struct sptlrpc_sepol *p) { void *buf; size_t buf_size; - struct ptlrpc_request *req = pill->rc_req; - if (strlen(req->rq_sepol) == 0) + if (!p || !p->ssp_sepol_size) return; buf = req_capsule_client_get(pill, &RMF_SELINUX_POL); buf_size = req_capsule_get_size(pill, &RMF_SELINUX_POL, RCL_CLIENT); - LASSERT(buf_size == strlen(req->rq_sepol) + 1); - snprintf(buf, strlen(req->rq_sepol) + 1, "%s", req->rq_sepol); + LASSERT(buf_size == p->ssp_sepol_size); + strscpy(buf, p->ssp_sepol, p->ssp_sepol_size); } void mdc_readdir_pack(struct req_capsule *pill, __u64 pgoff, size_t size, @@ -196,7 +195,8 @@ void mdc_readdir_pack(struct req_capsule *pill, __u64 pgoff, size_t size, /* packing of MDS records */ void mdc_create_pack(struct req_capsule *pill, struct md_op_data *op_data, const void *data, size_t datalen, umode_t mode, - uid_t uid, gid_t gid, kernel_cap_t cap_effective, u64 rdev) + uid_t uid, gid_t gid, kernel_cap_t cap_effective, u64 rdev, + struct sptlrpc_sepol *sepol) { struct mdt_rec_create *rec; char *tmp; @@ -243,7 +243,7 @@ void mdc_create_pack(struct req_capsule *pill, struct md_op_data *op_data, op_data->op_file_encctx_size); /* pack SELinux policy info if any */ - mdc_file_sepol_pack(pill); + mdc_file_sepol_pack(pill, sepol); } static inline __u64 mds_pack_open_flags(__u64 flags) @@ -282,7 +282,7 @@ static inline __u64 mds_pack_open_flags(__u64 flags) /* packing of MDS records */ void mdc_open_pack(struct req_capsule *pill, struct md_op_data *op_data, umode_t mode, __u64 rdev, __u64 flags, const void *lmm, - size_t lmmlen) + size_t lmmlen, struct sptlrpc_sepol *sepol) { struct mdt_rec_create *rec; char *tmp; @@ -326,7 +326,7 @@ void mdc_open_pack(struct req_capsule *pill, struct md_op_data *op_data, op_data->op_file_encctx_size); /* pack SELinux policy info if any */ - mdc_file_sepol_pack(pill); + mdc_file_sepol_pack(pill, sepol); } if (lmm) { @@ -457,7 +457,8 @@ void mdc_setattr_pack(struct req_capsule *pill, struct md_op_data *op_data, } } -void mdc_unlink_pack(struct req_capsule *pill, struct md_op_data *op_data) +void mdc_unlink_pack(struct req_capsule *pill, struct md_op_data *op_data, + struct sptlrpc_sepol *sepol) { struct mdt_rec_unlink *rec; @@ -482,10 +483,11 @@ void mdc_unlink_pack(struct req_capsule *pill, struct md_op_data *op_data) mdc_pack_name(pill, &RMF_NAME, op_data->op_name, op_data->op_namelen); /* pack SELinux policy info if any */ - mdc_file_sepol_pack(pill); + mdc_file_sepol_pack(pill, sepol); } -void mdc_link_pack(struct req_capsule *pill, struct md_op_data *op_data) +void mdc_link_pack(struct req_capsule *pill, struct md_op_data *op_data, + struct sptlrpc_sepol *sepol) { struct mdt_rec_link *rec; @@ -508,7 +510,7 @@ void mdc_link_pack(struct req_capsule *pill, struct md_op_data *op_data) mdc_pack_name(pill, &RMF_NAME, op_data->op_name, op_data->op_namelen); /* pack SELinux policy info if any */ - mdc_file_sepol_pack(pill); + mdc_file_sepol_pack(pill, sepol); } static void mdc_close_intent_pack(struct req_capsule *pill, @@ -558,7 +560,8 @@ static void mdc_close_intent_pack(struct req_capsule *pill, void mdc_rename_pack(struct req_capsule *pill, struct md_op_data *op_data, const char *old, size_t oldlen, - const char *new, size_t newlen) + const char *new, size_t newlen, + struct sptlrpc_sepol *sepol) { struct mdt_rec_rename *rec; @@ -585,7 +588,7 @@ void mdc_rename_pack(struct req_capsule *pill, struct md_op_data *op_data, mdc_pack_name(pill, &RMF_SYMTGT, new, newlen); /* pack SELinux policy info if any */ - mdc_file_sepol_pack(pill); + mdc_file_sepol_pack(pill, sepol); } void mdc_migrate_pack(struct req_capsule *pill, struct md_op_data *op_data, diff --git a/lustre/mdc/mdc_locks.c b/lustre/mdc/mdc_locks.c index 29629a7..4dc0696 100644 --- a/lustre/mdc/mdc_locks.c +++ b/lustre/mdc/mdc_locks.c @@ -259,6 +259,7 @@ mdc_intent_open_pack(struct obd_export *exp, struct lookup_intent *it, int count = 0; enum ldlm_mode mode; int repsize, repsize_estimate; + struct sptlrpc_sepol *sepol; int rc; ENTRY; @@ -328,20 +329,16 @@ mdc_intent_open_pack(struct obd_export *exp, struct lookup_intent *it, op_data->op_file_encctx_size); /* get SELinux policy info if any */ - rc = sptlrpc_get_sepol(req); - if (rc < 0) { - ptlrpc_request_free(req); - RETURN(ERR_PTR(rc)); - } + sepol = sptlrpc_sepol_get(req); + if (IS_ERR(sepol)) + GOTO(err_free_rq, rc = PTR_ERR(sepol)); + req_capsule_set_size(&req->rq_pill, &RMF_SELINUX_POL, RCL_CLIENT, - strlen(req->rq_sepol) ? - strlen(req->rq_sepol) + 1 : 0); + sptlrpc_sepol_size(sepol)); rc = ldlm_prep_enqueue_req(exp, req, &cancels, count); - if (rc < 0) { - ptlrpc_request_free(req); - RETURN(ERR_PTR(rc)); - } + if (rc < 0) + GOTO(err_put_sepol, rc); spin_lock(&req->rq_lock); req->rq_replay = req->rq_import->imp_replayable; @@ -353,7 +350,9 @@ mdc_intent_open_pack(struct obd_export *exp, struct lookup_intent *it, /* pack the intended request */ mdc_open_pack(&req->rq_pill, op_data, it->it_create_mode, 0, - it->it_flags, lmm, lmmsize); + it->it_flags, lmm, lmmsize, sepol); + + sptlrpc_sepol_put(sepol); req_capsule_set_size(&req->rq_pill, &RMF_MDT_MD, RCL_SERVER, mdt_md_capsule_size); @@ -433,6 +432,12 @@ mdc_intent_open_pack(struct obd_export *exp, struct lookup_intent *it, */ req->rq_reqmsg->lm_repsize = repsize; RETURN(req); + +err_put_sepol: + sptlrpc_sepol_put(sepol); +err_free_rq: + ptlrpc_request_free(req); + return ERR_PTR(rc); } #define GA_DEFAULT_EA_NAME_LEN 20 @@ -445,6 +450,7 @@ mdc_intent_getxattr_pack(struct obd_export *exp, struct lookup_intent *it, { struct ptlrpc_request *req; struct ldlm_intent *lit; + struct sptlrpc_sepol *sepol; int rc, count = 0; LIST_HEAD(cancels); u32 ea_vals_buf_size = GA_DEFAULT_EA_VAL_LEN * GA_DEFAULT_EA_NUM; @@ -456,20 +462,16 @@ mdc_intent_getxattr_pack(struct obd_export *exp, struct lookup_intent *it, RETURN(ERR_PTR(-ENOMEM)); /* get SELinux policy info if any */ - rc = sptlrpc_get_sepol(req); - if (rc < 0) { - ptlrpc_request_free(req); - RETURN(ERR_PTR(rc)); - } + sepol = sptlrpc_sepol_get(req); + if (IS_ERR(sepol)) + GOTO(err_free_rq, rc = PTR_ERR(sepol)); + req_capsule_set_size(&req->rq_pill, &RMF_SELINUX_POL, RCL_CLIENT, - strlen(req->rq_sepol) ? - strlen(req->rq_sepol) + 1 : 0); + sptlrpc_sepol_size(sepol)); rc = ldlm_prep_enqueue_req(exp, req, &cancels, count); - if (rc) { - ptlrpc_request_free(req); - RETURN(ERR_PTR(rc)); - } + if (rc) + GOTO(err_put_sepol, rc); /* pack the intent */ lit = req_capsule_client_get(&req->rq_pill, &RMF_LDLM_INTENT); @@ -499,7 +501,8 @@ mdc_intent_getxattr_pack(struct obd_export *exp, struct lookup_intent *it, ea_vals_buf_size, -1, 0); /* get SELinux policy info if any */ - mdc_file_sepol_pack(&req->rq_pill); + mdc_file_sepol_pack(&req->rq_pill, sepol); + sptlrpc_sepol_put(sepol); req_capsule_set_size(&req->rq_pill, &RMF_EADATA, RCL_SERVER, GA_DEFAULT_EA_NAME_LEN * GA_DEFAULT_EA_NUM); @@ -515,6 +518,12 @@ mdc_intent_getxattr_pack(struct obd_export *exp, struct lookup_intent *it, ptlrpc_request_set_replen(req); RETURN(req); + +err_put_sepol: + sptlrpc_sepol_put(sepol); +err_free_rq: + ptlrpc_request_free(req); + RETURN(ERR_PTR(rc)); } static struct ptlrpc_request * diff --git a/lustre/mdc/mdc_reint.c b/lustre/mdc/mdc_reint.c index 65fa922..5eb0cb5 100644 --- a/lustre/mdc/mdc_reint.c +++ b/lustre/mdc/mdc_reint.c @@ -164,13 +164,14 @@ int mdc_create(struct obd_export *exp, struct md_op_data *op_data, kernel_cap_t cap_effective, __u64 rdev, struct ptlrpc_request **request) { - struct ptlrpc_request *req; - int level, rc; - int count, resends = 0; - struct obd_import *import = exp->exp_obd->u.cli.cl_import; - int generation = import->imp_generation; + struct ptlrpc_request *req; + struct sptlrpc_sepol *sepol; + int level, rc; + int count, resends = 0; + struct obd_import *import = exp->exp_obd->u.cli.cl_import; + int generation = import->imp_generation; LIST_HEAD(cancels); - ENTRY; + ENTRY; /* For case if upper layer did not alloc fid, do it now. */ if (!fid_is_sane(&op_data->op_fid2)) { @@ -184,24 +185,24 @@ int mdc_create(struct obd_export *exp, struct md_op_data *op_data, } rebuild: - count = 0; - if ((op_data->op_flags & MF_MDC_CANCEL_FID1) && - (fid_is_sane(&op_data->op_fid1))) - count = mdc_resource_get_unused(exp, &op_data->op_fid1, - &cancels, LCK_EX, - MDS_INODELOCK_UPDATE); + count = 0; + if ((op_data->op_flags & MF_MDC_CANCEL_FID1) && + (fid_is_sane(&op_data->op_fid1))) + count = mdc_resource_get_unused(exp, &op_data->op_fid1, + &cancels, LCK_EX, + MDS_INODELOCK_UPDATE); - req = ptlrpc_request_alloc(class_exp2cliimp(exp), + req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_MDS_REINT_CREATE_ACL); - if (req == NULL) { - ldlm_lock_list_put(&cancels, l_bl_ast, count); - RETURN(-ENOMEM); - } + if (req == NULL) { + ldlm_lock_list_put(&cancels, l_bl_ast, count); + RETURN(-ENOMEM); + } - req_capsule_set_size(&req->rq_pill, &RMF_NAME, RCL_CLIENT, - op_data->op_namelen + 1); - req_capsule_set_size(&req->rq_pill, &RMF_EADATA, RCL_CLIENT, - data && datalen ? datalen : 0); + req_capsule_set_size(&req->rq_pill, &RMF_NAME, RCL_CLIENT, + op_data->op_namelen + 1); + req_capsule_set_size(&req->rq_pill, &RMF_EADATA, RCL_CLIENT, + data && datalen ? datalen : 0); req_capsule_set_size(&req->rq_pill, &RMF_FILE_SECCTX_NAME, RCL_CLIENT, op_data->op_file_secctx_name != NULL ? @@ -214,48 +215,46 @@ rebuild: op_data->op_file_encctx_size); /* get SELinux policy info if any */ - rc = sptlrpc_get_sepol(req); - if (rc < 0) { - ptlrpc_request_free(req); - RETURN(rc); - } + sepol = sptlrpc_sepol_get(req); + if (IS_ERR(sepol)) + GOTO(err_free_rq, rc = PTR_ERR(sepol)); + req_capsule_set_size(&req->rq_pill, &RMF_SELINUX_POL, RCL_CLIENT, - strlen(req->rq_sepol) ? - strlen(req->rq_sepol) + 1 : 0); + sptlrpc_sepol_size(sepol)); rc = mdc_prep_elc_req(exp, req, MDS_REINT, &cancels, count); - if (rc) { - ptlrpc_request_free(req); - RETURN(rc); - } + if (rc) + GOTO(err_put_sepol, rc); - /* - * mdc_create_pack() fills msg->bufs[1] with name and msg->bufs[2] with - * tgt, for symlinks or lov MD data. - */ + /* + * mdc_create_pack() fills msg->bufs[1] with name and msg->bufs[2] with + * tgt, for symlinks or lov MD data. + */ mdc_create_pack(&req->rq_pill, op_data, data, datalen, mode, uid, - gid, cap_effective, rdev); + gid, cap_effective, rdev, sepol); - ptlrpc_request_set_replen(req); + sptlrpc_sepol_put(sepol); + + ptlrpc_request_set_replen(req); /* ask ptlrpc not to resend on EINPROGRESS since we have our own retry * logic here */ req->rq_no_retry_einprogress = 1; - if (resends) { - req->rq_generation_set = 1; - req->rq_import_generation = generation; + if (resends) { + req->rq_generation_set = 1; + req->rq_import_generation = generation; req->rq_sent = ktime_get_real_seconds() + resends; - } - level = LUSTRE_IMP_FULL; + } + level = LUSTRE_IMP_FULL; resend: rc = mdc_reint(req, level); - /* Resend if we were told to. */ - if (rc == -ERESTARTSYS) { - level = LUSTRE_IMP_RECOVER; - goto resend; - } else if (rc == -EINPROGRESS) { + /* Resend if we were told to. */ + if (rc == -ERESTARTSYS) { + level = LUSTRE_IMP_RECOVER; + goto resend; + } else if (rc == -EINPROGRESS) { /* Retry create infinitely until succeed or get other * error code or interrupted. */ ptlrpc_req_finished(req); @@ -269,26 +268,36 @@ rebuild: PFID(&op_data->op_fid1), PFID(&op_data->op_fid2)); goto rebuild; - } else { - CDEBUG(D_HA, "resend cross eviction\n"); - RETURN(-EIO); - } - } + } else { + CDEBUG(D_HA, "resend cross eviction\n"); + RETURN(-EIO); + } + } - *request = req; - RETURN(rc); + *request = req; + + RETURN(rc); + +err_put_sepol: + sptlrpc_sepol_put(sepol); +err_free_rq: + ptlrpc_request_free(req); + + RETURN(rc); } int mdc_unlink(struct obd_export *exp, struct md_op_data *op_data, - struct ptlrpc_request **request) + struct ptlrpc_request **request) { LIST_HEAD(cancels); - struct obd_device *obd = class_exp2obd(exp); - struct ptlrpc_request *req = *request; - int count = 0, rc; - ENTRY; + struct obd_device *obd = class_exp2obd(exp); + struct ptlrpc_request *req = *request; + struct sptlrpc_sepol *sepol; + int count = 0, rc; - LASSERT(req == NULL); + ENTRY; + + LASSERT(req == NULL); if ((op_data->op_flags & MF_MDC_CANCEL_FID1) && (fid_is_sane(&op_data->op_fid1))) @@ -304,99 +313,111 @@ int mdc_unlink(struct obd_export *exp, struct md_op_data *op_data, CLI_DIRTY_DATA ? MDS_INODELOCK_ELC : MDS_INODELOCK_FULL); - req = ptlrpc_request_alloc(class_exp2cliimp(exp), - &RQF_MDS_REINT_UNLINK); - if (req == NULL) { - ldlm_lock_list_put(&cancels, l_bl_ast, count); - RETURN(-ENOMEM); - } + req = ptlrpc_request_alloc(class_exp2cliimp(exp), + &RQF_MDS_REINT_UNLINK); + if (req == NULL) { + ldlm_lock_list_put(&cancels, l_bl_ast, count); + RETURN(-ENOMEM); + } - req_capsule_set_size(&req->rq_pill, &RMF_NAME, RCL_CLIENT, - op_data->op_namelen + 1); + req_capsule_set_size(&req->rq_pill, &RMF_NAME, RCL_CLIENT, + op_data->op_namelen + 1); /* get SELinux policy info if any */ - rc = sptlrpc_get_sepol(req); - if (rc < 0) { - ptlrpc_request_free(req); - RETURN(rc); - } + sepol = sptlrpc_sepol_get(req); + if (IS_ERR(sepol)) + GOTO(err_free_rq, rc = PTR_ERR(sepol)); + req_capsule_set_size(&req->rq_pill, &RMF_SELINUX_POL, RCL_CLIENT, - strlen(req->rq_sepol) ? - strlen(req->rq_sepol) + 1 : 0); + sptlrpc_sepol_size(sepol)); rc = mdc_prep_elc_req(exp, req, MDS_REINT, &cancels, count); - if (rc) { - ptlrpc_request_free(req); - RETURN(rc); - } + if (rc) + GOTO(err_put_sepol, rc); - mdc_unlink_pack(&req->rq_pill, op_data); + mdc_unlink_pack(&req->rq_pill, op_data, sepol); + sptlrpc_sepol_put(sepol); req_capsule_set_size(&req->rq_pill, &RMF_MDT_MD, RCL_SERVER, obd->u.cli.cl_default_mds_easize); ptlrpc_request_set_replen(req); - *request = req; + *request = req; rc = mdc_reint(req, LUSTRE_IMP_FULL); - if (rc == -ERESTARTSYS) - rc = 0; - RETURN(rc); + if (rc == -ERESTARTSYS) + rc = 0; + + RETURN(rc); + +err_put_sepol: + sptlrpc_sepol_put(sepol); +err_free_rq: + ptlrpc_request_free(req); + + RETURN(rc); } int mdc_link(struct obd_export *exp, struct md_op_data *op_data, - struct ptlrpc_request **request) + struct ptlrpc_request **request) { LIST_HEAD(cancels); - struct ptlrpc_request *req; - int count = 0, rc; - ENTRY; + struct ptlrpc_request *req; + struct sptlrpc_sepol *sepol; + int count = 0, rc; - if ((op_data->op_flags & MF_MDC_CANCEL_FID2) && - (fid_is_sane(&op_data->op_fid2))) - count = mdc_resource_get_unused(exp, &op_data->op_fid2, - &cancels, LCK_EX, - MDS_INODELOCK_UPDATE); - if ((op_data->op_flags & MF_MDC_CANCEL_FID1) && - (fid_is_sane(&op_data->op_fid1))) - count += mdc_resource_get_unused(exp, &op_data->op_fid1, - &cancels, LCK_EX, - MDS_INODELOCK_UPDATE); - - req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_MDS_REINT_LINK); - if (req == NULL) { - ldlm_lock_list_put(&cancels, l_bl_ast, count); - RETURN(-ENOMEM); - } + ENTRY; - req_capsule_set_size(&req->rq_pill, &RMF_NAME, RCL_CLIENT, - op_data->op_namelen + 1); + if ((op_data->op_flags & MF_MDC_CANCEL_FID2) && + (fid_is_sane(&op_data->op_fid2))) + count = mdc_resource_get_unused(exp, &op_data->op_fid2, + &cancels, LCK_EX, + MDS_INODELOCK_UPDATE); + if ((op_data->op_flags & MF_MDC_CANCEL_FID1) && + (fid_is_sane(&op_data->op_fid1))) + count += mdc_resource_get_unused(exp, &op_data->op_fid1, + &cancels, LCK_EX, + MDS_INODELOCK_UPDATE); - /* get SELinux policy info if any */ - rc = sptlrpc_get_sepol(req); - if (rc < 0) { - ptlrpc_request_free(req); - RETURN(rc); + req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_MDS_REINT_LINK); + if (req == NULL) { + ldlm_lock_list_put(&cancels, l_bl_ast, count); + RETURN(-ENOMEM); } + + req_capsule_set_size(&req->rq_pill, &RMF_NAME, RCL_CLIENT, + op_data->op_namelen + 1); + + /* get SELinux policy info if any */ + sepol = sptlrpc_sepol_get(req); + if (IS_ERR(sepol)) + GOTO(err_free_rq, rc = PTR_ERR(sepol)); + req_capsule_set_size(&req->rq_pill, &RMF_SELINUX_POL, RCL_CLIENT, - strlen(req->rq_sepol) ? - strlen(req->rq_sepol) + 1 : 0); + sptlrpc_sepol_size(sepol)); rc = mdc_prep_elc_req(exp, req, MDS_REINT, &cancels, count); - if (rc) { - ptlrpc_request_free(req); - RETURN(rc); - } + if (rc) + GOTO(err_put_sepol, rc); + + mdc_link_pack(&req->rq_pill, op_data, sepol); + sptlrpc_sepol_put(sepol); - mdc_link_pack(&req->rq_pill, op_data); ptlrpc_request_set_replen(req); rc = mdc_reint(req, LUSTRE_IMP_FULL); - *request = req; - if (rc == -ERESTARTSYS) - rc = 0; + *request = req; + if (rc == -ERESTARTSYS) + rc = 0; - RETURN(rc); + RETURN(rc); + +err_put_sepol: + sptlrpc_sepol_put(sepol); +err_free_rq: + ptlrpc_request_free(req); + + RETURN(rc); } int mdc_rename(struct obd_export *exp, struct md_op_data *op_data, @@ -406,6 +427,7 @@ int mdc_rename(struct obd_export *exp, struct md_op_data *op_data, LIST_HEAD(cancels); struct obd_device *obd = exp->exp_obd; struct ptlrpc_request *req; + struct sptlrpc_sepol *sepol; int count = 0, rc; ENTRY; @@ -446,20 +468,16 @@ int mdc_rename(struct obd_export *exp, struct md_op_data *op_data, op_data->op_data_size); /* get SELinux policy info if any */ - rc = sptlrpc_get_sepol(req); - if (rc < 0) { - ptlrpc_request_free(req); - RETURN(rc); - } + sepol = sptlrpc_sepol_get(req); + if (IS_ERR(sepol)) + GOTO(err_free_rq, rc = PTR_ERR(sepol)); + req_capsule_set_size(&req->rq_pill, &RMF_SELINUX_POL, RCL_CLIENT, - strlen(req->rq_sepol) ? - strlen(req->rq_sepol) + 1 : 0); + sptlrpc_sepol_size(sepol)); rc = mdc_prep_elc_req(exp, req, MDS_REINT, &cancels, count); - if (rc) { - ptlrpc_request_free(req); - RETURN(rc); - } + if (rc) + GOTO(err_put_sepol, rc); if (exp_connect_cancelset(exp) && req) ldlm_cli_cancel_list(&cancels, count, req, 0); @@ -468,7 +486,9 @@ int mdc_rename(struct obd_export *exp, struct md_op_data *op_data, mdc_migrate_pack(&req->rq_pill, op_data, old, oldlen); else mdc_rename_pack(&req->rq_pill, op_data, old, oldlen, - new, newlen); + new, newlen, sepol); + + sptlrpc_sepol_put(sepol); /* LU-17441: avoid blocking MDS_REQUEST_PORTAL for renames with BFL */ #if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 20, 53, 0) @@ -488,6 +508,13 @@ int mdc_rename(struct obd_export *exp, struct md_op_data *op_data, rc = 0; RETURN(rc); + +err_put_sepol: + sptlrpc_sepol_put(sepol); +err_free_rq: + ptlrpc_request_free(req); + + RETURN(rc); } int mdc_file_resync(struct obd_export *exp, struct md_op_data *op_data) diff --git a/lustre/mdc/mdc_request.c b/lustre/mdc/mdc_request.c index be5b9f9..22ce0db 100644 --- a/lustre/mdc/mdc_request.c +++ b/lustre/mdc/mdc_request.c @@ -353,16 +353,18 @@ static int mdc_xattr_common(struct obd_export *exp,const struct req_format *fmt, int input_size, int output_size, int flags, __u32 suppgid, struct ptlrpc_request **request) { - struct ptlrpc_request *req; - int xattr_namelen = 0; - char *tmp; - int rc; - ENTRY; + struct ptlrpc_request *req; + struct sptlrpc_sepol *sepol; + int xattr_namelen = 0; + char *tmp; + int rc; - *request = NULL; - req = ptlrpc_request_alloc(class_exp2cliimp(exp), fmt); - if (req == NULL) - RETURN(-ENOMEM); + ENTRY; + + *request = NULL; + req = ptlrpc_request_alloc(class_exp2cliimp(exp), fmt); + if (req == NULL) + RETURN(-ENOMEM); if (xattr_name) { xattr_namelen = strlen(xattr_name) + 1; @@ -375,14 +377,12 @@ static int mdc_xattr_common(struct obd_export *exp,const struct req_format *fmt, input_size); /* get SELinux policy info if any */ - rc = sptlrpc_get_sepol(req); - if (rc < 0) { - ptlrpc_request_free(req); - RETURN(rc); - } + sepol = sptlrpc_sepol_get(req); + if (IS_ERR(sepol)) + GOTO(err_free_rq, rc = PTR_ERR(sepol)); + req_capsule_set_size(&req->rq_pill, &RMF_SELINUX_POL, RCL_CLIENT, - strlen(req->rq_sepol) ? - strlen(req->rq_sepol) + 1 : 0); + sptlrpc_sepol_size(sepol)); /* Flush local XATTR locks to get rid of a possible cancel RPC */ if (opcode == MDS_REINT && fid_is_sane(fid) && @@ -400,16 +400,12 @@ static int mdc_xattr_common(struct obd_export *exp,const struct req_format *fmt, MDS_INODELOCK_XATTR); rc = mdc_prep_elc_req(exp, req, MDS_REINT, &cancels, count); - if (rc) { - ptlrpc_request_free(req); - RETURN(rc); - } + if (rc) + GOTO(err_put_sepol, rc); } else { rc = ptlrpc_request_pack(req, LUSTRE_MDS_VERSION, opcode); - if (rc) { - ptlrpc_request_free(req); - RETURN(rc); - } + if (rc) + GOTO(err_put_sepol, rc); } if (opcode == MDS_REINT) { @@ -438,36 +434,44 @@ static int mdc_xattr_common(struct obd_export *exp,const struct req_format *fmt, req->rq_request_portal = MDS_READPAGE_PORTAL; } - if (xattr_name) { - tmp = req_capsule_client_get(&req->rq_pill, &RMF_NAME); - memcpy(tmp, xattr_name, xattr_namelen); - } - if (input_size) { - tmp = req_capsule_client_get(&req->rq_pill, &RMF_EADATA); - memcpy(tmp, input, input_size); - } + if (xattr_name) { + tmp = req_capsule_client_get(&req->rq_pill, &RMF_NAME); + memcpy(tmp, xattr_name, xattr_namelen); + } + if (input_size) { + tmp = req_capsule_client_get(&req->rq_pill, &RMF_EADATA); + memcpy(tmp, input, input_size); + } - mdc_file_sepol_pack(&req->rq_pill); + mdc_file_sepol_pack(&req->rq_pill, sepol); + sptlrpc_sepol_put(sepol); - if (req_capsule_has_field(&req->rq_pill, &RMF_EADATA, RCL_SERVER)) - req_capsule_set_size(&req->rq_pill, &RMF_EADATA, - RCL_SERVER, output_size); - ptlrpc_request_set_replen(req); + if (req_capsule_has_field(&req->rq_pill, &RMF_EADATA, RCL_SERVER)) + req_capsule_set_size(&req->rq_pill, &RMF_EADATA, + RCL_SERVER, output_size); + ptlrpc_request_set_replen(req); - /* make rpc */ - if (opcode == MDS_REINT) + /* make rpc */ + if (opcode == MDS_REINT) ptlrpc_get_mod_rpc_slot(req); - rc = ptlrpc_queue_wait(req); + rc = ptlrpc_queue_wait(req); if (opcode == MDS_REINT) ptlrpc_put_mod_rpc_slot(req); - if (rc) - ptlrpc_req_finished(req); - else - *request = req; - RETURN(rc); + if (rc) + ptlrpc_req_finished(req); + else + *request = req; + RETURN(rc); + +err_put_sepol: + sptlrpc_sepol_put(sepol); +err_free_rq: + ptlrpc_request_free(req); + RETURN(rc); + } static int mdc_setxattr(struct obd_export *exp, const struct lu_fid *fid, diff --git a/lustre/ptlrpc/gss/gss_keyring.c b/lustre/ptlrpc/gss/gss_keyring.c index 1b114b4..5b99599 100644 --- a/lustre/ptlrpc/gss/gss_keyring.c +++ b/lustre/ptlrpc/gss/gss_keyring.c @@ -612,6 +612,7 @@ void gss_sec_destroy_kr(struct ptlrpc_sec *sec) CDEBUG(D_SEC, "destroy %s@%p\n", sec->ps_policy->sp_name, sec); + LASSERT(atomic_read(&sec->ps_nctx) == 0); LASSERT(hlist_empty(&gsec_kr->gsk_clist)); LASSERT(gsec_kr->gsk_root_ctx == NULL); diff --git a/lustre/ptlrpc/gss/sec_gss.c b/lustre/ptlrpc/gss/sec_gss.c index 4f4ca6f..76ceac6 100644 --- a/lustre/ptlrpc/gss/sec_gss.c +++ b/lustre/ptlrpc/gss/sec_gss.c @@ -1106,9 +1106,6 @@ int gss_sec_create_common(struct gss_sec *gsec, sec->ps_import = class_import_get(imp); spin_lock_init(&sec->ps_lock); INIT_LIST_HEAD(&sec->ps_gc_list); - sec->ps_sepol_mtime = ktime_set(0, 0); - sec->ps_sepol_checknext = ktime_set(0, 0); - sec->ps_sepol[0] = '\0'; if (!svcctx) { sec->ps_gc_interval = GSS_GC_INTERVAL; diff --git a/lustre/ptlrpc/import.c b/lustre/ptlrpc/import.c index a255bda..536a8d4 100644 --- a/lustre/ptlrpc/import.c +++ b/lustre/ptlrpc/import.c @@ -687,6 +687,7 @@ int ptlrpc_connect_import_locked(struct obd_import *imp) int set_transno = 0; __u64 committed_before_reconnect = 0; struct ptlrpc_request *request; + struct sptlrpc_sepol *sepol; struct obd_connect_data ocd; char *bufs[] = { NULL, obd2cli_tgt(imp->imp_obd), @@ -758,20 +759,21 @@ int ptlrpc_connect_import_locked(struct obd_import *imp) GOTO(out, rc = -ENOMEM); /* get SELinux policy info if any */ - rc = sptlrpc_get_sepol(request); - if (rc < 0) { + sepol = sptlrpc_sepol_get(request); + if (IS_ERR(sepol)) { ptlrpc_request_free(request); - GOTO(out, rc); + GOTO(out, rc = PTR_ERR(sepol)); } - bufs[5] = request->rq_sepol; + bufs[5] = sepol->ssp_sepol; req_capsule_set_size(&request->rq_pill, &RMF_SELINUX_POL, RCL_CLIENT, - strlen(request->rq_sepol) ? - strlen(request->rq_sepol) + 1 : 0); + sptlrpc_sepol_size(sepol)); rc = ptlrpc_request_bufs_pack(request, LUSTRE_OBD_VERSION, imp->imp_connect_op, bufs, NULL); + + sptlrpc_sepol_put(sepol); if (rc) { ptlrpc_request_free(request); GOTO(out, rc); diff --git a/lustre/ptlrpc/sec.c b/lustre/ptlrpc/sec.c index abe40c5..90f4a6d 100644 --- a/lustre/ptlrpc/sec.c +++ b/lustre/ptlrpc/sec.c @@ -1351,12 +1351,20 @@ static int sec_cop_flush_ctx_cache(struct ptlrpc_sec *sec, uid_t uid, static void sec_cop_destroy_sec(struct ptlrpc_sec *sec) { struct ptlrpc_sec_policy *policy = sec->ps_policy; + struct sptlrpc_sepol *sepol; LASSERT_ATOMIC_ZERO(&sec->ps_refcount); - LASSERT_ATOMIC_ZERO(&sec->ps_nctx); LASSERT(policy->sp_cops->destroy_sec); - CDEBUG(D_SEC, "%s@%p: being destroied\n", sec->ps_policy->sp_name, sec); + CDEBUG(D_SEC, "%s@%p: being destroyed\n", sec->ps_policy->sp_name, sec); + + spin_lock(&sec->ps_lock); + sec->ps_sepol_checknext = ktime_set(0, 0); + sepol = rcu_dereference_protected(sec->ps_sepol, 1); + rcu_assign_pointer(sec->ps_sepol, NULL); + spin_unlock(&sec->ps_lock); + + sptlrpc_sepol_put(sepol); policy->sp_cops->destroy_sec(sec); sptlrpc_policy_put(policy); @@ -1870,6 +1878,7 @@ int sptlrpc_svc_install_rvs_ctx(struct obd_import *imp, return policy->sp_sops->install_rctx(imp, ctx); } + /* Get SELinux policy info from userspace */ static int sepol_helper(struct obd_import *imp) { @@ -1886,6 +1895,7 @@ static int sepol_helper(struct obd_import *imp) [8] = mode_str, /* enforcing mode */ [9] = NULL }; + struct sptlrpc_sepol *sepol; char *envp[] = { [0] = "HOME=/", [1] = "PATH=/sbin:/usr/sbin", @@ -1895,29 +1905,31 @@ static int sepol_helper(struct obd_import *imp) int rc = 0; if (imp == NULL || imp->imp_obd == NULL || - imp->imp_obd->obd_type == NULL) { - rc = -EINVAL; + imp->imp_obd->obd_type == NULL) + RETURN(-EINVAL); + + argv[2] = (char *)imp->imp_obd->obd_type->typ_name; + argv[4] = imp->imp_obd->obd_name; + + rcu_read_lock(); + sepol = rcu_dereference(imp->imp_sec->ps_sepol); + if (!sepol) { + /* ps_sepol has not been initialized */ + argv[5] = NULL; + argv[7] = NULL; } else { - argv[2] = (char *)imp->imp_obd->obd_type->typ_name; - argv[4] = imp->imp_obd->obd_name; - spin_lock(&imp->imp_sec->ps_lock); - if (ktime_to_ns(imp->imp_sec->ps_sepol_mtime) == 0 && - imp->imp_sec->ps_sepol[0] == '\0') { - /* ps_sepol has not been initialized */ - argv[5] = NULL; - argv[7] = NULL; - } else { - time64_t mtime_ms; + time64_t mtime_ms; - mtime_ms = ktime_to_ms(imp->imp_sec->ps_sepol_mtime); - snprintf(mtime_str, sizeof(mtime_str), "%lld", - mtime_ms / MSEC_PER_SEC); - mode_str[0] = imp->imp_sec->ps_sepol[0]; - } - spin_unlock(&imp->imp_sec->ps_lock); - ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC); - rc = ret>>8; + mtime_ms = ktime_to_ms(sepol->ssp_mtime); + snprintf(mtime_str, sizeof(mtime_str), "%lld", + mtime_ms / MSEC_PER_SEC); + if (sepol->ssp_sepol_size > 1) + mode_str[0] = sepol->ssp_sepol[0]; } + rcu_read_unlock(); + + ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC); + rc = ret>>8; return rc; } @@ -1956,45 +1968,78 @@ setnext: return 1; } -int sptlrpc_get_sepol(struct ptlrpc_request *req) +static void sptlrpc_sepol_release(struct kref *ref) +{ + struct sptlrpc_sepol *p = container_of(ref, struct sptlrpc_sepol, + ssp_ref); + kfree_rcu(p, ssp_rcu); +} + +void sptlrpc_sepol_put(struct sptlrpc_sepol *pol) +{ + if (!pol) + return; + kref_put(&pol->ssp_ref, sptlrpc_sepol_release); +} +EXPORT_SYMBOL(sptlrpc_sepol_put); + +struct sptlrpc_sepol *sptlrpc_sepol_get_cached(struct ptlrpc_sec *imp_sec) +{ + struct sptlrpc_sepol *p; + +retry: + rcu_read_lock(); + p = rcu_dereference(imp_sec->ps_sepol); + if (p && !kref_get_unless_zero(&p->ssp_ref)) { + rcu_read_unlock(); + goto retry; + } + rcu_read_unlock(); + + return p; +} +EXPORT_SYMBOL(sptlrpc_sepol_get_cached); + +struct sptlrpc_sepol *sptlrpc_sepol_get(struct ptlrpc_request *req) { struct ptlrpc_sec *imp_sec = req->rq_import->imp_sec; + struct sptlrpc_sepol *out; int rc = 0; ENTRY; - (req->rq_sepol)[0] = '\0'; - #ifndef HAVE_SELINUX if (unlikely(send_sepol != 0)) CDEBUG(D_SEC, "Client cannot report SELinux status, it was not built against libselinux.\n"); - RETURN(0); + RETURN(NULL); #endif if (send_sepol == 0) - RETURN(0); + RETURN(NULL); if (imp_sec == NULL) - RETURN(-EINVAL); + RETURN(ERR_PTR(-EINVAL)); /* Retrieve SELinux status info */ if (sptlrpc_sepol_needs_check(imp_sec)) rc = sepol_helper(req->rq_import); - if (likely(rc == 0)) { - spin_lock(&imp_sec->ps_lock); - memcpy(req->rq_sepol, imp_sec->ps_sepol, - sizeof(req->rq_sepol)); - spin_unlock(&imp_sec->ps_lock); - } else if (rc == -ENODEV) { + + if (unlikely(rc == -ENODEV)) { CDEBUG(D_SEC, "Client cannot report SELinux status, SELinux is disabled.\n"); - rc = 0; + RETURN(NULL); } + if (unlikely(rc)) + RETURN(ERR_PTR(rc)); - RETURN(rc); + out = sptlrpc_sepol_get_cached(imp_sec); + if (!out) + RETURN(ERR_PTR(-ENODATA)); + + RETURN(out); } -EXPORT_SYMBOL(sptlrpc_get_sepol); +EXPORT_SYMBOL(sptlrpc_sepol_get); /* * server side security diff --git a/lustre/ptlrpc/sec_lproc.c b/lustre/ptlrpc/sec_lproc.c index 83d4604..4b524fb 100644 --- a/lustre/ptlrpc/sec_lproc.c +++ b/lustre/ptlrpc/sec_lproc.c @@ -136,6 +136,62 @@ out: LDEBUGFS_SEQ_FOPS_RO(sptlrpc_ctxs_lprocfs); +static inline +bool sptlrpc_sepol_update_needed(struct ptlrpc_sec *imp_sec, + ktime_t mtime, char *pol, size_t pol_len) +{ + struct sptlrpc_sepol *old; + bool rc; + + rcu_read_lock(); + old = rcu_dereference(imp_sec->ps_sepol); + if (!old) + rc = true; + else if (!kref_read(&old->ssp_ref)) + rc = false; + else if (ktime_compare(old->ssp_mtime, mtime) != 0) + rc = true; + else + rc = false; + rcu_read_unlock(); + + return rc; +} +static int sptlrpc_sepol_update(struct obd_import *imp, + ktime_t mtime, char *pol, size_t pol_len) +{ + struct sptlrpc_sepol *old; + struct sptlrpc_sepol *new; + struct ptlrpc_sec *imp_sec; + int rc = 0; + + imp_sec = sptlrpc_import_sec_ref(imp); + if (!imp_sec) + RETURN(-ENODEV); + + if (!sptlrpc_sepol_update_needed(imp_sec, mtime, pol, pol_len)) + GOTO(out, rc); + + new = kmalloc(sizeof(typeof(*new)) + pol_len + 1, GFP_KERNEL); + if (!new) + GOTO(out, rc = -ENOMEM); + + kref_init(&new->ssp_ref); + new->ssp_sepol_size = pol_len + 1; + new->ssp_mtime = mtime; + snprintf(new->ssp_sepol, new->ssp_sepol_size, "%s", pol); + + spin_lock(&imp_sec->ps_lock); + old = rcu_dereference_protected(imp_sec->ps_sepol, 1); + rcu_assign_pointer(imp_sec->ps_sepol, new); + spin_unlock(&imp_sec->ps_lock); + sptlrpc_sepol_put(old); +out: + sptlrpc_sec_put(imp_sec); + + return rc; +} + #if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 16, 53, 0) static ssize_t sepol_seq_write_old(struct obd_device *obd, const char __user *buffer, size_t count) @@ -143,7 +199,7 @@ static ssize_t sepol_seq_write_old(struct obd_device *obd, struct client_obd *cli = &obd->u.cli; struct obd_import *imp = cli->cl_import; struct sepol_downcall_data_old *param; - size_t maxlen = sizeof(imp->imp_sec->ps_sepol); + size_t maxlen = LUSTRE_NODEMAP_SEPOL_LENGTH + 1; size_t size = sizeof(*param); size_t maxparam = sizeof(*param) + maxlen; int len; @@ -190,12 +246,8 @@ static ssize_t sepol_seq_write_old(struct obd_device *obd, GOTO(out, rc); } - spin_lock(&imp->imp_sec->ps_lock); - memcpy(imp->imp_sec->ps_sepol, param->sdd_sepol, len); - imp->imp_sec->ps_sepol[len + 1] = '\0'; - imp->imp_sec->ps_sepol_mtime = ktime_set(param->sdd_sepol_mtime, 0); - spin_unlock(&imp->imp_sec->ps_lock); - + rc = sptlrpc_sepol_update(imp, ktime_set(param->sdd_sepol_mtime, 0), + param->sdd_sepol, len); out: OBD_FREE(param, maxparam); @@ -212,7 +264,7 @@ ldebugfs_sptlrpc_sepol_seq_write(struct file *file, const char __user *buffer, struct client_obd *cli = &obd->u.cli; struct obd_import *imp = cli->cl_import; struct sepol_downcall_data *param; - size_t maxlen = sizeof(imp->imp_sec->ps_sepol); + size_t maxlen = LUSTRE_NODEMAP_SEPOL_LENGTH + 1; size_t size = sizeof(*param); size_t maxparam = size + maxlen; int len; @@ -275,18 +327,44 @@ ldebugfs_sptlrpc_sepol_seq_write(struct file *file, const char __user *buffer, GOTO(out, rc); } - spin_lock(&imp->imp_sec->ps_lock); - memcpy(imp->imp_sec->ps_sepol, param->sdd_sepol, len); - imp->imp_sec->ps_sepol[len + 1] = '\0'; - imp->imp_sec->ps_sepol_mtime = ktime_set(param->sdd_sepol_mtime, 0); - spin_unlock(&imp->imp_sec->ps_lock); - + rc = sptlrpc_sepol_update(imp, ktime_set(param->sdd_sepol_mtime, 0), + param->sdd_sepol, len); out: OBD_FREE(param, maxparam); return rc ?: count; } -LDEBUGFS_FOPS_WR_ONLY(srpc, sptlrpc_sepol); + +static int lprocfs_sptlrpc_sepol_seq_show(struct seq_file *seq, void *v) +{ + struct obd_device *obd = seq->private; + struct client_obd *cli = &obd->u.cli; + struct obd_import *imp = cli->cl_import; + struct ptlrpc_sec *imp_sec; + struct sptlrpc_sepol *sepol; + struct timespec64 ts; + int rc = 0; + + imp_sec = sptlrpc_import_sec_ref(imp); + if (!imp_sec) + RETURN(-ENODEV); + + rcu_read_lock(); + sepol = rcu_dereference(imp->imp_sec->ps_sepol); + if (sepol) { + ts = ktime_to_timespec64(sepol->ssp_mtime); + seq_printf(seq, "mtime: %lld\n", (long long int) ts.tv_sec); + seq_printf(seq, "sepol: %.*s\n", + sepol->ssp_sepol_size, sepol->ssp_sepol); + } else { + seq_puts(seq, "uninitialized\n"); + } + rcu_read_unlock(); + sptlrpc_sec_put(imp_sec); + + return rc; +} +LDEBUGFS_SEQ_FOPS_RW_TYPE(srpc, sptlrpc_sepol); int sptlrpc_lprocfs_cliobd_attach(struct obd_device *obd) { diff --git a/lustre/ptlrpc/sec_null.c b/lustre/ptlrpc/sec_null.c index d8408ed..f3343ea1 100644 --- a/lustre/ptlrpc/sec_null.c +++ b/lustre/ptlrpc/sec_null.c @@ -116,9 +116,13 @@ struct ptlrpc_sec *null_create_sec(struct obd_import *imp, /* * general layer has take a module reference for us, because we never - * really destroy the sec, simply release the reference here. + * really destroy the sec, take only 1 module reference for all the + * imports. This reference will be released by sec_cop_destroy_sec(). + * The additional ps_refcount will be released in null_kill_sec(). */ - sptlrpc_policy_put(&null_policy); + if (atomic_inc_return(&null_sec.ps_refcount) != 1) + sptlrpc_policy_put(&null_policy); + return &null_sec; } @@ -129,6 +133,13 @@ void null_destroy_sec(struct ptlrpc_sec *sec) } static +void null_kill_sec(struct ptlrpc_sec *sec) +{ + /* release the ref taken by null_create_sec() */ + sptlrpc_sec_put(sec); +} + +static struct ptlrpc_cli_ctx *null_lookup_ctx(struct ptlrpc_sec *sec, struct vfs_cred *vcred, int create, int remove_dead) @@ -373,6 +384,7 @@ static struct ptlrpc_ctx_ops null_ctx_ops = { static struct ptlrpc_sec_cops null_sec_cops = { .create_sec = null_create_sec, .destroy_sec = null_destroy_sec, + .kill_sec = null_kill_sec, .lookup_ctx = null_lookup_ctx, .flush_ctx_cache = null_flush_ctx_cache, .alloc_reqbuf = null_alloc_reqbuf, @@ -402,7 +414,7 @@ static void null_init_internal(void) static HLIST_HEAD(__list); null_sec.ps_policy = &null_policy; - atomic_set(&null_sec.ps_refcount, 1); /* always busy */ + atomic_set(&null_sec.ps_refcount, 0); null_sec.ps_id = -1; null_sec.ps_import = NULL; null_sec.ps_flvr.sf_rpc = SPTLRPC_FLVR_NULL; -- 1.8.3.1