From 76ecf306ae5da84ef8f48c7a2608736e6866440c Mon Sep 17 00:00:00 2001 From: Casey Schaufler Date: Wed, 23 Oct 2024 14:21:56 -0700 Subject: [PATCH] lsm: use lsm_context in security_inode_getsecctx Change the security_inode_getsecctx() interface to fill a lsm_context structure instead of data and length pointers. This provides the information about which LSM created the context so that security_release_secctx() can use the correct hook. Cc: linux-nfs@vger.kernel.org Signed-off-by: Casey Schaufler [PM: subject tweak] Signed-off-by: Paul Moore --- fs/nfsd/nfs4xdr.c | 26 ++++++++++---------------- include/linux/lsm_hook_defs.h | 4 ++-- include/linux/security.h | 5 +++-- security/security.c | 12 ++++++------ security/selinux/hooks.c | 10 ++++++---- security/smack/smack_lsm.c | 7 ++++--- 6 files changed, 31 insertions(+), 33 deletions(-) diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 95ec6a4b4da3..8dd2e2ada474 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -2818,11 +2818,11 @@ static __be32 nfsd4_encode_nfsace4(struct xdr_stream *xdr, struct svc_rqst *rqst #ifdef CONFIG_NFSD_V4_SECURITY_LABEL static inline __be32 nfsd4_encode_security_label(struct xdr_stream *xdr, struct svc_rqst *rqstp, - void *context, int len) + const struct lsm_context *context) { __be32 *p; - p = xdr_reserve_space(xdr, len + 4 + 4 + 4); + p = xdr_reserve_space(xdr, context->len + 4 + 4 + 4); if (!p) return nfserr_resource; @@ -2832,13 +2832,13 @@ nfsd4_encode_security_label(struct xdr_stream *xdr, struct svc_rqst *rqstp, */ *p++ = cpu_to_be32(0); /* lfs */ *p++ = cpu_to_be32(0); /* pi */ - p = xdr_encode_opaque(p, context, len); + p = xdr_encode_opaque(p, context->context, context->len); return 0; } #else static inline __be32 nfsd4_encode_security_label(struct xdr_stream *xdr, struct svc_rqst *rqstp, - void *context, int len) + struct lsm_context *context) { return 0; } #endif @@ -2920,8 +2920,7 @@ struct nfsd4_fattr_args { struct kstatfs statfs; struct nfs4_acl *acl; #ifdef CONFIG_NFSD_V4_SECURITY_LABEL - void *context; - int contextlen; + struct lsm_context context; #endif u32 rdattr_err; bool contextsupport; @@ -3376,8 +3375,7 @@ static __be32 nfsd4_encode_fattr4_suppattr_exclcreat(struct xdr_stream *xdr, static __be32 nfsd4_encode_fattr4_sec_label(struct xdr_stream *xdr, const struct nfsd4_fattr_args *args) { - return nfsd4_encode_security_label(xdr, args->rqstp, - args->context, args->contextlen); + return nfsd4_encode_security_label(xdr, args->rqstp, &args->context); } #endif @@ -3527,7 +3525,7 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr, args.ignore_crossmnt = (ignore_crossmnt != 0); args.acl = NULL; #ifdef CONFIG_NFSD_V4_SECURITY_LABEL - args.context = NULL; + args.context.context = NULL; #endif /* @@ -3607,7 +3605,7 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr, attrmask[0] & FATTR4_WORD0_SUPPORTED_ATTRS) { if (exp->ex_flags & NFSEXP_SECURITY_LABEL) err = security_inode_getsecctx(d_inode(dentry), - &args.context, &args.contextlen); + &args.context); else err = -EOPNOTSUPP; args.contextsupport = (err == 0); @@ -3644,12 +3642,8 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr, out: #ifdef CONFIG_NFSD_V4_SECURITY_LABEL - if (args.context) { - struct lsm_context scaff; /* scaffolding */ - - lsmcontext_init(&scaff, args.context, args.contextlen, 0); - security_release_secctx(&scaff); - } + if (args.context.context) + security_release_secctx(&args.context); #endif /* CONFIG_NFSD_V4_SECURITY_LABEL */ kfree(args.acl); if (tempfh) { diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h index 01e5a8e09bba..69e1076448c6 100644 --- a/include/linux/lsm_hook_defs.h +++ b/include/linux/lsm_hook_defs.h @@ -303,8 +303,8 @@ LSM_HOOK(void, LSM_RET_VOID, release_secctx, struct lsm_context *cp) LSM_HOOK(void, LSM_RET_VOID, inode_invalidate_secctx, struct inode *inode) LSM_HOOK(int, 0, inode_notifysecctx, struct inode *inode, void *ctx, u32 ctxlen) LSM_HOOK(int, 0, inode_setsecctx, struct dentry *dentry, void *ctx, u32 ctxlen) -LSM_HOOK(int, -EOPNOTSUPP, inode_getsecctx, struct inode *inode, void **ctx, - u32 *ctxlen) +LSM_HOOK(int, -EOPNOTSUPP, inode_getsecctx, struct inode *inode, + struct lsm_context *cp) #if defined(CONFIG_SECURITY) && defined(CONFIG_WATCH_QUEUE) LSM_HOOK(int, 0, post_notification, const struct cred *w_cred, diff --git a/include/linux/security.h b/include/linux/security.h index 58518bbc00a6..29f8100bc7c8 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -591,7 +591,7 @@ void security_release_secctx(struct lsm_context *cp); void security_inode_invalidate_secctx(struct inode *inode); int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen); int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen); -int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen); +int security_inode_getsecctx(struct inode *inode, struct lsm_context *cp); int security_locked_down(enum lockdown_reason what); int lsm_fill_user_ctx(struct lsm_ctx __user *uctx, u32 *uctx_len, void *val, size_t val_len, u64 id, u64 flags); @@ -1591,7 +1591,8 @@ static inline int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 { return -EOPNOTSUPP; } -static inline int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen) +static inline int security_inode_getsecctx(struct inode *inode, + struct lsm_context *cp) { return -EOPNOTSUPP; } diff --git a/security/security.c b/security/security.c index 1edf8fb2046c..1aecf1696c50 100644 --- a/security/security.c +++ b/security/security.c @@ -4426,17 +4426,17 @@ EXPORT_SYMBOL(security_inode_setsecctx); /** * security_inode_getsecctx() - Get the security label of an inode * @inode: inode - * @ctx: secctx - * @ctxlen: length of secctx + * @cp: security context * - * On success, returns 0 and fills out @ctx and @ctxlen with the security - * context for the given @inode. + * On success, returns 0 and fills out @cp with the security context + * for the given @inode. * * Return: Returns 0 on success, error on failure. */ -int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen) +int security_inode_getsecctx(struct inode *inode, struct lsm_context *cp) { - return call_int_hook(inode_getsecctx, inode, ctx, ctxlen); + memset(cp, 0, sizeof(*cp)); + return call_int_hook(inode_getsecctx, inode, cp); } EXPORT_SYMBOL(security_inode_getsecctx); diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index ddc24db7c0b2..9254570de103 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -6711,14 +6711,16 @@ static int selinux_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen) ctx, ctxlen, 0, NULL); } -static int selinux_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen) +static int selinux_inode_getsecctx(struct inode *inode, struct lsm_context *cp) { - int len = 0; + int len; len = selinux_inode_getsecurity(&nop_mnt_idmap, inode, - XATTR_SELINUX_SUFFIX, ctx, true); + XATTR_SELINUX_SUFFIX, + (void **)&cp->context, true); if (len < 0) return len; - *ctxlen = len; + cp->len = len; + cp->id = LSM_ID_SELINUX; return 0; } #ifdef CONFIG_KEYS diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 4084f99c493c..55a556f17ade 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -4898,12 +4898,13 @@ static int smack_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen) ctx, ctxlen, 0, NULL); } -static int smack_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen) +static int smack_inode_getsecctx(struct inode *inode, struct lsm_context *cp) { struct smack_known *skp = smk_of_inode(inode); - *ctx = skp->smk_known; - *ctxlen = strlen(skp->smk_known); + cp->context = skp->smk_known; + cp->len = strlen(skp->smk_known); + cp->id = LSM_ID_SMACK; return 0; }