On 7/24/20 1:32 PM, Casey Schaufler wrote: > Change the security_inode_getsecctx() interface to fill > a lsmcontext 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. > Reviewed-by: John Johansen <john.johansen@xxxxxxxxxxxxx> > Acked-by: Stephen Smalley <sds@xxxxxxxxxxxxx> > Signed-off-by: Casey Schaufler <casey@xxxxxxxxxxxxxxxx> > --- > fs/nfsd/nfs4xdr.c | 23 +++++++++-------------- > include/linux/security.h | 5 +++-- > security/security.c | 13 +++++++++++-- > 3 files changed, 23 insertions(+), 18 deletions(-) > > diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c > index 61d6b8a0e8f0..6673221d5606 100644 > --- a/fs/nfsd/nfs4xdr.c > +++ b/fs/nfsd/nfs4xdr.c > @@ -2379,11 +2379,11 @@ nfsd4_encode_layout_types(struct xdr_stream *xdr, u32 layout_types) > #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) > + struct lsmcontext *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; > > @@ -2393,13 +2393,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 lsmcontext *context) > { return 0; } > #endif > > @@ -2496,9 +2496,7 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp, > int err; > struct nfs4_acl *acl = NULL; > #ifdef CONFIG_NFSD_V4_SECURITY_LABEL > - struct lsmcontext scaff; /* scaffolding */ > - void *context = NULL; > - int contextlen; > + struct lsmcontext context = { }; > #endif > bool contextsupport = false; > struct nfsd4_compoundres *resp = rqstp->rq_resp; > @@ -2556,7 +2554,7 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp, > bmval0 & FATTR4_WORD0_SUPPORTED_ATTRS) { > if (exp->ex_flags & NFSEXP_SECURITY_LABEL) > err = security_inode_getsecctx(d_inode(dentry), > - &context, &contextlen); > + &context); > else > err = -EOPNOTSUPP; > contextsupport = (err == 0); > @@ -2986,8 +2984,7 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp, > > #ifdef CONFIG_NFSD_V4_SECURITY_LABEL > if (bmval2 & FATTR4_WORD2_SECURITY_LABEL) { > - status = nfsd4_encode_security_label(xdr, rqstp, context, > - contextlen); > + status = nfsd4_encode_security_label(xdr, rqstp, &context); > if (status) > goto out; > } > @@ -2999,10 +2996,8 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp, > > out: > #ifdef CONFIG_NFSD_V4_SECURITY_LABEL > - if (context) { > - lsmcontext_init(&scaff, context, contextlen, 0); /*scaffolding*/ > - security_release_secctx(&scaff); > - } > + if (context.context) > + security_release_secctx(&context); > #endif /* CONFIG_NFSD_V4_SECURITY_LABEL */ > kfree(acl); > if (tempfh) { > diff --git a/include/linux/security.h b/include/linux/security.h > index 43f8a2660d37..02dc3b5ef57b 100644 > --- a/include/linux/security.h > +++ b/include/linux/security.h > @@ -560,7 +560,7 @@ void security_release_secctx(struct lsmcontext *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 lsmcontext *cp); > int security_locked_down(enum lockdown_reason what); > #else /* CONFIG_SECURITY */ > > @@ -1399,7 +1399,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 lsmcontext *cp) > { > return -EOPNOTSUPP; > } > diff --git a/security/security.c b/security/security.c > index 862f0bc2f114..ddbaf2073b02 100644 > --- a/security/security.c > +++ b/security/security.c > @@ -2263,9 +2263,18 @@ int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen) > } > EXPORT_SYMBOL(security_inode_setsecctx); > > -int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen) > +int security_inode_getsecctx(struct inode *inode, struct lsmcontext *cp) > { > - return call_int_hook(inode_getsecctx, -EOPNOTSUPP, inode, ctx, ctxlen); > + struct security_hook_list *hp; > + > + memset(cp, 0, sizeof(*cp)); > + > + hlist_for_each_entry(hp, &security_hook_heads.inode_getsecctx, list) { > + cp->slot = hp->lsmid->slot; > + return hp->hook.inode_getsecctx(inode, (void **)&cp->context, > + &cp->len); > + } > + return -EOPNOTSUPP; > } > EXPORT_SYMBOL(security_inode_getsecctx); > >