@@ -1989,27 +1989,19 @@ nfsd4_encode_aclname(struct svc_rqst *rqstp, struct nfs4_ace *ace,
#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
static inline __be32
-nfsd4_encode_security_label(struct svc_rqst *rqstp, struct dentry *dentry, __be32 **pp, int *buflen)
+nfsd4_encode_security_label(struct svc_rqst *rqstp, void *context, int len, __be32 **pp, int *buflen)
{
- void *context;
- int host_err;
- __be32 err = nfserr_resource;
- u32 len;
__be32 *p = *pp;
- host_err = security_inode_getsecctx(dentry->d_inode, &context, &len);
- if (host_err)
- return nfserrno(host_err);
-
if (*buflen < ((XDR_QUADLEN(len) << 2) + 4 + 4 + 4))
- goto out;
+ return nfserr_resource;
/*
* For now we use a 0 here to indicate the null translation; in
* the future we may place a call to translation code here.
*/
if ((*buflen -= 8) < 0)
- goto out;
+ return nfserr_resource;
WRITE32(0); /* lfs */
WRITE32(0); /* pi */
@@ -2017,10 +2009,7 @@ nfsd4_encode_security_label(struct svc_rqst *rqstp, struct dentry *dentry, __be3
*buflen -= (XDR_QUADLEN(len) << 2) + 4;
*pp = p;
- err = 0;
-out:
- security_release_secctx(context, len);
- return err;
+ return 0;
}
#else
static inline __be32
@@ -2087,6 +2076,9 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
int err;
int aclsupport = 0;
struct nfs4_acl *acl = NULL;
+ void *context = NULL;
+ int contextlen;
+ bool contextsupport = false;
struct nfsd4_compoundres *resp = rqstp->rq_resp;
u32 minorversion = resp->cstate.minorversion;
struct path path = {
@@ -2140,6 +2132,21 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
}
}
+#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
+ if ((bmval[2] & FATTR4_WORD2_SECURITY_LABEL) ||
+ bmval[0] & FATTR4_WORD0_SUPPORTED_ATTRS) {
+ err = security_inode_getsecctx(dentry->d_inode,
+ &context, &contextlen);
+ contextsupport = (err = 0);
+ if (bmval2 & FATTR4_WORD2_SECURITY_LABEL) {
+ if (err == -EOPNOTSUPP)
+ bmval2 &= ~FATTR4_WORD2_SECURITY_LABEL;
+ else if (err)
+ goto out_nfserr;
+ }
+ }
+#endif /* CONFIG_NFSD_V4_SECURITY_LABEL */
+
if (bmval2) {
if ((buflen -= 16) < 0)
goto out_resource;
@@ -2168,6 +2175,8 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
if (!aclsupport)
word0 &= ~FATTR4_WORD0_ACL;
+ if (!contextsupport)
+ word2 &= ~FATTR4_WORD2_SECURITY_LABEL;
if (!word2) {
if ((buflen -= 12) < 0)
goto out_resource;
@@ -2476,8 +2485,8 @@ out_acl:
WRITE64(stat.ino);
}
if (bmval2 & FATTR4_WORD2_SECURITY_LABEL) {
- status = nfsd4_encode_security_label(rqstp, dentry,
- &p, &buflen);
+ status = nfsd4_encode_security_label(rqstp, context,
+ contextlen, &p, &buflen);
if (status)
goto out;
}
@@ -2493,6 +2502,8 @@ out_acl:
status = nfs_ok;
out:
+ if (context)
+ security_release_secctx(context, contextlen);
kfree(acl);
if (fhp == &tempfh)
fh_put(&tempfh);