aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJ. Bruce Fields <bfields@redhat.com>2014-01-08 09:49:01 -0500
committerJ. Bruce Fields <bfields@redhat.com>2014-01-08 12:18:53 -0500
commit3554116d3aae25353713f3d0131d86ae6c1e5674 (patch)
treefaa8c12948e667b34fa3b116f744ef14a034e394
parent87915c6472acbc5d7c809f3c9753808797da51a8 (diff)
nfsd4: simplify xdr encoding of nfsv4 names
We can simplify the idmapping code if it does its own encoding and returns nfs errors. Signed-off-by: J. Bruce Fields <bfields@redhat.com>
-rw-r--r--fs/nfsd/acl.h2
-rw-r--r--fs/nfsd/idmap.h4
-rw-r--r--fs/nfsd/nfs4acl.c20
-rw-r--r--fs/nfsd/nfs4idmap.c50
-rw-r--r--fs/nfsd/nfs4xdr.c52
5 files changed, 55 insertions, 73 deletions
diff --git a/fs/nfsd/acl.h b/fs/nfsd/acl.h
index 8b186a4955cc..afd3e0eae642 100644
--- a/fs/nfsd/acl.h
+++ b/fs/nfsd/acl.h
@@ -43,7 +43,7 @@
43 43
44struct nfs4_acl *nfs4_acl_new(int); 44struct nfs4_acl *nfs4_acl_new(int);
45int nfs4_acl_get_whotype(char *, u32); 45int nfs4_acl_get_whotype(char *, u32);
46int nfs4_acl_write_who(int who, char *p); 46__be32 nfs4_acl_write_who(int who, __be32 **p, int *len);
47 47
48#define NFS4_ACL_TYPE_DEFAULT 0x01 48#define NFS4_ACL_TYPE_DEFAULT 0x01
49#define NFS4_ACL_DIR 0x02 49#define NFS4_ACL_DIR 0x02
diff --git a/fs/nfsd/idmap.h b/fs/nfsd/idmap.h
index bf95f6b817a4..66e58db01936 100644
--- a/fs/nfsd/idmap.h
+++ b/fs/nfsd/idmap.h
@@ -56,7 +56,7 @@ static inline void nfsd_idmap_shutdown(struct net *net)
56 56
57__be32 nfsd_map_name_to_uid(struct svc_rqst *, const char *, size_t, kuid_t *); 57__be32 nfsd_map_name_to_uid(struct svc_rqst *, const char *, size_t, kuid_t *);
58__be32 nfsd_map_name_to_gid(struct svc_rqst *, const char *, size_t, kgid_t *); 58__be32 nfsd_map_name_to_gid(struct svc_rqst *, const char *, size_t, kgid_t *);
59int nfsd_map_uid_to_name(struct svc_rqst *, kuid_t, char *); 59__be32 nfsd4_encode_user(struct svc_rqst *, kuid_t, __be32 **, int *);
60int nfsd_map_gid_to_name(struct svc_rqst *, kgid_t, char *); 60__be32 nfsd4_encode_group(struct svc_rqst *, kgid_t, __be32 **, int *);
61 61
62#endif /* LINUX_NFSD_IDMAP_H */ 62#endif /* LINUX_NFSD_IDMAP_H */
diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c
index 8a50b3c18093..eea24c9a561d 100644
--- a/fs/nfsd/nfs4acl.c
+++ b/fs/nfsd/nfs4acl.c
@@ -37,6 +37,7 @@
37#include <linux/slab.h> 37#include <linux/slab.h>
38#include <linux/nfs_fs.h> 38#include <linux/nfs_fs.h>
39#include <linux/export.h> 39#include <linux/export.h>
40#include "nfsd.h"
40#include "acl.h" 41#include "acl.h"
41 42
42 43
@@ -848,18 +849,23 @@ nfs4_acl_get_whotype(char *p, u32 len)
848 return NFS4_ACL_WHO_NAMED; 849 return NFS4_ACL_WHO_NAMED;
849} 850}
850 851
851int 852__be32 nfs4_acl_write_who(int who, __be32 **p, int *len)
852nfs4_acl_write_who(int who, char *p)
853{ 853{
854 int i; 854 int i;
855 int bytes;
855 856
856 for (i = 0; i < ARRAY_SIZE(s2t_map); i++) { 857 for (i = 0; i < ARRAY_SIZE(s2t_map); i++) {
857 if (s2t_map[i].type == who) { 858 if (s2t_map[i].type != who)
858 memcpy(p, s2t_map[i].string, s2t_map[i].stringlen); 859 continue;
859 return s2t_map[i].stringlen; 860 bytes = 4 + (XDR_QUADLEN(s2t_map[i].stringlen) << 2);
860 } 861 if (bytes > *len)
862 return nfserr_resource;
863 *p = xdr_encode_opaque(*p, s2t_map[i].string,
864 s2t_map[i].stringlen);
865 *len -= bytes;
866 return 0;
861 } 867 }
862 BUG(); 868 WARN_ON_ONCE(1);
863 return -1; 869 return -1;
864} 870}
865 871
diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c
index 4832fd819f88..c0dfde68742e 100644
--- a/fs/nfsd/nfs4idmap.c
+++ b/fs/nfsd/nfs4idmap.c
@@ -551,27 +551,46 @@ idmap_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen
551 return 0; 551 return 0;
552} 552}
553 553
554static int 554static __be32 encode_ascii_id(u32 id, __be32 **p, int *buflen)
555idmap_id_to_name(struct svc_rqst *rqstp, int type, u32 id, char *name) 555{
556 char buf[11];
557 int len;
558 int bytes;
559
560 len = sprintf(buf, "%u", id);
561 bytes = 4 + (XDR_QUADLEN(len) << 2);
562 if (bytes > *buflen)
563 return nfserr_resource;
564 *p = xdr_encode_opaque(*p, buf, len);
565 *buflen -= bytes;
566 return 0;
567}
568
569static __be32 idmap_id_to_name(struct svc_rqst *rqstp, int type, u32 id, __be32 **p, int *buflen)
556{ 570{
557 struct ent *item, key = { 571 struct ent *item, key = {
558 .id = id, 572 .id = id,
559 .type = type, 573 .type = type,
560 }; 574 };
561 int ret; 575 int ret;
576 int bytes;
562 struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); 577 struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
563 578
564 strlcpy(key.authname, rqst_authname(rqstp), sizeof(key.authname)); 579 strlcpy(key.authname, rqst_authname(rqstp), sizeof(key.authname));
565 ret = idmap_lookup(rqstp, idtoname_lookup, &key, nn->idtoname_cache, &item); 580 ret = idmap_lookup(rqstp, idtoname_lookup, &key, nn->idtoname_cache, &item);
566 if (ret == -ENOENT) 581 if (ret == -ENOENT)
567 return sprintf(name, "%u", id); 582 return encode_ascii_id(id, p, buflen);
568 if (ret) 583 if (ret)
569 return ret; 584 return nfserrno(ret);
570 ret = strlen(item->name); 585 ret = strlen(item->name);
571 BUG_ON(ret > IDMAP_NAMESZ); 586 WARN_ON_ONCE(ret > IDMAP_NAMESZ);
572 memcpy(name, item->name, ret); 587 bytes = 4 + (XDR_QUADLEN(ret) << 2);
588 if (bytes > *buflen)
589 return nfserr_resource;
590 *p = xdr_encode_opaque(*p, item->name, ret);
591 *buflen -= bytes;
573 cache_put(&item->h, nn->idtoname_cache); 592 cache_put(&item->h, nn->idtoname_cache);
574 return ret; 593 return 0;
575} 594}
576 595
577static bool 596static bool
@@ -603,12 +622,11 @@ do_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen, u
603 return idmap_name_to_id(rqstp, type, name, namelen, id); 622 return idmap_name_to_id(rqstp, type, name, namelen, id);
604} 623}
605 624
606static int 625static __be32 encode_name_from_id(struct svc_rqst *rqstp, int type, u32 id, __be32 **p, int *buflen)
607do_id_to_name(struct svc_rqst *rqstp, int type, u32 id, char *name)
608{ 626{
609 if (nfs4_disable_idmapping && rqstp->rq_cred.cr_flavor < RPC_AUTH_GSS) 627 if (nfs4_disable_idmapping && rqstp->rq_cred.cr_flavor < RPC_AUTH_GSS)
610 return sprintf(name, "%u", id); 628 return encode_ascii_id(id, p, buflen);
611 return idmap_id_to_name(rqstp, type, id, name); 629 return idmap_id_to_name(rqstp, type, id, p, buflen);
612} 630}
613 631
614__be32 632__be32
@@ -637,16 +655,14 @@ nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name, size_t namelen,
637 return status; 655 return status;
638} 656}
639 657
640int 658__be32 nfsd4_encode_user(struct svc_rqst *rqstp, kuid_t uid, __be32 **p, int *buflen)
641nfsd_map_uid_to_name(struct svc_rqst *rqstp, kuid_t uid, char *name)
642{ 659{
643 u32 id = from_kuid(&init_user_ns, uid); 660 u32 id = from_kuid(&init_user_ns, uid);
644 return do_id_to_name(rqstp, IDMAP_TYPE_USER, id, name); 661 return encode_name_from_id(rqstp, IDMAP_TYPE_USER, id, p, buflen);
645} 662}
646 663
647int 664__be32 nfsd4_encode_group(struct svc_rqst *rqstp, kgid_t gid, __be32 **p, int *buflen)
648nfsd_map_gid_to_name(struct svc_rqst *rqstp, kgid_t gid, char *name)
649{ 665{
650 u32 id = from_kgid(&init_user_ns, gid); 666 u32 id = from_kgid(&init_user_ns, gid);
651 return do_id_to_name(rqstp, IDMAP_TYPE_GROUP, id, name); 667 return encode_name_from_id(rqstp, IDMAP_TYPE_GROUP, id, p, buflen);
652} 668}
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 67b44963e8ad..8198ecf3c03a 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1965,56 +1965,16 @@ static u32 nfs4_file_type(umode_t mode)
1965 }; 1965 };
1966} 1966}
1967 1967
1968static __be32
1969nfsd4_encode_name(struct svc_rqst *rqstp, int whotype, kuid_t uid, kgid_t gid,
1970 __be32 **p, int *buflen)
1971{
1972 int status;
1973
1974 if (*buflen < (XDR_QUADLEN(IDMAP_NAMESZ) << 2) + 4)
1975 return nfserr_resource;
1976 if (whotype != NFS4_ACL_WHO_NAMED)
1977 status = nfs4_acl_write_who(whotype, (u8 *)(*p + 1));
1978 else if (gid_valid(gid))
1979 status = nfsd_map_gid_to_name(rqstp, gid, (u8 *)(*p + 1));
1980 else
1981 status = nfsd_map_uid_to_name(rqstp, uid, (u8 *)(*p + 1));
1982 if (status < 0)
1983 return nfserrno(status);
1984 *p = xdr_encode_opaque(*p, NULL, status);
1985 *buflen -= (XDR_QUADLEN(status) << 2) + 4;
1986 BUG_ON(*buflen < 0);
1987 return 0;
1988}
1989
1990static inline __be32
1991nfsd4_encode_user(struct svc_rqst *rqstp, kuid_t user, __be32 **p, int *buflen)
1992{
1993 return nfsd4_encode_name(rqstp, NFS4_ACL_WHO_NAMED, user, INVALID_GID,
1994 p, buflen);
1995}
1996
1997static inline __be32
1998nfsd4_encode_group(struct svc_rqst *rqstp, kgid_t group, __be32 **p, int *buflen)
1999{
2000 return nfsd4_encode_name(rqstp, NFS4_ACL_WHO_NAMED, INVALID_UID, group,
2001 p, buflen);
2002}
2003
2004static inline __be32 1968static inline __be32
2005nfsd4_encode_aclname(struct svc_rqst *rqstp, struct nfs4_ace *ace, 1969nfsd4_encode_aclname(struct svc_rqst *rqstp, struct nfs4_ace *ace,
2006 __be32 **p, int *buflen) 1970 __be32 **p, int *buflen)
2007{ 1971{
2008 kuid_t uid = INVALID_UID; 1972 if (ace->whotype != NFS4_ACL_WHO_NAMED)
2009 kgid_t gid = INVALID_GID; 1973 return nfs4_acl_write_who(ace->whotype, p, buflen);
2010 1974 else if (ace->flag & NFS4_ACE_IDENTIFIER_GROUP)
2011 if (ace->whotype == NFS4_ACL_WHO_NAMED) { 1975 return nfsd4_encode_group(rqstp, ace->who_gid, p, buflen);
2012 if (ace->flag & NFS4_ACE_IDENTIFIER_GROUP) 1976 else
2013 gid = ace->who_gid; 1977 return nfsd4_encode_user(rqstp, ace->who_uid, p, buflen);
2014 else
2015 uid = ace->who_uid;
2016 }
2017 return nfsd4_encode_name(rqstp, ace->whotype, uid, gid, p, buflen);
2018} 1978}
2019 1979
2020#define WORD0_ABSENT_FS_ATTRS (FATTR4_WORD0_FS_LOCATIONS | FATTR4_WORD0_FSID | \ 1980#define WORD0_ABSENT_FS_ATTRS (FATTR4_WORD0_FS_LOCATIONS | FATTR4_WORD0_FSID | \