Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3554116d authored by J. Bruce Fields's avatar J. Bruce Fields
Browse files

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: default avatarJ. Bruce Fields <bfields@redhat.com>
parent 87915c64
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -43,7 +43,7 @@

struct nfs4_acl *nfs4_acl_new(int);
int nfs4_acl_get_whotype(char *, u32);
int nfs4_acl_write_who(int who, char *p);
__be32 nfs4_acl_write_who(int who, __be32 **p, int *len);

#define NFS4_ACL_TYPE_DEFAULT	0x01
#define NFS4_ACL_DIR		0x02
+2 −2
Original line number Diff line number Diff line
@@ -56,7 +56,7 @@ static inline void nfsd_idmap_shutdown(struct net *net)

__be32 nfsd_map_name_to_uid(struct svc_rqst *, const char *, size_t, kuid_t *);
__be32 nfsd_map_name_to_gid(struct svc_rqst *, const char *, size_t, kgid_t *);
int nfsd_map_uid_to_name(struct svc_rqst *, kuid_t, char *);
int nfsd_map_gid_to_name(struct svc_rqst *, kgid_t, char *);
__be32 nfsd4_encode_user(struct svc_rqst *, kuid_t, __be32 **, int *);
__be32 nfsd4_encode_group(struct svc_rqst *, kgid_t, __be32 **, int *);

#endif /* LINUX_NFSD_IDMAP_H */
+13 −7
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@
#include <linux/slab.h>
#include <linux/nfs_fs.h>
#include <linux/export.h>
#include "nfsd.h"
#include "acl.h"


@@ -848,18 +849,23 @@ nfs4_acl_get_whotype(char *p, u32 len)
	return NFS4_ACL_WHO_NAMED;
}

int
nfs4_acl_write_who(int who, char *p)
__be32 nfs4_acl_write_who(int who, __be32 **p, int *len)
{
	int i;
	int bytes;

	for (i = 0; i < ARRAY_SIZE(s2t_map); i++) {
		if (s2t_map[i].type == who) {
			memcpy(p, s2t_map[i].string, s2t_map[i].stringlen);
			return s2t_map[i].stringlen;
		}
		if (s2t_map[i].type != who)
			continue;
		bytes = 4 + (XDR_QUADLEN(s2t_map[i].stringlen) << 2);
		if (bytes > *len)
			return nfserr_resource;
		*p = xdr_encode_opaque(*p, s2t_map[i].string,
					s2t_map[i].stringlen);
		*len -= bytes;
		return 0;
	}
	BUG();
	WARN_ON_ONCE(1);
	return -1;
}

+33 −17
Original line number Diff line number Diff line
@@ -551,27 +551,46 @@ idmap_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen
	return 0;
}

static int
idmap_id_to_name(struct svc_rqst *rqstp, int type, u32 id, char *name)
static __be32 encode_ascii_id(u32 id, __be32 **p, int *buflen)
{
	char buf[11];
	int len;
	int bytes;

	len = sprintf(buf, "%u", id);
	bytes = 4 + (XDR_QUADLEN(len) << 2);
	if (bytes > *buflen)
		return nfserr_resource;
	*p = xdr_encode_opaque(*p, buf, len);
	*buflen -= bytes;
	return 0;
}

static __be32 idmap_id_to_name(struct svc_rqst *rqstp, int type, u32 id, __be32 **p, int *buflen)
{
	struct ent *item, key = {
		.id = id,
		.type = type,
	};
	int ret;
	int bytes;
	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);

	strlcpy(key.authname, rqst_authname(rqstp), sizeof(key.authname));
	ret = idmap_lookup(rqstp, idtoname_lookup, &key, nn->idtoname_cache, &item);
	if (ret == -ENOENT)
		return sprintf(name, "%u", id);
		return encode_ascii_id(id, p, buflen);
	if (ret)
		return ret;
		return nfserrno(ret);
	ret = strlen(item->name);
	BUG_ON(ret > IDMAP_NAMESZ);
	memcpy(name, item->name, ret);
	WARN_ON_ONCE(ret > IDMAP_NAMESZ);
	bytes = 4 + (XDR_QUADLEN(ret) << 2);
	if (bytes > *buflen)
		return nfserr_resource;
	*p = xdr_encode_opaque(*p, item->name, ret);
	*buflen -= bytes;
	cache_put(&item->h, nn->idtoname_cache);
	return ret;
	return 0;
}

static bool
@@ -603,12 +622,11 @@ do_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen, u
	return idmap_name_to_id(rqstp, type, name, namelen, id);
}

static int
do_id_to_name(struct svc_rqst *rqstp, int type, u32 id, char *name)
static __be32 encode_name_from_id(struct svc_rqst *rqstp, int type, u32 id, __be32 **p, int *buflen)
{
	if (nfs4_disable_idmapping && rqstp->rq_cred.cr_flavor < RPC_AUTH_GSS)
		return sprintf(name, "%u", id);
	return idmap_id_to_name(rqstp, type, id, name);
		return encode_ascii_id(id, p, buflen);
	return idmap_id_to_name(rqstp, type, id, p, buflen);
}

__be32
@@ -637,16 +655,14 @@ nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name, size_t namelen,
	return status;
}

int
nfsd_map_uid_to_name(struct svc_rqst *rqstp, kuid_t uid, char *name)
__be32 nfsd4_encode_user(struct svc_rqst *rqstp, kuid_t uid,  __be32 **p, int *buflen)
{
	u32 id = from_kuid(&init_user_ns, uid);
	return do_id_to_name(rqstp, IDMAP_TYPE_USER, id, name);
	return encode_name_from_id(rqstp, IDMAP_TYPE_USER, id, p, buflen);
}

int
nfsd_map_gid_to_name(struct svc_rqst *rqstp, kgid_t gid, char *name)
__be32 nfsd4_encode_group(struct svc_rqst *rqstp, kgid_t gid, __be32 **p, int *buflen)
{
	u32 id = from_kgid(&init_user_ns, gid);
	return do_id_to_name(rqstp, IDMAP_TYPE_GROUP, id, name);
	return encode_name_from_id(rqstp, IDMAP_TYPE_GROUP, id, p, buflen);
}
+6 −46
Original line number Diff line number Diff line
@@ -1965,56 +1965,16 @@ static u32 nfs4_file_type(umode_t mode)
	};
}

static __be32
nfsd4_encode_name(struct svc_rqst *rqstp, int whotype, kuid_t uid, kgid_t gid,
			__be32 **p, int *buflen)
{
	int status;

	if (*buflen < (XDR_QUADLEN(IDMAP_NAMESZ) << 2) + 4)
		return nfserr_resource;
	if (whotype != NFS4_ACL_WHO_NAMED)
		status = nfs4_acl_write_who(whotype, (u8 *)(*p + 1));
	else if (gid_valid(gid))
		status = nfsd_map_gid_to_name(rqstp, gid, (u8 *)(*p + 1));
	else
		status = nfsd_map_uid_to_name(rqstp, uid, (u8 *)(*p + 1));
	if (status < 0)
		return nfserrno(status);
	*p = xdr_encode_opaque(*p, NULL, status);
	*buflen -= (XDR_QUADLEN(status) << 2) + 4;
	BUG_ON(*buflen < 0);
	return 0;
}

static inline __be32
nfsd4_encode_user(struct svc_rqst *rqstp, kuid_t user, __be32 **p, int *buflen)
{
	return nfsd4_encode_name(rqstp, NFS4_ACL_WHO_NAMED, user, INVALID_GID,
				 p, buflen);
}

static inline __be32
nfsd4_encode_group(struct svc_rqst *rqstp, kgid_t group, __be32 **p, int *buflen)
{
	return nfsd4_encode_name(rqstp, NFS4_ACL_WHO_NAMED, INVALID_UID, group,
				 p, buflen);
}

static inline __be32
nfsd4_encode_aclname(struct svc_rqst *rqstp, struct nfs4_ace *ace,
		__be32 **p, int *buflen)
{
	kuid_t uid = INVALID_UID;
	kgid_t gid = INVALID_GID;

	if (ace->whotype == NFS4_ACL_WHO_NAMED) {
		if (ace->flag & NFS4_ACE_IDENTIFIER_GROUP)
			gid = ace->who_gid;
	if (ace->whotype != NFS4_ACL_WHO_NAMED)
		return nfs4_acl_write_who(ace->whotype, p, buflen);
	else if (ace->flag & NFS4_ACE_IDENTIFIER_GROUP)
		return nfsd4_encode_group(rqstp, ace->who_gid, p, buflen);
	else
			uid = ace->who_uid;
	}
	return nfsd4_encode_name(rqstp, ace->whotype, uid, gid, p, buflen);
		return nfsd4_encode_user(rqstp, ace->who_uid, p, buflen);
}

#define WORD0_ABSENT_FS_ATTRS (FATTR4_WORD0_FS_LOCATIONS | FATTR4_WORD0_FSID | \