Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.6 663 lines 16 kB view raw
1/* 2 * Mapping of UID/GIDs to name and vice versa. 3 * 4 * Copyright (c) 2002, 2003 The Regents of the University of 5 * Michigan. All rights reserved. 6 * 7 * Marius Aamodt Eriksen <marius@umich.edu> 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. Neither the name of the University nor the names of its 19 * contributors may be used to endorse or promote products derived 20 * from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 23 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 24 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 29 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 30 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 31 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35#include <linux/module.h> 36#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" 44 45/* 46 * Turn off idmapping when using AUTH_SYS. 47 */ 48static bool nfs4_disable_idmapping = true; 49module_param(nfs4_disable_idmapping, bool, 0644); 50MODULE_PARM_DESC(nfs4_disable_idmapping, 51 "Turn off server's NFSv4 idmapping when using 'sec=sys'"); 52 53/* 54 * Cache entry 55 */ 56 57/* 58 * XXX we know that IDMAP_NAMESZ < PAGE_SIZE, but it's ugly to rely on 59 * that. 60 */ 61 62struct ent { 63 struct cache_head h; 64 int type; /* User / Group */ 65 u32 id; 66 char name[IDMAP_NAMESZ]; 67 char authname[IDMAP_NAMESZ]; 68}; 69 70/* Common entry handling */ 71 72#define ENT_HASHBITS 8 73#define ENT_HASHMAX (1 << ENT_HASHBITS) 74 75static void 76ent_init(struct cache_head *cnew, struct cache_head *citm) 77{ 78 struct ent *new = container_of(cnew, struct ent, h); 79 struct ent *itm = container_of(citm, struct ent, h); 80 81 new->id = itm->id; 82 new->type = itm->type; 83 84 strlcpy(new->name, itm->name, sizeof(new->name)); 85 strlcpy(new->authname, itm->authname, sizeof(new->name)); 86} 87 88static void 89ent_put(struct kref *ref) 90{ 91 struct ent *map = container_of(ref, struct ent, h.ref); 92 kfree(map); 93} 94 95static struct cache_head * 96ent_alloc(void) 97{ 98 struct ent *e = kmalloc(sizeof(*e), GFP_KERNEL); 99 if (e) 100 return &e->h; 101 else 102 return NULL; 103} 104 105/* 106 * ID -> Name cache 107 */ 108 109static uint32_t 110idtoname_hash(struct ent *ent) 111{ 112 uint32_t hash; 113 114 hash = hash_str(ent->authname, ENT_HASHBITS); 115 hash = hash_long(hash ^ ent->id, ENT_HASHBITS); 116 117 /* Flip LSB for user/group */ 118 if (ent->type == IDMAP_TYPE_GROUP) 119 hash ^= 1; 120 121 return hash; 122} 123 124static void 125idtoname_request(struct cache_detail *cd, struct cache_head *ch, char **bpp, 126 int *blen) 127{ 128 struct ent *ent = container_of(ch, struct ent, h); 129 char idstr[11]; 130 131 qword_add(bpp, blen, ent->authname); 132 snprintf(idstr, sizeof(idstr), "%u", ent->id); 133 qword_add(bpp, blen, ent->type == IDMAP_TYPE_GROUP ? "group" : "user"); 134 qword_add(bpp, blen, idstr); 135 136 (*bpp)[-1] = '\n'; 137} 138 139static int 140idtoname_match(struct cache_head *ca, struct cache_head *cb) 141{ 142 struct ent *a = container_of(ca, struct ent, h); 143 struct ent *b = container_of(cb, struct ent, h); 144 145 return (a->id == b->id && a->type == b->type && 146 strcmp(a->authname, b->authname) == 0); 147} 148 149static int 150idtoname_show(struct seq_file *m, struct cache_detail *cd, struct cache_head *h) 151{ 152 struct ent *ent; 153 154 if (h == NULL) { 155 seq_puts(m, "#domain type id [name]\n"); 156 return 0; 157 } 158 ent = container_of(h, struct ent, h); 159 seq_printf(m, "%s %s %u", ent->authname, 160 ent->type == IDMAP_TYPE_GROUP ? "group" : "user", 161 ent->id); 162 if (test_bit(CACHE_VALID, &h->flags)) 163 seq_printf(m, " %s", ent->name); 164 seq_printf(m, "\n"); 165 return 0; 166} 167 168static void 169warn_no_idmapd(struct cache_detail *detail, int has_died) 170{ 171 printk("nfsd: nfsv4 idmapping failing: has idmapd %s?\n", 172 has_died ? "died" : "not been started"); 173} 174 175 176static int idtoname_parse(struct cache_detail *, char *, int); 177static struct ent *idtoname_lookup(struct cache_detail *, struct ent *); 178static struct ent *idtoname_update(struct cache_detail *, struct ent *, 179 struct ent *); 180 181static struct cache_detail idtoname_cache_template = { 182 .owner = THIS_MODULE, 183 .hash_size = ENT_HASHMAX, 184 .name = "nfs4.idtoname", 185 .cache_put = ent_put, 186 .cache_request = idtoname_request, 187 .cache_parse = idtoname_parse, 188 .cache_show = idtoname_show, 189 .warn_no_listener = warn_no_idmapd, 190 .match = idtoname_match, 191 .init = ent_init, 192 .update = ent_init, 193 .alloc = ent_alloc, 194}; 195 196static int 197idtoname_parse(struct cache_detail *cd, char *buf, int buflen) 198{ 199 struct ent ent, *res; 200 char *buf1, *bp; 201 int len; 202 int error = -EINVAL; 203 204 if (buf[buflen - 1] != '\n') 205 return (-EINVAL); 206 buf[buflen - 1]= '\0'; 207 208 buf1 = kmalloc(PAGE_SIZE, GFP_KERNEL); 209 if (buf1 == NULL) 210 return (-ENOMEM); 211 212 memset(&ent, 0, sizeof(ent)); 213 214 /* Authentication name */ 215 len = qword_get(&buf, buf1, PAGE_SIZE); 216 if (len <= 0 || len >= IDMAP_NAMESZ) 217 goto out; 218 memcpy(ent.authname, buf1, sizeof(ent.authname)); 219 220 /* Type */ 221 if (qword_get(&buf, buf1, PAGE_SIZE) <= 0) 222 goto out; 223 ent.type = strcmp(buf1, "user") == 0 ? 224 IDMAP_TYPE_USER : IDMAP_TYPE_GROUP; 225 226 /* ID */ 227 if (qword_get(&buf, buf1, PAGE_SIZE) <= 0) 228 goto out; 229 ent.id = simple_strtoul(buf1, &bp, 10); 230 if (bp == buf1) 231 goto out; 232 233 /* expiry */ 234 ent.h.expiry_time = get_expiry(&buf); 235 if (ent.h.expiry_time == 0) 236 goto out; 237 238 error = -ENOMEM; 239 res = idtoname_lookup(cd, &ent); 240 if (!res) 241 goto out; 242 243 /* Name */ 244 error = -EINVAL; 245 len = qword_get(&buf, buf1, PAGE_SIZE); 246 if (len < 0 || len >= IDMAP_NAMESZ) 247 goto out; 248 if (len == 0) 249 set_bit(CACHE_NEGATIVE, &ent.h.flags); 250 else 251 memcpy(ent.name, buf1, sizeof(ent.name)); 252 error = -ENOMEM; 253 res = idtoname_update(cd, &ent, res); 254 if (res == NULL) 255 goto out; 256 257 cache_put(&res->h, cd); 258 error = 0; 259out: 260 kfree(buf1); 261 return error; 262} 263 264static struct ent * 265idtoname_lookup(struct cache_detail *cd, struct ent *item) 266{ 267 struct cache_head *ch = sunrpc_cache_lookup(cd, &item->h, 268 idtoname_hash(item)); 269 if (ch) 270 return container_of(ch, struct ent, h); 271 else 272 return NULL; 273} 274 275static struct ent * 276idtoname_update(struct cache_detail *cd, struct ent *new, struct ent *old) 277{ 278 struct cache_head *ch = sunrpc_cache_update(cd, &new->h, &old->h, 279 idtoname_hash(new)); 280 if (ch) 281 return container_of(ch, struct ent, h); 282 else 283 return NULL; 284} 285 286 287/* 288 * Name -> ID cache 289 */ 290 291static inline int 292nametoid_hash(struct ent *ent) 293{ 294 return hash_str(ent->name, ENT_HASHBITS); 295} 296 297static void 298nametoid_request(struct cache_detail *cd, struct cache_head *ch, char **bpp, 299 int *blen) 300{ 301 struct ent *ent = container_of(ch, struct ent, h); 302 303 qword_add(bpp, blen, ent->authname); 304 qword_add(bpp, blen, ent->type == IDMAP_TYPE_GROUP ? "group" : "user"); 305 qword_add(bpp, blen, ent->name); 306 307 (*bpp)[-1] = '\n'; 308} 309 310static int 311nametoid_match(struct cache_head *ca, struct cache_head *cb) 312{ 313 struct ent *a = container_of(ca, struct ent, h); 314 struct ent *b = container_of(cb, struct ent, h); 315 316 return (a->type == b->type && strcmp(a->name, b->name) == 0 && 317 strcmp(a->authname, b->authname) == 0); 318} 319 320static int 321nametoid_show(struct seq_file *m, struct cache_detail *cd, struct cache_head *h) 322{ 323 struct ent *ent; 324 325 if (h == NULL) { 326 seq_puts(m, "#domain type name [id]\n"); 327 return 0; 328 } 329 ent = container_of(h, struct ent, h); 330 seq_printf(m, "%s %s %s", ent->authname, 331 ent->type == IDMAP_TYPE_GROUP ? "group" : "user", 332 ent->name); 333 if (test_bit(CACHE_VALID, &h->flags)) 334 seq_printf(m, " %u", ent->id); 335 seq_printf(m, "\n"); 336 return 0; 337} 338 339static struct ent *nametoid_lookup(struct cache_detail *, struct ent *); 340static struct ent *nametoid_update(struct cache_detail *, struct ent *, 341 struct ent *); 342static int nametoid_parse(struct cache_detail *, char *, int); 343 344static struct cache_detail nametoid_cache_template = { 345 .owner = THIS_MODULE, 346 .hash_size = ENT_HASHMAX, 347 .name = "nfs4.nametoid", 348 .cache_put = ent_put, 349 .cache_request = nametoid_request, 350 .cache_parse = nametoid_parse, 351 .cache_show = nametoid_show, 352 .warn_no_listener = warn_no_idmapd, 353 .match = nametoid_match, 354 .init = ent_init, 355 .update = ent_init, 356 .alloc = ent_alloc, 357}; 358 359static int 360nametoid_parse(struct cache_detail *cd, char *buf, int buflen) 361{ 362 struct ent ent, *res; 363 char *buf1; 364 int len, error = -EINVAL; 365 366 if (buf[buflen - 1] != '\n') 367 return (-EINVAL); 368 buf[buflen - 1]= '\0'; 369 370 buf1 = kmalloc(PAGE_SIZE, GFP_KERNEL); 371 if (buf1 == NULL) 372 return (-ENOMEM); 373 374 memset(&ent, 0, sizeof(ent)); 375 376 /* Authentication name */ 377 len = qword_get(&buf, buf1, PAGE_SIZE); 378 if (len <= 0 || len >= IDMAP_NAMESZ) 379 goto out; 380 memcpy(ent.authname, buf1, sizeof(ent.authname)); 381 382 /* Type */ 383 if (qword_get(&buf, buf1, PAGE_SIZE) <= 0) 384 goto out; 385 ent.type = strcmp(buf1, "user") == 0 ? 386 IDMAP_TYPE_USER : IDMAP_TYPE_GROUP; 387 388 /* Name */ 389 len = qword_get(&buf, buf1, PAGE_SIZE); 390 if (len <= 0 || len >= IDMAP_NAMESZ) 391 goto out; 392 memcpy(ent.name, buf1, sizeof(ent.name)); 393 394 /* expiry */ 395 ent.h.expiry_time = get_expiry(&buf); 396 if (ent.h.expiry_time == 0) 397 goto out; 398 399 /* ID */ 400 error = get_int(&buf, &ent.id); 401 if (error == -EINVAL) 402 goto out; 403 if (error == -ENOENT) 404 set_bit(CACHE_NEGATIVE, &ent.h.flags); 405 406 error = -ENOMEM; 407 res = nametoid_lookup(cd, &ent); 408 if (res == NULL) 409 goto out; 410 res = nametoid_update(cd, &ent, res); 411 if (res == NULL) 412 goto out; 413 414 cache_put(&res->h, cd); 415 error = 0; 416out: 417 kfree(buf1); 418 return (error); 419} 420 421 422static struct ent * 423nametoid_lookup(struct cache_detail *cd, struct ent *item) 424{ 425 struct cache_head *ch = sunrpc_cache_lookup(cd, &item->h, 426 nametoid_hash(item)); 427 if (ch) 428 return container_of(ch, struct ent, h); 429 else 430 return NULL; 431} 432 433static struct ent * 434nametoid_update(struct cache_detail *cd, struct ent *new, struct ent *old) 435{ 436 struct cache_head *ch = sunrpc_cache_update(cd, &new->h, &old->h, 437 nametoid_hash(new)); 438 if (ch) 439 return container_of(ch, struct ent, h); 440 else 441 return NULL; 442} 443 444/* 445 * Exported API 446 */ 447 448int 449nfsd_idmap_init(struct net *net) 450{ 451 int rv; 452 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 453 454 nn->idtoname_cache = cache_create_net(&idtoname_cache_template, net); 455 if (IS_ERR(nn->idtoname_cache)) 456 return PTR_ERR(nn->idtoname_cache); 457 rv = cache_register_net(nn->idtoname_cache, net); 458 if (rv) 459 goto destroy_idtoname_cache; 460 nn->nametoid_cache = cache_create_net(&nametoid_cache_template, net); 461 if (IS_ERR(nn->nametoid_cache)) { 462 rv = PTR_ERR(nn->nametoid_cache); 463 goto unregister_idtoname_cache; 464 } 465 rv = cache_register_net(nn->nametoid_cache, net); 466 if (rv) 467 goto destroy_nametoid_cache; 468 return 0; 469 470destroy_nametoid_cache: 471 cache_destroy_net(nn->nametoid_cache, net); 472unregister_idtoname_cache: 473 cache_unregister_net(nn->idtoname_cache, net); 474destroy_idtoname_cache: 475 cache_destroy_net(nn->idtoname_cache, net); 476 return rv; 477} 478 479void 480nfsd_idmap_shutdown(struct net *net) 481{ 482 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 483 484 cache_unregister_net(nn->idtoname_cache, net); 485 cache_unregister_net(nn->nametoid_cache, net); 486 cache_destroy_net(nn->idtoname_cache, net); 487 cache_destroy_net(nn->nametoid_cache, net); 488} 489 490static int 491idmap_lookup(struct svc_rqst *rqstp, 492 struct ent *(*lookup_fn)(struct cache_detail *, struct ent *), 493 struct ent *key, struct cache_detail *detail, struct ent **item) 494{ 495 int ret; 496 497 *item = lookup_fn(detail, key); 498 if (!*item) 499 return -ENOMEM; 500 retry: 501 ret = cache_check(detail, &(*item)->h, &rqstp->rq_chandle); 502 503 if (ret == -ETIMEDOUT) { 504 struct ent *prev_item = *item; 505 *item = lookup_fn(detail, key); 506 if (*item != prev_item) 507 goto retry; 508 cache_put(&(*item)->h, detail); 509 } 510 return ret; 511} 512 513static char * 514rqst_authname(struct svc_rqst *rqstp) 515{ 516 struct auth_domain *clp; 517 518 clp = rqstp->rq_gssclient ? rqstp->rq_gssclient : rqstp->rq_client; 519 return clp->name; 520} 521 522static __be32 523idmap_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen, 524 u32 *id) 525{ 526 struct ent *item, key = { 527 .type = type, 528 }; 529 int ret; 530 struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); 531 532 if (namelen + 1 > sizeof(key.name)) 533 return nfserr_badowner; 534 memcpy(key.name, name, namelen); 535 key.name[namelen] = '\0'; 536 strlcpy(key.authname, rqst_authname(rqstp), sizeof(key.authname)); 537 ret = idmap_lookup(rqstp, nametoid_lookup, &key, nn->nametoid_cache, &item); 538 if (ret == -ENOENT) 539 return nfserr_badowner; 540 if (ret) 541 return nfserrno(ret); 542 *id = item->id; 543 cache_put(&item->h, nn->nametoid_cache); 544 return 0; 545} 546 547static __be32 encode_ascii_id(struct xdr_stream *xdr, u32 id) 548{ 549 char buf[11]; 550 int len; 551 __be32 *p; 552 553 len = sprintf(buf, "%u", id); 554 p = xdr_reserve_space(xdr, len + 4); 555 if (!p) 556 return nfserr_resource; 557 p = xdr_encode_opaque(p, buf, len); 558 return 0; 559} 560 561static __be32 idmap_id_to_name(struct xdr_stream *xdr, 562 struct svc_rqst *rqstp, int type, u32 id) 563{ 564 struct ent *item, key = { 565 .id = id, 566 .type = type, 567 }; 568 __be32 *p; 569 int ret; 570 struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); 571 572 strlcpy(key.authname, rqst_authname(rqstp), sizeof(key.authname)); 573 ret = idmap_lookup(rqstp, idtoname_lookup, &key, nn->idtoname_cache, &item); 574 if (ret == -ENOENT) 575 return encode_ascii_id(xdr, id); 576 if (ret) 577 return nfserrno(ret); 578 ret = strlen(item->name); 579 WARN_ON_ONCE(ret > IDMAP_NAMESZ); 580 p = xdr_reserve_space(xdr, ret + 4); 581 if (!p) 582 return nfserr_resource; 583 p = xdr_encode_opaque(p, item->name, ret); 584 cache_put(&item->h, nn->idtoname_cache); 585 return 0; 586} 587 588static bool 589numeric_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen, u32 *id) 590{ 591 int ret; 592 char buf[11]; 593 594 if (namelen + 1 > sizeof(buf)) 595 /* too long to represent a 32-bit id: */ 596 return false; 597 /* Just to make sure it's null-terminated: */ 598 memcpy(buf, name, namelen); 599 buf[namelen] = '\0'; 600 ret = kstrtouint(buf, 10, id); 601 return ret == 0; 602} 603 604static __be32 605do_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen, u32 *id) 606{ 607 if (nfs4_disable_idmapping && rqstp->rq_cred.cr_flavor < RPC_AUTH_GSS) 608 if (numeric_name_to_id(rqstp, type, name, namelen, id)) 609 return 0; 610 /* 611 * otherwise, fall through and try idmapping, for 612 * backwards compatibility with clients sending names: 613 */ 614 return idmap_name_to_id(rqstp, type, name, namelen, id); 615} 616 617static __be32 encode_name_from_id(struct xdr_stream *xdr, 618 struct svc_rqst *rqstp, int type, u32 id) 619{ 620 if (nfs4_disable_idmapping && rqstp->rq_cred.cr_flavor < RPC_AUTH_GSS) 621 return encode_ascii_id(xdr, id); 622 return idmap_id_to_name(xdr, rqstp, type, id); 623} 624 625__be32 626nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, size_t namelen, 627 kuid_t *uid) 628{ 629 __be32 status; 630 u32 id = -1; 631 status = do_name_to_id(rqstp, IDMAP_TYPE_USER, name, namelen, &id); 632 *uid = make_kuid(&init_user_ns, id); 633 if (!uid_valid(*uid)) 634 status = nfserr_badowner; 635 return status; 636} 637 638__be32 639nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name, size_t namelen, 640 kgid_t *gid) 641{ 642 __be32 status; 643 u32 id = -1; 644 status = do_name_to_id(rqstp, IDMAP_TYPE_GROUP, name, namelen, &id); 645 *gid = make_kgid(&init_user_ns, id); 646 if (!gid_valid(*gid)) 647 status = nfserr_badowner; 648 return status; 649} 650 651__be32 nfsd4_encode_user(struct xdr_stream *xdr, struct svc_rqst *rqstp, 652 kuid_t uid) 653{ 654 u32 id = from_kuid(&init_user_ns, uid); 655 return encode_name_from_id(xdr, rqstp, IDMAP_TYPE_USER, id); 656} 657 658__be32 nfsd4_encode_group(struct xdr_stream *xdr, struct svc_rqst *rqstp, 659 kgid_t gid) 660{ 661 u32 id = from_kgid(&init_user_ns, gid); 662 return encode_name_from_id(xdr, rqstp, IDMAP_TYPE_GROUP, id); 663}