[PATCH 4/6] patch add_translation_hooks

Dave Quigley dpquigl at tycho.nsa.gov
Thu Nov 29 14:04:05 EST 2007


Signed-off-by: David P. Quigley <dpquigl at tycho.nsa.gov>
---
 fs/nfs/nfs4xdr.c  |   57 +++++++++++++++++++++++++++++++++++++++++++++-------
 fs/nfsd/nfs4xdr.c |   33 ++++++++++++++++++++----------
 2 files changed, 71 insertions(+), 19 deletions(-)

diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 3cc8e5f..691584e 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -51,6 +51,7 @@
 #include <linux/nfs4.h>
 #include <linux/nfs_fs.h>
 #include <linux/nfs_idmap.h>
+#include <linux/nfs_doimap.h>
 #include "nfs4_fs.h"
 
 #define NFSDBG_FACILITY		NFSDBG_XDR
@@ -603,8 +604,10 @@ static int encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const s
 {
 	char owner_name[IDMAP_NAMESZ];
 	char owner_group[IDMAP_NAMESZ];
+	char *owner_label;
 	int owner_namelen = 0;
 	int owner_grouplen = 0;
+	int owner_labellen = 0;
 	__be32 *p;
 	__be32 *q;
 	int len;
@@ -650,8 +653,21 @@ static int encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const s
 		len += 4 + (XDR_QUADLEN(owner_grouplen) << 2);
 	}
 #ifdef CONFIG_NFS_V4_SECURITY_LABEL
-	if (iap->ia_valid & ATTR_SECURITY_LABEL)
-		len += 4 + (XDR_QUADLEN(iap->ia_label_len) << 2);
+	if (iap->ia_valid & ATTR_SECURITY_LABEL) {
+		owner_labellen = nfs_map_local_to_global(server->nfs_client,
+				iap->ia_label,
+				iap->ia_label_len,
+				&owner_label);
+
+		if (owner_labellen <= 0)
+			printk(KERN_WARNING "nfs4: couldn't resolve local label %s to global label\n",
+					iap->ia_label);
+
+		if (owner_label)
+			len += 4 + (XDR_QUADLEN(owner_labellen) << 2);
+		else
+			len += 4 + (XDR_QUADLEN(iap->ia_label_len) << 2);
+	}
 #endif
 	if (iap->ia_valid & ATTR_ATIME_SET)
 		len += 16;
@@ -714,8 +730,14 @@ static int encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const s
 #ifdef CONFIG_NFS_V4_SECURITY_LABEL
 	if (iap->ia_valid & ATTR_SECURITY_LABEL) {
 		bmval1 |= FATTR4_WORD1_SECURITY_LABEL;
-		WRITE32(iap->ia_label_len);
-		WRITEMEM(iap->ia_label, iap->ia_label_len);
+		if (owner_label) {
+			WRITE32(owner_labellen);
+			WRITEMEM(owner_label, owner_labellen);
+			kfree(owner_label);
+		} else {
+			WRITE32(iap->ia_label_len);
+			WRITEMEM(iap->ia_label, iap->ia_label_len);
+		}
 	}
 #endif /* CONFIG_NFS_V4_SECURITY_LABEL */
 	
@@ -2963,10 +2985,11 @@ static int decode_attr_time_modify(struct xdr_stream *xdr, uint32_t *bitmap, str
 	return status;
 }
 
-static int decode_attr_security_label(struct xdr_stream *xdr, uint32_t *bitmap, char **ctx, u32 *ctxlen)
+static int decode_attr_security_label(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_client *clp, char **ctx, u32 *ctxlen)
 {
-	uint32_t len;
+	uint32_t len, translen;
 	__be32 *p;
+	char *_ctx, *_transctx;
 	int rc = 0;
 
 	if (unlikely(bitmap[1] & (FATTR4_WORD1_SECURITY_LABEL - 1U)))
@@ -2982,8 +3005,25 @@ static int decode_attr_security_label(struct xdr_stream *xdr, uint32_t *bitmap,
 					    "%s(): ctxlen (%d) < len (%d)\n", 
 						__func__, *ctxlen, len);
 				} else {
-					memcpy(*ctx, (char *)p, len);
-					(*ctx)[len + 1] = '\0';
+					_ctx = kmalloc(len + 1, GFP_KERNEL);
+					if (!_ctx)
+						return -ENOMEM;
+
+					memcpy(_ctx, (char *)p, len);
+					_ctx[len + 1] = '\0';
+
+					translen = nfs_map_global_to_local(clp,
+							_ctx, len, &_transctx);
+					if (translen <= 0) {
+						printk(KERN_WARNING 
+						"nfs4: couldn't resolve global label %s to local label\n",
+						_ctx);
+						memcpy(*ctx, _ctx, len + 1);
+						*ctxlen = len + 1;
+					} else {
+						memcpy(*ctx, _transctx, translen);
+						*ctxlen = translen;
+					}
 				}
 			}
 			*ctxlen = len;
@@ -3228,6 +3268,7 @@ static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, cons
 	if ((status = decode_attr_mounted_on_fileid(xdr, bitmap, &fileid)) != 0)
 		goto xdr_error;
 	if ((status = decode_attr_security_label(xdr, bitmap,
+						 server->nfs_client,
 						 &fattr->label,
 						 &fattr->label_len)) != 0)
 		goto xdr_error;
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 36c69a2..d3c0984 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -55,6 +55,7 @@
 #include <linux/nfsd/state.h>
 #include <linux/nfsd/xdr4.h>
 #include <linux/nfsd_idmap.h>
+#include <linux/nfsd_doimap.h>
 #include <linux/nfs4.h>
 #include <linux/nfs4_acl.h>
 #include <linux/sunrpc/gss_api.h>
@@ -251,7 +252,7 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, struct iattr *ia
 {
 	int expected_len, len = 0;
 	u32 dummy32;
-	char *buf;
+	char *buf, *label;
 	int host_err;
 
 	DECODE_HEAD;
@@ -422,10 +423,12 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, struct iattr *ia
 		READ_BUF(dummy32);
 		len += (XDR_QUADLEN(dummy32) << 2);
 		READMEM(buf, dummy32);
-		iattr->ia_label_len = dummy32;
-		iattr->ia_label = kmalloc(dummy32 + 1, GFP_ATOMIC);
-		memcpy(iattr->ia_label, buf, dummy32);
-		((char *)iattr->ia_label)[dummy32 + 1] = '\0';
+		label = kmalloc(dummy32, GFP_ATOMIC);
+		memcpy(label, buf, dummy32);
+		iattr->ia_label_len = nfsd_map_global_to_local(argp->rqstp, 
+					label, dummy32, 
+					(char **)&iattr->ia_label);
+		kfree(label);
 		iattr->ia_valid |= ATTR_SECURITY_LABEL;
 		defer_free(argp, kfree, iattr->ia_label);
 	}
@@ -1443,8 +1446,8 @@ nfsd4_encode_security_label(struct svc_rqst *rqstp,
 			    struct dentry *dentry,
 			    __be32 **p, int *buflen)
 {
-	void *context;
-	int err = 0, len;
+	void *context, *context_trans = NULL;
+	int err = 0, len, len_trans;
 
 	const char *suffix = security_inode_xattr_getname()
 				+ XATTR_SECURITY_PREFIX_LEN;
@@ -1455,20 +1458,28 @@ nfsd4_encode_security_label(struct svc_rqst *rqstp,
 		goto out;
 	}
 
-	if (len > NFS4_MAXLABELLEN) {
+	len_trans = nfsd_map_local_to_global(rqstp, context, len,
+			(char **)&context_trans);
+	if (len_trans < 0) {
+		err = nfserrno(len_trans);
+		goto out_err;
+	}
+
+	if (len_trans > NFS4_MAXLABELLEN) {
 		err = nfserrno(len);
 		goto out_err;
 	}
-	if (*buflen < ((XDR_QUADLEN(len) << 2) + 4)) {
+	if (*buflen < ((XDR_QUADLEN(len_trans) << 2) + 4)) {
 		err =  nfserr_resource;
 		goto out_err;
 	}
 
-	*p = xdr_encode_opaque(*p, context, len);
-	*buflen -= (XDR_QUADLEN(len) << 2) + 4;
+	*p = xdr_encode_opaque(*p, context_trans, len_trans);
+	*buflen -= (XDR_QUADLEN(len_trans) << 2) + 4;
 	BUG_ON(*buflen < 0);
 
 out_err:
+	kfree(context_trans);
 	security_release_secctx(context, len);
 out:
 	return err;
-- 
1.5.3.4




More information about the NFSv4 mailing list