xref: /illumos-gate/usr/src/uts/common/idmap/idmap_cache.c (revision 32c2a899b6e4eab014fd5243af6c011a84dc103f)
1c5c4113dSnw141292 /*
2c5c4113dSnw141292  * CDDL HEADER START
3c5c4113dSnw141292  *
4c5c4113dSnw141292  * The contents of this file are subject to the terms of the
5c5c4113dSnw141292  * Common Development and Distribution License (the "License").
6c5c4113dSnw141292  * You may not use this file except in compliance with the License.
7c5c4113dSnw141292  *
8c5c4113dSnw141292  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9c5c4113dSnw141292  * or http://www.opensolaris.org/os/licensing.
10c5c4113dSnw141292  * See the License for the specific language governing permissions
11c5c4113dSnw141292  * and limitations under the License.
12c5c4113dSnw141292  *
13c5c4113dSnw141292  * When distributing Covered Code, include this CDDL HEADER in each
14c5c4113dSnw141292  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15c5c4113dSnw141292  * If applicable, add the following below this CDDL HEADER, with the
16c5c4113dSnw141292  * fields enclosed by brackets "[]" replaced with your own identifying
17c5c4113dSnw141292  * information: Portions Copyright [yyyy] [name of copyright owner]
18c5c4113dSnw141292  *
19c5c4113dSnw141292  * CDDL HEADER END
20c5c4113dSnw141292  */
21c5c4113dSnw141292 
22c5c4113dSnw141292 /*
239b214d32SJordan Brown  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24c5c4113dSnw141292  * Use is subject to license terms.
25*32c2a899SGordon Ross  *
26*32c2a899SGordon Ross  * Copyright 2023 RackTop Systems, Inc.
27c5c4113dSnw141292  */
28c5c4113dSnw141292 
29c5c4113dSnw141292 /*
30c5c4113dSnw141292  * Windows to Solaris Identity Mapping kernel API
31c5c4113dSnw141292  * This module provides the kernel cache.
32c5c4113dSnw141292  */
33c5c4113dSnw141292 
34c5c4113dSnw141292 
35c5c4113dSnw141292 #include <sys/types.h>
36c5c4113dSnw141292 #include <sys/avl.h>
37c5c4113dSnw141292 #include <sys/systm.h>
38c5c4113dSnw141292 #include <sys/sysmacros.h>
39c5c4113dSnw141292 #include <sys/ksynch.h>
40c5c4113dSnw141292 #include <sys/kidmap.h>
419b214d32SJordan Brown #include <rpcsvc/idmap_prot.h>
42c5c4113dSnw141292 #include "kidmap_priv.h"
43c5c4113dSnw141292 
44c5c4113dSnw141292 
45c5c4113dSnw141292 /*
46c5c4113dSnw141292  * External functions
47c5c4113dSnw141292  */
48c5c4113dSnw141292 extern	uintptr_t	space_fetch(char *key);
49c5c4113dSnw141292 extern	int		space_store(char *key, uintptr_t ptr);
50c5c4113dSnw141292 
51c5c4113dSnw141292 
52c5c4113dSnw141292 /*
53c5c4113dSnw141292  * Internal definitions and functions
54c5c4113dSnw141292  */
55c5c4113dSnw141292 
56d15447b6Sjp151216 #define	CACHE_UID_TRIGGER_SIZE	4096
57d15447b6Sjp151216 #define	CACHE_GID_TRIGGER_SIZE	2048
58d15447b6Sjp151216 #define	CACHE_PID_TRIGGER_SIZE \
59d15447b6Sjp151216 	(CACHE_UID_TRIGGER_SIZE + CACHE_GID_TRIGGER_SIZE)
60d15447b6Sjp151216 
61d15447b6Sjp151216 
62d15447b6Sjp151216 #define	UNDEF_UID	((uid_t)-1)
63d15447b6Sjp151216 #define	UNDEF_GID	((gid_t)-1)
64d15447b6Sjp151216 #define	UNDEF_ISUSER	(-1)
65d15447b6Sjp151216 
66c5c4113dSnw141292 #define	CACHE_PURGE_INTERVAL	(60 * 3)
670b10de9fSjp151216 #define	CACHE_TTL		(60 * 10)
68c5c4113dSnw141292 
6932ff2b3cSJulian Pullen 
7032ff2b3cSJulian Pullen 
7132ff2b3cSJulian Pullen #define	list_insert(head, ele)\
7232ff2b3cSJulian Pullen 	do {\
7332ff2b3cSJulian Pullen 		(ele)->flink = (head)->flink;\
7432ff2b3cSJulian Pullen 		(head)->flink = (ele);\
7532ff2b3cSJulian Pullen 		(ele)->blink = (ele)->flink->blink;\
7632ff2b3cSJulian Pullen 		(ele)->flink->blink = (ele);\
7732ff2b3cSJulian Pullen 	} while (0)
7832ff2b3cSJulian Pullen 
7932ff2b3cSJulian Pullen 
8032ff2b3cSJulian Pullen 
8132ff2b3cSJulian Pullen #define	list_remove(ele)\
8232ff2b3cSJulian Pullen 	do {\
8332ff2b3cSJulian Pullen 		(ele)->flink->blink = (ele)->blink;\
8432ff2b3cSJulian Pullen 		(ele)->blink->flink = (ele)->flink;\
8532ff2b3cSJulian Pullen 	} while (0)
8632ff2b3cSJulian Pullen 
8732ff2b3cSJulian Pullen 
8832ff2b3cSJulian Pullen #define	list_move(head, ele) \
8932ff2b3cSJulian Pullen 	do {\
9032ff2b3cSJulian Pullen 		if ((head)->flink != (ele)) {\
9132ff2b3cSJulian Pullen 			list_remove(ele);\
9232ff2b3cSJulian Pullen 			list_insert(head, ele);\
9332ff2b3cSJulian Pullen 		}\
9432ff2b3cSJulian Pullen 	} while (0)
9532ff2b3cSJulian Pullen 
9632ff2b3cSJulian Pullen 
97c5c4113dSnw141292 typedef struct sid_prefix_node {
98c5c4113dSnw141292 	avl_node_t	avl_link;
99c5c4113dSnw141292 	const char 	*sid_prefix;
100c5c4113dSnw141292 } sid_prefix_node_t;
101c5c4113dSnw141292 
102c5c4113dSnw141292 
103c5c4113dSnw141292 struct sid_prefix_store {
104c5c4113dSnw141292 	struct avl_tree	tree;
105c5c4113dSnw141292 	krwlock_t	lock;
106c5c4113dSnw141292 };
107c5c4113dSnw141292 
108c5c4113dSnw141292 struct sid_prefix_store *kidmap_sid_prefix_store = NULL;
109c5c4113dSnw141292 
110c5c4113dSnw141292 
111c5c4113dSnw141292 
112c5c4113dSnw141292 static void
11332ff2b3cSJulian Pullen kidmap_purge_sid2pid_cache(idmap_sid2pid_cache_t *cache, size_t limit);
114d15447b6Sjp151216 
115d15447b6Sjp151216 static void
11632ff2b3cSJulian Pullen kidmap_purge_pid2sid_cache(idmap_pid2sid_cache_t *cache, size_t limit);
117d15447b6Sjp151216 
118c5c4113dSnw141292 
119c5c4113dSnw141292 /*
120c5c4113dSnw141292  * kidmap_strdup() copied from uts/common/fs/sockfs/nl7c.c
121c5c4113dSnw141292  */
122c5c4113dSnw141292 static char *
kidmap_strdup(const char * s)123c5c4113dSnw141292 kidmap_strdup(const char *s)
124c5c4113dSnw141292 {
125c5c4113dSnw141292 	int	len = strlen(s) + 1;
126c5c4113dSnw141292 	char	*ret = kmem_alloc(len, KM_SLEEP);
127c5c4113dSnw141292 
128c5c4113dSnw141292 	bcopy(s, ret, len);
129c5c4113dSnw141292 	return (ret);
130c5c4113dSnw141292 }
131c5c4113dSnw141292 
132c5c4113dSnw141292 
133c5c4113dSnw141292 static int
kidmap_compare_sid(const void * p1,const void * p2)134*32c2a899SGordon Ross kidmap_compare_sid(const void *p1, const void *p2)
135c5c4113dSnw141292 {
136*32c2a899SGordon Ross 	const sid2pid_t *entry1 = p1;
137*32c2a899SGordon Ross 	const sid2pid_t *entry2 = p2;
1380b10de9fSjp151216 	int64_t comp = ((int64_t)entry2->rid) - ((int64_t)entry1->rid);
139c5c4113dSnw141292 
140c5c4113dSnw141292 	if (comp == 0)
141c5c4113dSnw141292 		comp = strcmp(entry2->sid_prefix, entry1->sid_prefix);
142c5c4113dSnw141292 
143c5c4113dSnw141292 	if (comp < 0)
144c5c4113dSnw141292 		comp = -1;
145c5c4113dSnw141292 	else if (comp > 0)
146c5c4113dSnw141292 		comp = 1;
147c5c4113dSnw141292 
1480b10de9fSjp151216 	return ((int)comp);
149c5c4113dSnw141292 }
150c5c4113dSnw141292 
151c5c4113dSnw141292 
152c5c4113dSnw141292 static int
kidmap_compare_pid(const void * p1,const void * p2)153*32c2a899SGordon Ross kidmap_compare_pid(const void *p1, const void *p2)
154c5c4113dSnw141292 {
155*32c2a899SGordon Ross 	const pid2sid_t *entry1 = p1;
156*32c2a899SGordon Ross 	const pid2sid_t *entry2 = p2;
157*32c2a899SGordon Ross 
1580b10de9fSjp151216 	if (entry2->pid > entry1->pid)
1590b10de9fSjp151216 		return (1);
1600b10de9fSjp151216 	if (entry2->pid < entry1->pid)
1610b10de9fSjp151216 		return (-1);
1620b10de9fSjp151216 	return (0);
163c5c4113dSnw141292 }
164c5c4113dSnw141292 
165c5c4113dSnw141292 
166c5c4113dSnw141292 static int
kidmap_compare_sid_prefix(const void * p1,const void * p2)167*32c2a899SGordon Ross kidmap_compare_sid_prefix(const void *p1, const void *p2)
168c5c4113dSnw141292 {
169*32c2a899SGordon Ross 	const sid_prefix_node_t *entry1 = p1;
170*32c2a899SGordon Ross 	const sid_prefix_node_t *entry2 = p2;
171c5c4113dSnw141292 	int comp;
172c5c4113dSnw141292 
173c5c4113dSnw141292 	comp = strcmp(entry2->sid_prefix, entry1->sid_prefix);
174c5c4113dSnw141292 
175c5c4113dSnw141292 	if (comp < 0)
176c5c4113dSnw141292 		comp = -1;
177c5c4113dSnw141292 	else if (comp > 0)
178c5c4113dSnw141292 		comp = 1;
179c5c4113dSnw141292 
180c5c4113dSnw141292 	return (comp);
181c5c4113dSnw141292 }
182c5c4113dSnw141292 
183c5c4113dSnw141292 
184c5c4113dSnw141292 void
kidmap_cache_create(idmap_cache_t * cache)185c5c4113dSnw141292 kidmap_cache_create(idmap_cache_t *cache)
186c5c4113dSnw141292 {
187*32c2a899SGordon Ross 	int i;
188*32c2a899SGordon Ross 
189*32c2a899SGordon Ross 	/*
190*32c2a899SGordon Ross 	 * Create SID-2-PID hash table
191*32c2a899SGordon Ross 	 */
192*32c2a899SGordon Ross 	for (i = 0; i < KIDMAP_HASH_SIZE; i++) {
193*32c2a899SGordon Ross 		idmap_sid2pid_cache_t *sid2pid_hb = &cache->sid2pid_hash[i];
194*32c2a899SGordon Ross 
195*32c2a899SGordon Ross 		avl_create(&sid2pid_hb->tree, kidmap_compare_sid,
196d15447b6Sjp151216 		    sizeof (sid2pid_t), offsetof(sid2pid_t, avl_link));
197*32c2a899SGordon Ross 		mutex_init(&sid2pid_hb->mutex, NULL, MUTEX_DEFAULT, NULL);
198*32c2a899SGordon Ross 		sid2pid_hb->purge_time = 0;
199*32c2a899SGordon Ross 		sid2pid_hb->head.flink = &sid2pid_hb->head;
200*32c2a899SGordon Ross 		sid2pid_hb->head.blink = &sid2pid_hb->head;
201*32c2a899SGordon Ross 		sid2pid_hb->uid_num = 0;
202*32c2a899SGordon Ross 		sid2pid_hb->gid_num = 0;
203*32c2a899SGordon Ross 		sid2pid_hb->pid_num = 0;
204*32c2a899SGordon Ross 	}
205c5c4113dSnw141292 
206*32c2a899SGordon Ross 	/*
207*32c2a899SGordon Ross 	 * Create UID-2-SID hash table
208*32c2a899SGordon Ross 	 */
209*32c2a899SGordon Ross 	for (i = 0; i < KIDMAP_HASH_SIZE; i++) {
210*32c2a899SGordon Ross 		idmap_pid2sid_cache_t *uid2sid_hb = &cache->uid2sid_hash[i];
2110b10de9fSjp151216 
212*32c2a899SGordon Ross 		avl_create(&uid2sid_hb->tree, kidmap_compare_pid,
213d15447b6Sjp151216 		    sizeof (pid2sid_t), offsetof(pid2sid_t, avl_link));
214*32c2a899SGordon Ross 		mutex_init(&uid2sid_hb->mutex, NULL, MUTEX_DEFAULT, NULL);
215*32c2a899SGordon Ross 		uid2sid_hb->purge_time = 0;
216*32c2a899SGordon Ross 		uid2sid_hb->head.flink = &uid2sid_hb->head;
217*32c2a899SGordon Ross 		uid2sid_hb->head.blink = &uid2sid_hb->head;
218*32c2a899SGordon Ross 	}
219*32c2a899SGordon Ross 
220*32c2a899SGordon Ross 	/*
221*32c2a899SGordon Ross 	 * Create GID-2-SID hash table
222*32c2a899SGordon Ross 	 */
223*32c2a899SGordon Ross 	for (i = 0; i < KIDMAP_HASH_SIZE; i++) {
224*32c2a899SGordon Ross 		idmap_pid2sid_cache_t *gid2sid_hb  = &cache->gid2sid_hash[i];
225*32c2a899SGordon Ross 
226*32c2a899SGordon Ross 		avl_create(&gid2sid_hb->tree, kidmap_compare_pid,
227*32c2a899SGordon Ross 		    sizeof (pid2sid_t), offsetof(pid2sid_t, avl_link));
228*32c2a899SGordon Ross 		mutex_init(&gid2sid_hb->mutex, NULL, MUTEX_DEFAULT, NULL);
229*32c2a899SGordon Ross 		gid2sid_hb->purge_time = 0;
230*32c2a899SGordon Ross 		gid2sid_hb->head.flink = &gid2sid_hb->head;
231*32c2a899SGordon Ross 		gid2sid_hb->head.blink = &gid2sid_hb->head;
232*32c2a899SGordon Ross 	}
233c5c4113dSnw141292 }
234c5c4113dSnw141292 
235c5c4113dSnw141292 
236c5c4113dSnw141292 void
kidmap_cache_delete(idmap_cache_t * cache)237c5c4113dSnw141292 kidmap_cache_delete(idmap_cache_t *cache)
238c5c4113dSnw141292 {
239c5c4113dSnw141292 	void *cookie;
240*32c2a899SGordon Ross 	int i;
241*32c2a899SGordon Ross 
242*32c2a899SGordon Ross 	for (i = 0; i < KIDMAP_HASH_SIZE; i++) {
243*32c2a899SGordon Ross 		idmap_sid2pid_cache_t *sid2pid_hb = &cache->sid2pid_hash[i];
244*32c2a899SGordon Ross 		sid2pid_t *sid2pid;
245c5c4113dSnw141292 
246c5c4113dSnw141292 		cookie = NULL;
247*32c2a899SGordon Ross 		while ((sid2pid = avl_destroy_nodes(&sid2pid_hb->tree,
248*32c2a899SGordon Ross 		    &cookie)) != NULL) {
249d15447b6Sjp151216 			kmem_free(sid2pid, sizeof (sid2pid_t));
250c5c4113dSnw141292 		}
251*32c2a899SGordon Ross 		avl_destroy(&sid2pid_hb->tree);
252*32c2a899SGordon Ross 		mutex_destroy(&sid2pid_hb->mutex);
253*32c2a899SGordon Ross 	}
254d15447b6Sjp151216 
255*32c2a899SGordon Ross 	for (i = 0; i < KIDMAP_HASH_SIZE; i++) {
256*32c2a899SGordon Ross 		idmap_pid2sid_cache_t *uid2sid_hb = &cache->uid2sid_hash[i];
257*32c2a899SGordon Ross 		pid2sid_t *uid2sid;
258c5c4113dSnw141292 
259c5c4113dSnw141292 		cookie = NULL;
260*32c2a899SGordon Ross 		while ((uid2sid = avl_destroy_nodes(&uid2sid_hb->tree,
261*32c2a899SGordon Ross 		    &cookie)) != NULL) {
262*32c2a899SGordon Ross 			kmem_free(uid2sid, sizeof (pid2sid_t));
263c5c4113dSnw141292 		}
264*32c2a899SGordon Ross 		avl_destroy(&uid2sid_hb->tree);
265*32c2a899SGordon Ross 		mutex_destroy(&uid2sid_hb->mutex);
266*32c2a899SGordon Ross 	}
267d15447b6Sjp151216 
268*32c2a899SGordon Ross 	for (i = 0; i < KIDMAP_HASH_SIZE; i++) {
269*32c2a899SGordon Ross 		idmap_pid2sid_cache_t *gid2sid_hb = &cache->gid2sid_hash[i];
270*32c2a899SGordon Ross 		pid2sid_t *gid2sid;
2710b10de9fSjp151216 
2720b10de9fSjp151216 		cookie = NULL;
273*32c2a899SGordon Ross 		while ((gid2sid = avl_destroy_nodes(&gid2sid_hb->tree,
274*32c2a899SGordon Ross 		    &cookie)) != NULL) {
275*32c2a899SGordon Ross 			kmem_free(gid2sid, sizeof (pid2sid_t));
2760b10de9fSjp151216 		}
277*32c2a899SGordon Ross 		avl_destroy(&gid2sid_hb->tree);
278*32c2a899SGordon Ross 		mutex_destroy(&gid2sid_hb->mutex);
279*32c2a899SGordon Ross 	}
2800b10de9fSjp151216 }
2810b10de9fSjp151216 
2820b10de9fSjp151216 
283*32c2a899SGordon Ross /*
284*32c2a899SGordon Ross  * Get counts of cache entries
285*32c2a899SGordon Ross  */
2860b10de9fSjp151216 void
kidmap_cache_get_data(idmap_cache_t * cache,size_t * uidbysid,size_t * gidbysid,size_t * pidbysid,size_t * sidbyuid,size_t * sidbygid)287f7b4b2feSjp151216 kidmap_cache_get_data(idmap_cache_t *cache, size_t *uidbysid, size_t *gidbysid,
288f7b4b2feSjp151216 	size_t *pidbysid, size_t *sidbyuid, size_t *sidbygid)
289f7b4b2feSjp151216 {
290*32c2a899SGordon Ross 	int i;
291f7b4b2feSjp151216 
292*32c2a899SGordon Ross 	*uidbysid = 0;
293*32c2a899SGordon Ross 	*gidbysid = 0;
294*32c2a899SGordon Ross 	*pidbysid = 0;
295*32c2a899SGordon Ross 	*sidbyuid = 0;
296*32c2a899SGordon Ross 	*sidbygid = 0;
297f7b4b2feSjp151216 
298*32c2a899SGordon Ross 
299*32c2a899SGordon Ross 	for (i = 0; i < KIDMAP_HASH_SIZE; i++) {
300*32c2a899SGordon Ross 		idmap_sid2pid_cache_t *sid2pid_hb = &cache->sid2pid_hash[i];
301*32c2a899SGordon Ross 
302*32c2a899SGordon Ross 		mutex_enter(&sid2pid_hb->mutex);
303*32c2a899SGordon Ross 		*uidbysid += sid2pid_hb->uid_num;
304*32c2a899SGordon Ross 		*gidbysid += sid2pid_hb->gid_num;
305*32c2a899SGordon Ross 		*pidbysid += sid2pid_hb->pid_num;
306*32c2a899SGordon Ross 		mutex_exit(&sid2pid_hb->mutex);
307*32c2a899SGordon Ross 	}
308*32c2a899SGordon Ross 
309*32c2a899SGordon Ross 	for (i = 0; i < KIDMAP_HASH_SIZE; i++) {
310*32c2a899SGordon Ross 		idmap_pid2sid_cache_t *uid2sid_hb = &cache->uid2sid_hash[i];
311*32c2a899SGordon Ross 
312*32c2a899SGordon Ross 		mutex_enter(&uid2sid_hb->mutex);
313*32c2a899SGordon Ross 		*sidbyuid += avl_numnodes(&uid2sid_hb->tree);
314*32c2a899SGordon Ross 		mutex_exit(&uid2sid_hb->mutex);
315*32c2a899SGordon Ross 	}
316*32c2a899SGordon Ross 
317*32c2a899SGordon Ross 	for (i = 0; i < KIDMAP_HASH_SIZE; i++) {
318*32c2a899SGordon Ross 		idmap_pid2sid_cache_t *gid2sid_hb = &cache->gid2sid_hash[i];
319*32c2a899SGordon Ross 
320*32c2a899SGordon Ross 		mutex_enter(&gid2sid_hb->mutex);
321*32c2a899SGordon Ross 		*sidbygid += avl_numnodes(&gid2sid_hb->tree);
322*32c2a899SGordon Ross 		mutex_exit(&gid2sid_hb->mutex);
323*32c2a899SGordon Ross 	}
324f7b4b2feSjp151216 }
325f7b4b2feSjp151216 
326f7b4b2feSjp151216 
327f7b4b2feSjp151216 void
kidmap_cache_purge(idmap_cache_t * cache)3280b10de9fSjp151216 kidmap_cache_purge(idmap_cache_t *cache)
3290b10de9fSjp151216 {
3300b10de9fSjp151216 	void *cookie;
331*32c2a899SGordon Ross 	int i;
3320b10de9fSjp151216 
333*32c2a899SGordon Ross 	for (i = 0; i < KIDMAP_HASH_SIZE; i++) {
334*32c2a899SGordon Ross 		idmap_sid2pid_cache_t *sid2pid_hb = &cache->sid2pid_hash[i];
335*32c2a899SGordon Ross 		sid2pid_t *sid2pid;
336*32c2a899SGordon Ross 
337*32c2a899SGordon Ross 		mutex_enter(&sid2pid_hb->mutex);
3380b10de9fSjp151216 		cookie = NULL;
339*32c2a899SGordon Ross 		while ((sid2pid = avl_destroy_nodes(&sid2pid_hb->tree,
340*32c2a899SGordon Ross 		    &cookie)) != NULL) {
341d15447b6Sjp151216 			kmem_free(sid2pid, sizeof (sid2pid_t));
3420b10de9fSjp151216 		}
343*32c2a899SGordon Ross 		avl_destroy(&sid2pid_hb->tree);
344*32c2a899SGordon Ross 		avl_create(&sid2pid_hb->tree, kidmap_compare_sid,
345d15447b6Sjp151216 		    sizeof (sid2pid_t), offsetof(sid2pid_t, avl_link));
346*32c2a899SGordon Ross 		sid2pid_hb->purge_time = 0;
347*32c2a899SGordon Ross 		sid2pid_hb->head.flink = &sid2pid_hb->head;
348*32c2a899SGordon Ross 		sid2pid_hb->head.blink = &sid2pid_hb->head;
349*32c2a899SGordon Ross 		sid2pid_hb->uid_num = 0;
350*32c2a899SGordon Ross 		sid2pid_hb->gid_num = 0;
351*32c2a899SGordon Ross 		sid2pid_hb->pid_num = 0;
352*32c2a899SGordon Ross 		mutex_exit(&sid2pid_hb->mutex);
3530b10de9fSjp151216 	}
3540b10de9fSjp151216 
355*32c2a899SGordon Ross 	for (i = 0; i < KIDMAP_HASH_SIZE; i++) {
356*32c2a899SGordon Ross 		idmap_pid2sid_cache_t *uid2sid_hb = &cache->uid2sid_hash[i];
357*32c2a899SGordon Ross 		pid2sid_t *uid2sid;
3580b10de9fSjp151216 
359*32c2a899SGordon Ross 		mutex_enter(&uid2sid_hb->mutex);
3600b10de9fSjp151216 		cookie = NULL;
361*32c2a899SGordon Ross 		while ((uid2sid = avl_destroy_nodes(&uid2sid_hb->tree,
362*32c2a899SGordon Ross 		    &cookie)) != NULL) {
363*32c2a899SGordon Ross 			kmem_free(uid2sid, sizeof (pid2sid_t));
3640b10de9fSjp151216 		}
365*32c2a899SGordon Ross 		avl_destroy(&uid2sid_hb->tree);
366*32c2a899SGordon Ross 		avl_create(&uid2sid_hb->tree, kidmap_compare_pid,
367d15447b6Sjp151216 		    sizeof (pid2sid_t), offsetof(pid2sid_t, avl_link));
368*32c2a899SGordon Ross 		uid2sid_hb->purge_time = 0;
369*32c2a899SGordon Ross 		uid2sid_hb->head.flink = &uid2sid_hb->head;
370*32c2a899SGordon Ross 		uid2sid_hb->head.blink = &uid2sid_hb->head;
371*32c2a899SGordon Ross 		mutex_exit(&uid2sid_hb->mutex);
372*32c2a899SGordon Ross 	}
373*32c2a899SGordon Ross 
374*32c2a899SGordon Ross 	for (i = 0; i < KIDMAP_HASH_SIZE; i++) {
375*32c2a899SGordon Ross 		idmap_pid2sid_cache_t *gid2sid_hb = &cache->gid2sid_hash[i];
376*32c2a899SGordon Ross 		pid2sid_t *gid2sid;
377*32c2a899SGordon Ross 
378*32c2a899SGordon Ross 		mutex_enter(&gid2sid_hb->mutex);
379*32c2a899SGordon Ross 		cookie = NULL;
380*32c2a899SGordon Ross 		while ((gid2sid = avl_destroy_nodes(&gid2sid_hb->tree,
381*32c2a899SGordon Ross 		    &cookie)) != NULL) {
382*32c2a899SGordon Ross 			kmem_free(gid2sid, sizeof (pid2sid_t));
383*32c2a899SGordon Ross 		}
384*32c2a899SGordon Ross 		avl_destroy(&gid2sid_hb->tree);
385*32c2a899SGordon Ross 		avl_create(&gid2sid_hb->tree, kidmap_compare_pid,
386*32c2a899SGordon Ross 		    sizeof (pid2sid_t), offsetof(pid2sid_t, avl_link));
387*32c2a899SGordon Ross 		gid2sid_hb->purge_time = 0;
388*32c2a899SGordon Ross 		gid2sid_hb->head.flink = &gid2sid_hb->head;
389*32c2a899SGordon Ross 		gid2sid_hb->head.blink = &gid2sid_hb->head;
390*32c2a899SGordon Ross 		mutex_exit(&gid2sid_hb->mutex);
391*32c2a899SGordon Ross 	}
392c5c4113dSnw141292 }
393c5c4113dSnw141292 
394c5c4113dSnw141292 
395c5c4113dSnw141292 int
kidmap_cache_lookup_uidbysid(idmap_cache_t * cache,const char * sid_prefix,uint32_t rid,uid_t * uid)3960b10de9fSjp151216 kidmap_cache_lookup_uidbysid(idmap_cache_t *cache, const char *sid_prefix,
3970b10de9fSjp151216 			uint32_t rid, uid_t *uid)
398c5c4113dSnw141292 {
399d15447b6Sjp151216 	sid2pid_t	entry;
400d15447b6Sjp151216 	sid2pid_t	*result;
401c5c4113dSnw141292 	avl_index_t	where;
40232ff2b3cSJulian Pullen 	int		status = IDMAP_ERR_NOMAPPING;
403*32c2a899SGordon Ross 	int		idx = (rid & KIDMAP_HASH_MASK);
404*32c2a899SGordon Ross 	idmap_sid2pid_cache_t *sid2pid_hb = &cache->sid2pid_hash[idx];
405c5c4113dSnw141292 	time_t		now = gethrestime_sec();
406c5c4113dSnw141292 
4070b10de9fSjp151216 	entry.sid_prefix = sid_prefix;
4080b10de9fSjp151216 	entry.rid = rid;
409c5c4113dSnw141292 
410*32c2a899SGordon Ross 	mutex_enter(&sid2pid_hb->mutex);
411c5c4113dSnw141292 
412*32c2a899SGordon Ross 	result = avl_find(&sid2pid_hb->tree, &entry, &where);
41332ff2b3cSJulian Pullen 	if (result != NULL) {
414*32c2a899SGordon Ross 		list_move(&sid2pid_hb->head, result);
41532ff2b3cSJulian Pullen 		if (result->uid != UNDEF_UID && result->uid_ttl > now) {
416d15447b6Sjp151216 			*uid = result->uid;
417c5c4113dSnw141292 			status = IDMAP_SUCCESS;
41832ff2b3cSJulian Pullen 		}
41932ff2b3cSJulian Pullen 	}
420c5c4113dSnw141292 
421*32c2a899SGordon Ross 	mutex_exit(&sid2pid_hb->mutex);
422c5c4113dSnw141292 
423c5c4113dSnw141292 	return (status);
424c5c4113dSnw141292 }
425c5c4113dSnw141292 
426c5c4113dSnw141292 
427c5c4113dSnw141292 int
kidmap_cache_lookup_gidbysid(idmap_cache_t * cache,const char * sid_prefix,uint32_t rid,gid_t * gid)4280b10de9fSjp151216 kidmap_cache_lookup_gidbysid(idmap_cache_t *cache, const char *sid_prefix,
4290b10de9fSjp151216 			uint32_t rid, gid_t *gid)
4300b10de9fSjp151216 {
431d15447b6Sjp151216 	sid2pid_t	entry;
432d15447b6Sjp151216 	sid2pid_t	*result;
4330b10de9fSjp151216 	avl_index_t	where;
43432ff2b3cSJulian Pullen 	int		status = IDMAP_ERR_NOMAPPING;
435*32c2a899SGordon Ross 	int		idx = (rid & KIDMAP_HASH_MASK);
436*32c2a899SGordon Ross 	idmap_sid2pid_cache_t *sid2pid_hb = &cache->sid2pid_hash[idx];
4370b10de9fSjp151216 	time_t		now = gethrestime_sec();
4380b10de9fSjp151216 
4390b10de9fSjp151216 	entry.sid_prefix = sid_prefix;
4400b10de9fSjp151216 	entry.rid = rid;
4410b10de9fSjp151216 
442*32c2a899SGordon Ross 	mutex_enter(&sid2pid_hb->mutex);
4430b10de9fSjp151216 
444*32c2a899SGordon Ross 	result = avl_find(&sid2pid_hb->tree, &entry, &where);
44532ff2b3cSJulian Pullen 	if (result != NULL) {
446*32c2a899SGordon Ross 		list_move(&sid2pid_hb->head, result);
44732ff2b3cSJulian Pullen 		if (result->gid != UNDEF_GID && result->gid_ttl > now) {
448d15447b6Sjp151216 			*gid = result->gid;
4490b10de9fSjp151216 			status = IDMAP_SUCCESS;
45032ff2b3cSJulian Pullen 		}
45132ff2b3cSJulian Pullen 	}
4520b10de9fSjp151216 
453*32c2a899SGordon Ross 	mutex_exit(&sid2pid_hb->mutex);
4540b10de9fSjp151216 
4550b10de9fSjp151216 	return (status);
4560b10de9fSjp151216 }
4570b10de9fSjp151216 
4580b10de9fSjp151216 
4590b10de9fSjp151216 int
kidmap_cache_lookup_pidbysid(idmap_cache_t * cache,const char * sid_prefix,uint32_t rid,uid_t * pid,int * is_user)4600b10de9fSjp151216 kidmap_cache_lookup_pidbysid(idmap_cache_t *cache, const char *sid_prefix,
461c5c4113dSnw141292 			uint32_t rid, uid_t *pid, int *is_user)
462c5c4113dSnw141292 {
463d15447b6Sjp151216 	sid2pid_t	entry;
464d15447b6Sjp151216 	sid2pid_t	*result;
465c5c4113dSnw141292 	avl_index_t	where;
46632ff2b3cSJulian Pullen 	int		status = IDMAP_ERR_NOMAPPING;
467*32c2a899SGordon Ross 	int		idx = (rid & KIDMAP_HASH_MASK);
468*32c2a899SGordon Ross 	idmap_sid2pid_cache_t *sid2pid_hb = &cache->sid2pid_hash[idx];
469c5c4113dSnw141292 	time_t		now = gethrestime_sec();
470c5c4113dSnw141292 
471c5c4113dSnw141292 	entry.sid_prefix = sid_prefix;
472c5c4113dSnw141292 	entry.rid = rid;
473c5c4113dSnw141292 
474*32c2a899SGordon Ross 	mutex_enter(&sid2pid_hb->mutex);
475c5c4113dSnw141292 
476*32c2a899SGordon Ross 	result = avl_find(&sid2pid_hb->tree, &entry, &where);
47732ff2b3cSJulian Pullen 	if (result != NULL) {
478*32c2a899SGordon Ross 		list_move(&sid2pid_hb->head, result);
47932ff2b3cSJulian Pullen 		if (result->is_user != UNDEF_ISUSER) {
480d15447b6Sjp151216 			if (result->is_user && result->uid_ttl > now) {
481d15447b6Sjp151216 				*pid = result->uid;
482d15447b6Sjp151216 				*is_user = result->is_user;
483d15447b6Sjp151216 				status = IDMAP_SUCCESS;
484d15447b6Sjp151216 			} else if (!result->is_user && result->gid_ttl > now) {
485d15447b6Sjp151216 				*pid = result->gid;
486c5c4113dSnw141292 				*is_user = result->is_user;
487c5c4113dSnw141292 				status = IDMAP_SUCCESS;
48832ff2b3cSJulian Pullen 			}
48932ff2b3cSJulian Pullen 		}
49032ff2b3cSJulian Pullen 	}
491c5c4113dSnw141292 
492*32c2a899SGordon Ross 	mutex_exit(&sid2pid_hb->mutex);
493c5c4113dSnw141292 
494c5c4113dSnw141292 	return (status);
495c5c4113dSnw141292 }
496c5c4113dSnw141292 
497c5c4113dSnw141292 
4980b10de9fSjp151216 
4990b10de9fSjp151216 int
kidmap_cache_lookup_sidbyuid(idmap_cache_t * cache,const char ** sid_prefix,uint32_t * rid,uid_t uid)5000b10de9fSjp151216 kidmap_cache_lookup_sidbyuid(idmap_cache_t *cache, const char **sid_prefix,
5010b10de9fSjp151216 			uint32_t *rid, uid_t uid)
502c5c4113dSnw141292 {
503d15447b6Sjp151216 	pid2sid_t	entry;
504d15447b6Sjp151216 	pid2sid_t	*result;
505c5c4113dSnw141292 	avl_index_t	where;
50632ff2b3cSJulian Pullen 	int		status = IDMAP_ERR_NOMAPPING;
507*32c2a899SGordon Ross 	int		idx = (uid & KIDMAP_HASH_MASK);
508*32c2a899SGordon Ross 	idmap_pid2sid_cache_t *uid2sid_hb = &cache->uid2sid_hash[idx];
5090b10de9fSjp151216 	time_t		now = gethrestime_sec();
510c5c4113dSnw141292 
5110b10de9fSjp151216 	entry.pid = uid;
512c5c4113dSnw141292 
513*32c2a899SGordon Ross 	mutex_enter(&uid2sid_hb->mutex);
514c5c4113dSnw141292 
515*32c2a899SGordon Ross 	result = avl_find(&uid2sid_hb->tree, &entry, &where);
51632ff2b3cSJulian Pullen 	if (result != NULL) {
517*32c2a899SGordon Ross 		list_move(&uid2sid_hb->head, result);
51832ff2b3cSJulian Pullen 		if (result->ttl > now) {
5190b10de9fSjp151216 			*sid_prefix = result->sid_prefix;
5200b10de9fSjp151216 			*rid = result->rid;
5210b10de9fSjp151216 			status = IDMAP_SUCCESS;
52232ff2b3cSJulian Pullen 		}
52332ff2b3cSJulian Pullen 	}
5240b10de9fSjp151216 
525*32c2a899SGordon Ross 	mutex_exit(&uid2sid_hb->mutex);
5260b10de9fSjp151216 
5270b10de9fSjp151216 	return (status);
528c5c4113dSnw141292 }
529c5c4113dSnw141292 
53032ff2b3cSJulian Pullen 
5310b10de9fSjp151216 int
kidmap_cache_lookup_sidbygid(idmap_cache_t * cache,const char ** sid_prefix,uint32_t * rid,gid_t gid)5320b10de9fSjp151216 kidmap_cache_lookup_sidbygid(idmap_cache_t *cache, const char **sid_prefix,
5330b10de9fSjp151216 			uint32_t *rid, gid_t gid)
5340b10de9fSjp151216 {
535d15447b6Sjp151216 	pid2sid_t	entry;
536d15447b6Sjp151216 	pid2sid_t	*result;
5370b10de9fSjp151216 	avl_index_t	where;
53832ff2b3cSJulian Pullen 	int		status = IDMAP_ERR_NOMAPPING;
539*32c2a899SGordon Ross 	int		idx = (gid & KIDMAP_HASH_MASK);
540*32c2a899SGordon Ross 	idmap_pid2sid_cache_t *gid2sid_hb = &cache->gid2sid_hash[idx];
5410b10de9fSjp151216 	time_t		now = gethrestime_sec();
542c5c4113dSnw141292 
5430b10de9fSjp151216 	entry.pid = gid;
5440b10de9fSjp151216 
545*32c2a899SGordon Ross 	mutex_enter(&gid2sid_hb->mutex);
5460b10de9fSjp151216 
547*32c2a899SGordon Ross 	result = avl_find(&gid2sid_hb->tree, &entry, &where);
54832ff2b3cSJulian Pullen 	if (result != NULL) {
549*32c2a899SGordon Ross 		list_move(&gid2sid_hb->head, result);
55032ff2b3cSJulian Pullen 		if (result->ttl > now) {
5510b10de9fSjp151216 			*sid_prefix = result->sid_prefix;
5520b10de9fSjp151216 			*rid = result->rid;
5530b10de9fSjp151216 			status = IDMAP_SUCCESS;
55432ff2b3cSJulian Pullen 		}
55532ff2b3cSJulian Pullen 	}
5560b10de9fSjp151216 
557*32c2a899SGordon Ross 	mutex_exit(&gid2sid_hb->mutex);
5580b10de9fSjp151216 
5590b10de9fSjp151216 	return (status);
560c5c4113dSnw141292 }
561c5c4113dSnw141292 
562c5c4113dSnw141292 
563c5c4113dSnw141292 void
kidmap_cache_add_sid2uid(idmap_cache_t * cache,const char * sid_prefix,uint32_t rid,uid_t uid,int direction)564d15447b6Sjp151216 kidmap_cache_add_sid2uid(idmap_cache_t *cache, const char *sid_prefix,
565d15447b6Sjp151216 			uint32_t rid, uid_t uid, int direction)
566c5c4113dSnw141292 
567c5c4113dSnw141292 {
568c5c4113dSnw141292 	avl_index_t	where;
5690b10de9fSjp151216 	time_t		ttl = CACHE_TTL + gethrestime_sec();
570c5c4113dSnw141292 
571d15447b6Sjp151216 
572d15447b6Sjp151216 	if (direction == IDMAP_DIRECTION_BI ||
573d15447b6Sjp151216 	    direction == IDMAP_DIRECTION_W2U) {
574d15447b6Sjp151216 		sid2pid_t	find;
575d15447b6Sjp151216 		sid2pid_t	*result;
576d15447b6Sjp151216 		sid2pid_t	*new;
577*32c2a899SGordon Ross 		idmap_sid2pid_cache_t *sid2pid_hb =
578*32c2a899SGordon Ross 		    &cache->sid2pid_hash[rid & KIDMAP_HASH_MASK];
579d15447b6Sjp151216 
580c5c4113dSnw141292 		find.sid_prefix = sid_prefix;
581c5c4113dSnw141292 		find.rid = rid;
582c5c4113dSnw141292 
583*32c2a899SGordon Ross 		mutex_enter(&sid2pid_hb->mutex);
5840b10de9fSjp151216 
585*32c2a899SGordon Ross 		result = avl_find(&sid2pid_hb->tree, &find, &where);
5860b10de9fSjp151216 		if (result) {
587d15447b6Sjp151216 			if (result->uid == UNDEF_UID)
588*32c2a899SGordon Ross 				sid2pid_hb->uid_num++;
589d15447b6Sjp151216 			result->uid = uid;
590d15447b6Sjp151216 			result->uid_ttl = ttl;
5910b10de9fSjp151216 		} else {
592d15447b6Sjp151216 			new = kmem_alloc(sizeof (sid2pid_t), KM_SLEEP);
5930b10de9fSjp151216 			new->sid_prefix = sid_prefix;
5940b10de9fSjp151216 			new->rid = rid;
595d15447b6Sjp151216 			new->uid = uid;
596d15447b6Sjp151216 			new->uid_ttl = ttl;
597d15447b6Sjp151216 			new->gid = UNDEF_GID;
598d15447b6Sjp151216 			new->gid_ttl = 0;
599d15447b6Sjp151216 			new->is_user = UNDEF_ISUSER; /* Unknown */
600*32c2a899SGordon Ross 			sid2pid_hb->uid_num++;
6010b10de9fSjp151216 
602*32c2a899SGordon Ross 			list_insert(&sid2pid_hb->head, new);
603*32c2a899SGordon Ross 			avl_insert(&sid2pid_hb->tree, new, where);
60432ff2b3cSJulian Pullen 		}
6050b10de9fSjp151216 
606*32c2a899SGordon Ross 		if ((avl_numnodes(&sid2pid_hb->tree) >
607d15447b6Sjp151216 		    CACHE_PID_TRIGGER_SIZE) &&
608*32c2a899SGordon Ross 		    (sid2pid_hb->purge_time + CACHE_PURGE_INTERVAL <
6090b10de9fSjp151216 		    gethrestime_sec()))
610*32c2a899SGordon Ross 			kidmap_purge_sid2pid_cache(sid2pid_hb,
61132ff2b3cSJulian Pullen 			    CACHE_PID_TRIGGER_SIZE);
6120b10de9fSjp151216 
613*32c2a899SGordon Ross 		mutex_exit(&sid2pid_hb->mutex);
6140b10de9fSjp151216 	}
6150b10de9fSjp151216 
616d15447b6Sjp151216 	if (direction == IDMAP_DIRECTION_BI ||
617d15447b6Sjp151216 	    direction == IDMAP_DIRECTION_U2W) {
618d15447b6Sjp151216 		pid2sid_t	find;
619d15447b6Sjp151216 		pid2sid_t	*result;
620d15447b6Sjp151216 		pid2sid_t	*new;
621*32c2a899SGordon Ross 		idmap_pid2sid_cache_t *uid2sid_hb =
622*32c2a899SGordon Ross 		    &cache->uid2sid_hash[uid & KIDMAP_HASH_MASK];
6230b10de9fSjp151216 
6240b10de9fSjp151216 		find.pid = uid;
6250b10de9fSjp151216 
626*32c2a899SGordon Ross 		mutex_enter(&uid2sid_hb->mutex);
6270b10de9fSjp151216 
628*32c2a899SGordon Ross 		result = avl_find(&uid2sid_hb->tree, &find, &where);
6290b10de9fSjp151216 		if (result) {
6300b10de9fSjp151216 			result->sid_prefix = sid_prefix;
6310b10de9fSjp151216 			result->rid = rid;
6320b10de9fSjp151216 			result->ttl = ttl;
6330b10de9fSjp151216 		} else {
634d15447b6Sjp151216 			new = kmem_alloc(sizeof (pid2sid_t), KM_SLEEP);
6350b10de9fSjp151216 			new->sid_prefix = sid_prefix;
6360b10de9fSjp151216 			new->rid = rid;
637d15447b6Sjp151216 			new->pid = uid;
6380b10de9fSjp151216 			new->ttl = ttl;
6390b10de9fSjp151216 
640*32c2a899SGordon Ross 			list_insert(&uid2sid_hb->head, new);
641*32c2a899SGordon Ross 			avl_insert(&uid2sid_hb->tree, new, where);
64232ff2b3cSJulian Pullen 		}
643d15447b6Sjp151216 
644*32c2a899SGordon Ross 		if ((avl_numnodes(&uid2sid_hb->tree) >
645d15447b6Sjp151216 		    CACHE_UID_TRIGGER_SIZE) &&
646*32c2a899SGordon Ross 		    (uid2sid_hb->purge_time + CACHE_PURGE_INTERVAL <
6470b10de9fSjp151216 		    gethrestime_sec()))
648*32c2a899SGordon Ross 			kidmap_purge_pid2sid_cache(uid2sid_hb,
649d15447b6Sjp151216 			    CACHE_UID_TRIGGER_SIZE);
65032ff2b3cSJulian Pullen 
651*32c2a899SGordon Ross 		mutex_exit(&uid2sid_hb->mutex);
652d15447b6Sjp151216 	}
653d15447b6Sjp151216 }
654d15447b6Sjp151216 
655d15447b6Sjp151216 
656d15447b6Sjp151216 
657d15447b6Sjp151216 void
kidmap_cache_add_sid2gid(idmap_cache_t * cache,const char * sid_prefix,uint32_t rid,gid_t gid,int direction)658d15447b6Sjp151216 kidmap_cache_add_sid2gid(idmap_cache_t *cache, const char *sid_prefix,
659d15447b6Sjp151216 			uint32_t rid, gid_t gid, int direction)
660d15447b6Sjp151216 {
661d15447b6Sjp151216 	avl_index_t	where;
662d15447b6Sjp151216 	time_t		ttl = CACHE_TTL + gethrestime_sec();
663d15447b6Sjp151216 
664d15447b6Sjp151216 
665d15447b6Sjp151216 	if (direction == IDMAP_DIRECTION_BI ||
666d15447b6Sjp151216 	    direction == IDMAP_DIRECTION_W2U) {
667d15447b6Sjp151216 		sid2pid_t	find;
668d15447b6Sjp151216 		sid2pid_t	*result;
669d15447b6Sjp151216 		sid2pid_t	*new;
670*32c2a899SGordon Ross 		idmap_sid2pid_cache_t *sid2pid_hb =
671*32c2a899SGordon Ross 		    &cache->sid2pid_hash[rid & KIDMAP_HASH_MASK];
672d15447b6Sjp151216 
673d15447b6Sjp151216 		find.sid_prefix = sid_prefix;
674d15447b6Sjp151216 		find.rid = rid;
675d15447b6Sjp151216 
676*32c2a899SGordon Ross 		mutex_enter(&sid2pid_hb->mutex);
677d15447b6Sjp151216 
678*32c2a899SGordon Ross 		result = avl_find(&sid2pid_hb->tree, &find, &where);
679d15447b6Sjp151216 		if (result) {
680d15447b6Sjp151216 			if (result->gid == UNDEF_GID)
681*32c2a899SGordon Ross 				sid2pid_hb->gid_num++;
682d15447b6Sjp151216 			result->gid = gid;
683d15447b6Sjp151216 			result->gid_ttl = ttl;
684d15447b6Sjp151216 		} else {
685d15447b6Sjp151216 			new = kmem_alloc(sizeof (sid2pid_t), KM_SLEEP);
686d15447b6Sjp151216 			new->sid_prefix = sid_prefix;
687d15447b6Sjp151216 			new->rid = rid;
688d15447b6Sjp151216 			new->uid = UNDEF_UID;
689d15447b6Sjp151216 			new->uid_ttl = 0;
690d15447b6Sjp151216 			new->gid = gid;
691d15447b6Sjp151216 			new->gid_ttl = ttl;
692d15447b6Sjp151216 			new->is_user = UNDEF_ISUSER; /* Unknown */
693*32c2a899SGordon Ross 			sid2pid_hb->gid_num++;
694d15447b6Sjp151216 
695*32c2a899SGordon Ross 			list_insert(&sid2pid_hb->head, new);
696*32c2a899SGordon Ross 			avl_insert(&sid2pid_hb->tree, new, where);
69732ff2b3cSJulian Pullen 		}
698d15447b6Sjp151216 
699*32c2a899SGordon Ross 		if ((avl_numnodes(&sid2pid_hb->tree) >
700d15447b6Sjp151216 		    CACHE_PID_TRIGGER_SIZE) &&
701*32c2a899SGordon Ross 		    (sid2pid_hb->purge_time + CACHE_PURGE_INTERVAL <
702d15447b6Sjp151216 		    gethrestime_sec()))
703*32c2a899SGordon Ross 			kidmap_purge_sid2pid_cache(sid2pid_hb,
704d15447b6Sjp151216 			    CACHE_PID_TRIGGER_SIZE);
70532ff2b3cSJulian Pullen 
706*32c2a899SGordon Ross 		mutex_exit(&sid2pid_hb->mutex);
707d15447b6Sjp151216 	}
708d15447b6Sjp151216 
709d15447b6Sjp151216 	if (direction == IDMAP_DIRECTION_BI ||
710d15447b6Sjp151216 	    direction == IDMAP_DIRECTION_U2W) {
711d15447b6Sjp151216 		pid2sid_t	find;
712d15447b6Sjp151216 		pid2sid_t	*result;
713d15447b6Sjp151216 		pid2sid_t	*new;
714*32c2a899SGordon Ross 		idmap_pid2sid_cache_t *gid2sid_hb =
715*32c2a899SGordon Ross 		    &cache->gid2sid_hash[gid & KIDMAP_HASH_MASK];
716d15447b6Sjp151216 
717d15447b6Sjp151216 		find.pid = gid;
718d15447b6Sjp151216 
719*32c2a899SGordon Ross 		mutex_enter(&gid2sid_hb->mutex);
720d15447b6Sjp151216 
721*32c2a899SGordon Ross 		result = avl_find(&gid2sid_hb->tree, &find, &where);
722d15447b6Sjp151216 		if (result) {
723d15447b6Sjp151216 			result->sid_prefix = sid_prefix;
724d15447b6Sjp151216 			result->rid = rid;
725d15447b6Sjp151216 			result->ttl = ttl;
726d15447b6Sjp151216 		} else {
727d15447b6Sjp151216 			new = kmem_alloc(sizeof (pid2sid_t), KM_SLEEP);
728d15447b6Sjp151216 			new->sid_prefix = sid_prefix;
729d15447b6Sjp151216 			new->rid = rid;
730d15447b6Sjp151216 			new->pid = gid;
731d15447b6Sjp151216 			new->ttl = ttl;
732d15447b6Sjp151216 
733*32c2a899SGordon Ross 			list_insert(&gid2sid_hb->head, new);
734*32c2a899SGordon Ross 			avl_insert(&gid2sid_hb->tree, new, where);
73532ff2b3cSJulian Pullen 		}
736d15447b6Sjp151216 
737*32c2a899SGordon Ross 		if ((avl_numnodes(&gid2sid_hb->tree) >
738d15447b6Sjp151216 		    CACHE_GID_TRIGGER_SIZE) &&
739*32c2a899SGordon Ross 		    (gid2sid_hb->purge_time + CACHE_PURGE_INTERVAL <
740d15447b6Sjp151216 		    gethrestime_sec()))
741*32c2a899SGordon Ross 			kidmap_purge_pid2sid_cache(gid2sid_hb,
742d15447b6Sjp151216 			    CACHE_GID_TRIGGER_SIZE);
74332ff2b3cSJulian Pullen 
744*32c2a899SGordon Ross 		mutex_exit(&gid2sid_hb->mutex);
745d15447b6Sjp151216 	}
7460b10de9fSjp151216 }
7470b10de9fSjp151216 
7480b10de9fSjp151216 
7490b10de9fSjp151216 void
kidmap_cache_add_sid2pid(idmap_cache_t * cache,const char * sid_prefix,uint32_t rid,uid_t pid,int is_user,int direction)750d15447b6Sjp151216 kidmap_cache_add_sid2pid(idmap_cache_t *cache, const char *sid_prefix,
751d15447b6Sjp151216 			uint32_t rid, uid_t pid, int is_user, int direction)
7520b10de9fSjp151216 {
7530b10de9fSjp151216 	avl_index_t	where;
7540b10de9fSjp151216 	time_t		ttl = CACHE_TTL + gethrestime_sec();
7550b10de9fSjp151216 
7560b10de9fSjp151216 
757d15447b6Sjp151216 	if (direction == IDMAP_DIRECTION_BI ||
758d15447b6Sjp151216 	    direction == IDMAP_DIRECTION_W2U) {
759d15447b6Sjp151216 		sid2pid_t	find;
760d15447b6Sjp151216 		sid2pid_t	*result;
761d15447b6Sjp151216 		sid2pid_t	*new;
762*32c2a899SGordon Ross 		idmap_sid2pid_cache_t *sid2pid_hb =
763*32c2a899SGordon Ross 		    &cache->sid2pid_hash[rid & KIDMAP_HASH_MASK];
764d15447b6Sjp151216 
765d15447b6Sjp151216 		find.sid_prefix = sid_prefix;
766d15447b6Sjp151216 		find.rid = rid;
767d15447b6Sjp151216 
768*32c2a899SGordon Ross 		mutex_enter(&sid2pid_hb->mutex);
769d15447b6Sjp151216 
770*32c2a899SGordon Ross 		result = avl_find(&sid2pid_hb->tree, &find, &where);
771d15447b6Sjp151216 		if (result) {
772d15447b6Sjp151216 			if (result->is_user == UNDEF_ISUSER)
773*32c2a899SGordon Ross 				sid2pid_hb->pid_num++;
774d15447b6Sjp151216 			result->is_user = is_user;
775d15447b6Sjp151216 			if (is_user) {
776d15447b6Sjp151216 				if (result->uid == UNDEF_UID)
777*32c2a899SGordon Ross 					sid2pid_hb->uid_num++;
778d15447b6Sjp151216 				result->uid = pid;
779d15447b6Sjp151216 				result->uid_ttl = ttl;
780d15447b6Sjp151216 			} else {
781d15447b6Sjp151216 				if (result->gid == UNDEF_GID)
782*32c2a899SGordon Ross 					sid2pid_hb->gid_num++;
783d15447b6Sjp151216 				result->gid = pid;
784d15447b6Sjp151216 				result->gid_ttl = ttl;
785d15447b6Sjp151216 			}
786d15447b6Sjp151216 		} else {
787d15447b6Sjp151216 			new = kmem_alloc(sizeof (sid2pid_t), KM_SLEEP);
788d15447b6Sjp151216 			new->sid_prefix = sid_prefix;
789d15447b6Sjp151216 			new->rid = rid;
790d15447b6Sjp151216 			new->is_user = is_user;
791d15447b6Sjp151216 			if (is_user) {
792d15447b6Sjp151216 				new->uid = pid;
793d15447b6Sjp151216 				new->uid_ttl = ttl;
794d15447b6Sjp151216 				new->gid = UNDEF_GID;
795d15447b6Sjp151216 				new->gid_ttl = 0;
796*32c2a899SGordon Ross 				sid2pid_hb->uid_num++;
797d15447b6Sjp151216 			} else {
798d15447b6Sjp151216 				new->uid = UNDEF_UID;
799d15447b6Sjp151216 				new->uid_ttl = 0;
800d15447b6Sjp151216 				new->gid = pid;
801d15447b6Sjp151216 				new->gid_ttl = ttl;
802*32c2a899SGordon Ross 				sid2pid_hb->gid_num++;
803d15447b6Sjp151216 			}
804*32c2a899SGordon Ross 			sid2pid_hb->pid_num++;
805d15447b6Sjp151216 
806*32c2a899SGordon Ross 			list_insert(&sid2pid_hb->head, new);
807*32c2a899SGordon Ross 			avl_insert(&sid2pid_hb->tree, new, where);
80832ff2b3cSJulian Pullen 		}
809d15447b6Sjp151216 
810*32c2a899SGordon Ross 		if ((avl_numnodes(&sid2pid_hb->tree) >
811d15447b6Sjp151216 		    CACHE_PID_TRIGGER_SIZE) &&
812*32c2a899SGordon Ross 		    (sid2pid_hb->purge_time + CACHE_PURGE_INTERVAL <
813d15447b6Sjp151216 		    gethrestime_sec()))
814*32c2a899SGordon Ross 			kidmap_purge_sid2pid_cache(sid2pid_hb,
815d15447b6Sjp151216 			    CACHE_PID_TRIGGER_SIZE);
81632ff2b3cSJulian Pullen 
817*32c2a899SGordon Ross 		mutex_exit(&sid2pid_hb->mutex);
818d15447b6Sjp151216 	}
819d15447b6Sjp151216 
820d15447b6Sjp151216 	if (direction == IDMAP_DIRECTION_BI ||
821d15447b6Sjp151216 	    direction == IDMAP_DIRECTION_U2W) {
822d15447b6Sjp151216 		pid2sid_t	find;
823d15447b6Sjp151216 		pid2sid_t	*result;
824d15447b6Sjp151216 		pid2sid_t	*new;
825*32c2a899SGordon Ross 		int		idx = pid & KIDMAP_HASH_MASK;
826d15447b6Sjp151216 
827d15447b6Sjp151216 		find.pid = pid;
828d15447b6Sjp151216 		if (is_user) {
829*32c2a899SGordon Ross 			idmap_pid2sid_cache_t *uid2sid_hb =
830*32c2a899SGordon Ross 				&cache->uid2sid_hash[idx];
8310b10de9fSjp151216 
832*32c2a899SGordon Ross 			mutex_enter(&uid2sid_hb->mutex);
833*32c2a899SGordon Ross 
834*32c2a899SGordon Ross 			result = avl_find(&uid2sid_hb->tree, &find, &where);
8350b10de9fSjp151216 			if (result) {
8360b10de9fSjp151216 				result->sid_prefix = sid_prefix;
8370b10de9fSjp151216 				result->rid = rid;
8380b10de9fSjp151216 				result->ttl = ttl;
8390b10de9fSjp151216 			} else {
840d15447b6Sjp151216 				new = kmem_alloc(sizeof (pid2sid_t), KM_SLEEP);
8410b10de9fSjp151216 				new->sid_prefix = sid_prefix;
8420b10de9fSjp151216 				new->rid = rid;
843d15447b6Sjp151216 				new->pid = pid;
8440b10de9fSjp151216 				new->ttl = ttl;
8450b10de9fSjp151216 
846*32c2a899SGordon Ross 				list_insert(&uid2sid_hb->head, new);
847*32c2a899SGordon Ross 				avl_insert(&uid2sid_hb->tree, new, where);
84832ff2b3cSJulian Pullen 			}
849d15447b6Sjp151216 
850*32c2a899SGordon Ross 			if ((avl_numnodes(&uid2sid_hb->tree) >
851d15447b6Sjp151216 			    CACHE_UID_TRIGGER_SIZE) &&
852*32c2a899SGordon Ross 			    (uid2sid_hb->purge_time +
853d15447b6Sjp151216 			    CACHE_PURGE_INTERVAL <
8540b10de9fSjp151216 			    gethrestime_sec()))
855*32c2a899SGordon Ross 				kidmap_purge_pid2sid_cache(uid2sid_hb,
856d15447b6Sjp151216 				    CACHE_UID_TRIGGER_SIZE);
85732ff2b3cSJulian Pullen 
858*32c2a899SGordon Ross 			mutex_exit(&uid2sid_hb->mutex);
859d15447b6Sjp151216 		} else {
860*32c2a899SGordon Ross 			idmap_pid2sid_cache_t *gid2sid_hb =
861*32c2a899SGordon Ross 			    &cache->gid2sid_hash[idx];
862d15447b6Sjp151216 
863*32c2a899SGordon Ross 			mutex_enter(&gid2sid_hb->mutex);
864*32c2a899SGordon Ross 
865*32c2a899SGordon Ross 			result = avl_find(&gid2sid_hb->tree, &find, &where);
866d15447b6Sjp151216 			if (result) {
867d15447b6Sjp151216 				result->sid_prefix = sid_prefix;
868d15447b6Sjp151216 				result->rid = rid;
869d15447b6Sjp151216 				result->ttl = ttl;
870d15447b6Sjp151216 			} else {
871d15447b6Sjp151216 				new = kmem_alloc(sizeof (pid2sid_t), KM_SLEEP);
872d15447b6Sjp151216 				new->sid_prefix = sid_prefix;
873d15447b6Sjp151216 				new->rid = rid;
874d15447b6Sjp151216 				new->pid = pid;
875d15447b6Sjp151216 				new->ttl = ttl;
876d15447b6Sjp151216 
877*32c2a899SGordon Ross 				list_insert(&gid2sid_hb->head, new);
878*32c2a899SGordon Ross 				avl_insert(&gid2sid_hb->tree, new, where);
87932ff2b3cSJulian Pullen 			}
880d15447b6Sjp151216 
881*32c2a899SGordon Ross 			if ((avl_numnodes(&gid2sid_hb->tree) >
882d15447b6Sjp151216 			    CACHE_GID_TRIGGER_SIZE) &&
883*32c2a899SGordon Ross 			    (gid2sid_hb->purge_time +
88432ff2b3cSJulian Pullen 			    CACHE_PURGE_INTERVAL < gethrestime_sec()))
885*32c2a899SGordon Ross 				kidmap_purge_pid2sid_cache(gid2sid_hb,
886d15447b6Sjp151216 				    CACHE_GID_TRIGGER_SIZE);
88732ff2b3cSJulian Pullen 
888*32c2a899SGordon Ross 			mutex_exit(&gid2sid_hb->mutex);
889d15447b6Sjp151216 		}
890d15447b6Sjp151216 	}
891d15447b6Sjp151216 }
892d15447b6Sjp151216 
893d15447b6Sjp151216 
894d15447b6Sjp151216 
895d15447b6Sjp151216 
896d15447b6Sjp151216 
897d15447b6Sjp151216 static void
kidmap_purge_sid2pid_cache(idmap_sid2pid_cache_t * cache,size_t limit)89832ff2b3cSJulian Pullen kidmap_purge_sid2pid_cache(idmap_sid2pid_cache_t *cache, size_t limit)
899d15447b6Sjp151216 {
900d15447b6Sjp151216 	time_t		now = gethrestime_sec();
90132ff2b3cSJulian Pullen 	sid2pid_t	*item;
902d15447b6Sjp151216 
90332ff2b3cSJulian Pullen 	while (avl_numnodes(&cache->tree) > limit) {
90432ff2b3cSJulian Pullen 		/* Remove least recently used */
90532ff2b3cSJulian Pullen 		item = cache->head.blink;
90632ff2b3cSJulian Pullen 		list_remove(item);
90732ff2b3cSJulian Pullen 		avl_remove(&cache->tree, item);
90832ff2b3cSJulian Pullen 		if (item->uid != UNDEF_UID)
90932ff2b3cSJulian Pullen 			cache->uid_num--;
91032ff2b3cSJulian Pullen 		if (item->gid != UNDEF_GID)
91132ff2b3cSJulian Pullen 			cache->gid_num--;
91232ff2b3cSJulian Pullen 		if (item->is_user != UNDEF_ISUSER)
91332ff2b3cSJulian Pullen 			cache->pid_num--;
91432ff2b3cSJulian Pullen 		kmem_free(item, sizeof (sid2pid_t));
915d15447b6Sjp151216 	}
91632ff2b3cSJulian Pullen 	cache->purge_time = now;
917c5c4113dSnw141292 }
918c5c4113dSnw141292 
919c5c4113dSnw141292 
920c5c4113dSnw141292 static void
kidmap_purge_pid2sid_cache(idmap_pid2sid_cache_t * cache,size_t limit)92132ff2b3cSJulian Pullen kidmap_purge_pid2sid_cache(idmap_pid2sid_cache_t *cache, size_t limit)
922c5c4113dSnw141292 {
923c5c4113dSnw141292 	time_t		now = gethrestime_sec();
92432ff2b3cSJulian Pullen 	pid2sid_t	*item;
925c5c4113dSnw141292 
92632ff2b3cSJulian Pullen 	while (avl_numnodes(&cache->tree) > limit) {
92732ff2b3cSJulian Pullen 		/* Remove least recently used */
92832ff2b3cSJulian Pullen 		item = cache->head.blink;
92932ff2b3cSJulian Pullen 		list_remove(item);
93032ff2b3cSJulian Pullen 		avl_remove(&cache->tree, item);
93132ff2b3cSJulian Pullen 		kmem_free(item, sizeof (pid2sid_t));
932d15447b6Sjp151216 	}
93332ff2b3cSJulian Pullen 	cache->purge_time = now;
934c5c4113dSnw141292 }
935d15447b6Sjp151216 
936d15447b6Sjp151216 
937c5c4113dSnw141292 void
kidmap_sid_prefix_store_init(void)938c5c4113dSnw141292 kidmap_sid_prefix_store_init(void)
939c5c4113dSnw141292 {
940c5c4113dSnw141292 	kidmap_sid_prefix_store = (struct sid_prefix_store *)
941c5c4113dSnw141292 	    space_fetch("SUNW,idmap_sid_prefix");
942c5c4113dSnw141292 	if (kidmap_sid_prefix_store == NULL) {
943c5c4113dSnw141292 		kidmap_sid_prefix_store = kmem_alloc(
944c5c4113dSnw141292 		    sizeof (struct sid_prefix_store), KM_SLEEP);
945c5c4113dSnw141292 		rw_init(&kidmap_sid_prefix_store->lock, NULL, RW_DRIVER, NULL);
946c5c4113dSnw141292 		avl_create(&kidmap_sid_prefix_store->tree,
947*32c2a899SGordon Ross 		    kidmap_compare_sid_prefix,
948c5c4113dSnw141292 		    sizeof (sid_prefix_node_t),
949c5c4113dSnw141292 		    offsetof(sid_prefix_node_t, avl_link));
950c5c4113dSnw141292 		(void) space_store("SUNW,idmap_sid_prefix",
951c5c4113dSnw141292 		    (uintptr_t)kidmap_sid_prefix_store);
952c5c4113dSnw141292 	} else {
953c5c4113dSnw141292 		/*
954c5c4113dSnw141292 		 * The AVL comparison function must be re-initialised on
955c5c4113dSnw141292 		 * re-load because may not be loaded into the same
956c5c4113dSnw141292 		 * address space.
957c5c4113dSnw141292 		 */
958c5c4113dSnw141292 		kidmap_sid_prefix_store->tree.avl_compar =
959*32c2a899SGordon Ross 		    kidmap_compare_sid_prefix;
960c5c4113dSnw141292 	}
961c5c4113dSnw141292 }
962c5c4113dSnw141292 
963c5c4113dSnw141292 
964c5c4113dSnw141292 const char *
kidmap_find_sid_prefix(const char * sid_prefix)965c5c4113dSnw141292 kidmap_find_sid_prefix(const char *sid_prefix) {
966c5c4113dSnw141292 	sid_prefix_node_t 	find;
967c5c4113dSnw141292 	sid_prefix_node_t	*result;
968c5c4113dSnw141292 	sid_prefix_node_t 	*new;
969c5c4113dSnw141292 	avl_index_t		where;
970c5c4113dSnw141292 
971c5c4113dSnw141292 	if (sid_prefix == NULL || *sid_prefix == '\0')
972c5c4113dSnw141292 		return (NULL);
973c5c4113dSnw141292 
974c5c4113dSnw141292 	find.sid_prefix = sid_prefix;
975c5c4113dSnw141292 
976c5c4113dSnw141292 	rw_enter(&kidmap_sid_prefix_store->lock, RW_READER);
977c5c4113dSnw141292 
978c5c4113dSnw141292 	result = avl_find(&kidmap_sid_prefix_store->tree, &find, &where);
979c5c4113dSnw141292 
980c5c4113dSnw141292 	if (result) {
981c5c4113dSnw141292 		rw_exit(&kidmap_sid_prefix_store->lock);
982c5c4113dSnw141292 		return (result->sid_prefix);
983c5c4113dSnw141292 	}
984c5c4113dSnw141292 
985c5c4113dSnw141292 	if (rw_tryupgrade(&kidmap_sid_prefix_store->lock) == 0) {
986c5c4113dSnw141292 		/*
987c5c4113dSnw141292 		 * Could not upgrade lock so release lock
988da6c28aaSamw 		 * and acquire the write lock
989c5c4113dSnw141292 		 */
990c5c4113dSnw141292 		rw_exit(&kidmap_sid_prefix_store->lock);
991c5c4113dSnw141292 		rw_enter(&kidmap_sid_prefix_store->lock, RW_WRITER);
992c5c4113dSnw141292 
993c5c4113dSnw141292 		result = avl_find(&kidmap_sid_prefix_store->tree,
994c5c4113dSnw141292 			&find, &where);
995c5c4113dSnw141292 		if (result) {
996c5c4113dSnw141292 			rw_exit(&kidmap_sid_prefix_store->lock);
997c5c4113dSnw141292 			return (result->sid_prefix);
998c5c4113dSnw141292 		}
999c5c4113dSnw141292 	}
1000c5c4113dSnw141292 
1001c5c4113dSnw141292 	new = kmem_alloc(sizeof (sid_prefix_node_t), KM_SLEEP);
1002c5c4113dSnw141292 	new->sid_prefix = kidmap_strdup(sid_prefix);
1003c5c4113dSnw141292 	avl_insert(&kidmap_sid_prefix_store->tree, new, where);
1004c5c4113dSnw141292 	rw_exit(&kidmap_sid_prefix_store->lock);
1005c5c4113dSnw141292 
1006c5c4113dSnw141292 	return (new->sid_prefix);
1007c5c4113dSnw141292 }
1008