1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2014 Nexenta Systems, Inc. All rights reserved. 24 * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved. 25 */ 26 27 #include <sys/param.h> 28 #include <sys/errno.h> 29 #include <sys/vfs.h> 30 #include <sys/vnode.h> 31 #include <sys/cred.h> 32 #include <sys/cmn_err.h> 33 #include <sys/systm.h> 34 #include <sys/kmem.h> 35 #include <sys/pathname.h> 36 #include <sys/utsname.h> 37 #include <sys/debug.h> 38 #include <sys/door.h> 39 #include <sys/sdt.h> 40 #include <sys/thread.h> 41 42 #include <rpc/types.h> 43 #include <rpc/auth.h> 44 #include <rpc/clnt.h> 45 46 #include <nfs/nfs.h> 47 #include <nfs/export.h> 48 #include <nfs/nfs_clnt.h> 49 #include <nfs/auth.h> 50 51 #define EQADDR(a1, a2) \ 52 (bcmp((char *)(a1)->buf, (char *)(a2)->buf, (a1)->len) == 0 && \ 53 (a1)->len == (a2)->len) 54 55 static struct knetconfig auth_knconf; 56 static servinfo_t svp; 57 static clinfo_t ci; 58 59 static struct kmem_cache *exi_cache_handle; 60 static void exi_cache_reclaim(void *); 61 static void exi_cache_trim(struct exportinfo *exi); 62 63 extern pri_t minclsyspri; 64 65 int nfsauth_cache_hit; 66 int nfsauth_cache_miss; 67 int nfsauth_cache_refresh; 68 int nfsauth_cache_reclaim; 69 70 /* 71 * The lifetime of an auth cache entry: 72 * ------------------------------------ 73 * 74 * An auth cache entry is created with both the auth_time 75 * and auth_freshness times set to the current time. 76 * 77 * Upon every client access which results in a hit, the 78 * auth_time will be updated. 79 * 80 * If a client access determines that the auth_freshness 81 * indicates that the entry is STALE, then it will be 82 * refreshed. Note that this will explicitly reset 83 * auth_time. 84 * 85 * When the REFRESH successfully occurs, then the 86 * auth_freshness is updated. 87 * 88 * There are two ways for an entry to leave the cache: 89 * 90 * 1) Purged by an action on the export (remove or changed) 91 * 2) Memory backpressure from the kernel (check against NFSAUTH_CACHE_TRIM) 92 * 93 * For 2) we check the timeout value against auth_time. 94 */ 95 96 /* 97 * Number of seconds until we mark for refresh an auth cache entry. 98 */ 99 #define NFSAUTH_CACHE_REFRESH 600 100 101 /* 102 * Number of idle seconds until we yield to backpressure 103 * to trim a cache entry. 104 */ 105 #define NFSAUTH_CACHE_TRIM 3600 106 107 /* 108 * While we could encapuslate the exi_list inside the 109 * exi structure, we can't do that for the auth_list. 110 * So, to keep things looking clean, we keep them both 111 * in these external lists. 112 */ 113 typedef struct refreshq_exi_node { 114 struct exportinfo *ren_exi; 115 list_t ren_authlist; 116 list_node_t ren_node; 117 } refreshq_exi_node_t; 118 119 typedef struct refreshq_auth_node { 120 struct auth_cache *ran_auth; 121 list_node_t ran_node; 122 } refreshq_auth_node_t; 123 124 /* 125 * Used to manipulate things on the refreshq_queue. 126 * Note that the refresh thread will effectively 127 * pop a node off of the queue, at which point it 128 * will no longer need to hold the mutex. 129 */ 130 static kmutex_t refreshq_lock; 131 static list_t refreshq_queue; 132 static kcondvar_t refreshq_cv; 133 134 /* 135 * A list_t would be overkill. These are auth_cache 136 * entries which are no longer linked to an exi. 137 * It should be the case that all of their states 138 * are NFS_AUTH_INVALID. 139 * 140 * I.e., the only way to be put on this list is 141 * iff their state indicated that they had been placed 142 * on the refreshq_queue. 143 * 144 * Note that while there is no link from the exi or 145 * back to the exi, the exi can not go away until 146 * these entries are harvested. 147 */ 148 static struct auth_cache *refreshq_dead_entries; 149 150 /* 151 * If there is ever a problem with loading the 152 * module, then nfsauth_fini() needs to be called 153 * to remove state. In that event, since the 154 * refreshq thread has been started, they need to 155 * work together to get rid of state. 156 */ 157 typedef enum nfsauth_refreshq_thread_state { 158 REFRESHQ_THREAD_RUNNING, 159 REFRESHQ_THREAD_FINI_REQ, 160 REFRESHQ_THREAD_HALTED 161 } nfsauth_refreshq_thread_state_t; 162 163 nfsauth_refreshq_thread_state_t 164 refreshq_thread_state = REFRESHQ_THREAD_HALTED; 165 166 static void nfsauth_free_node(struct auth_cache *); 167 static void nfsauth_remove_dead_entry(struct auth_cache *); 168 static void nfsauth_refresh_thread(void); 169 170 /* 171 * mountd is a server-side only daemon. This will need to be 172 * revisited if the NFS server is ever made zones-aware. 173 */ 174 kmutex_t mountd_lock; 175 door_handle_t mountd_dh; 176 177 void 178 mountd_args(uint_t did) 179 { 180 mutex_enter(&mountd_lock); 181 if (mountd_dh != NULL) 182 door_ki_rele(mountd_dh); 183 mountd_dh = door_ki_lookup(did); 184 mutex_exit(&mountd_lock); 185 } 186 187 void 188 nfsauth_init(void) 189 { 190 /* 191 * mountd can be restarted by smf(5). We need to make sure 192 * the updated door handle will safely make it to mountd_dh 193 */ 194 mutex_init(&mountd_lock, NULL, MUTEX_DEFAULT, NULL); 195 196 mutex_init(&refreshq_lock, NULL, MUTEX_DEFAULT, NULL); 197 list_create(&refreshq_queue, sizeof (refreshq_exi_node_t), 198 offsetof(refreshq_exi_node_t, ren_node)); 199 refreshq_dead_entries = NULL; 200 201 cv_init(&refreshq_cv, NULL, CV_DEFAULT, NULL); 202 203 /* 204 * Allocate nfsauth cache handle 205 */ 206 exi_cache_handle = kmem_cache_create("exi_cache_handle", 207 sizeof (struct auth_cache), 0, NULL, NULL, 208 exi_cache_reclaim, NULL, NULL, 0); 209 210 refreshq_thread_state = REFRESHQ_THREAD_RUNNING; 211 (void) zthread_create(NULL, 0, nfsauth_refresh_thread, 212 NULL, 0, minclsyspri); 213 } 214 215 /* 216 * Finalization routine for nfsauth. It is important to call this routine 217 * before destroying the exported_lock. 218 */ 219 void 220 nfsauth_fini(void) 221 { 222 refreshq_exi_node_t *ren; 223 refreshq_auth_node_t *ran; 224 struct auth_cache *p; 225 struct auth_cache *auth_next; 226 227 /* 228 * Prevent the refreshq_thread from getting new 229 * work. 230 */ 231 mutex_enter(&refreshq_lock); 232 if (refreshq_thread_state != REFRESHQ_THREAD_HALTED) { 233 refreshq_thread_state = REFRESHQ_THREAD_FINI_REQ; 234 cv_broadcast(&refreshq_cv); 235 236 /* 237 * Also, wait for nfsauth_refresh_thread() to exit. 238 */ 239 while (refreshq_thread_state != REFRESHQ_THREAD_HALTED) { 240 cv_wait(&refreshq_cv, &refreshq_lock); 241 } 242 } 243 244 /* 245 * Walk the exi_list and in turn, walk the 246 * auth_lists. 247 */ 248 while ((ren = list_remove_head(&refreshq_queue))) { 249 while ((ran = list_remove_head(&ren->ren_authlist))) { 250 kmem_free(ran, sizeof (refreshq_auth_node_t)); 251 } 252 253 list_destroy(&ren->ren_authlist); 254 exi_rele(ren->ren_exi); 255 kmem_free(ren, sizeof (refreshq_exi_node_t)); 256 } 257 258 /* 259 * Okay, now that the lists are deleted, we 260 * need to see if there are any dead entries 261 * to harvest. 262 */ 263 for (p = refreshq_dead_entries; p != NULL; p = auth_next) { 264 auth_next = p->auth_next; 265 nfsauth_free_node(p); 266 } 267 268 mutex_exit(&refreshq_lock); 269 270 list_destroy(&refreshq_queue); 271 272 cv_destroy(&refreshq_cv); 273 mutex_destroy(&refreshq_lock); 274 275 mutex_destroy(&mountd_lock); 276 277 /* 278 * Deallocate nfsauth cache handle 279 */ 280 kmem_cache_destroy(exi_cache_handle); 281 } 282 283 /* 284 * Convert the address in a netbuf to 285 * a hash index for the auth_cache table. 286 */ 287 static int 288 hash(struct netbuf *a) 289 { 290 int i, h = 0; 291 292 for (i = 0; i < a->len; i++) 293 h ^= a->buf[i]; 294 295 return (h & (AUTH_TABLESIZE - 1)); 296 } 297 298 /* 299 * Mask out the components of an 300 * address that do not identify 301 * a host. For socket addresses the 302 * masking gets rid of the port number. 303 */ 304 static void 305 addrmask(struct netbuf *addr, struct netbuf *mask) 306 { 307 int i; 308 309 for (i = 0; i < addr->len; i++) 310 addr->buf[i] &= mask->buf[i]; 311 } 312 313 /* 314 * nfsauth4_access is used for NFS V4 auth checking. Besides doing 315 * the common nfsauth_access(), it will check if the client can 316 * have a limited access to this vnode even if the security flavor 317 * used does not meet the policy. 318 */ 319 int 320 nfsauth4_access(struct exportinfo *exi, vnode_t *vp, struct svc_req *req, 321 cred_t *cr, uid_t *uid, gid_t *gid, uint_t *ngids, gid_t **gids) 322 { 323 int access; 324 325 access = nfsauth_access(exi, req, cr, uid, gid, ngids, gids); 326 327 /* 328 * There are cases that the server needs to allow the client 329 * to have a limited view. 330 * 331 * e.g. 332 * /export is shared as "sec=sys,rw=dfs-test-4,sec=krb5,rw" 333 * /export/home is shared as "sec=sys,rw" 334 * 335 * When the client mounts /export with sec=sys, the client 336 * would get a limited view with RO access on /export to see 337 * "home" only because the client is allowed to access 338 * /export/home with auth_sys. 339 */ 340 if (access & NFSAUTH_DENIED || access & NFSAUTH_WRONGSEC) { 341 /* 342 * Allow ro permission with LIMITED view if there is a 343 * sub-dir exported under vp. 344 */ 345 if (has_visible(exi, vp)) 346 return (NFSAUTH_LIMITED); 347 } 348 349 return (access); 350 } 351 352 static void 353 sys_log(const char *msg) 354 { 355 static time_t tstamp = 0; 356 time_t now; 357 358 /* 359 * msg is shown (at most) once per minute 360 */ 361 now = gethrestime_sec(); 362 if ((tstamp + 60) < now) { 363 tstamp = now; 364 cmn_err(CE_WARN, msg); 365 } 366 } 367 368 /* 369 * Callup to the mountd to get access information in the kernel. 370 */ 371 static bool_t 372 nfsauth_retrieve(struct exportinfo *exi, char *req_netid, int flavor, 373 struct netbuf *addr, int *access, uid_t clnt_uid, gid_t clnt_gid, 374 uint_t clnt_gids_cnt, const gid_t *clnt_gids, uid_t *srv_uid, 375 gid_t *srv_gid, uint_t *srv_gids_cnt, gid_t **srv_gids) 376 { 377 varg_t varg = {0}; 378 nfsauth_res_t res = {0}; 379 XDR xdrs; 380 size_t absz; 381 caddr_t abuf; 382 int last = 0; 383 door_arg_t da; 384 door_info_t di; 385 door_handle_t dh; 386 uint_t ntries = 0; 387 388 /* 389 * No entry in the cache for this client/flavor 390 * so we need to call the nfsauth service in the 391 * mount daemon. 392 */ 393 394 varg.vers = V_PROTO; 395 varg.arg_u.arg.cmd = NFSAUTH_ACCESS; 396 varg.arg_u.arg.areq.req_client.n_len = addr->len; 397 varg.arg_u.arg.areq.req_client.n_bytes = addr->buf; 398 varg.arg_u.arg.areq.req_netid = req_netid; 399 varg.arg_u.arg.areq.req_path = exi->exi_export.ex_path; 400 varg.arg_u.arg.areq.req_flavor = flavor; 401 varg.arg_u.arg.areq.req_clnt_uid = clnt_uid; 402 varg.arg_u.arg.areq.req_clnt_gid = clnt_gid; 403 varg.arg_u.arg.areq.req_clnt_gids.len = clnt_gids_cnt; 404 varg.arg_u.arg.areq.req_clnt_gids.val = (gid_t *)clnt_gids; 405 406 DTRACE_PROBE1(nfsserv__func__nfsauth__varg, varg_t *, &varg); 407 408 /* 409 * Setup the XDR stream for encoding the arguments. Notice that 410 * in addition to the args having variable fields (req_netid and 411 * req_path), the argument data structure is itself versioned, 412 * so we need to make sure we can size the arguments buffer 413 * appropriately to encode all the args. If we can't get sizing 414 * info _or_ properly encode the arguments, there's really no 415 * point in continuting, so we fail the request. 416 */ 417 if ((absz = xdr_sizeof(xdr_varg, &varg)) == 0) { 418 *access = NFSAUTH_DENIED; 419 return (FALSE); 420 } 421 422 abuf = (caddr_t)kmem_alloc(absz, KM_SLEEP); 423 xdrmem_create(&xdrs, abuf, absz, XDR_ENCODE); 424 if (!xdr_varg(&xdrs, &varg)) { 425 XDR_DESTROY(&xdrs); 426 goto fail; 427 } 428 XDR_DESTROY(&xdrs); 429 430 /* 431 * Prepare the door arguments 432 * 433 * We don't know the size of the message the daemon 434 * will pass back to us. By setting rbuf to NULL, 435 * we force the door code to allocate a buf of the 436 * appropriate size. We must set rsize > 0, however, 437 * else the door code acts as if no response was 438 * expected and doesn't pass the data to us. 439 */ 440 da.data_ptr = (char *)abuf; 441 da.data_size = absz; 442 da.desc_ptr = NULL; 443 da.desc_num = 0; 444 da.rbuf = NULL; 445 da.rsize = 1; 446 447 retry: 448 mutex_enter(&mountd_lock); 449 dh = mountd_dh; 450 if (dh != NULL) 451 door_ki_hold(dh); 452 mutex_exit(&mountd_lock); 453 454 if (dh == NULL) { 455 /* 456 * The rendezvous point has not been established yet! 457 * This could mean that either mountd(1m) has not yet 458 * been started or that _this_ routine nuked the door 459 * handle after receiving an EINTR for a REVOKED door. 460 * 461 * Returning NFSAUTH_DROP will cause the NFS client 462 * to retransmit the request, so let's try to be more 463 * rescillient and attempt for ntries before we bail. 464 */ 465 if (++ntries % NFSAUTH_DR_TRYCNT) { 466 delay(hz); 467 goto retry; 468 } 469 470 kmem_free(abuf, absz); 471 472 sys_log("nfsauth: mountd has not established door"); 473 *access = NFSAUTH_DROP; 474 return (FALSE); 475 } 476 477 ntries = 0; 478 479 /* 480 * Now that we've got what we need, place the call. 481 */ 482 switch (door_ki_upcall_limited(dh, &da, NULL, SIZE_MAX, 0)) { 483 case 0: /* Success */ 484 door_ki_rele(dh); 485 486 if (da.data_ptr == NULL && da.data_size == 0) { 487 /* 488 * The door_return that contained the data 489 * failed! We're here because of the 2nd 490 * door_return (w/o data) such that we can 491 * get control of the thread (and exit 492 * gracefully). 493 */ 494 DTRACE_PROBE1(nfsserv__func__nfsauth__door__nil, 495 door_arg_t *, &da); 496 goto fail; 497 } 498 499 break; 500 501 case EAGAIN: 502 /* 503 * Server out of resources; back off for a bit 504 */ 505 door_ki_rele(dh); 506 delay(hz); 507 goto retry; 508 /* NOTREACHED */ 509 510 case EINTR: 511 if (!door_ki_info(dh, &di)) { 512 door_ki_rele(dh); 513 514 if (di.di_attributes & DOOR_REVOKED) { 515 /* 516 * The server barfed and revoked 517 * the (existing) door on us; we 518 * want to wait to give smf(5) a 519 * chance to restart mountd(1m) 520 * and establish a new door handle. 521 */ 522 mutex_enter(&mountd_lock); 523 if (dh == mountd_dh) { 524 door_ki_rele(mountd_dh); 525 mountd_dh = NULL; 526 } 527 mutex_exit(&mountd_lock); 528 delay(hz); 529 goto retry; 530 } 531 /* 532 * If the door was _not_ revoked on us, 533 * then more than likely we took an INTR, 534 * so we need to fail the operation. 535 */ 536 goto fail; 537 } 538 /* 539 * The only failure that can occur from getting 540 * the door info is EINVAL, so we let the code 541 * below handle it. 542 */ 543 /* FALLTHROUGH */ 544 545 case EBADF: 546 case EINVAL: 547 default: 548 /* 549 * If we have a stale door handle, give smf a last 550 * chance to start it by sleeping for a little bit. 551 * If we're still hosed, we'll fail the call. 552 * 553 * Since we're going to reacquire the door handle 554 * upon the retry, we opt to sleep for a bit and 555 * _not_ to clear mountd_dh. If mountd restarted 556 * and was able to set mountd_dh, we should see 557 * the new instance; if not, we won't get caught 558 * up in the retry/DELAY loop. 559 */ 560 door_ki_rele(dh); 561 if (!last) { 562 delay(hz); 563 last++; 564 goto retry; 565 } 566 sys_log("nfsauth: stale mountd door handle"); 567 goto fail; 568 } 569 570 ASSERT(da.rbuf != NULL); 571 572 /* 573 * No door errors encountered; setup the XDR stream for decoding 574 * the results. If we fail to decode the results, we've got no 575 * other recourse than to fail the request. 576 */ 577 xdrmem_create(&xdrs, da.rbuf, da.rsize, XDR_DECODE); 578 if (!xdr_nfsauth_res(&xdrs, &res)) { 579 xdr_free(xdr_nfsauth_res, (char *)&res); 580 XDR_DESTROY(&xdrs); 581 kmem_free(da.rbuf, da.rsize); 582 goto fail; 583 } 584 XDR_DESTROY(&xdrs); 585 kmem_free(da.rbuf, da.rsize); 586 587 DTRACE_PROBE1(nfsserv__func__nfsauth__results, nfsauth_res_t *, &res); 588 switch (res.stat) { 589 case NFSAUTH_DR_OKAY: 590 *access = res.ares.auth_perm; 591 *srv_uid = res.ares.auth_srv_uid; 592 *srv_gid = res.ares.auth_srv_gid; 593 *srv_gids_cnt = res.ares.auth_srv_gids.len; 594 *srv_gids = kmem_alloc(*srv_gids_cnt * sizeof (gid_t), 595 KM_SLEEP); 596 bcopy(res.ares.auth_srv_gids.val, *srv_gids, 597 *srv_gids_cnt * sizeof (gid_t)); 598 break; 599 600 case NFSAUTH_DR_EFAIL: 601 case NFSAUTH_DR_DECERR: 602 case NFSAUTH_DR_BADCMD: 603 default: 604 xdr_free(xdr_nfsauth_res, (char *)&res); 605 fail: 606 *access = NFSAUTH_DENIED; 607 kmem_free(abuf, absz); 608 return (FALSE); 609 /* NOTREACHED */ 610 } 611 612 xdr_free(xdr_nfsauth_res, (char *)&res); 613 kmem_free(abuf, absz); 614 615 return (TRUE); 616 } 617 618 static void 619 nfsauth_refresh_thread(void) 620 { 621 refreshq_exi_node_t *ren; 622 refreshq_auth_node_t *ran; 623 624 struct exportinfo *exi; 625 626 int access; 627 bool_t retrieval; 628 629 callb_cpr_t cprinfo; 630 631 CALLB_CPR_INIT(&cprinfo, &refreshq_lock, callb_generic_cpr, 632 "nfsauth_refresh"); 633 634 for (;;) { 635 mutex_enter(&refreshq_lock); 636 if (refreshq_thread_state != REFRESHQ_THREAD_RUNNING) { 637 /* Keep the hold on the lock! */ 638 break; 639 } 640 641 ren = list_remove_head(&refreshq_queue); 642 if (ren == NULL) { 643 CALLB_CPR_SAFE_BEGIN(&cprinfo); 644 cv_wait(&refreshq_cv, &refreshq_lock); 645 CALLB_CPR_SAFE_END(&cprinfo, &refreshq_lock); 646 mutex_exit(&refreshq_lock); 647 continue; 648 } 649 mutex_exit(&refreshq_lock); 650 651 exi = ren->ren_exi; 652 ASSERT(exi != NULL); 653 654 /* 655 * Since the ren was removed from the refreshq_queue above, 656 * this is the only thread aware about the ren existence, so we 657 * have the exclusive ownership of it and we do not need to 658 * protect it by any lock. 659 */ 660 while ((ran = list_remove_head(&ren->ren_authlist))) { 661 662 uint_t ngids; 663 gid_t *gids; 664 struct auth_cache *p = ran->ran_auth; 665 666 ASSERT(p != NULL); 667 kmem_free(ran, sizeof (refreshq_auth_node_t)); 668 669 /* 670 * We are shutting down. No need to refresh 671 * entries which are about to be nuked. 672 * 673 * So just throw them away until we are done 674 * with this exi node... 675 */ 676 if (refreshq_thread_state != REFRESHQ_THREAD_RUNNING) 677 continue; 678 679 mutex_enter(&p->auth_lock); 680 681 /* 682 * Make sure the state is valid now that 683 * we have the lock. Note that once we 684 * change the state to NFS_AUTH_REFRESHING, 685 * no other thread will be able to work on 686 * this entry. 687 */ 688 if (p->auth_state != NFS_AUTH_STALE) { 689 /* 690 * Once it goes INVALID, it can not 691 * change state. 692 */ 693 if (p->auth_state == NFS_AUTH_INVALID) { 694 mutex_exit(&p->auth_lock); 695 nfsauth_remove_dead_entry(p); 696 } else 697 mutex_exit(&p->auth_lock); 698 699 continue; 700 } 701 702 p->auth_state = NFS_AUTH_REFRESHING; 703 mutex_exit(&p->auth_lock); 704 705 DTRACE_PROBE2(nfsauth__debug__cache__refresh, 706 struct exportinfo *, exi, 707 struct auth_cache *, p); 708 709 /* 710 * The first caching of the access rights 711 * is done with the netid pulled out of the 712 * request from the client. All subsequent 713 * users of the cache may or may not have 714 * the same netid. It doesn't matter. So 715 * when we refresh, we simply use the netid 716 * of the request which triggered the 717 * refresh attempt. 718 */ 719 ASSERT(p->auth_netid != NULL); 720 721 retrieval = nfsauth_retrieve(exi, p->auth_netid, 722 p->auth_flavor, &p->auth_addr, &access, 723 p->auth_clnt_uid, p->auth_clnt_gid, 724 p->auth_clnt_ngids, p->auth_clnt_gids, 725 &p->auth_srv_uid, &p->auth_srv_gid, &ngids, &gids); 726 727 /* 728 * This can only be set in one other place 729 * and the state has to be NFS_AUTH_FRESH. 730 */ 731 kmem_free(p->auth_netid, strlen(p->auth_netid) + 1); 732 p->auth_netid = NULL; 733 734 mutex_enter(&p->auth_lock); 735 if (p->auth_state == NFS_AUTH_INVALID) { 736 mutex_exit(&p->auth_lock); 737 nfsauth_remove_dead_entry(p); 738 if (retrieval == TRUE) 739 kmem_free(gids, ngids * sizeof (gid_t)); 740 } else { 741 /* 742 * If we got an error, do not reset the 743 * time. This will cause the next access 744 * check for the client to reschedule this 745 * node. 746 */ 747 if (retrieval == TRUE) { 748 p->auth_access = access; 749 750 kmem_free(p->auth_srv_gids, 751 p->auth_srv_ngids * sizeof (gid_t)); 752 p->auth_srv_ngids = ngids; 753 p->auth_srv_gids = gids; 754 755 p->auth_freshness = gethrestime_sec(); 756 } 757 p->auth_state = NFS_AUTH_FRESH; 758 mutex_exit(&p->auth_lock); 759 } 760 } 761 762 list_destroy(&ren->ren_authlist); 763 exi_rele(ren->ren_exi); 764 kmem_free(ren, sizeof (refreshq_exi_node_t)); 765 } 766 767 refreshq_thread_state = REFRESHQ_THREAD_HALTED; 768 cv_broadcast(&refreshq_cv); 769 CALLB_CPR_EXIT(&cprinfo); 770 zthread_exit(); 771 } 772 773 /* 774 * Get the access information from the cache or callup to the mountd 775 * to get and cache the access information in the kernel. 776 */ 777 static int 778 nfsauth_cache_get(struct exportinfo *exi, struct svc_req *req, int flavor, 779 cred_t *cr, uid_t *uid, gid_t *gid, uint_t *ngids, gid_t **gids) 780 { 781 struct netbuf *taddrmask; 782 struct netbuf addr; 783 struct netbuf *claddr; 784 struct auth_cache **head; 785 struct auth_cache *p; 786 struct auth_cache *prev; 787 int access; 788 time_t refresh; 789 790 refreshq_exi_node_t *ren; 791 refreshq_auth_node_t *ran; 792 793 uid_t tmpuid; 794 gid_t tmpgid; 795 uint_t tmpngids; 796 gid_t *tmpgids; 797 798 ASSERT(cr != NULL); 799 800 /* 801 * Now check whether this client already 802 * has an entry for this flavor in the cache 803 * for this export. 804 * Get the caller's address, mask off the 805 * parts of the address that do not identify 806 * the host (port number, etc), and then hash 807 * it to find the chain of cache entries. 808 */ 809 810 claddr = svc_getrpccaller(req->rq_xprt); 811 addr = *claddr; 812 addr.buf = kmem_alloc(addr.len, KM_SLEEP); 813 bcopy(claddr->buf, addr.buf, claddr->len); 814 SVC_GETADDRMASK(req->rq_xprt, SVC_TATTR_ADDRMASK, (void **)&taddrmask); 815 ASSERT(taddrmask != NULL); 816 if (taddrmask) 817 addrmask(&addr, taddrmask); 818 819 rw_enter(&exi->exi_cache_lock, RW_READER); 820 head = &exi->exi_cache[hash(&addr)]; 821 retry: 822 prev = NULL; 823 for (p = *head; p != NULL; p = p->auth_next) { 824 if (EQADDR(&addr, &p->auth_addr) && flavor == p->auth_flavor && 825 crgetuid(cr) == p->auth_clnt_uid && 826 crgetgid(cr) == p->auth_clnt_gid) 827 break; 828 prev = p; 829 } 830 831 if (p != NULL) { 832 /* 833 * In a case the client's supplemental groups changed we need 834 * to discard the auth_cache entry and re-retrieve it. 835 */ 836 if (p->auth_clnt_ngids != crgetngroups(cr) || 837 bcmp(p->auth_clnt_gids, crgetgroups(cr), 838 p->auth_clnt_ngids * sizeof (gid_t))) { 839 struct auth_cache *next; 840 841 /* 842 * To remove the auth_cache entry from exi we need to 843 * hold the exi_cache_lock for write. If we do not 844 * have it yet, we will try to upgrade, or re-lock as a 845 * last resort. In a case of re-lock we will retry the 846 * search for the auth_cache entry because it might 847 * changed in the meantime. 848 */ 849 ASSERT(RW_LOCK_HELD(&exi->exi_cache_lock)); 850 if (rw_read_locked(&exi->exi_cache_lock) != 0) { 851 if (rw_tryupgrade(&exi->exi_cache_lock) == 0) { 852 rw_exit(&exi->exi_cache_lock); 853 rw_enter(&exi->exi_cache_lock, 854 RW_WRITER); 855 856 goto retry; 857 } 858 } 859 860 /* 861 * Now, remove the entry from exi and free it, or place 862 * it at the dead list. 863 */ 864 next = p->auth_next; 865 mutex_enter(&p->auth_lock); 866 if (p->auth_state != NFS_AUTH_FRESH) { 867 p->auth_state = NFS_AUTH_INVALID; 868 mutex_exit(&p->auth_lock); 869 870 mutex_enter(&refreshq_lock); 871 p->auth_next = refreshq_dead_entries; 872 refreshq_dead_entries = p; 873 mutex_exit(&refreshq_lock); 874 } else { 875 mutex_exit(&p->auth_lock); 876 nfsauth_free_node(p); 877 } 878 879 /* 880 * Finally, disconnect the entry from exi 881 */ 882 if (prev == NULL) 883 *head = next; 884 else 885 prev->auth_next = next; 886 887 goto retrieve; 888 } 889 890 /* 891 * If we hold the lock for write, downgrade 892 */ 893 if (rw_read_locked(&exi->exi_cache_lock) == 0) 894 rw_downgrade(&exi->exi_cache_lock); 895 896 nfsauth_cache_hit++; 897 898 refresh = gethrestime_sec() - p->auth_freshness; 899 DTRACE_PROBE2(nfsauth__debug__cache__hit, 900 int, nfsauth_cache_hit, 901 time_t, refresh); 902 903 mutex_enter(&p->auth_lock); 904 if ((refresh > NFSAUTH_CACHE_REFRESH) && 905 p->auth_state == NFS_AUTH_FRESH) { 906 p->auth_state = NFS_AUTH_STALE; 907 mutex_exit(&p->auth_lock); 908 909 ASSERT(p->auth_netid == NULL); 910 p->auth_netid = 911 strdup(svc_getnetid(req->rq_xprt)); 912 913 nfsauth_cache_refresh++; 914 915 DTRACE_PROBE3(nfsauth__debug__cache__stale, 916 struct exportinfo *, exi, 917 struct auth_cache *, p, 918 int, nfsauth_cache_refresh); 919 920 ran = kmem_alloc(sizeof (refreshq_auth_node_t), 921 KM_SLEEP); 922 ran->ran_auth = p; 923 924 mutex_enter(&refreshq_lock); 925 /* 926 * We should not add a work queue 927 * item if the thread is not 928 * accepting them. 929 */ 930 if (refreshq_thread_state == REFRESHQ_THREAD_RUNNING) { 931 /* 932 * Is there an existing exi_list? 933 */ 934 for (ren = list_head(&refreshq_queue); 935 ren != NULL; 936 ren = list_next(&refreshq_queue, ren)) { 937 if (ren->ren_exi == exi) { 938 list_insert_tail( 939 &ren->ren_authlist, ran); 940 break; 941 } 942 } 943 944 if (ren == NULL) { 945 ren = kmem_alloc( 946 sizeof (refreshq_exi_node_t), 947 KM_SLEEP); 948 949 exi_hold(exi); 950 ren->ren_exi = exi; 951 952 list_create(&ren->ren_authlist, 953 sizeof (refreshq_auth_node_t), 954 offsetof(refreshq_auth_node_t, 955 ran_node)); 956 957 list_insert_tail(&ren->ren_authlist, 958 ran); 959 list_insert_tail(&refreshq_queue, ren); 960 } 961 962 cv_broadcast(&refreshq_cv); 963 } else { 964 kmem_free(ran, sizeof (refreshq_auth_node_t)); 965 } 966 967 mutex_exit(&refreshq_lock); 968 } else { 969 mutex_exit(&p->auth_lock); 970 } 971 972 access = p->auth_access; 973 if (uid != NULL) 974 *uid = p->auth_srv_uid; 975 if (gid != NULL) 976 *gid = p->auth_srv_gid; 977 if (ngids != NULL && gids != NULL) { 978 *ngids = p->auth_srv_ngids; 979 *gids = kmem_alloc(*ngids * sizeof (gid_t), KM_SLEEP); 980 bcopy(p->auth_srv_gids, *gids, *ngids * sizeof (gid_t)); 981 } 982 983 p->auth_time = gethrestime_sec(); 984 985 rw_exit(&exi->exi_cache_lock); 986 kmem_free(addr.buf, addr.len); 987 988 return (access); 989 } 990 991 retrieve: 992 rw_exit(&exi->exi_cache_lock); 993 994 nfsauth_cache_miss++; 995 996 if (!nfsauth_retrieve(exi, svc_getnetid(req->rq_xprt), flavor, 997 &addr, &access, crgetuid(cr), crgetgid(cr), crgetngroups(cr), 998 crgetgroups(cr), &tmpuid, &tmpgid, &tmpngids, &tmpgids)) { 999 kmem_free(addr.buf, addr.len); 1000 if (ngids != NULL && gids != NULL) { 1001 *ngids = 0; 1002 *gids = NULL; 1003 } 1004 return (access); 1005 } 1006 1007 if (uid != NULL) 1008 *uid = tmpuid; 1009 if (gid != NULL) 1010 *gid = tmpgid; 1011 if (ngids != NULL && gids != NULL) { 1012 *ngids = tmpngids; 1013 *gids = tmpgids; 1014 1015 /* 1016 * We need a copy of gids for the auth_cache entry 1017 */ 1018 tmpgids = kmem_alloc(tmpngids * sizeof (gid_t), KM_NOSLEEP); 1019 if (tmpgids != NULL) 1020 bcopy(*gids, tmpgids, tmpngids * sizeof (gid_t)); 1021 } 1022 1023 /* 1024 * Now cache the result on the cache chain 1025 * for this export (if there's enough memory) 1026 */ 1027 p = kmem_cache_alloc(exi_cache_handle, KM_NOSLEEP); 1028 if (p != NULL) 1029 p->auth_clnt_gids = kmem_alloc( 1030 crgetngroups(cr) * sizeof (gid_t), KM_NOSLEEP); 1031 if (p != NULL && (tmpngids == 0 || tmpgids != NULL) && 1032 (crgetngroups(cr) == 0 || p->auth_clnt_gids != NULL)) { 1033 p->auth_addr = addr; 1034 p->auth_flavor = flavor; 1035 p->auth_clnt_uid = crgetuid(cr); 1036 p->auth_clnt_gid = crgetgid(cr); 1037 p->auth_clnt_ngids = crgetngroups(cr); 1038 bcopy(crgetgroups(cr), p->auth_clnt_gids, 1039 p->auth_clnt_ngids * sizeof (gid_t)); 1040 p->auth_srv_uid = tmpuid; 1041 p->auth_srv_gid = tmpgid; 1042 p->auth_srv_ngids = tmpngids; 1043 p->auth_srv_gids = tmpgids; 1044 p->auth_access = access; 1045 p->auth_time = p->auth_freshness = gethrestime_sec(); 1046 p->auth_state = NFS_AUTH_FRESH; 1047 p->auth_netid = NULL; 1048 mutex_init(&p->auth_lock, NULL, MUTEX_DEFAULT, NULL); 1049 1050 rw_enter(&exi->exi_cache_lock, RW_WRITER); 1051 p->auth_next = *head; 1052 *head = p; 1053 rw_exit(&exi->exi_cache_lock); 1054 } else { 1055 kmem_free(addr.buf, addr.len); 1056 if (tmpgids != NULL) 1057 kmem_free(tmpgids, tmpngids * sizeof (gid_t)); 1058 if (p != NULL) { 1059 if (p->auth_clnt_gids != NULL) 1060 kmem_free(p->auth_clnt_gids, 1061 crgetngroups(cr) * sizeof (gid_t)); 1062 kmem_cache_free(exi_cache_handle, p); 1063 } 1064 } 1065 1066 return (access); 1067 } 1068 1069 /* 1070 * Check if the requesting client has access to the filesystem with 1071 * a given nfs flavor number which is an explicitly shared flavor. 1072 */ 1073 int 1074 nfsauth4_secinfo_access(struct exportinfo *exi, struct svc_req *req, 1075 int flavor, int perm, cred_t *cr) 1076 { 1077 int access; 1078 1079 if (! (perm & M_4SEC_EXPORTED)) { 1080 return (NFSAUTH_DENIED); 1081 } 1082 1083 /* 1084 * Optimize if there are no lists 1085 */ 1086 if ((perm & (M_ROOT | M_NONE | M_MAP)) == 0) { 1087 perm &= ~M_4SEC_EXPORTED; 1088 if (perm == M_RO) 1089 return (NFSAUTH_RO); 1090 if (perm == M_RW) 1091 return (NFSAUTH_RW); 1092 } 1093 1094 access = nfsauth_cache_get(exi, req, flavor, cr, NULL, NULL, NULL, 1095 NULL); 1096 1097 return (access); 1098 } 1099 1100 int 1101 nfsauth_access(struct exportinfo *exi, struct svc_req *req, cred_t *cr, 1102 uid_t *uid, gid_t *gid, uint_t *ngids, gid_t **gids) 1103 { 1104 int access, mapaccess; 1105 struct secinfo *sp; 1106 int i, flavor, perm; 1107 int authnone_entry = -1; 1108 1109 /* 1110 * By default root is mapped to anonymous user. 1111 * This might get overriden later in nfsauth_cache_get(). 1112 */ 1113 if (crgetuid(cr) == 0) { 1114 if (uid != NULL) 1115 *uid = exi->exi_export.ex_anon; 1116 if (gid != NULL) 1117 *gid = exi->exi_export.ex_anon; 1118 } else { 1119 if (uid != NULL) 1120 *uid = crgetuid(cr); 1121 if (gid != NULL) 1122 *gid = crgetgid(cr); 1123 } 1124 1125 if (ngids != NULL) 1126 *ngids = 0; 1127 if (gids != NULL) 1128 *gids = NULL; 1129 1130 /* 1131 * Get the nfs flavor number from xprt. 1132 */ 1133 flavor = (int)(uintptr_t)req->rq_xprt->xp_cookie; 1134 1135 /* 1136 * First check the access restrictions on the filesystem. If 1137 * there are no lists associated with this flavor then there's no 1138 * need to make an expensive call to the nfsauth service or to 1139 * cache anything. 1140 */ 1141 1142 sp = exi->exi_export.ex_secinfo; 1143 for (i = 0; i < exi->exi_export.ex_seccnt; i++) { 1144 if (flavor != sp[i].s_secinfo.sc_nfsnum) { 1145 if (sp[i].s_secinfo.sc_nfsnum == AUTH_NONE) 1146 authnone_entry = i; 1147 continue; 1148 } 1149 break; 1150 } 1151 1152 mapaccess = 0; 1153 1154 if (i >= exi->exi_export.ex_seccnt) { 1155 /* 1156 * Flavor not found, but use AUTH_NONE if it exists 1157 */ 1158 if (authnone_entry == -1) 1159 return (NFSAUTH_DENIED); 1160 flavor = AUTH_NONE; 1161 mapaccess = NFSAUTH_MAPNONE; 1162 i = authnone_entry; 1163 } 1164 1165 /* 1166 * If the flavor is in the ex_secinfo list, but not an explicitly 1167 * shared flavor by the user, it is a result of the nfsv4 server 1168 * namespace setup. We will grant an RO permission similar for 1169 * a pseudo node except that this node is a shared one. 1170 * 1171 * e.g. flavor in (flavor) indicates that it is not explictly 1172 * shared by the user: 1173 * 1174 * / (sys, krb5) 1175 * | 1176 * export #share -o sec=sys (krb5) 1177 * | 1178 * secure #share -o sec=krb5 1179 * 1180 * In this case, when a krb5 request coming in to access 1181 * /export, RO permission is granted. 1182 */ 1183 if (!(sp[i].s_flags & M_4SEC_EXPORTED)) 1184 return (mapaccess | NFSAUTH_RO); 1185 1186 /* 1187 * Optimize if there are no lists. 1188 * We cannot optimize for AUTH_SYS with NGRPS (16) supplemental groups. 1189 */ 1190 perm = sp[i].s_flags; 1191 if ((perm & (M_ROOT | M_NONE | M_MAP)) == 0 && (ngroups_max <= NGRPS || 1192 flavor != AUTH_SYS || crgetngroups(cr) < NGRPS)) { 1193 perm &= ~M_4SEC_EXPORTED; 1194 if (perm == M_RO) 1195 return (mapaccess | NFSAUTH_RO); 1196 if (perm == M_RW) 1197 return (mapaccess | NFSAUTH_RW); 1198 } 1199 1200 access = nfsauth_cache_get(exi, req, flavor, cr, uid, gid, ngids, gids); 1201 1202 /* 1203 * For both NFSAUTH_DENIED and NFSAUTH_WRONGSEC we do not care about 1204 * the supplemental groups. 1205 */ 1206 if (access & NFSAUTH_DENIED || access & NFSAUTH_WRONGSEC) { 1207 if (ngids != NULL && gids != NULL) { 1208 kmem_free(*gids, *ngids * sizeof (gid_t)); 1209 *ngids = 0; 1210 *gids = NULL; 1211 } 1212 } 1213 1214 /* 1215 * Client's security flavor doesn't match with "ro" or 1216 * "rw" list. Try again using AUTH_NONE if present. 1217 */ 1218 if ((access & NFSAUTH_WRONGSEC) && (flavor != AUTH_NONE)) { 1219 /* 1220 * Have we already encountered AUTH_NONE ? 1221 */ 1222 if (authnone_entry != -1) { 1223 mapaccess = NFSAUTH_MAPNONE; 1224 access = nfsauth_cache_get(exi, req, AUTH_NONE, cr, 1225 NULL, NULL, NULL, NULL); 1226 } else { 1227 /* 1228 * Check for AUTH_NONE presence. 1229 */ 1230 for (; i < exi->exi_export.ex_seccnt; i++) { 1231 if (sp[i].s_secinfo.sc_nfsnum == AUTH_NONE) { 1232 mapaccess = NFSAUTH_MAPNONE; 1233 access = nfsauth_cache_get(exi, req, 1234 AUTH_NONE, cr, NULL, NULL, NULL, 1235 NULL); 1236 break; 1237 } 1238 } 1239 } 1240 } 1241 1242 if (access & NFSAUTH_DENIED) 1243 access = NFSAUTH_DENIED; 1244 1245 return (access | mapaccess); 1246 } 1247 1248 static void 1249 nfsauth_free_node(struct auth_cache *p) 1250 { 1251 if (p->auth_netid != NULL) 1252 kmem_free(p->auth_netid, strlen(p->auth_netid) + 1); 1253 kmem_free(p->auth_addr.buf, p->auth_addr.len); 1254 kmem_free(p->auth_clnt_gids, p->auth_clnt_ngids * sizeof (gid_t)); 1255 kmem_free(p->auth_srv_gids, p->auth_srv_ngids * sizeof (gid_t)); 1256 mutex_destroy(&p->auth_lock); 1257 kmem_cache_free(exi_cache_handle, p); 1258 } 1259 1260 /* 1261 * Remove the dead entry from the refreshq_dead_entries 1262 * list. 1263 */ 1264 static void 1265 nfsauth_remove_dead_entry(struct auth_cache *dead) 1266 { 1267 struct auth_cache *p; 1268 struct auth_cache *prev; 1269 struct auth_cache *next; 1270 1271 mutex_enter(&refreshq_lock); 1272 prev = NULL; 1273 for (p = refreshq_dead_entries; p != NULL; p = next) { 1274 next = p->auth_next; 1275 1276 if (p == dead) { 1277 if (prev == NULL) 1278 refreshq_dead_entries = next; 1279 else 1280 prev->auth_next = next; 1281 1282 nfsauth_free_node(dead); 1283 break; 1284 } 1285 1286 prev = p; 1287 } 1288 mutex_exit(&refreshq_lock); 1289 } 1290 1291 /* 1292 * Free the nfsauth cache for a given export 1293 */ 1294 void 1295 nfsauth_cache_free(struct exportinfo *exi) 1296 { 1297 int i; 1298 struct auth_cache *p, *next; 1299 1300 for (i = 0; i < AUTH_TABLESIZE; i++) { 1301 for (p = exi->exi_cache[i]; p; p = next) { 1302 next = p->auth_next; 1303 1304 /* 1305 * The only way we got here 1306 * was with an exi_rele, which 1307 * means that no auth cache entry 1308 * is being refreshed. 1309 */ 1310 nfsauth_free_node(p); 1311 } 1312 } 1313 } 1314 1315 /* 1316 * Called by the kernel memory allocator when 1317 * memory is low. Free unused cache entries. 1318 * If that's not enough, the VM system will 1319 * call again for some more. 1320 */ 1321 /*ARGSUSED*/ 1322 void 1323 exi_cache_reclaim(void *cdrarg) 1324 { 1325 int i; 1326 struct exportinfo *exi; 1327 1328 rw_enter(&exported_lock, RW_READER); 1329 1330 for (i = 0; i < EXPTABLESIZE; i++) { 1331 for (exi = exptable[i]; exi; exi = exi->fid_hash.next) { 1332 exi_cache_trim(exi); 1333 } 1334 } 1335 nfsauth_cache_reclaim++; 1336 1337 rw_exit(&exported_lock); 1338 } 1339 1340 void 1341 exi_cache_trim(struct exportinfo *exi) 1342 { 1343 struct auth_cache *p; 1344 struct auth_cache *prev, *next; 1345 int i; 1346 time_t stale_time; 1347 1348 stale_time = gethrestime_sec() - NFSAUTH_CACHE_TRIM; 1349 1350 rw_enter(&exi->exi_cache_lock, RW_WRITER); 1351 1352 for (i = 0; i < AUTH_TABLESIZE; i++) { 1353 1354 /* 1355 * Free entries that have not been 1356 * used for NFSAUTH_CACHE_TRIM seconds. 1357 */ 1358 prev = NULL; 1359 for (p = exi->exi_cache[i]; p; p = next) { 1360 next = p->auth_next; 1361 if (p->auth_time > stale_time) { 1362 prev = p; 1363 continue; 1364 } 1365 1366 mutex_enter(&p->auth_lock); 1367 DTRACE_PROBE1(nfsauth__debug__trim__state, 1368 auth_state_t, p->auth_state); 1369 1370 if (p->auth_state != NFS_AUTH_FRESH) { 1371 p->auth_state = NFS_AUTH_INVALID; 1372 mutex_exit(&p->auth_lock); 1373 1374 mutex_enter(&refreshq_lock); 1375 p->auth_next = refreshq_dead_entries; 1376 refreshq_dead_entries = p; 1377 mutex_exit(&refreshq_lock); 1378 } else { 1379 mutex_exit(&p->auth_lock); 1380 nfsauth_free_node(p); 1381 } 1382 1383 if (prev == NULL) 1384 exi->exi_cache[i] = next; 1385 else 1386 prev->auth_next = next; 1387 } 1388 } 1389 1390 rw_exit(&exi->exi_cache_lock); 1391 } 1392