Deleted Added
full compact
nfs_commonsubs.c (275941) nfs_commonsubs.c (291527)
1/*-
2 * Copyright (c) 1989, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Rick Macklem at The University of Guelph.
7 *
8 * Redistribution and use in source and binary forms, with or without

--- 18 unchanged lines hidden (view full) ---

27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 */
33
34#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 1989, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Rick Macklem at The University of Guelph.
7 *
8 * Redistribution and use in source and binary forms, with or without

--- 18 unchanged lines hidden (view full) ---

27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 */
33
34#include <sys/cdefs.h>
35__FBSDID("$FreeBSD: head/sys/fs/nfs/nfs_commonsubs.c 275941 2014-12-19 19:09:22Z benno $");
35__FBSDID("$FreeBSD: head/sys/fs/nfs/nfs_commonsubs.c 291527 2015-11-30 21:54:27Z rmacklem $");
36
37/*
38 * These functions support the macros and help fiddle mbuf chains for
39 * the nfs op functions. They do things like create the rpc header and
40 * copy data between mbuf chains and uio lists.
41 */
42#ifndef APPLEKEXT
43#include "opt_inet6.h"
44
45#include <fs/nfs/nfsport.h>
46
36
37/*
38 * These functions support the macros and help fiddle mbuf chains for
39 * the nfs op functions. They do things like create the rpc header and
40 * copy data between mbuf chains and uio lists.
41 */
42#ifndef APPLEKEXT
43#include "opt_inet6.h"
44
45#include <fs/nfs/nfsport.h>
46
47#include <security/mac/mac_framework.h>
48
47/*
48 * Data items converted to xdr at startup, since they are constant
49 * This is kinda hokey, but may save a little time doing byte swaps
50 */
51u_int32_t newnfs_true, newnfs_false, newnfs_xdrneg1;
52
53/* And other global data */
54nfstype nfsv34_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFSOCK,

--- 8 unchanged lines hidden (view full) ---

63struct nfsreqhead nfsd_reqq;
64uid_t nfsrv_defaultuid;
65gid_t nfsrv_defaultgid;
66int nfsrv_lease = NFSRV_LEASE;
67int ncl_mbuf_mlen = MLEN;
68int nfsd_enable_stringtouid = 0;
69NFSNAMEIDMUTEX;
70NFSSOCKMUTEX;
49/*
50 * Data items converted to xdr at startup, since they are constant
51 * This is kinda hokey, but may save a little time doing byte swaps
52 */
53u_int32_t newnfs_true, newnfs_false, newnfs_xdrneg1;
54
55/* And other global data */
56nfstype nfsv34_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFSOCK,

--- 8 unchanged lines hidden (view full) ---

65struct nfsreqhead nfsd_reqq;
66uid_t nfsrv_defaultuid;
67gid_t nfsrv_defaultgid;
68int nfsrv_lease = NFSRV_LEASE;
69int ncl_mbuf_mlen = MLEN;
70int nfsd_enable_stringtouid = 0;
71NFSNAMEIDMUTEX;
72NFSSOCKMUTEX;
73extern int nfsrv_lughashsize;
71
72/*
73 * This array of structures indicates, for V4:
74 * retfh - which of 3 types of calling args are used
75 * 0 - doesn't change cfh or use a sfh
76 * 1 - replaces cfh with a new one (unless it returns an error status)
77 * 2 - uses cfh and sfh
78 * needscfh - if the op wants a cfh and premtime

--- 70 unchanged lines hidden (view full) ---

149};
150#endif /* !APPLEKEXT */
151
152static int ncl_mbuf_mhlen = MHLEN;
153static int nfsrv_usercnt = 0;
154static int nfsrv_dnsnamelen;
155static u_char *nfsrv_dnsname = NULL;
156static int nfsrv_usermax = 999999999;
74
75/*
76 * This array of structures indicates, for V4:
77 * retfh - which of 3 types of calling args are used
78 * 0 - doesn't change cfh or use a sfh
79 * 1 - replaces cfh with a new one (unless it returns an error status)
80 * 2 - uses cfh and sfh
81 * needscfh - if the op wants a cfh and premtime

--- 70 unchanged lines hidden (view full) ---

152};
153#endif /* !APPLEKEXT */
154
155static int ncl_mbuf_mhlen = MHLEN;
156static int nfsrv_usercnt = 0;
157static int nfsrv_dnsnamelen;
158static u_char *nfsrv_dnsname = NULL;
159static int nfsrv_usermax = 999999999;
157static struct nfsuserhashhead nfsuserhash[NFSUSERHASHSIZE];
158static struct nfsuserhashhead nfsusernamehash[NFSUSERHASHSIZE];
159static struct nfsuserhashhead nfsgrouphash[NFSGROUPHASHSIZE];
160static struct nfsuserhashhead nfsgroupnamehash[NFSGROUPHASHSIZE];
161static struct nfsuserlruhead nfsuserlruhead;
160struct nfsrv_lughash {
161 struct mtx mtx;
162 struct nfsuserhashhead lughead;
163};
164static struct nfsrv_lughash *nfsuserhash;
165static struct nfsrv_lughash *nfsusernamehash;
166static struct nfsrv_lughash *nfsgrouphash;
167static struct nfsrv_lughash *nfsgroupnamehash;
162
163/*
164 * This static array indicates whether or not the RPC generates a large
165 * reply. This is used by nfs_reply() to decide whether or not an mbuf
166 * cluster should be allocated. (If a cluster is required by an RPC
167 * marked 0 in this array, the code will still work, just not quite as
168 * efficiently.)
169 */
170int nfs_bigreply[NFSV41_NPROCS] = { 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0,
171 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
172 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 };
173
174/* local functions */
175static int nfsrv_skipace(struct nfsrv_descript *nd, int *acesizep);
176static void nfsv4_wanted(struct nfsv4lock *lp);
177static int nfsrv_cmpmixedcase(u_char *cp, u_char *cp2, int len);
178static int nfsrv_getuser(int procnum, uid_t uid, gid_t gid, char *name,
179 NFSPROC_T *p);
168
169/*
170 * This static array indicates whether or not the RPC generates a large
171 * reply. This is used by nfs_reply() to decide whether or not an mbuf
172 * cluster should be allocated. (If a cluster is required by an RPC
173 * marked 0 in this array, the code will still work, just not quite as
174 * efficiently.)
175 */
176int nfs_bigreply[NFSV41_NPROCS] = { 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0,
177 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
178 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 };
179
180/* local functions */
181static int nfsrv_skipace(struct nfsrv_descript *nd, int *acesizep);
182static void nfsv4_wanted(struct nfsv4lock *lp);
183static int nfsrv_cmpmixedcase(u_char *cp, u_char *cp2, int len);
184static int nfsrv_getuser(int procnum, uid_t uid, gid_t gid, char *name,
185 NFSPROC_T *p);
180static void nfsrv_removeuser(struct nfsusrgrp *usrp);
186static void nfsrv_removeuser(struct nfsusrgrp *usrp, int isuser);
181static int nfsrv_getrefstr(struct nfsrv_descript *, u_char **, u_char **,
182 int *, int *);
183static void nfsrv_refstrbigenough(int, u_char **, u_char **, int *);
184
185
186#ifndef APPLE
187/*
188 * copies mbuf chain to the uio scatter/gather list

--- 2354 unchanged lines hidden (view full) ---

2543APPLESTATIC void
2544nfsv4_uidtostr(uid_t uid, u_char **cpp, int *retlenp, NFSPROC_T *p)
2545{
2546 int i;
2547 struct nfsusrgrp *usrp;
2548 u_char *cp = *cpp;
2549 uid_t tmp;
2550 int cnt, hasampersand, len = NFSV4_SMALLSTR, ret;
187static int nfsrv_getrefstr(struct nfsrv_descript *, u_char **, u_char **,
188 int *, int *);
189static void nfsrv_refstrbigenough(int, u_char **, u_char **, int *);
190
191
192#ifndef APPLE
193/*
194 * copies mbuf chain to the uio scatter/gather list

--- 2354 unchanged lines hidden (view full) ---

2549APPLESTATIC void
2550nfsv4_uidtostr(uid_t uid, u_char **cpp, int *retlenp, NFSPROC_T *p)
2551{
2552 int i;
2553 struct nfsusrgrp *usrp;
2554 u_char *cp = *cpp;
2555 uid_t tmp;
2556 int cnt, hasampersand, len = NFSV4_SMALLSTR, ret;
2557 struct nfsrv_lughash *hp;
2551
2552 cnt = 0;
2553tryagain:
2558
2559 cnt = 0;
2560tryagain:
2554 NFSLOCKNAMEID();
2555 if (nfsrv_dnsname) {
2561 if (nfsrv_dnsnamelen > 0) {
2556 /*
2557 * Always map nfsrv_defaultuid to "nobody".
2558 */
2559 if (uid == nfsrv_defaultuid) {
2560 i = nfsrv_dnsnamelen + 7;
2561 if (i > len) {
2562 /*
2563 * Always map nfsrv_defaultuid to "nobody".
2564 */
2565 if (uid == nfsrv_defaultuid) {
2566 i = nfsrv_dnsnamelen + 7;
2567 if (i > len) {
2562 NFSUNLOCKNAMEID();
2563 if (len > NFSV4_SMALLSTR)
2564 free(cp, M_NFSSTRING);
2565 cp = malloc(i, M_NFSSTRING, M_WAITOK);
2566 *cpp = cp;
2567 len = i;
2568 goto tryagain;
2569 }
2570 *retlenp = i;
2571 NFSBCOPY("nobody@", cp, 7);
2572 cp += 7;
2573 NFSBCOPY(nfsrv_dnsname, cp, nfsrv_dnsnamelen);
2568 if (len > NFSV4_SMALLSTR)
2569 free(cp, M_NFSSTRING);
2570 cp = malloc(i, M_NFSSTRING, M_WAITOK);
2571 *cpp = cp;
2572 len = i;
2573 goto tryagain;
2574 }
2575 *retlenp = i;
2576 NFSBCOPY("nobody@", cp, 7);
2577 cp += 7;
2578 NFSBCOPY(nfsrv_dnsname, cp, nfsrv_dnsnamelen);
2574 NFSUNLOCKNAMEID();
2575 return;
2576 }
2577 hasampersand = 0;
2579 return;
2580 }
2581 hasampersand = 0;
2578 LIST_FOREACH(usrp, NFSUSERHASH(uid), lug_numhash) {
2582 hp = NFSUSERHASH(uid);
2583 mtx_lock(&hp->mtx);
2584 TAILQ_FOREACH(usrp, &hp->lughead, lug_numhash) {
2579 if (usrp->lug_uid == uid) {
2580 if (usrp->lug_expiry < NFSD_MONOSEC)
2581 break;
2582 /*
2583 * If the name doesn't already have an '@'
2584 * in it, append @domainname to it.
2585 */
2586 for (i = 0; i < usrp->lug_namelen; i++) {
2587 if (usrp->lug_name[i] == '@') {
2588 hasampersand = 1;
2589 break;
2590 }
2591 }
2592 if (hasampersand)
2593 i = usrp->lug_namelen;
2594 else
2595 i = usrp->lug_namelen +
2596 nfsrv_dnsnamelen + 1;
2597 if (i > len) {
2585 if (usrp->lug_uid == uid) {
2586 if (usrp->lug_expiry < NFSD_MONOSEC)
2587 break;
2588 /*
2589 * If the name doesn't already have an '@'
2590 * in it, append @domainname to it.
2591 */
2592 for (i = 0; i < usrp->lug_namelen; i++) {
2593 if (usrp->lug_name[i] == '@') {
2594 hasampersand = 1;
2595 break;
2596 }
2597 }
2598 if (hasampersand)
2599 i = usrp->lug_namelen;
2600 else
2601 i = usrp->lug_namelen +
2602 nfsrv_dnsnamelen + 1;
2603 if (i > len) {
2598 NFSUNLOCKNAMEID();
2604 mtx_unlock(&hp->mtx);
2599 if (len > NFSV4_SMALLSTR)
2600 free(cp, M_NFSSTRING);
2601 cp = malloc(i, M_NFSSTRING, M_WAITOK);
2602 *cpp = cp;
2603 len = i;
2604 goto tryagain;
2605 }
2606 *retlenp = i;
2607 NFSBCOPY(usrp->lug_name, cp, usrp->lug_namelen);
2608 if (!hasampersand) {
2609 cp += usrp->lug_namelen;
2610 *cp++ = '@';
2611 NFSBCOPY(nfsrv_dnsname, cp, nfsrv_dnsnamelen);
2612 }
2605 if (len > NFSV4_SMALLSTR)
2606 free(cp, M_NFSSTRING);
2607 cp = malloc(i, M_NFSSTRING, M_WAITOK);
2608 *cpp = cp;
2609 len = i;
2610 goto tryagain;
2611 }
2612 *retlenp = i;
2613 NFSBCOPY(usrp->lug_name, cp, usrp->lug_namelen);
2614 if (!hasampersand) {
2615 cp += usrp->lug_namelen;
2616 *cp++ = '@';
2617 NFSBCOPY(nfsrv_dnsname, cp, nfsrv_dnsnamelen);
2618 }
2613 TAILQ_REMOVE(&nfsuserlruhead, usrp, lug_lru);
2614 TAILQ_INSERT_TAIL(&nfsuserlruhead, usrp, lug_lru);
2615 NFSUNLOCKNAMEID();
2619 TAILQ_REMOVE(&hp->lughead, usrp, lug_numhash);
2620 TAILQ_INSERT_TAIL(&hp->lughead, usrp,
2621 lug_numhash);
2622 mtx_unlock(&hp->mtx);
2616 return;
2617 }
2618 }
2623 return;
2624 }
2625 }
2619 NFSUNLOCKNAMEID();
2626 mtx_unlock(&hp->mtx);
2620 cnt++;
2621 ret = nfsrv_getuser(RPCNFSUSERD_GETUID, uid, (gid_t)0,
2622 NULL, p);
2623 if (ret == 0 && cnt < 2)
2624 goto tryagain;
2627 cnt++;
2628 ret = nfsrv_getuser(RPCNFSUSERD_GETUID, uid, (gid_t)0,
2629 NULL, p);
2630 if (ret == 0 && cnt < 2)
2631 goto tryagain;
2625 } else {
2626 NFSUNLOCKNAMEID();
2627 }
2628
2629 /*
2630 * No match, just return a string of digits.
2631 */
2632 tmp = uid;
2633 i = 0;
2634 while (tmp || i == 0) {

--- 7 unchanged lines hidden (view full) ---

2642 for (i = 0; i < len; i++) {
2643 *cp-- = '0' + (tmp % 10);
2644 tmp /= 10;
2645 }
2646 return;
2647}
2648
2649/*
2632 }
2633
2634 /*
2635 * No match, just return a string of digits.
2636 */
2637 tmp = uid;
2638 i = 0;
2639 while (tmp || i == 0) {

--- 7 unchanged lines hidden (view full) ---

2647 for (i = 0; i < len; i++) {
2648 *cp-- = '0' + (tmp % 10);
2649 tmp /= 10;
2650 }
2651 return;
2652}
2653
2654/*
2655 * Get a credential for the uid with the server's group list.
2656 * If none is found, just return the credential passed in after
2657 * logging a warning message.
2658 */
2659struct ucred *
2660nfsrv_getgrpscred(struct ucred *oldcred)
2661{
2662 struct nfsusrgrp *usrp;
2663 struct ucred *newcred;
2664 int cnt, ret;
2665 uid_t uid;
2666 struct nfsrv_lughash *hp;
2667
2668 cnt = 0;
2669 uid = oldcred->cr_uid;
2670tryagain:
2671 if (nfsrv_dnsnamelen > 0) {
2672 hp = NFSUSERHASH(uid);
2673 mtx_lock(&hp->mtx);
2674 TAILQ_FOREACH(usrp, &hp->lughead, lug_numhash) {
2675 if (usrp->lug_uid == uid) {
2676 if (usrp->lug_expiry < NFSD_MONOSEC)
2677 break;
2678 if (usrp->lug_cred != NULL) {
2679 newcred = crhold(usrp->lug_cred);
2680 crfree(oldcred);
2681 } else
2682 newcred = oldcred;
2683 TAILQ_REMOVE(&hp->lughead, usrp, lug_numhash);
2684 TAILQ_INSERT_TAIL(&hp->lughead, usrp,
2685 lug_numhash);
2686 mtx_unlock(&hp->mtx);
2687 return (newcred);
2688 }
2689 }
2690 mtx_unlock(&hp->mtx);
2691 cnt++;
2692 ret = nfsrv_getuser(RPCNFSUSERD_GETUID, uid, (gid_t)0,
2693 NULL, curthread);
2694 if (ret == 0 && cnt < 2)
2695 goto tryagain;
2696 }
2697 return (oldcred);
2698}
2699
2700/*
2650 * Convert a string to a uid.
2651 * If no conversion is possible return NFSERR_BADOWNER, otherwise
2652 * return 0.
2653 * If this is called from a client side mount using AUTH_SYS and the
2654 * string is made up entirely of digits, just convert the string to
2655 * a number.
2656 */
2657APPLESTATIC int
2658nfsv4_strtouid(struct nfsrv_descript *nd, u_char *str, int len, uid_t *uidp,
2659 NFSPROC_T *p)
2660{
2661 int i;
2662 char *cp, *endstr, *str0;
2663 struct nfsusrgrp *usrp;
2664 int cnt, ret;
2665 int error = 0;
2666 uid_t tuid;
2701 * Convert a string to a uid.
2702 * If no conversion is possible return NFSERR_BADOWNER, otherwise
2703 * return 0.
2704 * If this is called from a client side mount using AUTH_SYS and the
2705 * string is made up entirely of digits, just convert the string to
2706 * a number.
2707 */
2708APPLESTATIC int
2709nfsv4_strtouid(struct nfsrv_descript *nd, u_char *str, int len, uid_t *uidp,
2710 NFSPROC_T *p)
2711{
2712 int i;
2713 char *cp, *endstr, *str0;
2714 struct nfsusrgrp *usrp;
2715 int cnt, ret;
2716 int error = 0;
2717 uid_t tuid;
2718 struct nfsrv_lughash *hp, *hp2;
2667
2668 if (len == 0) {
2669 error = NFSERR_BADOWNER;
2670 goto out;
2671 }
2672 /* If a string of digits and an AUTH_SYS mount, just convert it. */
2673 str0 = str;
2674 tuid = (uid_t)strtoul(str0, &endstr, 10);

--- 13 unchanged lines hidden (view full) ---

2688 cp = strchr(str0, '@');
2689 if (cp != NULL)
2690 i = (int)(cp++ - str0);
2691 else
2692 i = len;
2693
2694 cnt = 0;
2695tryagain:
2719
2720 if (len == 0) {
2721 error = NFSERR_BADOWNER;
2722 goto out;
2723 }
2724 /* If a string of digits and an AUTH_SYS mount, just convert it. */
2725 str0 = str;
2726 tuid = (uid_t)strtoul(str0, &endstr, 10);

--- 13 unchanged lines hidden (view full) ---

2740 cp = strchr(str0, '@');
2741 if (cp != NULL)
2742 i = (int)(cp++ - str0);
2743 else
2744 i = len;
2745
2746 cnt = 0;
2747tryagain:
2696 NFSLOCKNAMEID();
2697 /*
2698 * If an '@' is found and the domain name matches, search for the name
2699 * with dns stripped off.
2700 * Mixed case alpahbetics will match for the domain name, but all
2701 * upper case will not.
2702 */
2703 if (cnt == 0 && i < len && i > 0 && nfsrv_dnsname &&
2704 (len - 1 - i) == nfsrv_dnsnamelen &&
2705 !nfsrv_cmpmixedcase(cp, nfsrv_dnsname, nfsrv_dnsnamelen)) {
2706 len -= (nfsrv_dnsnamelen + 1);
2707 *(cp - 1) = '\0';
2708 }
2709
2710 /*
2711 * Check for the special case of "nobody".
2712 */
2713 if (len == 6 && !NFSBCMP(str, "nobody", 6)) {
2714 *uidp = nfsrv_defaultuid;
2715 NFSUNLOCKNAMEID();
2716 error = 0;
2717 goto out;
2718 }
2719
2720 LIST_FOREACH(usrp, NFSUSERNAMEHASH(str, len), lug_namehash) {
2721 if (usrp->lug_namelen == len &&
2722 !NFSBCMP(usrp->lug_name, str, len)) {
2723 if (usrp->lug_expiry < NFSD_MONOSEC)
2724 break;
2725 *uidp = usrp->lug_uid;
2726 TAILQ_REMOVE(&nfsuserlruhead, usrp, lug_lru);
2727 TAILQ_INSERT_TAIL(&nfsuserlruhead, usrp, lug_lru);
2728 NFSUNLOCKNAMEID();
2748 if (nfsrv_dnsnamelen > 0) {
2749 /*
2750 * If an '@' is found and the domain name matches, search for
2751 * the name with dns stripped off.
2752 * Mixed case alpahbetics will match for the domain name, but
2753 * all upper case will not.
2754 */
2755 if (cnt == 0 && i < len && i > 0 &&
2756 (len - 1 - i) == nfsrv_dnsnamelen &&
2757 !nfsrv_cmpmixedcase(cp, nfsrv_dnsname, nfsrv_dnsnamelen)) {
2758 len -= (nfsrv_dnsnamelen + 1);
2759 *(cp - 1) = '\0';
2760 }
2761
2762 /*
2763 * Check for the special case of "nobody".
2764 */
2765 if (len == 6 && !NFSBCMP(str, "nobody", 6)) {
2766 *uidp = nfsrv_defaultuid;
2729 error = 0;
2730 goto out;
2731 }
2767 error = 0;
2768 goto out;
2769 }
2770
2771 hp = NFSUSERNAMEHASH(str, len);
2772 mtx_lock(&hp->mtx);
2773 TAILQ_FOREACH(usrp, &hp->lughead, lug_namehash) {
2774 if (usrp->lug_namelen == len &&
2775 !NFSBCMP(usrp->lug_name, str, len)) {
2776 if (usrp->lug_expiry < NFSD_MONOSEC)
2777 break;
2778 hp2 = NFSUSERHASH(usrp->lug_uid);
2779 mtx_lock(&hp2->mtx);
2780 TAILQ_REMOVE(&hp2->lughead, usrp, lug_numhash);
2781 TAILQ_INSERT_TAIL(&hp2->lughead, usrp,
2782 lug_numhash);
2783 *uidp = usrp->lug_uid;
2784 mtx_unlock(&hp2->mtx);
2785 mtx_unlock(&hp->mtx);
2786 error = 0;
2787 goto out;
2788 }
2789 }
2790 mtx_unlock(&hp->mtx);
2791 cnt++;
2792 ret = nfsrv_getuser(RPCNFSUSERD_GETUSER, (uid_t)0, (gid_t)0,
2793 str, p);
2794 if (ret == 0 && cnt < 2)
2795 goto tryagain;
2732 }
2796 }
2733 NFSUNLOCKNAMEID();
2734 cnt++;
2735 ret = nfsrv_getuser(RPCNFSUSERD_GETUSER, (uid_t)0, (gid_t)0,
2736 str, p);
2737 if (ret == 0 && cnt < 2)
2738 goto tryagain;
2739 error = NFSERR_BADOWNER;
2740
2741out:
2742 NFSEXITCODE(error);
2743 return (error);
2744}
2745
2746/*

--- 6 unchanged lines hidden (view full) ---

2753APPLESTATIC void
2754nfsv4_gidtostr(gid_t gid, u_char **cpp, int *retlenp, NFSPROC_T *p)
2755{
2756 int i;
2757 struct nfsusrgrp *usrp;
2758 u_char *cp = *cpp;
2759 gid_t tmp;
2760 int cnt, hasampersand, len = NFSV4_SMALLSTR, ret;
2797 error = NFSERR_BADOWNER;
2798
2799out:
2800 NFSEXITCODE(error);
2801 return (error);
2802}
2803
2804/*

--- 6 unchanged lines hidden (view full) ---

2811APPLESTATIC void
2812nfsv4_gidtostr(gid_t gid, u_char **cpp, int *retlenp, NFSPROC_T *p)
2813{
2814 int i;
2815 struct nfsusrgrp *usrp;
2816 u_char *cp = *cpp;
2817 gid_t tmp;
2818 int cnt, hasampersand, len = NFSV4_SMALLSTR, ret;
2819 struct nfsrv_lughash *hp;
2761
2762 cnt = 0;
2763tryagain:
2820
2821 cnt = 0;
2822tryagain:
2764 NFSLOCKNAMEID();
2765 if (nfsrv_dnsname) {
2823 if (nfsrv_dnsnamelen > 0) {
2766 /*
2767 * Always map nfsrv_defaultgid to "nogroup".
2768 */
2769 if (gid == nfsrv_defaultgid) {
2770 i = nfsrv_dnsnamelen + 8;
2771 if (i > len) {
2824 /*
2825 * Always map nfsrv_defaultgid to "nogroup".
2826 */
2827 if (gid == nfsrv_defaultgid) {
2828 i = nfsrv_dnsnamelen + 8;
2829 if (i > len) {
2772 NFSUNLOCKNAMEID();
2773 if (len > NFSV4_SMALLSTR)
2774 free(cp, M_NFSSTRING);
2775 cp = malloc(i, M_NFSSTRING, M_WAITOK);
2776 *cpp = cp;
2777 len = i;
2778 goto tryagain;
2779 }
2780 *retlenp = i;
2781 NFSBCOPY("nogroup@", cp, 8);
2782 cp += 8;
2783 NFSBCOPY(nfsrv_dnsname, cp, nfsrv_dnsnamelen);
2830 if (len > NFSV4_SMALLSTR)
2831 free(cp, M_NFSSTRING);
2832 cp = malloc(i, M_NFSSTRING, M_WAITOK);
2833 *cpp = cp;
2834 len = i;
2835 goto tryagain;
2836 }
2837 *retlenp = i;
2838 NFSBCOPY("nogroup@", cp, 8);
2839 cp += 8;
2840 NFSBCOPY(nfsrv_dnsname, cp, nfsrv_dnsnamelen);
2784 NFSUNLOCKNAMEID();
2785 return;
2786 }
2787 hasampersand = 0;
2841 return;
2842 }
2843 hasampersand = 0;
2788 LIST_FOREACH(usrp, NFSGROUPHASH(gid), lug_numhash) {
2844 hp = NFSGROUPHASH(gid);
2845 mtx_lock(&hp->mtx);
2846 TAILQ_FOREACH(usrp, &hp->lughead, lug_numhash) {
2789 if (usrp->lug_gid == gid) {
2790 if (usrp->lug_expiry < NFSD_MONOSEC)
2791 break;
2792 /*
2793 * If the name doesn't already have an '@'
2794 * in it, append @domainname to it.
2795 */
2796 for (i = 0; i < usrp->lug_namelen; i++) {
2797 if (usrp->lug_name[i] == '@') {
2798 hasampersand = 1;
2799 break;
2800 }
2801 }
2802 if (hasampersand)
2803 i = usrp->lug_namelen;
2804 else
2805 i = usrp->lug_namelen +
2806 nfsrv_dnsnamelen + 1;
2807 if (i > len) {
2847 if (usrp->lug_gid == gid) {
2848 if (usrp->lug_expiry < NFSD_MONOSEC)
2849 break;
2850 /*
2851 * If the name doesn't already have an '@'
2852 * in it, append @domainname to it.
2853 */
2854 for (i = 0; i < usrp->lug_namelen; i++) {
2855 if (usrp->lug_name[i] == '@') {
2856 hasampersand = 1;
2857 break;
2858 }
2859 }
2860 if (hasampersand)
2861 i = usrp->lug_namelen;
2862 else
2863 i = usrp->lug_namelen +
2864 nfsrv_dnsnamelen + 1;
2865 if (i > len) {
2808 NFSUNLOCKNAMEID();
2866 mtx_unlock(&hp->mtx);
2809 if (len > NFSV4_SMALLSTR)
2810 free(cp, M_NFSSTRING);
2811 cp = malloc(i, M_NFSSTRING, M_WAITOK);
2812 *cpp = cp;
2813 len = i;
2814 goto tryagain;
2815 }
2816 *retlenp = i;
2817 NFSBCOPY(usrp->lug_name, cp, usrp->lug_namelen);
2818 if (!hasampersand) {
2819 cp += usrp->lug_namelen;
2820 *cp++ = '@';
2821 NFSBCOPY(nfsrv_dnsname, cp, nfsrv_dnsnamelen);
2822 }
2867 if (len > NFSV4_SMALLSTR)
2868 free(cp, M_NFSSTRING);
2869 cp = malloc(i, M_NFSSTRING, M_WAITOK);
2870 *cpp = cp;
2871 len = i;
2872 goto tryagain;
2873 }
2874 *retlenp = i;
2875 NFSBCOPY(usrp->lug_name, cp, usrp->lug_namelen);
2876 if (!hasampersand) {
2877 cp += usrp->lug_namelen;
2878 *cp++ = '@';
2879 NFSBCOPY(nfsrv_dnsname, cp, nfsrv_dnsnamelen);
2880 }
2823 TAILQ_REMOVE(&nfsuserlruhead, usrp, lug_lru);
2824 TAILQ_INSERT_TAIL(&nfsuserlruhead, usrp, lug_lru);
2825 NFSUNLOCKNAMEID();
2881 TAILQ_REMOVE(&hp->lughead, usrp, lug_numhash);
2882 TAILQ_INSERT_TAIL(&hp->lughead, usrp,
2883 lug_numhash);
2884 mtx_unlock(&hp->mtx);
2826 return;
2827 }
2828 }
2885 return;
2886 }
2887 }
2829 NFSUNLOCKNAMEID();
2888 mtx_unlock(&hp->mtx);
2830 cnt++;
2831 ret = nfsrv_getuser(RPCNFSUSERD_GETGID, (uid_t)0, gid,
2832 NULL, p);
2833 if (ret == 0 && cnt < 2)
2834 goto tryagain;
2889 cnt++;
2890 ret = nfsrv_getuser(RPCNFSUSERD_GETGID, (uid_t)0, gid,
2891 NULL, p);
2892 if (ret == 0 && cnt < 2)
2893 goto tryagain;
2835 } else {
2836 NFSUNLOCKNAMEID();
2837 }
2838
2839 /*
2840 * No match, just return a string of digits.
2841 */
2842 tmp = gid;
2843 i = 0;
2844 while (tmp || i == 0) {

--- 24 unchanged lines hidden (view full) ---

2869 NFSPROC_T *p)
2870{
2871 int i;
2872 char *cp, *endstr, *str0;
2873 struct nfsusrgrp *usrp;
2874 int cnt, ret;
2875 int error = 0;
2876 gid_t tgid;
2894 }
2895
2896 /*
2897 * No match, just return a string of digits.
2898 */
2899 tmp = gid;
2900 i = 0;
2901 while (tmp || i == 0) {

--- 24 unchanged lines hidden (view full) ---

2926 NFSPROC_T *p)
2927{
2928 int i;
2929 char *cp, *endstr, *str0;
2930 struct nfsusrgrp *usrp;
2931 int cnt, ret;
2932 int error = 0;
2933 gid_t tgid;
2934 struct nfsrv_lughash *hp, *hp2;
2877
2878 if (len == 0) {
2879 error = NFSERR_BADOWNER;
2880 goto out;
2881 }
2882 /* If a string of digits and an AUTH_SYS mount, just convert it. */
2883 str0 = str;
2884 tgid = (gid_t)strtoul(str0, &endstr, 10);

--- 13 unchanged lines hidden (view full) ---

2898 cp = strchr(str0, '@');
2899 if (cp != NULL)
2900 i = (int)(cp++ - str0);
2901 else
2902 i = len;
2903
2904 cnt = 0;
2905tryagain:
2935
2936 if (len == 0) {
2937 error = NFSERR_BADOWNER;
2938 goto out;
2939 }
2940 /* If a string of digits and an AUTH_SYS mount, just convert it. */
2941 str0 = str;
2942 tgid = (gid_t)strtoul(str0, &endstr, 10);

--- 13 unchanged lines hidden (view full) ---

2956 cp = strchr(str0, '@');
2957 if (cp != NULL)
2958 i = (int)(cp++ - str0);
2959 else
2960 i = len;
2961
2962 cnt = 0;
2963tryagain:
2906 NFSLOCKNAMEID();
2907 /*
2908 * If an '@' is found and the dns name matches, search for the name
2909 * with the dns stripped off.
2910 */
2911 if (cnt == 0 && i < len && i > 0 && nfsrv_dnsname &&
2912 (len - 1 - i) == nfsrv_dnsnamelen &&
2913 !nfsrv_cmpmixedcase(cp, nfsrv_dnsname, nfsrv_dnsnamelen)) {
2914 len -= (nfsrv_dnsnamelen + 1);
2915 *(cp - 1) = '\0';
2916 }
2917
2918 /*
2919 * Check for the special case of "nogroup".
2920 */
2921 if (len == 7 && !NFSBCMP(str, "nogroup", 7)) {
2922 *gidp = nfsrv_defaultgid;
2923 NFSUNLOCKNAMEID();
2924 error = 0;
2925 goto out;
2926 }
2927
2928 LIST_FOREACH(usrp, NFSGROUPNAMEHASH(str, len), lug_namehash) {
2929 if (usrp->lug_namelen == len &&
2930 !NFSBCMP(usrp->lug_name, str, len)) {
2931 if (usrp->lug_expiry < NFSD_MONOSEC)
2932 break;
2933 *gidp = usrp->lug_gid;
2934 TAILQ_REMOVE(&nfsuserlruhead, usrp, lug_lru);
2935 TAILQ_INSERT_TAIL(&nfsuserlruhead, usrp, lug_lru);
2936 NFSUNLOCKNAMEID();
2964 if (nfsrv_dnsnamelen > 0) {
2965 /*
2966 * If an '@' is found and the dns name matches, search for the
2967 * name with the dns stripped off.
2968 */
2969 if (cnt == 0 && i < len && i > 0 &&
2970 (len - 1 - i) == nfsrv_dnsnamelen &&
2971 !nfsrv_cmpmixedcase(cp, nfsrv_dnsname, nfsrv_dnsnamelen)) {
2972 len -= (nfsrv_dnsnamelen + 1);
2973 *(cp - 1) = '\0';
2974 }
2975
2976 /*
2977 * Check for the special case of "nogroup".
2978 */
2979 if (len == 7 && !NFSBCMP(str, "nogroup", 7)) {
2980 *gidp = nfsrv_defaultgid;
2937 error = 0;
2938 goto out;
2939 }
2981 error = 0;
2982 goto out;
2983 }
2984
2985 hp = NFSGROUPNAMEHASH(str, len);
2986 mtx_lock(&hp->mtx);
2987 TAILQ_FOREACH(usrp, &hp->lughead, lug_namehash) {
2988 if (usrp->lug_namelen == len &&
2989 !NFSBCMP(usrp->lug_name, str, len)) {
2990 if (usrp->lug_expiry < NFSD_MONOSEC)
2991 break;
2992 hp2 = NFSGROUPHASH(usrp->lug_gid);
2993 mtx_lock(&hp2->mtx);
2994 TAILQ_REMOVE(&hp2->lughead, usrp, lug_numhash);
2995 TAILQ_INSERT_TAIL(&hp2->lughead, usrp,
2996 lug_numhash);
2997 *gidp = usrp->lug_gid;
2998 mtx_unlock(&hp2->mtx);
2999 mtx_unlock(&hp->mtx);
3000 error = 0;
3001 goto out;
3002 }
3003 }
3004 mtx_unlock(&hp->mtx);
3005 cnt++;
3006 ret = nfsrv_getuser(RPCNFSUSERD_GETGROUP, (uid_t)0, (gid_t)0,
3007 str, p);
3008 if (ret == 0 && cnt < 2)
3009 goto tryagain;
2940 }
3010 }
2941 NFSUNLOCKNAMEID();
2942 cnt++;
2943 ret = nfsrv_getuser(RPCNFSUSERD_GETGROUP, (uid_t)0, (gid_t)0,
2944 str, p);
2945 if (ret == 0 && cnt < 2)
2946 goto tryagain;
2947 error = NFSERR_BADOWNER;
2948
2949out:
2950 NFSEXITCODE(error);
2951 return (error);
2952}
2953
2954/*

--- 141 unchanged lines hidden (view full) ---

3096/*
3097 * This function is called from the nfssvc(2) system call, to update the
3098 * kernel user/group name list(s) for the V4 owner and ownergroup attributes.
3099 */
3100APPLESTATIC int
3101nfssvc_idname(struct nfsd_idargs *nidp)
3102{
3103 struct nfsusrgrp *nusrp, *usrp, *newusrp;
3011 error = NFSERR_BADOWNER;
3012
3013out:
3014 NFSEXITCODE(error);
3015 return (error);
3016}
3017
3018/*

--- 141 unchanged lines hidden (view full) ---

3160/*
3161 * This function is called from the nfssvc(2) system call, to update the
3162 * kernel user/group name list(s) for the V4 owner and ownergroup attributes.
3163 */
3164APPLESTATIC int
3165nfssvc_idname(struct nfsd_idargs *nidp)
3166{
3167 struct nfsusrgrp *nusrp, *usrp, *newusrp;
3104 struct nfsuserhashhead *hp;
3105 int i;
3168 struct nfsrv_lughash *hp_name, *hp_idnum, *thp;
3169 int i, group_locked, groupname_locked, user_locked, username_locked;
3106 int error = 0;
3107 u_char *cp;
3170 int error = 0;
3171 u_char *cp;
3172 gid_t *grps;
3173 struct ucred *cr;
3174 static int onethread = 0;
3175 static time_t lasttime = 0;
3108
3109 if (nidp->nid_flag & NFSID_INITIALIZE) {
3176
3177 if (nidp->nid_flag & NFSID_INITIALIZE) {
3110 cp = (u_char *)malloc(nidp->nid_namelen + 1,
3111 M_NFSSTRING, M_WAITOK);
3112 error = copyin(CAST_USER_ADDR_T(nidp->nid_name), cp,
3113 nidp->nid_namelen);
3114 NFSLOCKNAMEID();
3115 if (nfsrv_dnsname) {
3116 /*
3117 * Free up all the old stuff and reinitialize hash lists.
3118 */
3119 TAILQ_FOREACH_SAFE(usrp, &nfsuserlruhead, lug_lru, nusrp) {
3120 nfsrv_removeuser(usrp);
3178 cp = malloc(nidp->nid_namelen + 1, M_NFSSTRING, M_WAITOK);
3179 error = copyin(CAST_USER_ADDR_T(nidp->nid_name), cp,
3180 nidp->nid_namelen);
3181 if (error != 0) {
3182 free(cp, M_NFSSTRING);
3183 goto out;
3121 }
3184 }
3122 free(nfsrv_dnsname, M_NFSSTRING);
3123 nfsrv_dnsname = NULL;
3124 }
3125 TAILQ_INIT(&nfsuserlruhead);
3126 for (i = 0; i < NFSUSERHASHSIZE; i++)
3127 LIST_INIT(&nfsuserhash[i]);
3128 for (i = 0; i < NFSGROUPHASHSIZE; i++)
3129 LIST_INIT(&nfsgrouphash[i]);
3130 for (i = 0; i < NFSUSERHASHSIZE; i++)
3131 LIST_INIT(&nfsusernamehash[i]);
3132 for (i = 0; i < NFSGROUPHASHSIZE; i++)
3133 LIST_INIT(&nfsgroupnamehash[i]);
3185 if (atomic_cmpset_acq_int(&nfsrv_dnsnamelen, 0, 0) == 0) {
3186 /*
3187 * Free up all the old stuff and reinitialize hash
3188 * lists. All mutexes for both lists must be locked,
3189 * with the user/group name ones before the uid/gid
3190 * ones, to avoid a LOR.
3191 */
3192 for (i = 0; i < nfsrv_lughashsize; i++)
3193 mtx_lock(&nfsusernamehash[i].mtx);
3194 for (i = 0; i < nfsrv_lughashsize; i++)
3195 mtx_lock(&nfsuserhash[i].mtx);
3196 for (i = 0; i < nfsrv_lughashsize; i++)
3197 TAILQ_FOREACH_SAFE(usrp,
3198 &nfsuserhash[i].lughead, lug_numhash, nusrp)
3199 nfsrv_removeuser(usrp, 1);
3200 for (i = 0; i < nfsrv_lughashsize; i++)
3201 mtx_unlock(&nfsuserhash[i].mtx);
3202 for (i = 0; i < nfsrv_lughashsize; i++)
3203 mtx_unlock(&nfsusernamehash[i].mtx);
3204 for (i = 0; i < nfsrv_lughashsize; i++)
3205 mtx_lock(&nfsgroupnamehash[i].mtx);
3206 for (i = 0; i < nfsrv_lughashsize; i++)
3207 mtx_lock(&nfsgrouphash[i].mtx);
3208 for (i = 0; i < nfsrv_lughashsize; i++)
3209 TAILQ_FOREACH_SAFE(usrp,
3210 &nfsgrouphash[i].lughead, lug_numhash,
3211 nusrp)
3212 nfsrv_removeuser(usrp, 0);
3213 for (i = 0; i < nfsrv_lughashsize; i++)
3214 mtx_unlock(&nfsgrouphash[i].mtx);
3215 for (i = 0; i < nfsrv_lughashsize; i++)
3216 mtx_unlock(&nfsgroupnamehash[i].mtx);
3217 free(nfsrv_dnsname, M_NFSSTRING);
3218 nfsrv_dnsname = NULL;
3219 }
3220 if (nfsuserhash == NULL) {
3221 /* Allocate the hash tables. */
3222 nfsuserhash = malloc(sizeof(struct nfsrv_lughash) *
3223 nfsrv_lughashsize, M_NFSUSERGROUP, M_WAITOK |
3224 M_ZERO);
3225 for (i = 0; i < nfsrv_lughashsize; i++)
3226 mtx_init(&nfsuserhash[i].mtx, "nfsuidhash",
3227 NULL, MTX_DEF | MTX_DUPOK);
3228 nfsusernamehash = malloc(sizeof(struct nfsrv_lughash) *
3229 nfsrv_lughashsize, M_NFSUSERGROUP, M_WAITOK |
3230 M_ZERO);
3231 for (i = 0; i < nfsrv_lughashsize; i++)
3232 mtx_init(&nfsusernamehash[i].mtx,
3233 "nfsusrhash", NULL, MTX_DEF |
3234 MTX_DUPOK);
3235 nfsgrouphash = malloc(sizeof(struct nfsrv_lughash) *
3236 nfsrv_lughashsize, M_NFSUSERGROUP, M_WAITOK |
3237 M_ZERO);
3238 for (i = 0; i < nfsrv_lughashsize; i++)
3239 mtx_init(&nfsgrouphash[i].mtx, "nfsgidhash",
3240 NULL, MTX_DEF | MTX_DUPOK);
3241 nfsgroupnamehash = malloc(sizeof(struct nfsrv_lughash) *
3242 nfsrv_lughashsize, M_NFSUSERGROUP, M_WAITOK |
3243 M_ZERO);
3244 for (i = 0; i < nfsrv_lughashsize; i++)
3245 mtx_init(&nfsgroupnamehash[i].mtx,
3246 "nfsgrphash", NULL, MTX_DEF | MTX_DUPOK);
3247 }
3248 /* (Re)initialize the list heads. */
3249 for (i = 0; i < nfsrv_lughashsize; i++)
3250 TAILQ_INIT(&nfsuserhash[i].lughead);
3251 for (i = 0; i < nfsrv_lughashsize; i++)
3252 TAILQ_INIT(&nfsusernamehash[i].lughead);
3253 for (i = 0; i < nfsrv_lughashsize; i++)
3254 TAILQ_INIT(&nfsgrouphash[i].lughead);
3255 for (i = 0; i < nfsrv_lughashsize; i++)
3256 TAILQ_INIT(&nfsgroupnamehash[i].lughead);
3134
3257
3135 /*
3136 * Put name in "DNS" string.
3137 */
3138 if (!error) {
3258 /*
3259 * Put name in "DNS" string.
3260 */
3139 nfsrv_dnsname = cp;
3261 nfsrv_dnsname = cp;
3140 nfsrv_dnsnamelen = nidp->nid_namelen;
3141 nfsrv_defaultuid = nidp->nid_uid;
3142 nfsrv_defaultgid = nidp->nid_gid;
3143 nfsrv_usercnt = 0;
3144 nfsrv_usermax = nidp->nid_usermax;
3262 nfsrv_defaultuid = nidp->nid_uid;
3263 nfsrv_defaultgid = nidp->nid_gid;
3264 nfsrv_usercnt = 0;
3265 nfsrv_usermax = nidp->nid_usermax;
3145 }
3146 NFSUNLOCKNAMEID();
3147 if (error)
3148 free(cp, M_NFSSTRING);
3149 goto out;
3266 atomic_store_rel_int(&nfsrv_dnsnamelen, nidp->nid_namelen);
3267 goto out;
3150 }
3151
3152 /*
3153 * malloc the new one now, so any potential sleep occurs before
3154 * manipulation of the lists.
3155 */
3268 }
3269
3270 /*
3271 * malloc the new one now, so any potential sleep occurs before
3272 * manipulation of the lists.
3273 */
3156 MALLOC(newusrp, struct nfsusrgrp *, sizeof (struct nfsusrgrp) +
3157 nidp->nid_namelen, M_NFSUSERGROUP, M_WAITOK);
3274 newusrp = malloc(sizeof(struct nfsusrgrp) + nidp->nid_namelen,
3275 M_NFSUSERGROUP, M_WAITOK | M_ZERO);
3158 error = copyin(CAST_USER_ADDR_T(nidp->nid_name), newusrp->lug_name,
3159 nidp->nid_namelen);
3276 error = copyin(CAST_USER_ADDR_T(nidp->nid_name), newusrp->lug_name,
3277 nidp->nid_namelen);
3278 if (error == 0 && nidp->nid_ngroup > 0 &&
3279 (nidp->nid_flag & NFSID_ADDUID) != 0) {
3280 grps = malloc(sizeof(gid_t) * nidp->nid_ngroup, M_TEMP,
3281 M_WAITOK);
3282 error = copyin(CAST_USER_ADDR_T(nidp->nid_grps), grps,
3283 sizeof(gid_t) * nidp->nid_ngroup);
3284 if (error == 0) {
3285 /*
3286 * Create a credential just like svc_getcred(),
3287 * but using the group list provided.
3288 */
3289 cr = crget();
3290 cr->cr_uid = cr->cr_ruid = cr->cr_svuid = nidp->nid_uid;
3291 crsetgroups(cr, nidp->nid_ngroup, grps);
3292 cr->cr_rgid = cr->cr_svgid = cr->cr_groups[0];
3293 cr->cr_prison = &prison0;
3294 prison_hold(cr->cr_prison);
3295#ifdef MAC
3296 mac_cred_associate_nfsd(cr);
3297#endif
3298 newusrp->lug_cred = cr;
3299 }
3300 free(grps, M_TEMP);
3301 }
3160 if (error) {
3302 if (error) {
3161 free((caddr_t)newusrp, M_NFSUSERGROUP);
3303 free(newusrp, M_NFSUSERGROUP);
3162 goto out;
3163 }
3164 newusrp->lug_namelen = nidp->nid_namelen;
3165
3304 goto out;
3305 }
3306 newusrp->lug_namelen = nidp->nid_namelen;
3307
3166 NFSLOCKNAMEID();
3167 /*
3308 /*
3309 * The lock order is username[0]->[nfsrv_lughashsize - 1] followed
3310 * by uid[0]->[nfsrv_lughashsize - 1], with the same for group.
3311 * The flags user_locked, username_locked, group_locked and
3312 * groupname_locked are set to indicate all of those hash lists are
3313 * locked. hp_name != NULL and hp_idnum != NULL indicates that
3314 * the respective one mutex is locked.
3315 */
3316 user_locked = username_locked = group_locked = groupname_locked = 0;
3317 hp_name = hp_idnum = NULL;
3318
3319 /*
3168 * Delete old entries, as required.
3169 */
3170 if (nidp->nid_flag & (NFSID_DELUID | NFSID_ADDUID)) {
3320 * Delete old entries, as required.
3321 */
3322 if (nidp->nid_flag & (NFSID_DELUID | NFSID_ADDUID)) {
3171 hp = NFSUSERHASH(nidp->nid_uid);
3172 LIST_FOREACH_SAFE(usrp, hp, lug_numhash, nusrp) {
3323 /* Must lock all username hash lists first, to avoid a LOR. */
3324 for (i = 0; i < nfsrv_lughashsize; i++)
3325 mtx_lock(&nfsusernamehash[i].mtx);
3326 username_locked = 1;
3327 hp_idnum = NFSUSERHASH(nidp->nid_uid);
3328 mtx_lock(&hp_idnum->mtx);
3329 TAILQ_FOREACH_SAFE(usrp, &hp_idnum->lughead, lug_numhash,
3330 nusrp) {
3173 if (usrp->lug_uid == nidp->nid_uid)
3331 if (usrp->lug_uid == nidp->nid_uid)
3174 nfsrv_removeuser(usrp);
3332 nfsrv_removeuser(usrp, 1);
3175 }
3333 }
3176 }
3177 if (nidp->nid_flag & (NFSID_DELUSERNAME | NFSID_ADDUSERNAME)) {
3178 hp = NFSUSERNAMEHASH(newusrp->lug_name, newusrp->lug_namelen);
3179 LIST_FOREACH_SAFE(usrp, hp, lug_namehash, nusrp) {
3334 } else if (nidp->nid_flag & (NFSID_DELUSERNAME | NFSID_ADDUSERNAME)) {
3335 hp_name = NFSUSERNAMEHASH(newusrp->lug_name,
3336 newusrp->lug_namelen);
3337 mtx_lock(&hp_name->mtx);
3338 TAILQ_FOREACH_SAFE(usrp, &hp_name->lughead, lug_namehash,
3339 nusrp) {
3180 if (usrp->lug_namelen == newusrp->lug_namelen &&
3181 !NFSBCMP(usrp->lug_name, newusrp->lug_name,
3340 if (usrp->lug_namelen == newusrp->lug_namelen &&
3341 !NFSBCMP(usrp->lug_name, newusrp->lug_name,
3182 usrp->lug_namelen))
3183 nfsrv_removeuser(usrp);
3342 usrp->lug_namelen)) {
3343 thp = NFSUSERHASH(usrp->lug_uid);
3344 mtx_lock(&thp->mtx);
3345 nfsrv_removeuser(usrp, 1);
3346 mtx_unlock(&thp->mtx);
3347 }
3184 }
3348 }
3185 }
3186 if (nidp->nid_flag & (NFSID_DELGID | NFSID_ADDGID)) {
3187 hp = NFSGROUPHASH(nidp->nid_gid);
3188 LIST_FOREACH_SAFE(usrp, hp, lug_numhash, nusrp) {
3349 hp_idnum = NFSUSERHASH(nidp->nid_uid);
3350 mtx_lock(&hp_idnum->mtx);
3351 } else if (nidp->nid_flag & (NFSID_DELGID | NFSID_ADDGID)) {
3352 /* Must lock all groupname hash lists first, to avoid a LOR. */
3353 for (i = 0; i < nfsrv_lughashsize; i++)
3354 mtx_lock(&nfsgroupnamehash[i].mtx);
3355 groupname_locked = 1;
3356 hp_idnum = NFSGROUPHASH(nidp->nid_gid);
3357 mtx_lock(&hp_idnum->mtx);
3358 TAILQ_FOREACH_SAFE(usrp, &hp_idnum->lughead, lug_numhash,
3359 nusrp) {
3189 if (usrp->lug_gid == nidp->nid_gid)
3360 if (usrp->lug_gid == nidp->nid_gid)
3190 nfsrv_removeuser(usrp);
3361 nfsrv_removeuser(usrp, 0);
3191 }
3362 }
3192 }
3193 if (nidp->nid_flag & (NFSID_DELGROUPNAME | NFSID_ADDGROUPNAME)) {
3194 hp = NFSGROUPNAMEHASH(newusrp->lug_name, newusrp->lug_namelen);
3195 LIST_FOREACH_SAFE(usrp, hp, lug_namehash, nusrp) {
3363 } else if (nidp->nid_flag & (NFSID_DELGROUPNAME | NFSID_ADDGROUPNAME)) {
3364 hp_name = NFSGROUPNAMEHASH(newusrp->lug_name,
3365 newusrp->lug_namelen);
3366 mtx_lock(&hp_name->mtx);
3367 TAILQ_FOREACH_SAFE(usrp, &hp_name->lughead, lug_namehash,
3368 nusrp) {
3196 if (usrp->lug_namelen == newusrp->lug_namelen &&
3197 !NFSBCMP(usrp->lug_name, newusrp->lug_name,
3369 if (usrp->lug_namelen == newusrp->lug_namelen &&
3370 !NFSBCMP(usrp->lug_name, newusrp->lug_name,
3198 usrp->lug_namelen))
3199 nfsrv_removeuser(usrp);
3371 usrp->lug_namelen)) {
3372 thp = NFSGROUPHASH(usrp->lug_gid);
3373 mtx_lock(&thp->mtx);
3374 nfsrv_removeuser(usrp, 0);
3375 mtx_unlock(&thp->mtx);
3376 }
3200 }
3377 }
3378 hp_idnum = NFSGROUPHASH(nidp->nid_gid);
3379 mtx_lock(&hp_idnum->mtx);
3201 }
3380 }
3202 TAILQ_FOREACH_SAFE(usrp, &nfsuserlruhead, lug_lru, nusrp) {
3203 if (usrp->lug_expiry < NFSD_MONOSEC)
3204 nfsrv_removeuser(usrp);
3205 }
3206 while (nfsrv_usercnt >= nfsrv_usermax) {
3207 usrp = TAILQ_FIRST(&nfsuserlruhead);
3208 nfsrv_removeuser(usrp);
3209 }
3210
3211 /*
3212 * Now, we can add the new one.
3213 */
3214 if (nidp->nid_usertimeout)
3215 newusrp->lug_expiry = NFSD_MONOSEC + nidp->nid_usertimeout;
3216 else
3217 newusrp->lug_expiry = NFSD_MONOSEC + 5;
3218 if (nidp->nid_flag & (NFSID_ADDUID | NFSID_ADDUSERNAME)) {
3219 newusrp->lug_uid = nidp->nid_uid;
3381
3382 /*
3383 * Now, we can add the new one.
3384 */
3385 if (nidp->nid_usertimeout)
3386 newusrp->lug_expiry = NFSD_MONOSEC + nidp->nid_usertimeout;
3387 else
3388 newusrp->lug_expiry = NFSD_MONOSEC + 5;
3389 if (nidp->nid_flag & (NFSID_ADDUID | NFSID_ADDUSERNAME)) {
3390 newusrp->lug_uid = nidp->nid_uid;
3220 LIST_INSERT_HEAD(NFSUSERHASH(newusrp->lug_uid), newusrp,
3221 lug_numhash);
3222 LIST_INSERT_HEAD(NFSUSERNAMEHASH(newusrp->lug_name,
3223 newusrp->lug_namelen), newusrp, lug_namehash);
3224 TAILQ_INSERT_TAIL(&nfsuserlruhead, newusrp, lug_lru);
3225 nfsrv_usercnt++;
3391 thp = NFSUSERHASH(newusrp->lug_uid);
3392 mtx_assert(&thp->mtx, MA_OWNED);
3393 TAILQ_INSERT_TAIL(&thp->lughead, newusrp, lug_numhash);
3394 thp = NFSUSERNAMEHASH(newusrp->lug_name, newusrp->lug_namelen);
3395 mtx_assert(&thp->mtx, MA_OWNED);
3396 TAILQ_INSERT_TAIL(&thp->lughead, newusrp, lug_namehash);
3397 atomic_add_int(&nfsrv_usercnt, 1);
3226 } else if (nidp->nid_flag & (NFSID_ADDGID | NFSID_ADDGROUPNAME)) {
3227 newusrp->lug_gid = nidp->nid_gid;
3398 } else if (nidp->nid_flag & (NFSID_ADDGID | NFSID_ADDGROUPNAME)) {
3399 newusrp->lug_gid = nidp->nid_gid;
3228 LIST_INSERT_HEAD(NFSGROUPHASH(newusrp->lug_gid), newusrp,
3229 lug_numhash);
3230 LIST_INSERT_HEAD(NFSGROUPNAMEHASH(newusrp->lug_name,
3231 newusrp->lug_namelen), newusrp, lug_namehash);
3232 TAILQ_INSERT_TAIL(&nfsuserlruhead, newusrp, lug_lru);
3233 nfsrv_usercnt++;
3234 } else
3235 FREE((caddr_t)newusrp, M_NFSUSERGROUP);
3236 NFSUNLOCKNAMEID();
3400 thp = NFSGROUPHASH(newusrp->lug_gid);
3401 mtx_assert(&thp->mtx, MA_OWNED);
3402 TAILQ_INSERT_TAIL(&thp->lughead, newusrp, lug_numhash);
3403 thp = NFSGROUPNAMEHASH(newusrp->lug_name, newusrp->lug_namelen);
3404 mtx_assert(&thp->mtx, MA_OWNED);
3405 TAILQ_INSERT_TAIL(&thp->lughead, newusrp, lug_namehash);
3406 atomic_add_int(&nfsrv_usercnt, 1);
3407 } else {
3408 if (newusrp->lug_cred != NULL)
3409 crfree(newusrp->lug_cred);
3410 free(newusrp, M_NFSUSERGROUP);
3411 }
3412
3413 /*
3414 * Once per second, allow one thread to trim the cache.
3415 */
3416 if (lasttime < NFSD_MONOSEC &&
3417 atomic_cmpset_acq_int(&onethread, 0, 1) != 0) {
3418 /*
3419 * First, unlock the single mutexes, so that all entries
3420 * can be locked and any LOR is avoided.
3421 */
3422 if (hp_name != NULL) {
3423 mtx_unlock(&hp_name->mtx);
3424 hp_name = NULL;
3425 }
3426 if (hp_idnum != NULL) {
3427 mtx_unlock(&hp_idnum->mtx);
3428 hp_idnum = NULL;
3429 }
3430
3431 if ((nidp->nid_flag & (NFSID_DELUID | NFSID_ADDUID |
3432 NFSID_DELUSERNAME | NFSID_ADDUSERNAME)) != 0) {
3433 if (username_locked == 0) {
3434 for (i = 0; i < nfsrv_lughashsize; i++)
3435 mtx_lock(&nfsusernamehash[i].mtx);
3436 username_locked = 1;
3437 }
3438 KASSERT(user_locked == 0,
3439 ("nfssvc_idname: user_locked"));
3440 for (i = 0; i < nfsrv_lughashsize; i++)
3441 mtx_lock(&nfsuserhash[i].mtx);
3442 user_locked = 1;
3443 for (i = 0; i < nfsrv_lughashsize; i++) {
3444 TAILQ_FOREACH_SAFE(usrp,
3445 &nfsuserhash[i].lughead, lug_numhash,
3446 nusrp)
3447 if (usrp->lug_expiry < NFSD_MONOSEC)
3448 nfsrv_removeuser(usrp, 1);
3449 }
3450 for (i = 0; i < nfsrv_lughashsize; i++) {
3451 /*
3452 * Trim the cache using an approximate LRU
3453 * algorithm. This code deletes the least
3454 * recently used entry on each hash list.
3455 */
3456 if (nfsrv_usercnt <= nfsrv_usermax)
3457 break;
3458 usrp = TAILQ_FIRST(&nfsuserhash[i].lughead);
3459 if (usrp != NULL)
3460 nfsrv_removeuser(usrp, 1);
3461 }
3462 } else {
3463 if (groupname_locked == 0) {
3464 for (i = 0; i < nfsrv_lughashsize; i++)
3465 mtx_lock(&nfsgroupnamehash[i].mtx);
3466 groupname_locked = 1;
3467 }
3468 KASSERT(group_locked == 0,
3469 ("nfssvc_idname: group_locked"));
3470 for (i = 0; i < nfsrv_lughashsize; i++)
3471 mtx_lock(&nfsgrouphash[i].mtx);
3472 group_locked = 1;
3473 for (i = 0; i < nfsrv_lughashsize; i++) {
3474 TAILQ_FOREACH_SAFE(usrp,
3475 &nfsgrouphash[i].lughead, lug_numhash,
3476 nusrp)
3477 if (usrp->lug_expiry < NFSD_MONOSEC)
3478 nfsrv_removeuser(usrp, 0);
3479 }
3480 for (i = 0; i < nfsrv_lughashsize; i++) {
3481 /*
3482 * Trim the cache using an approximate LRU
3483 * algorithm. This code deletes the least
3484 * recently user entry on each hash list.
3485 */
3486 if (nfsrv_usercnt <= nfsrv_usermax)
3487 break;
3488 usrp = TAILQ_FIRST(&nfsgrouphash[i].lughead);
3489 if (usrp != NULL)
3490 nfsrv_removeuser(usrp, 0);
3491 }
3492 }
3493 lasttime = NFSD_MONOSEC;
3494 atomic_store_rel_int(&onethread, 0);
3495 }
3496
3497 /* Now, unlock all locked mutexes. */
3498 if (hp_idnum != NULL)
3499 mtx_unlock(&hp_idnum->mtx);
3500 if (hp_name != NULL)
3501 mtx_unlock(&hp_name->mtx);
3502 if (user_locked != 0)
3503 for (i = 0; i < nfsrv_lughashsize; i++)
3504 mtx_unlock(&nfsuserhash[i].mtx);
3505 if (username_locked != 0)
3506 for (i = 0; i < nfsrv_lughashsize; i++)
3507 mtx_unlock(&nfsusernamehash[i].mtx);
3508 if (group_locked != 0)
3509 for (i = 0; i < nfsrv_lughashsize; i++)
3510 mtx_unlock(&nfsgrouphash[i].mtx);
3511 if (groupname_locked != 0)
3512 for (i = 0; i < nfsrv_lughashsize; i++)
3513 mtx_unlock(&nfsgroupnamehash[i].mtx);
3237out:
3238 NFSEXITCODE(error);
3239 return (error);
3240}
3241
3242/*
3243 * Remove a user/group name element.
3244 */
3245static void
3514out:
3515 NFSEXITCODE(error);
3516 return (error);
3517}
3518
3519/*
3520 * Remove a user/group name element.
3521 */
3522static void
3246nfsrv_removeuser(struct nfsusrgrp *usrp)
3523nfsrv_removeuser(struct nfsusrgrp *usrp, int isuser)
3247{
3524{
3525 struct nfsrv_lughash *hp;
3248
3526
3249 NFSNAMEIDREQUIRED();
3250 LIST_REMOVE(usrp, lug_numhash);
3251 LIST_REMOVE(usrp, lug_namehash);
3252 TAILQ_REMOVE(&nfsuserlruhead, usrp, lug_lru);
3253 nfsrv_usercnt--;
3254 FREE((caddr_t)usrp, M_NFSUSERGROUP);
3527 if (isuser != 0) {
3528 hp = NFSUSERHASH(usrp->lug_uid);
3529 mtx_assert(&hp->mtx, MA_OWNED);
3530 TAILQ_REMOVE(&hp->lughead, usrp, lug_numhash);
3531 hp = NFSUSERNAMEHASH(usrp->lug_name, usrp->lug_namelen);
3532 mtx_assert(&hp->mtx, MA_OWNED);
3533 TAILQ_REMOVE(&hp->lughead, usrp, lug_namehash);
3534 } else {
3535 hp = NFSGROUPHASH(usrp->lug_gid);
3536 mtx_assert(&hp->mtx, MA_OWNED);
3537 TAILQ_REMOVE(&hp->lughead, usrp, lug_numhash);
3538 hp = NFSGROUPNAMEHASH(usrp->lug_name, usrp->lug_namelen);
3539 mtx_assert(&hp->mtx, MA_OWNED);
3540 TAILQ_REMOVE(&hp->lughead, usrp, lug_namehash);
3541 }
3542 atomic_add_int(&nfsrv_usercnt, -1);
3543 if (usrp->lug_cred != NULL)
3544 crfree(usrp->lug_cred);
3545 free(usrp, M_NFSUSERGROUP);
3255}
3256
3257/*
3258 * This function scans a byte string and checks for UTF-8 compliance.
3259 * It returns 0 if it conforms and NFSERR_INVAL if not.
3260 */
3261APPLESTATIC int
3262nfsrv_checkutf8(u_int8_t *cp, int len)

--- 600 unchanged lines hidden ---
3546}
3547
3548/*
3549 * This function scans a byte string and checks for UTF-8 compliance.
3550 * It returns 0 if it conforms and NFSERR_INVAL if not.
3551 */
3552APPLESTATIC int
3553nfsrv_checkutf8(u_int8_t *cp, int len)

--- 600 unchanged lines hidden ---