[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