nfs4idmap.c 16.0 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
/*
 *  Mapping of UID/GIDs to name and vice versa.
 *
 *  Copyright (c) 2002, 2003 The Regents of the University of
 *  Michigan.  All rights reserved.
 *
 *  Marius Aamodt Eriksen <marius@umich.edu>
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *  1. Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *  3. Neither the name of the University nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
 *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
 *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <linux/module.h>
#include <linux/seq_file.h>
37
#include <linux/sched.h>
38
#include <linux/slab.h>
39
#include <linux/sunrpc/svc_xprt.h>
40
#include <net/net_namespace.h>
41
#include "idmap.h"
42
#include "nfsd.h"
43
#include "netns.h"
L
Linus Torvalds 已提交
44

J
J. Bruce Fields 已提交
45 46 47 48 49 50 51 52
/*
 * Turn off idmapping when using AUTH_SYS.
 */
static bool nfs4_disable_idmapping = true;
module_param(nfs4_disable_idmapping, bool, 0644);
MODULE_PARM_DESC(nfs4_disable_idmapping,
		"Turn off server's NFSv4 idmapping when using 'sec=sys'");

L
Linus Torvalds 已提交
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
/*
 * Cache entry
 */

/*
 * XXX we know that IDMAP_NAMESZ < PAGE_SIZE, but it's ugly to rely on
 * that.
 */

#define IDMAP_TYPE_USER  0
#define IDMAP_TYPE_GROUP 1

struct ent {
	struct cache_head h;
	int               type;		       /* User / Group */
68
	u32               id;
L
Linus Torvalds 已提交
69 70 71 72 73 74 75 76 77
	char              name[IDMAP_NAMESZ];
	char              authname[IDMAP_NAMESZ];
};

/* Common entry handling */

#define ENT_HASHBITS          8
#define ENT_HASHMAX           (1 << ENT_HASHBITS)

78 79
static void
ent_init(struct cache_head *cnew, struct cache_head *citm)
L
Linus Torvalds 已提交
80
{
81 82 83
	struct ent *new = container_of(cnew, struct ent, h);
	struct ent *itm = container_of(citm, struct ent, h);

L
Linus Torvalds 已提交
84 85 86 87 88 89 90
	new->id = itm->id;
	new->type = itm->type;

	strlcpy(new->name, itm->name, sizeof(new->name));
	strlcpy(new->authname, itm->authname, sizeof(new->name));
}

91
static void
92
ent_put(struct kref *ref)
L
Linus Torvalds 已提交
93
{
94 95
	struct ent *map = container_of(ref, struct ent, h.ref);
	kfree(map);
L
Linus Torvalds 已提交
96 97
}

98 99 100 101 102 103 104 105 106 107
static struct cache_head *
ent_alloc(void)
{
	struct ent *e = kmalloc(sizeof(*e), GFP_KERNEL);
	if (e)
		return &e->h;
	else
		return NULL;
}

L
Linus Torvalds 已提交
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
/*
 * ID -> Name cache
 */

static uint32_t
idtoname_hash(struct ent *ent)
{
	uint32_t hash;

	hash = hash_str(ent->authname, ENT_HASHBITS);
	hash = hash_long(hash ^ ent->id, ENT_HASHBITS);

	/* Flip LSB for user/group */
	if (ent->type == IDMAP_TYPE_GROUP)
		hash ^= 1;

	return hash;
}

static void
idtoname_request(struct cache_detail *cd, struct cache_head *ch, char **bpp,
    int *blen)
{
 	struct ent *ent = container_of(ch, struct ent, h);
	char idstr[11];

	qword_add(bpp, blen, ent->authname);
135
	snprintf(idstr, sizeof(idstr), "%u", ent->id);
L
Linus Torvalds 已提交
136 137 138 139 140 141
	qword_add(bpp, blen, ent->type == IDMAP_TYPE_GROUP ? "group" : "user");
	qword_add(bpp, blen, idstr);

	(*bpp)[-1] = '\n';
}

142 143
static int
idtoname_match(struct cache_head *ca, struct cache_head *cb)
L
Linus Torvalds 已提交
144
{
145 146 147
	struct ent *a = container_of(ca, struct ent, h);
	struct ent *b = container_of(cb, struct ent, h);

L
Linus Torvalds 已提交
148 149 150 151 152 153 154 155 156 157 158 159 160 161
	return (a->id == b->id && a->type == b->type &&
	    strcmp(a->authname, b->authname) == 0);
}

static int
idtoname_show(struct seq_file *m, struct cache_detail *cd, struct cache_head *h)
{
	struct ent *ent;

	if (h == NULL) {
		seq_puts(m, "#domain type id [name]\n");
		return 0;
	}
	ent = container_of(h, struct ent, h);
162
	seq_printf(m, "%s %s %u", ent->authname,
L
Linus Torvalds 已提交
163 164 165 166 167 168 169 170 171
			ent->type == IDMAP_TYPE_GROUP ? "group" : "user",
			ent->id);
	if (test_bit(CACHE_VALID, &h->flags))
		seq_printf(m, " %s", ent->name);
	seq_printf(m, "\n");
	return 0;
}

static void
172
warn_no_idmapd(struct cache_detail *detail, int has_died)
L
Linus Torvalds 已提交
173 174
{
	printk("nfsd: nfsv4 idmapping failing: has idmapd %s?\n",
175
			has_died ? "died" : "not been started");
L
Linus Torvalds 已提交
176 177 178 179
}


static int         idtoname_parse(struct cache_detail *, char *, int);
180 181 182
static struct ent *idtoname_lookup(struct cache_detail *, struct ent *);
static struct ent *idtoname_update(struct cache_detail *, struct ent *,
				   struct ent *);
L
Linus Torvalds 已提交
183

184
static struct cache_detail idtoname_cache_template = {
185
	.owner		= THIS_MODULE,
L
Linus Torvalds 已提交
186 187 188
	.hash_size	= ENT_HASHMAX,
	.name		= "nfs4.idtoname",
	.cache_put	= ent_put,
189
	.cache_request	= idtoname_request,
L
Linus Torvalds 已提交
190 191 192
	.cache_parse	= idtoname_parse,
	.cache_show	= idtoname_show,
	.warn_no_listener = warn_no_idmapd,
193 194 195 196
	.match		= idtoname_match,
	.init		= ent_init,
	.update		= ent_init,
	.alloc		= ent_alloc,
L
Linus Torvalds 已提交
197 198
};

H
Harvey Harrison 已提交
199
static int
L
Linus Torvalds 已提交
200 201 202 203
idtoname_parse(struct cache_detail *cd, char *buf, int buflen)
{
	struct ent ent, *res;
	char *buf1, *bp;
204
	int len;
L
Linus Torvalds 已提交
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239
	int error = -EINVAL;

	if (buf[buflen - 1] != '\n')
		return (-EINVAL);
	buf[buflen - 1]= '\0';

	buf1 = kmalloc(PAGE_SIZE, GFP_KERNEL);
	if (buf1 == NULL)
		return (-ENOMEM);

	memset(&ent, 0, sizeof(ent));

	/* Authentication name */
	if (qword_get(&buf, buf1, PAGE_SIZE) <= 0)
		goto out;
	memcpy(ent.authname, buf1, sizeof(ent.authname));

	/* Type */
	if (qword_get(&buf, buf1, PAGE_SIZE) <= 0)
		goto out;
	ent.type = strcmp(buf1, "user") == 0 ?
		IDMAP_TYPE_USER : IDMAP_TYPE_GROUP;

	/* ID */
	if (qword_get(&buf, buf1, PAGE_SIZE) <= 0)
		goto out;
	ent.id = simple_strtoul(buf1, &bp, 10);
	if (bp == buf1)
		goto out;

	/* expiry */
	ent.h.expiry_time = get_expiry(&buf);
	if (ent.h.expiry_time == 0)
		goto out;

240
	error = -ENOMEM;
241
	res = idtoname_lookup(cd, &ent);
242 243 244
	if (!res)
		goto out;

L
Linus Torvalds 已提交
245
	/* Name */
246 247 248
	error = -EINVAL;
	len = qword_get(&buf, buf1, PAGE_SIZE);
	if (len < 0)
L
Linus Torvalds 已提交
249
		goto out;
250
	if (len == 0)
L
Linus Torvalds 已提交
251
		set_bit(CACHE_NEGATIVE, &ent.h.flags);
252 253 254
	else if (len >= IDMAP_NAMESZ)
		goto out;
	else
L
Linus Torvalds 已提交
255 256
		memcpy(ent.name, buf1, sizeof(ent.name));
	error = -ENOMEM;
257
	res = idtoname_update(cd, &ent, res);
258
	if (res == NULL)
L
Linus Torvalds 已提交
259 260
		goto out;

261
	cache_put(&res->h, cd);
L
Linus Torvalds 已提交
262 263 264 265 266 267 268 269

	error = 0;
out:
	kfree(buf1);

	return error;
}

270 271

static struct ent *
272
idtoname_lookup(struct cache_detail *cd, struct ent *item)
273
{
274
	struct cache_head *ch = sunrpc_cache_lookup(cd, &item->h,
275 276 277 278 279 280 281 282
						    idtoname_hash(item));
	if (ch)
		return container_of(ch, struct ent, h);
	else
		return NULL;
}

static struct ent *
283
idtoname_update(struct cache_detail *cd, struct ent *new, struct ent *old)
284
{
285
	struct cache_head *ch = sunrpc_cache_update(cd, &new->h, &old->h,
286 287 288 289 290 291 292
						    idtoname_hash(new));
	if (ch)
		return container_of(ch, struct ent, h);
	else
		return NULL;
}

L
Linus Torvalds 已提交
293 294 295 296 297 298 299 300 301 302 303

/*
 * Name -> ID cache
 */

static inline int
nametoid_hash(struct ent *ent)
{
	return hash_str(ent->name, ENT_HASHBITS);
}

304
static void
L
Linus Torvalds 已提交
305 306 307 308 309 310 311 312 313 314 315 316
nametoid_request(struct cache_detail *cd, struct cache_head *ch, char **bpp,
    int *blen)
{
 	struct ent *ent = container_of(ch, struct ent, h);

	qword_add(bpp, blen, ent->authname);
	qword_add(bpp, blen, ent->type == IDMAP_TYPE_GROUP ? "group" : "user");
	qword_add(bpp, blen, ent->name);

	(*bpp)[-1] = '\n';
}

317 318
static int
nametoid_match(struct cache_head *ca, struct cache_head *cb)
L
Linus Torvalds 已提交
319
{
320 321 322
	struct ent *a = container_of(ca, struct ent, h);
	struct ent *b = container_of(cb, struct ent, h);

L
Linus Torvalds 已提交
323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340
	return (a->type == b->type && strcmp(a->name, b->name) == 0 &&
	    strcmp(a->authname, b->authname) == 0);
}

static int
nametoid_show(struct seq_file *m, struct cache_detail *cd, struct cache_head *h)
{
	struct ent *ent;

	if (h == NULL) {
		seq_puts(m, "#domain type name [id]\n");
		return 0;
	}
	ent = container_of(h, struct ent, h);
	seq_printf(m, "%s %s %s", ent->authname,
			ent->type == IDMAP_TYPE_GROUP ? "group" : "user",
			ent->name);
	if (test_bit(CACHE_VALID, &h->flags))
341
		seq_printf(m, " %u", ent->id);
L
Linus Torvalds 已提交
342 343 344 345
	seq_printf(m, "\n");
	return 0;
}

346 347 348
static struct ent *nametoid_lookup(struct cache_detail *, struct ent *);
static struct ent *nametoid_update(struct cache_detail *, struct ent *,
				   struct ent *);
349
static int         nametoid_parse(struct cache_detail *, char *, int);
L
Linus Torvalds 已提交
350

351
static struct cache_detail nametoid_cache_template = {
352
	.owner		= THIS_MODULE,
L
Linus Torvalds 已提交
353 354 355
	.hash_size	= ENT_HASHMAX,
	.name		= "nfs4.nametoid",
	.cache_put	= ent_put,
356
	.cache_request	= nametoid_request,
L
Linus Torvalds 已提交
357 358 359
	.cache_parse	= nametoid_parse,
	.cache_show	= nametoid_show,
	.warn_no_listener = warn_no_idmapd,
360 361 362 363
	.match		= nametoid_match,
	.init		= ent_init,
	.update		= ent_init,
	.alloc		= ent_alloc,
L
Linus Torvalds 已提交
364 365
};

366
static int
L
Linus Torvalds 已提交
367 368 369 370
nametoid_parse(struct cache_detail *cd, char *buf, int buflen)
{
	struct ent ent, *res;
	char *buf1;
371
	int len, error = -EINVAL;
L
Linus Torvalds 已提交
372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394

	if (buf[buflen - 1] != '\n')
		return (-EINVAL);
	buf[buflen - 1]= '\0';

	buf1 = kmalloc(PAGE_SIZE, GFP_KERNEL);
	if (buf1 == NULL)
		return (-ENOMEM);

	memset(&ent, 0, sizeof(ent));

	/* Authentication name */
	if (qword_get(&buf, buf1, PAGE_SIZE) <= 0)
		goto out;
	memcpy(ent.authname, buf1, sizeof(ent.authname));

	/* Type */
	if (qword_get(&buf, buf1, PAGE_SIZE) <= 0)
		goto out;
	ent.type = strcmp(buf1, "user") == 0 ?
		IDMAP_TYPE_USER : IDMAP_TYPE_GROUP;

	/* Name */
395 396
	len = qword_get(&buf, buf1, PAGE_SIZE);
	if (len <= 0 || len >= IDMAP_NAMESZ)
L
Linus Torvalds 已提交
397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412
		goto out;
	memcpy(ent.name, buf1, sizeof(ent.name));

	/* expiry */
	ent.h.expiry_time = get_expiry(&buf);
	if (ent.h.expiry_time == 0)
		goto out;

	/* ID */
	error = get_int(&buf, &ent.id);
	if (error == -EINVAL)
		goto out;
	if (error == -ENOENT)
		set_bit(CACHE_NEGATIVE, &ent.h.flags);

	error = -ENOMEM;
413
	res = nametoid_lookup(cd, &ent);
414 415
	if (res == NULL)
		goto out;
416
	res = nametoid_update(cd, &ent, res);
417
	if (res == NULL)
L
Linus Torvalds 已提交
418 419
		goto out;

420
	cache_put(&res->h, cd);
L
Linus Torvalds 已提交
421 422 423 424 425 426 427
	error = 0;
out:
	kfree(buf1);

	return (error);
}

428 429

static struct ent *
430
nametoid_lookup(struct cache_detail *cd, struct ent *item)
431
{
432
	struct cache_head *ch = sunrpc_cache_lookup(cd, &item->h,
433 434 435 436 437 438 439 440
						    nametoid_hash(item));
	if (ch)
		return container_of(ch, struct ent, h);
	else
		return NULL;
}

static struct ent *
441
nametoid_update(struct cache_detail *cd, struct ent *new, struct ent *old)
442
{
443
	struct cache_head *ch = sunrpc_cache_update(cd, &new->h, &old->h,
444 445 446 447 448 449
						    nametoid_hash(new));
	if (ch)
		return container_of(ch, struct ent, h);
	else
		return NULL;
}
L
Linus Torvalds 已提交
450 451 452 453 454

/*
 * Exported API
 */

455
int
456
nfsd_idmap_init(struct net *net)
L
Linus Torvalds 已提交
457
{
458
	int rv;
459
	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
460

461 462 463 464
	nn->idtoname_cache = cache_create_net(&idtoname_cache_template, net);
	if (IS_ERR(nn->idtoname_cache))
		return PTR_ERR(nn->idtoname_cache);
	rv = cache_register_net(nn->idtoname_cache, net);
465
	if (rv)
466
		goto destroy_idtoname_cache;
467 468
	nn->nametoid_cache = cache_create_net(&nametoid_cache_template, net);
	if (IS_ERR(nn->nametoid_cache)) {
469
		rv = PTR_ERR(nn->nametoid_cache);
470
		goto unregister_idtoname_cache;
471 472 473 474
	}
	rv = cache_register_net(nn->nametoid_cache, net);
	if (rv)
		goto destroy_nametoid_cache;
475 476
	return 0;

477 478
destroy_nametoid_cache:
	cache_destroy_net(nn->nametoid_cache, net);
479 480 481 482
unregister_idtoname_cache:
	cache_unregister_net(nn->idtoname_cache, net);
destroy_idtoname_cache:
	cache_destroy_net(nn->idtoname_cache, net);
483
	return rv;
L
Linus Torvalds 已提交
484 485 486
}

void
487
nfsd_idmap_shutdown(struct net *net)
L
Linus Torvalds 已提交
488
{
489 490 491
	struct nfsd_net *nn = net_generic(net, nfsd_net_id);

	cache_unregister_net(nn->idtoname_cache, net);
492
	cache_unregister_net(nn->nametoid_cache, net);
493
	cache_destroy_net(nn->idtoname_cache, net);
494
	cache_destroy_net(nn->nametoid_cache, net);
L
Linus Torvalds 已提交
495 496 497 498
}

static int
idmap_lookup(struct svc_rqst *rqstp,
499 500
		struct ent *(*lookup_fn)(struct cache_detail *, struct ent *),
		struct ent *key, struct cache_detail *detail, struct ent **item)
L
Linus Torvalds 已提交
501 502 503
{
	int ret;

504
	*item = lookup_fn(detail, key);
505
	if (!*item)
L
Linus Torvalds 已提交
506
		return -ENOMEM;
507 508 509 510 511
 retry:
	ret = cache_check(detail, &(*item)->h, &rqstp->rq_chandle);

	if (ret == -ETIMEDOUT) {
		struct ent *prev_item = *item;
512
		*item = lookup_fn(detail, key);
513 514 515
		if (*item != prev_item)
			goto retry;
		cache_put(&(*item)->h, detail);
L
Linus Torvalds 已提交
516 517 518 519
	}
	return ret;
}

520 521 522 523 524 525 526 527 528
static char *
rqst_authname(struct svc_rqst *rqstp)
{
	struct auth_domain *clp;

	clp = rqstp->rq_gssclient ? rqstp->rq_gssclient : rqstp->rq_client;
	return clp->name;
}

529
static __be32
L
Linus Torvalds 已提交
530
idmap_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen,
531
		u32 *id)
L
Linus Torvalds 已提交
532 533 534 535 536
{
	struct ent *item, key = {
		.type = type,
	};
	int ret;
537
	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
L
Linus Torvalds 已提交
538 539

	if (namelen + 1 > sizeof(key.name))
540
		return nfserr_badowner;
L
Linus Torvalds 已提交
541 542
	memcpy(key.name, name, namelen);
	key.name[namelen] = '\0';
543
	strlcpy(key.authname, rqst_authname(rqstp), sizeof(key.authname));
544
	ret = idmap_lookup(rqstp, nametoid_lookup, &key, nn->nametoid_cache, &item);
L
Linus Torvalds 已提交
545
	if (ret == -ENOENT)
546
		return nfserr_badowner;
L
Linus Torvalds 已提交
547
	if (ret)
548
		return nfserrno(ret);
L
Linus Torvalds 已提交
549
	*id = item->id;
550
	cache_put(&item->h, nn->nametoid_cache);
L
Linus Torvalds 已提交
551 552 553
	return 0;
}

554
static __be32 encode_ascii_id(struct xdr_stream *xdr, u32 id)
555 556 557
{
	char buf[11];
	int len;
558
	__be32 *p;
559 560

	len = sprintf(buf, "%u", id);
561 562
	p = xdr_reserve_space(xdr, len + 4);
	if (!p)
563
		return nfserr_resource;
564
	p = xdr_encode_opaque(p, buf, len);
565 566 567
	return 0;
}

568 569
static __be32 idmap_id_to_name(struct xdr_stream *xdr,
			       struct svc_rqst *rqstp, int type, u32 id)
L
Linus Torvalds 已提交
570 571 572 573 574
{
	struct ent *item, key = {
		.id = id,
		.type = type,
	};
575
	__be32 *p;
L
Linus Torvalds 已提交
576
	int ret;
577
	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
L
Linus Torvalds 已提交
578

579
	strlcpy(key.authname, rqst_authname(rqstp), sizeof(key.authname));
580
	ret = idmap_lookup(rqstp, idtoname_lookup, &key, nn->idtoname_cache, &item);
L
Linus Torvalds 已提交
581
	if (ret == -ENOENT)
582
		return encode_ascii_id(xdr, id);
L
Linus Torvalds 已提交
583
	if (ret)
584
		return nfserrno(ret);
L
Linus Torvalds 已提交
585
	ret = strlen(item->name);
586
	WARN_ON_ONCE(ret > IDMAP_NAMESZ);
587 588
	p = xdr_reserve_space(xdr, ret + 4);
	if (!p)
589
		return nfserr_resource;
590
	p = xdr_encode_opaque(p, item->name, ret);
591
	cache_put(&item->h, nn->idtoname_cache);
592
	return 0;
L
Linus Torvalds 已提交
593 594
}

J
J. Bruce Fields 已提交
595
static bool
596
numeric_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen, u32 *id)
J
J. Bruce Fields 已提交
597 598 599 600 601 602 603 604 605 606
{
	int ret;
	char buf[11];

	if (namelen + 1 > sizeof(buf))
		/* too long to represent a 32-bit id: */
		return false;
	/* Just to make sure it's null-terminated: */
	memcpy(buf, name, namelen);
	buf[namelen] = '\0';
607
	ret = kstrtouint(buf, 10, id);
J
J. Bruce Fields 已提交
608 609 610 611
	return ret == 0;
}

static __be32
612
do_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen, u32 *id)
J
J. Bruce Fields 已提交
613
{
614
	if (nfs4_disable_idmapping && rqstp->rq_cred.cr_flavor < RPC_AUTH_GSS)
J
J. Bruce Fields 已提交
615 616 617 618 619 620 621 622 623
		if (numeric_name_to_id(rqstp, type, name, namelen, id))
			return 0;
		/*
		 * otherwise, fall through and try idmapping, for
		 * backwards compatibility with clients sending names:
		 */
	return idmap_name_to_id(rqstp, type, name, namelen, id);
}

624 625
static __be32 encode_name_from_id(struct xdr_stream *xdr,
				  struct svc_rqst *rqstp, int type, u32 id)
J
J. Bruce Fields 已提交
626
{
627
	if (nfs4_disable_idmapping && rqstp->rq_cred.cr_flavor < RPC_AUTH_GSS)
628 629
		return encode_ascii_id(xdr, id);
	return idmap_id_to_name(xdr, rqstp, type, id);
J
J. Bruce Fields 已提交
630 631
}

632
__be32
L
Linus Torvalds 已提交
633
nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, size_t namelen,
634
		kuid_t *uid)
L
Linus Torvalds 已提交
635
{
636 637 638 639 640 641 642
	__be32 status;
	u32 id = -1;
	status = do_name_to_id(rqstp, IDMAP_TYPE_USER, name, namelen, &id);
	*uid = make_kuid(&init_user_ns, id);
	if (!uid_valid(*uid))
		status = nfserr_badowner;
	return status;
L
Linus Torvalds 已提交
643 644
}

645
__be32
L
Linus Torvalds 已提交
646
nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name, size_t namelen,
647
		kgid_t *gid)
L
Linus Torvalds 已提交
648
{
649 650 651 652 653 654 655
	__be32 status;
	u32 id = -1;
	status = do_name_to_id(rqstp, IDMAP_TYPE_GROUP, name, namelen, &id);
	*gid = make_kgid(&init_user_ns, id);
	if (!gid_valid(*gid))
		status = nfserr_badowner;
	return status;
L
Linus Torvalds 已提交
656 657
}

658 659
__be32 nfsd4_encode_user(struct xdr_stream *xdr, struct svc_rqst *rqstp,
			 kuid_t uid)
L
Linus Torvalds 已提交
660
{
661
	u32 id = from_kuid(&init_user_ns, uid);
662
	return encode_name_from_id(xdr, rqstp, IDMAP_TYPE_USER, id);
L
Linus Torvalds 已提交
663 664
}

665 666
__be32 nfsd4_encode_group(struct xdr_stream *xdr, struct svc_rqst *rqstp,
			  kgid_t gid)
L
Linus Torvalds 已提交
667
{
668
	u32 id = from_kgid(&init_user_ns, gid);
669
	return encode_name_from_id(xdr, rqstp, IDMAP_TYPE_GROUP, id);
L
Linus Torvalds 已提交
670
}