diff options
author | J. Bruce Fields <bfields@redhat.com> | 2014-01-08 09:49:01 -0500 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2014-01-08 12:18:53 -0500 |
commit | 3554116d3aae25353713f3d0131d86ae6c1e5674 (patch) | |
tree | faa8c12948e667b34fa3b116f744ef14a034e394 | |
parent | 87915c6472acbc5d7c809f3c9753808797da51a8 (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.h | 2 | ||||
-rw-r--r-- | fs/nfsd/idmap.h | 4 | ||||
-rw-r--r-- | fs/nfsd/nfs4acl.c | 20 | ||||
-rw-r--r-- | fs/nfsd/nfs4idmap.c | 50 | ||||
-rw-r--r-- | fs/nfsd/nfs4xdr.c | 52 |
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 | ||
44 | struct nfs4_acl *nfs4_acl_new(int); | 44 | struct nfs4_acl *nfs4_acl_new(int); |
45 | int nfs4_acl_get_whotype(char *, u32); | 45 | int nfs4_acl_get_whotype(char *, u32); |
46 | int 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 *); |
59 | int nfsd_map_uid_to_name(struct svc_rqst *, kuid_t, char *); | 59 | __be32 nfsd4_encode_user(struct svc_rqst *, kuid_t, __be32 **, int *); |
60 | int 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 | ||
851 | int | 852 | __be32 nfs4_acl_write_who(int who, __be32 **p, int *len) |
852 | nfs4_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 | ||
554 | static int | 554 | static __be32 encode_ascii_id(u32 id, __be32 **p, int *buflen) |
555 | idmap_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 | |||
569 | static __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 | ||
577 | static bool | 596 | static 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 | ||
606 | static int | 625 | static __be32 encode_name_from_id(struct svc_rqst *rqstp, int type, u32 id, __be32 **p, int *buflen) |
607 | do_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 | ||
640 | int | 658 | __be32 nfsd4_encode_user(struct svc_rqst *rqstp, kuid_t uid, __be32 **p, int *buflen) |
641 | nfsd_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 | ||
647 | int | 664 | __be32 nfsd4_encode_group(struct svc_rqst *rqstp, kgid_t gid, __be32 **p, int *buflen) |
648 | nfsd_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 | ||
1968 | static __be32 | ||
1969 | nfsd4_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 | |||
1990 | static inline __be32 | ||
1991 | nfsd4_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 | |||
1997 | static inline __be32 | ||
1998 | nfsd4_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 | |||
2004 | static inline __be32 | 1968 | static inline __be32 |
2005 | nfsd4_encode_aclname(struct svc_rqst *rqstp, struct nfs4_ace *ace, | 1969 | nfsd4_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 | \ |