xref: /illumos-gate/usr/src/uts/common/idmap/idmap_cache.c (revision 0b10de9fc92843e871f48de87f623808c5913a71)
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 /*
23c5c4113dSnw141292  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24c5c4113dSnw141292  * Use is subject to license terms.
25c5c4113dSnw141292  */
26c5c4113dSnw141292 
27c5c4113dSnw141292 /*
28c5c4113dSnw141292  * Windows to Solaris Identity Mapping kernel API
29c5c4113dSnw141292  * This module provides the kernel cache.
30c5c4113dSnw141292  */
31c5c4113dSnw141292 
32c5c4113dSnw141292 #pragma ident	"%Z%%M%	%I%	%E% SMI"
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>
41c5c4113dSnw141292 #include "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 
56*0b10de9fSjp151216 #define	CACHE_TRIGGER_SIZE	4096
57c5c4113dSnw141292 #define	CACHE_PURGE_INTERVAL	(60 * 3)
58*0b10de9fSjp151216 #define	CACHE_TTL		(60 * 10)
59c5c4113dSnw141292 
60c5c4113dSnw141292 typedef struct sid_prefix_node {
61c5c4113dSnw141292 	avl_node_t	avl_link;
62c5c4113dSnw141292 	const char 	*sid_prefix;
63c5c4113dSnw141292 } sid_prefix_node_t;
64c5c4113dSnw141292 
65c5c4113dSnw141292 
66c5c4113dSnw141292 typedef struct entry {
67c5c4113dSnw141292 	avl_node_t	avl_link;
68c5c4113dSnw141292 	const char 	*sid_prefix;
69c5c4113dSnw141292 	uint32_t	rid;
70c5c4113dSnw141292 	uid_t		pid;
71c5c4113dSnw141292 	int		is_user;
72c5c4113dSnw141292 	time_t		ttl;
73c5c4113dSnw141292 } entry_t;
74c5c4113dSnw141292 
75c5c4113dSnw141292 typedef int (*avl_comp_fn)(const void*, const void*);
76c5c4113dSnw141292 
77c5c4113dSnw141292 
78c5c4113dSnw141292 struct sid_prefix_store {
79c5c4113dSnw141292 	struct avl_tree	tree;
80c5c4113dSnw141292 	krwlock_t	lock;
81c5c4113dSnw141292 };
82c5c4113dSnw141292 
83c5c4113dSnw141292 struct sid_prefix_store *kidmap_sid_prefix_store = NULL;
84c5c4113dSnw141292 
85c5c4113dSnw141292 
86c5c4113dSnw141292 
87c5c4113dSnw141292 static void
88c5c4113dSnw141292 kidmap_cache_purge_avl(idmap_avl_cache_t *cache);
89c5c4113dSnw141292 
90c5c4113dSnw141292 /*
91c5c4113dSnw141292  * kidmap_strdup() copied from uts/common/fs/sockfs/nl7c.c
92c5c4113dSnw141292  */
93c5c4113dSnw141292 static char *
94c5c4113dSnw141292 kidmap_strdup(const char *s)
95c5c4113dSnw141292 {
96c5c4113dSnw141292 	int	len = strlen(s) + 1;
97c5c4113dSnw141292 	char	*ret = kmem_alloc(len, KM_SLEEP);
98c5c4113dSnw141292 
99c5c4113dSnw141292 	bcopy(s, ret, len);
100c5c4113dSnw141292 	return (ret);
101c5c4113dSnw141292 }
102c5c4113dSnw141292 
103c5c4113dSnw141292 
104c5c4113dSnw141292 static int
105c5c4113dSnw141292 kidmap_compare_sid(const entry_t *entry1, const entry_t *entry2)
106c5c4113dSnw141292 {
107*0b10de9fSjp151216 	int64_t comp = ((int64_t)entry2->rid) - ((int64_t)entry1->rid);
108c5c4113dSnw141292 
109c5c4113dSnw141292 	if (comp == 0)
110c5c4113dSnw141292 		comp = strcmp(entry2->sid_prefix, entry1->sid_prefix);
111c5c4113dSnw141292 
112c5c4113dSnw141292 	if (comp < 0)
113c5c4113dSnw141292 		comp = -1;
114c5c4113dSnw141292 	else if (comp > 0)
115c5c4113dSnw141292 		comp = 1;
116c5c4113dSnw141292 
117*0b10de9fSjp151216 	return ((int)comp);
118c5c4113dSnw141292 }
119c5c4113dSnw141292 
120c5c4113dSnw141292 
121c5c4113dSnw141292 static int
122c5c4113dSnw141292 kidmap_compare_pid(const entry_t *entry1, const entry_t *entry2)
123c5c4113dSnw141292 {
124*0b10de9fSjp151216 	if (entry2->pid > entry1->pid)
125*0b10de9fSjp151216 		return (1);
126*0b10de9fSjp151216 	if (entry2->pid < entry1->pid)
127*0b10de9fSjp151216 		return (-1);
128*0b10de9fSjp151216 	return (0);
129c5c4113dSnw141292 }
130c5c4113dSnw141292 
131c5c4113dSnw141292 
132c5c4113dSnw141292 static int
133c5c4113dSnw141292 kidmap_compare_sid_prefix(const sid_prefix_node_t *entry1,
134c5c4113dSnw141292 			const sid_prefix_node_t *entry2)
135c5c4113dSnw141292 {
136c5c4113dSnw141292 	int comp;
137c5c4113dSnw141292 
138c5c4113dSnw141292 	comp = strcmp(entry2->sid_prefix, entry1->sid_prefix);
139c5c4113dSnw141292 
140c5c4113dSnw141292 	if (comp < 0)
141c5c4113dSnw141292 		comp = -1;
142c5c4113dSnw141292 	else if (comp > 0)
143c5c4113dSnw141292 		comp = 1;
144c5c4113dSnw141292 
145c5c4113dSnw141292 	return (comp);
146c5c4113dSnw141292 }
147c5c4113dSnw141292 
148c5c4113dSnw141292 
149c5c4113dSnw141292 void
150c5c4113dSnw141292 kidmap_cache_create(idmap_cache_t *cache)
151c5c4113dSnw141292 {
152*0b10de9fSjp151216 	avl_create(&cache->uidbysid.tree, (avl_comp_fn)kidmap_compare_sid,
153c5c4113dSnw141292 	    sizeof (entry_t), offsetof(entry_t, avl_link));
154*0b10de9fSjp151216 	mutex_init(&cache->uidbysid.mutex, NULL, MUTEX_DEFAULT, NULL);
155*0b10de9fSjp151216 	cache->uidbysid.purge_time = 0;
156c5c4113dSnw141292 
157*0b10de9fSjp151216 	avl_create(&cache->gidbysid.tree, (avl_comp_fn)kidmap_compare_sid,
158c5c4113dSnw141292 	    sizeof (entry_t), offsetof(entry_t, avl_link));
159*0b10de9fSjp151216 	mutex_init(&cache->gidbysid.mutex, NULL, MUTEX_DEFAULT, NULL);
160*0b10de9fSjp151216 	cache->gidbysid.purge_time = 0;
161*0b10de9fSjp151216 
162*0b10de9fSjp151216 	avl_create(&cache->pidbysid.tree, (avl_comp_fn)kidmap_compare_sid,
163*0b10de9fSjp151216 	    sizeof (entry_t), offsetof(entry_t, avl_link));
164*0b10de9fSjp151216 	mutex_init(&cache->pidbysid.mutex, NULL, MUTEX_DEFAULT, NULL);
165*0b10de9fSjp151216 	cache->pidbysid.purge_time = 0;
166*0b10de9fSjp151216 
167*0b10de9fSjp151216 	avl_create(&cache->sidbyuid.tree, (avl_comp_fn)kidmap_compare_pid,
168*0b10de9fSjp151216 	    sizeof (entry_t), offsetof(entry_t, avl_link));
169*0b10de9fSjp151216 	mutex_init(&cache->sidbyuid.mutex, NULL, MUTEX_DEFAULT, NULL);
170*0b10de9fSjp151216 	cache->sidbyuid.purge_time = 0;
171*0b10de9fSjp151216 
172*0b10de9fSjp151216 	avl_create(&cache->sidbygid.tree, (avl_comp_fn)kidmap_compare_pid,
173*0b10de9fSjp151216 	    sizeof (entry_t), offsetof(entry_t, avl_link));
174*0b10de9fSjp151216 	mutex_init(&cache->sidbygid.mutex, NULL, MUTEX_DEFAULT, NULL);
175*0b10de9fSjp151216 	cache->sidbygid.purge_time = 0;
176c5c4113dSnw141292 }
177c5c4113dSnw141292 
178c5c4113dSnw141292 
179c5c4113dSnw141292 void
180c5c4113dSnw141292 kidmap_cache_delete(idmap_cache_t *cache)
181c5c4113dSnw141292 {
182c5c4113dSnw141292 	entry_t *entry;
183c5c4113dSnw141292 	void *cookie;
184c5c4113dSnw141292 
185c5c4113dSnw141292 	cookie = NULL;
186*0b10de9fSjp151216 	while ((entry = avl_destroy_nodes(&cache->uidbysid.tree, &cookie))
187c5c4113dSnw141292 	    != NULL) {
188c5c4113dSnw141292 		kmem_free(entry, sizeof (entry_t));
189c5c4113dSnw141292 	}
190*0b10de9fSjp151216 	avl_destroy(&cache->uidbysid.tree);
191*0b10de9fSjp151216 	mutex_destroy(&cache->uidbysid.mutex);
192c5c4113dSnw141292 
193c5c4113dSnw141292 	cookie = NULL;
194*0b10de9fSjp151216 	while ((entry = avl_destroy_nodes(&cache->gidbysid.tree, &cookie))
195c5c4113dSnw141292 	    != NULL) {
196c5c4113dSnw141292 		kmem_free(entry, sizeof (entry_t));
197c5c4113dSnw141292 	}
198*0b10de9fSjp151216 	avl_destroy(&cache->gidbysid.tree);
199*0b10de9fSjp151216 	mutex_destroy(&cache->gidbysid.mutex);
200*0b10de9fSjp151216 
201*0b10de9fSjp151216 	cookie = NULL;
202*0b10de9fSjp151216 	while ((entry = avl_destroy_nodes(&cache->pidbysid.tree, &cookie))
203*0b10de9fSjp151216 	    != NULL) {
204*0b10de9fSjp151216 		kmem_free(entry, sizeof (entry_t));
205*0b10de9fSjp151216 	}
206*0b10de9fSjp151216 	avl_destroy(&cache->pidbysid.tree);
207*0b10de9fSjp151216 	mutex_destroy(&cache->pidbysid.mutex);
208*0b10de9fSjp151216 
209*0b10de9fSjp151216 	cookie = NULL;
210*0b10de9fSjp151216 	while ((entry = avl_destroy_nodes(&cache->sidbyuid.tree, &cookie))
211*0b10de9fSjp151216 	    != NULL) {
212*0b10de9fSjp151216 		kmem_free(entry, sizeof (entry_t));
213*0b10de9fSjp151216 	}
214*0b10de9fSjp151216 	avl_destroy(&cache->sidbyuid.tree);
215*0b10de9fSjp151216 	mutex_destroy(&cache->sidbyuid.mutex);
216*0b10de9fSjp151216 
217*0b10de9fSjp151216 	cookie = NULL;
218*0b10de9fSjp151216 	while ((entry = avl_destroy_nodes(&cache->sidbygid.tree, &cookie))
219*0b10de9fSjp151216 	    != NULL) {
220*0b10de9fSjp151216 		kmem_free(entry, sizeof (entry_t));
221*0b10de9fSjp151216 	}
222*0b10de9fSjp151216 	avl_destroy(&cache->sidbygid.tree);
223*0b10de9fSjp151216 	mutex_destroy(&cache->sidbygid.mutex);
224*0b10de9fSjp151216 }
225*0b10de9fSjp151216 
226*0b10de9fSjp151216 
227*0b10de9fSjp151216 void
228*0b10de9fSjp151216 kidmap_cache_purge(idmap_cache_t *cache)
229*0b10de9fSjp151216 {
230*0b10de9fSjp151216 	entry_t *entry;
231*0b10de9fSjp151216 	void *cookie;
232*0b10de9fSjp151216 
233*0b10de9fSjp151216 	mutex_enter(&cache->uidbysid.mutex);
234*0b10de9fSjp151216 	cookie = NULL;
235*0b10de9fSjp151216 	while ((entry = avl_destroy_nodes(&cache->uidbysid.tree, &cookie))
236*0b10de9fSjp151216 	    != NULL) {
237*0b10de9fSjp151216 		kmem_free(entry, sizeof (entry_t));
238*0b10de9fSjp151216 	}
239*0b10de9fSjp151216 	avl_destroy(&cache->uidbysid.tree);
240*0b10de9fSjp151216 	avl_create(&cache->uidbysid.tree, (avl_comp_fn)kidmap_compare_sid,
241*0b10de9fSjp151216 	    sizeof (entry_t), offsetof(entry_t, avl_link));
242*0b10de9fSjp151216 	mutex_exit(&cache->uidbysid.mutex);
243*0b10de9fSjp151216 
244*0b10de9fSjp151216 	mutex_enter(&cache->gidbysid.mutex);
245*0b10de9fSjp151216 	cookie = NULL;
246*0b10de9fSjp151216 	while ((entry = avl_destroy_nodes(&cache->gidbysid.tree, &cookie))
247*0b10de9fSjp151216 	    != NULL) {
248*0b10de9fSjp151216 		kmem_free(entry, sizeof (entry_t));
249*0b10de9fSjp151216 	}
250*0b10de9fSjp151216 	avl_destroy(&cache->gidbysid.tree);
251*0b10de9fSjp151216 	avl_create(&cache->gidbysid.tree, (avl_comp_fn)kidmap_compare_sid,
252*0b10de9fSjp151216 	    sizeof (entry_t), offsetof(entry_t, avl_link));
253*0b10de9fSjp151216 	mutex_exit(&cache->gidbysid.mutex);
254*0b10de9fSjp151216 
255*0b10de9fSjp151216 	mutex_enter(&cache->pidbysid.mutex);
256*0b10de9fSjp151216 	cookie = NULL;
257*0b10de9fSjp151216 	while ((entry = avl_destroy_nodes(&cache->pidbysid.tree, &cookie))
258*0b10de9fSjp151216 	    != NULL) {
259*0b10de9fSjp151216 		kmem_free(entry, sizeof (entry_t));
260*0b10de9fSjp151216 	}
261*0b10de9fSjp151216 	avl_destroy(&cache->pidbysid.tree);
262*0b10de9fSjp151216 	avl_create(&cache->pidbysid.tree, (avl_comp_fn)kidmap_compare_sid,
263*0b10de9fSjp151216 	    sizeof (entry_t), offsetof(entry_t, avl_link));
264*0b10de9fSjp151216 	mutex_exit(&cache->pidbysid.mutex);
265*0b10de9fSjp151216 
266*0b10de9fSjp151216 	mutex_enter(&cache->sidbyuid.mutex);
267*0b10de9fSjp151216 	cookie = NULL;
268*0b10de9fSjp151216 	while ((entry = avl_destroy_nodes(&cache->sidbyuid.tree, &cookie))
269*0b10de9fSjp151216 	    != NULL) {
270*0b10de9fSjp151216 		kmem_free(entry, sizeof (entry_t));
271*0b10de9fSjp151216 	}
272*0b10de9fSjp151216 	avl_destroy(&cache->sidbyuid.tree);
273*0b10de9fSjp151216 	avl_create(&cache->sidbyuid.tree, (avl_comp_fn)kidmap_compare_pid,
274*0b10de9fSjp151216 	    sizeof (entry_t), offsetof(entry_t, avl_link));
275*0b10de9fSjp151216 	mutex_exit(&cache->sidbyuid.mutex);
276*0b10de9fSjp151216 
277*0b10de9fSjp151216 	mutex_enter(&cache->sidbygid.mutex);
278*0b10de9fSjp151216 	cookie = NULL;
279*0b10de9fSjp151216 	while ((entry = avl_destroy_nodes(&cache->sidbygid.tree, &cookie))
280*0b10de9fSjp151216 	    != NULL) {
281*0b10de9fSjp151216 		kmem_free(entry, sizeof (entry_t));
282*0b10de9fSjp151216 	}
283*0b10de9fSjp151216 	avl_destroy(&cache->sidbygid.tree);
284*0b10de9fSjp151216 	avl_create(&cache->sidbygid.tree, (avl_comp_fn)kidmap_compare_pid,
285*0b10de9fSjp151216 	    sizeof (entry_t), offsetof(entry_t, avl_link));
286*0b10de9fSjp151216 	mutex_exit(&cache->sidbygid.mutex);
287c5c4113dSnw141292 }
288c5c4113dSnw141292 
289c5c4113dSnw141292 
290c5c4113dSnw141292 int
291*0b10de9fSjp151216 kidmap_cache_lookup_uidbysid(idmap_cache_t *cache, const char *sid_prefix,
292*0b10de9fSjp151216 			uint32_t rid, uid_t *uid)
293c5c4113dSnw141292 {
294c5c4113dSnw141292 	entry_t		entry;
295c5c4113dSnw141292 	entry_t		*result;
296c5c4113dSnw141292 	avl_index_t	where;
297c5c4113dSnw141292 	int		status;
298c5c4113dSnw141292 	time_t		now = gethrestime_sec();
299c5c4113dSnw141292 
300*0b10de9fSjp151216 	entry.sid_prefix = sid_prefix;
301*0b10de9fSjp151216 	entry.rid = rid;
302c5c4113dSnw141292 
303*0b10de9fSjp151216 	mutex_enter(&cache->uidbysid.mutex);
304c5c4113dSnw141292 
305*0b10de9fSjp151216 	result = avl_find(&cache->uidbysid.tree, &entry, &where);
306c5c4113dSnw141292 
307c5c4113dSnw141292 	if (result && result->ttl > now) {
308*0b10de9fSjp151216 		*uid = result->pid;
309c5c4113dSnw141292 		status = IDMAP_SUCCESS;
310c5c4113dSnw141292 	} else
311c5c4113dSnw141292 		status = IDMAP_ERR_NOMAPPING;
312c5c4113dSnw141292 
313*0b10de9fSjp151216 	mutex_exit(&cache->uidbysid.mutex);
314c5c4113dSnw141292 
315c5c4113dSnw141292 	return (status);
316c5c4113dSnw141292 }
317c5c4113dSnw141292 
318c5c4113dSnw141292 
319*0b10de9fSjp151216 
320c5c4113dSnw141292 int
321*0b10de9fSjp151216 kidmap_cache_lookup_gidbysid(idmap_cache_t *cache, const char *sid_prefix,
322*0b10de9fSjp151216 			uint32_t rid, gid_t *gid)
323*0b10de9fSjp151216 {
324*0b10de9fSjp151216 	entry_t		entry;
325*0b10de9fSjp151216 	entry_t		*result;
326*0b10de9fSjp151216 	avl_index_t	where;
327*0b10de9fSjp151216 	int		status;
328*0b10de9fSjp151216 	time_t		now = gethrestime_sec();
329*0b10de9fSjp151216 
330*0b10de9fSjp151216 	entry.sid_prefix = sid_prefix;
331*0b10de9fSjp151216 	entry.rid = rid;
332*0b10de9fSjp151216 
333*0b10de9fSjp151216 	mutex_enter(&cache->gidbysid.mutex);
334*0b10de9fSjp151216 
335*0b10de9fSjp151216 	result = avl_find(&cache->gidbysid.tree, &entry, &where);
336*0b10de9fSjp151216 
337*0b10de9fSjp151216 	if (result && result->ttl > now) {
338*0b10de9fSjp151216 		*gid = result->pid;
339*0b10de9fSjp151216 		status = IDMAP_SUCCESS;
340*0b10de9fSjp151216 	} else
341*0b10de9fSjp151216 		status = IDMAP_ERR_NOMAPPING;
342*0b10de9fSjp151216 
343*0b10de9fSjp151216 	mutex_exit(&cache->gidbysid.mutex);
344*0b10de9fSjp151216 
345*0b10de9fSjp151216 	return (status);
346*0b10de9fSjp151216 }
347*0b10de9fSjp151216 
348*0b10de9fSjp151216 
349*0b10de9fSjp151216 
350*0b10de9fSjp151216 
351*0b10de9fSjp151216 int
352*0b10de9fSjp151216 kidmap_cache_lookup_pidbysid(idmap_cache_t *cache, const char *sid_prefix,
353c5c4113dSnw141292 			uint32_t rid, uid_t *pid, int *is_user)
354c5c4113dSnw141292 {
355c5c4113dSnw141292 	entry_t		entry;
356c5c4113dSnw141292 	entry_t		*result;
357c5c4113dSnw141292 	avl_index_t	where;
358c5c4113dSnw141292 	int		status;
359c5c4113dSnw141292 	time_t		now = gethrestime_sec();
360c5c4113dSnw141292 
361c5c4113dSnw141292 	entry.sid_prefix = sid_prefix;
362c5c4113dSnw141292 	entry.rid = rid;
363c5c4113dSnw141292 
364*0b10de9fSjp151216 	mutex_enter(&cache->pidbysid.mutex);
365c5c4113dSnw141292 
366*0b10de9fSjp151216 	result = avl_find(&cache->pidbysid.tree, &entry, &where);
367c5c4113dSnw141292 
368c5c4113dSnw141292 	if (result && result->ttl > now) {
369c5c4113dSnw141292 		*pid = result->pid;
370c5c4113dSnw141292 		*is_user = result->is_user;
371c5c4113dSnw141292 		status = IDMAP_SUCCESS;
372c5c4113dSnw141292 	} else
373c5c4113dSnw141292 		status = IDMAP_ERR_NOMAPPING;
374c5c4113dSnw141292 
375*0b10de9fSjp151216 	mutex_exit(&cache->pidbysid.mutex);
376c5c4113dSnw141292 
377c5c4113dSnw141292 	return (status);
378c5c4113dSnw141292 }
379c5c4113dSnw141292 
380c5c4113dSnw141292 
381*0b10de9fSjp151216 
382*0b10de9fSjp151216 int
383*0b10de9fSjp151216 kidmap_cache_lookup_sidbyuid(idmap_cache_t *cache, const char **sid_prefix,
384*0b10de9fSjp151216 			uint32_t *rid, uid_t uid)
385c5c4113dSnw141292 {
386*0b10de9fSjp151216 	entry_t		entry;
387c5c4113dSnw141292 	entry_t		*result;
388c5c4113dSnw141292 	avl_index_t	where;
389*0b10de9fSjp151216 	int		status;
390*0b10de9fSjp151216 	time_t		now = gethrestime_sec();
391c5c4113dSnw141292 
392*0b10de9fSjp151216 	entry.pid = uid;
393c5c4113dSnw141292 
394*0b10de9fSjp151216 	mutex_enter(&cache->sidbyuid.mutex);
395c5c4113dSnw141292 
396*0b10de9fSjp151216 	result = avl_find(&cache->sidbyuid.tree, &entry, &where);
397c5c4113dSnw141292 
398*0b10de9fSjp151216 	if (result && result->ttl > now) {
399*0b10de9fSjp151216 		*sid_prefix = result->sid_prefix;
400*0b10de9fSjp151216 		*rid = result->rid;
401*0b10de9fSjp151216 		status = IDMAP_SUCCESS;
402*0b10de9fSjp151216 	} else
403*0b10de9fSjp151216 		status = IDMAP_ERR_NOMAPPING;
404*0b10de9fSjp151216 
405*0b10de9fSjp151216 	mutex_exit(&cache->sidbyuid.mutex);
406*0b10de9fSjp151216 
407*0b10de9fSjp151216 	return (status);
408c5c4113dSnw141292 }
409c5c4113dSnw141292 
410*0b10de9fSjp151216 int
411*0b10de9fSjp151216 kidmap_cache_lookup_sidbygid(idmap_cache_t *cache, const char **sid_prefix,
412*0b10de9fSjp151216 			uint32_t *rid, gid_t gid)
413*0b10de9fSjp151216 {
414*0b10de9fSjp151216 	entry_t		entry;
415*0b10de9fSjp151216 	entry_t		*result;
416*0b10de9fSjp151216 	avl_index_t	where;
417*0b10de9fSjp151216 	int		status;
418*0b10de9fSjp151216 	time_t		now = gethrestime_sec();
419c5c4113dSnw141292 
420*0b10de9fSjp151216 	entry.pid = gid;
421*0b10de9fSjp151216 
422*0b10de9fSjp151216 	mutex_enter(&cache->sidbygid.mutex);
423*0b10de9fSjp151216 
424*0b10de9fSjp151216 	result = avl_find(&cache->sidbygid.tree, &entry, &where);
425*0b10de9fSjp151216 
426*0b10de9fSjp151216 	if (result && result->ttl > now) {
427*0b10de9fSjp151216 		*sid_prefix = result->sid_prefix;
428*0b10de9fSjp151216 		*rid = result->rid;
429*0b10de9fSjp151216 		status = IDMAP_SUCCESS;
430*0b10de9fSjp151216 	} else
431*0b10de9fSjp151216 		status = IDMAP_ERR_NOMAPPING;
432*0b10de9fSjp151216 
433*0b10de9fSjp151216 	mutex_exit(&cache->sidbygid.mutex);
434*0b10de9fSjp151216 
435*0b10de9fSjp151216 	return (status);
436c5c4113dSnw141292 }
437c5c4113dSnw141292 
438c5c4113dSnw141292 
439*0b10de9fSjp151216 
440*0b10de9fSjp151216 
441c5c4113dSnw141292 void
442*0b10de9fSjp151216 kidmap_cache_add_uidbysid(idmap_cache_t *cache, const char *sid_prefix,
443*0b10de9fSjp151216 			uint32_t rid, uid_t uid)
444c5c4113dSnw141292 
445c5c4113dSnw141292 {
446c5c4113dSnw141292 	entry_t		find;
447c5c4113dSnw141292 	entry_t		*result;
448c5c4113dSnw141292 	entry_t		*new;
449c5c4113dSnw141292 	avl_index_t	where;
450c5c4113dSnw141292 	int		purge_required = FALSE;
451*0b10de9fSjp151216 	time_t		ttl = CACHE_TTL + gethrestime_sec();
452c5c4113dSnw141292 
453c5c4113dSnw141292 	find.sid_prefix = sid_prefix;
454c5c4113dSnw141292 	find.rid = rid;
455c5c4113dSnw141292 
456*0b10de9fSjp151216 	mutex_enter(&cache->uidbysid.mutex);
457*0b10de9fSjp151216 	result = avl_find(&cache->uidbysid.tree, &find, &where);
458*0b10de9fSjp151216 
459*0b10de9fSjp151216 	if (result) {
460*0b10de9fSjp151216 		result->pid = uid;
461*0b10de9fSjp151216 		result->ttl = ttl;
462*0b10de9fSjp151216 	} else {
463*0b10de9fSjp151216 		new = kmem_alloc(sizeof (entry_t), KM_SLEEP);
464*0b10de9fSjp151216 		new->pid = uid;
465*0b10de9fSjp151216 		new->sid_prefix = sid_prefix;
466*0b10de9fSjp151216 		new->rid = rid;
467*0b10de9fSjp151216 		new->ttl = ttl;
468*0b10de9fSjp151216 
469*0b10de9fSjp151216 		avl_insert(&cache->uidbysid.tree, new, where);
470*0b10de9fSjp151216 
471*0b10de9fSjp151216 		if ((avl_numnodes(&cache->uidbysid.tree) >
472*0b10de9fSjp151216 		    CACHE_TRIGGER_SIZE) &&
473*0b10de9fSjp151216 		    (cache->uidbysid.purge_time + CACHE_PURGE_INTERVAL <
474*0b10de9fSjp151216 		    gethrestime_sec()))
475*0b10de9fSjp151216 			purge_required = TRUE;
476*0b10de9fSjp151216 	}
477*0b10de9fSjp151216 
478*0b10de9fSjp151216 	mutex_exit(&cache->uidbysid.mutex);
479*0b10de9fSjp151216 
480*0b10de9fSjp151216 	if (purge_required)
481*0b10de9fSjp151216 		kidmap_cache_purge_avl(&cache->uidbysid);
482*0b10de9fSjp151216 }
483*0b10de9fSjp151216 
484*0b10de9fSjp151216 
485*0b10de9fSjp151216 void
486*0b10de9fSjp151216 kidmap_cache_add_gidbysid(idmap_cache_t *cache, const char *sid_prefix,
487*0b10de9fSjp151216 			uint32_t rid, gid_t gid)
488*0b10de9fSjp151216 
489*0b10de9fSjp151216 {
490*0b10de9fSjp151216 	entry_t		find;
491*0b10de9fSjp151216 	entry_t		*result;
492*0b10de9fSjp151216 	entry_t		*new;
493*0b10de9fSjp151216 	avl_index_t	where;
494*0b10de9fSjp151216 	int		purge_required = FALSE;
495*0b10de9fSjp151216 	time_t		ttl = CACHE_TTL + gethrestime_sec();
496*0b10de9fSjp151216 
497*0b10de9fSjp151216 	find.sid_prefix = sid_prefix;
498*0b10de9fSjp151216 	find.rid = rid;
499*0b10de9fSjp151216 
500*0b10de9fSjp151216 	mutex_enter(&cache->gidbysid.mutex);
501*0b10de9fSjp151216 	result = avl_find(&cache->gidbysid.tree, &find, &where);
502*0b10de9fSjp151216 
503*0b10de9fSjp151216 	if (result) {
504*0b10de9fSjp151216 		result->pid = gid;
505*0b10de9fSjp151216 		result->ttl = ttl;
506*0b10de9fSjp151216 	} else {
507*0b10de9fSjp151216 		new = kmem_alloc(sizeof (entry_t), KM_SLEEP);
508*0b10de9fSjp151216 		new->pid = gid;
509*0b10de9fSjp151216 		new->sid_prefix = sid_prefix;
510*0b10de9fSjp151216 		new->rid = rid;
511*0b10de9fSjp151216 		new->ttl = ttl;
512*0b10de9fSjp151216 
513*0b10de9fSjp151216 		avl_insert(&cache->gidbysid.tree, new, where);
514*0b10de9fSjp151216 
515*0b10de9fSjp151216 		if ((avl_numnodes(&cache->gidbysid.tree) >
516*0b10de9fSjp151216 		    CACHE_TRIGGER_SIZE) &&
517*0b10de9fSjp151216 		    (cache->gidbysid.purge_time + CACHE_PURGE_INTERVAL <
518*0b10de9fSjp151216 		    gethrestime_sec()))
519*0b10de9fSjp151216 			purge_required = TRUE;
520*0b10de9fSjp151216 	}
521*0b10de9fSjp151216 
522*0b10de9fSjp151216 	mutex_exit(&cache->gidbysid.mutex);
523*0b10de9fSjp151216 
524*0b10de9fSjp151216 	if (purge_required)
525*0b10de9fSjp151216 		kidmap_cache_purge_avl(&cache->gidbysid);
526*0b10de9fSjp151216 }
527*0b10de9fSjp151216 
528*0b10de9fSjp151216 void
529*0b10de9fSjp151216 kidmap_cache_add_pidbysid(idmap_cache_t *cache, const char *sid_prefix,
530*0b10de9fSjp151216 			uint32_t rid, uid_t pid, int is_user)
531*0b10de9fSjp151216 
532*0b10de9fSjp151216 {
533*0b10de9fSjp151216 	entry_t		find;
534*0b10de9fSjp151216 	entry_t		*result;
535*0b10de9fSjp151216 	entry_t		*new;
536*0b10de9fSjp151216 	avl_index_t	where;
537*0b10de9fSjp151216 	int		purge_required = FALSE;
538*0b10de9fSjp151216 	time_t		ttl = CACHE_TTL + gethrestime_sec();
539*0b10de9fSjp151216 
540*0b10de9fSjp151216 	find.sid_prefix = sid_prefix;
541*0b10de9fSjp151216 	find.rid = rid;
542*0b10de9fSjp151216 
543*0b10de9fSjp151216 	mutex_enter(&cache->pidbysid.mutex);
544*0b10de9fSjp151216 	result = avl_find(&cache->pidbysid.tree, &find, &where);
545c5c4113dSnw141292 
546c5c4113dSnw141292 	if (result) {
547c5c4113dSnw141292 		result->pid = pid;
548c5c4113dSnw141292 		result->is_user = is_user;
549c5c4113dSnw141292 		result->ttl = ttl;
550c5c4113dSnw141292 	} else {
551c5c4113dSnw141292 		new = kmem_alloc(sizeof (entry_t), KM_SLEEP);
552c5c4113dSnw141292 		new->pid = pid;
553c5c4113dSnw141292 		new->is_user = is_user;
554c5c4113dSnw141292 		new->sid_prefix = sid_prefix;
555c5c4113dSnw141292 		new->rid = rid;
556c5c4113dSnw141292 		new->ttl = ttl;
557c5c4113dSnw141292 
558*0b10de9fSjp151216 		avl_insert(&cache->pidbysid.tree, new, where);
559c5c4113dSnw141292 
560*0b10de9fSjp151216 		if ((avl_numnodes(&cache->pidbysid.tree) >
561*0b10de9fSjp151216 		    CACHE_TRIGGER_SIZE) &&
562*0b10de9fSjp151216 		    (cache->pidbysid.purge_time + CACHE_PURGE_INTERVAL <
563c5c4113dSnw141292 		    gethrestime_sec()))
564c5c4113dSnw141292 			purge_required = TRUE;
565c5c4113dSnw141292 	}
566c5c4113dSnw141292 
567*0b10de9fSjp151216 	mutex_exit(&cache->pidbysid.mutex);
568c5c4113dSnw141292 
569c5c4113dSnw141292 	if (purge_required)
570*0b10de9fSjp151216 		kidmap_cache_purge_avl(&cache->pidbysid);
571*0b10de9fSjp151216 }
572*0b10de9fSjp151216 
573*0b10de9fSjp151216 
574*0b10de9fSjp151216 
575*0b10de9fSjp151216 void
576*0b10de9fSjp151216 kidmap_cache_add_sidbyuid(idmap_cache_t *cache, const char *sid_prefix,
577*0b10de9fSjp151216 			uint32_t rid, uid_t uid)
578*0b10de9fSjp151216 {
579*0b10de9fSjp151216 	entry_t		find;
580*0b10de9fSjp151216 	entry_t		*result;
581*0b10de9fSjp151216 	entry_t		*new;
582*0b10de9fSjp151216 	avl_index_t	where;
583*0b10de9fSjp151216 	int		purge_required = FALSE;
584*0b10de9fSjp151216 	time_t		ttl = CACHE_TTL + gethrestime_sec();
585*0b10de9fSjp151216 
586*0b10de9fSjp151216 	find.pid = uid;
587*0b10de9fSjp151216 
588*0b10de9fSjp151216 	mutex_enter(&cache->sidbyuid.mutex);
589*0b10de9fSjp151216 	result = avl_find(&cache->sidbyuid.tree, &find, &where);
590*0b10de9fSjp151216 
591*0b10de9fSjp151216 	if (result) {
592*0b10de9fSjp151216 		result->sid_prefix = sid_prefix;
593*0b10de9fSjp151216 		result->rid = rid;
594*0b10de9fSjp151216 		result->ttl = ttl;
595*0b10de9fSjp151216 	} else {
596*0b10de9fSjp151216 		new = kmem_alloc(sizeof (entry_t), KM_SLEEP);
597*0b10de9fSjp151216 		new->pid = uid;
598*0b10de9fSjp151216 		new->sid_prefix = sid_prefix;
599*0b10de9fSjp151216 		new->rid = rid;
600*0b10de9fSjp151216 		new->ttl = ttl;
601*0b10de9fSjp151216 
602*0b10de9fSjp151216 		avl_insert(&cache->sidbyuid.tree, new, where);
603*0b10de9fSjp151216 		if ((avl_numnodes(&cache->sidbyuid.tree) >
604*0b10de9fSjp151216 		    CACHE_TRIGGER_SIZE) &&
605*0b10de9fSjp151216 		    (cache->sidbyuid.purge_time + CACHE_PURGE_INTERVAL <
606*0b10de9fSjp151216 		    gethrestime_sec()))
607*0b10de9fSjp151216 			purge_required = TRUE;
608*0b10de9fSjp151216 	}
609*0b10de9fSjp151216 
610*0b10de9fSjp151216 	mutex_exit(&cache->sidbyuid.mutex);
611*0b10de9fSjp151216 
612*0b10de9fSjp151216 	if (purge_required)
613*0b10de9fSjp151216 		kidmap_cache_purge_avl(&cache->sidbyuid);
614*0b10de9fSjp151216 }
615*0b10de9fSjp151216 
616*0b10de9fSjp151216 
617*0b10de9fSjp151216 void
618*0b10de9fSjp151216 kidmap_cache_add_sidbygid(idmap_cache_t *cache, const char *sid_prefix,
619*0b10de9fSjp151216 			uint32_t rid, gid_t gid)
620*0b10de9fSjp151216 {
621*0b10de9fSjp151216 	entry_t		find;
622*0b10de9fSjp151216 	entry_t		*result;
623*0b10de9fSjp151216 	entry_t		*new;
624*0b10de9fSjp151216 	avl_index_t	where;
625*0b10de9fSjp151216 	int		purge_required = FALSE;
626*0b10de9fSjp151216 	time_t		ttl = CACHE_TTL + gethrestime_sec();
627*0b10de9fSjp151216 
628*0b10de9fSjp151216 	find.pid = gid;
629*0b10de9fSjp151216 
630*0b10de9fSjp151216 	mutex_enter(&cache->sidbygid.mutex);
631*0b10de9fSjp151216 	result = avl_find(&cache->sidbygid.tree, &find, &where);
632*0b10de9fSjp151216 
633*0b10de9fSjp151216 	if (result) {
634*0b10de9fSjp151216 		result->sid_prefix = sid_prefix;
635*0b10de9fSjp151216 		result->rid = rid;
636*0b10de9fSjp151216 		result->ttl = ttl;
637*0b10de9fSjp151216 	} else {
638*0b10de9fSjp151216 		new = kmem_alloc(sizeof (entry_t), KM_SLEEP);
639*0b10de9fSjp151216 		new->pid = gid;
640*0b10de9fSjp151216 		new->sid_prefix = sid_prefix;
641*0b10de9fSjp151216 		new->rid = rid;
642*0b10de9fSjp151216 		new->ttl = ttl;
643*0b10de9fSjp151216 
644*0b10de9fSjp151216 		avl_insert(&cache->sidbygid.tree, new, where);
645*0b10de9fSjp151216 		if ((avl_numnodes(&cache->sidbygid.tree) >
646*0b10de9fSjp151216 		    CACHE_TRIGGER_SIZE) &&
647*0b10de9fSjp151216 		    (cache->sidbygid.purge_time + CACHE_PURGE_INTERVAL <
648*0b10de9fSjp151216 		    gethrestime_sec()))
649*0b10de9fSjp151216 			purge_required = TRUE;
650*0b10de9fSjp151216 	}
651*0b10de9fSjp151216 
652*0b10de9fSjp151216 	mutex_exit(&cache->sidbygid.mutex);
653*0b10de9fSjp151216 
654*0b10de9fSjp151216 	if (purge_required)
655*0b10de9fSjp151216 		kidmap_cache_purge_avl(&cache->sidbygid);
656c5c4113dSnw141292 }
657c5c4113dSnw141292 
658c5c4113dSnw141292 
659c5c4113dSnw141292 static void
660c5c4113dSnw141292 kidmap_cache_purge_avl(idmap_avl_cache_t *cache)
661c5c4113dSnw141292 {
662c5c4113dSnw141292 	time_t		now = gethrestime_sec();
663c5c4113dSnw141292 	entry_t		*curr;
664c5c4113dSnw141292 	entry_t		*prev = NULL;
665c5c4113dSnw141292 
666c5c4113dSnw141292 	mutex_enter(&cache->mutex);
667c5c4113dSnw141292 
668c5c4113dSnw141292 	curr = avl_first(&cache->tree);
669c5c4113dSnw141292 	while (curr != NULL) {
670c5c4113dSnw141292 		if (curr->ttl < now) {
671c5c4113dSnw141292 			/* Old entry to remove */
672c5c4113dSnw141292 			avl_remove(&cache->tree, curr);
673c5c4113dSnw141292 			curr = prev;
674c5c4113dSnw141292 			if (curr == NULL) {
675c5c4113dSnw141292 				/* We removed the first entery */
676c5c4113dSnw141292 				curr = avl_first(&cache->tree);
677c5c4113dSnw141292 				continue;
678c5c4113dSnw141292 			}
679c5c4113dSnw141292 		}
680c5c4113dSnw141292 		prev = curr;
681c5c4113dSnw141292 		curr = AVL_NEXT(&cache->tree, curr);
682c5c4113dSnw141292 	}
683c5c4113dSnw141292 	cache->purge_time = now;
684*0b10de9fSjp151216 
685c5c4113dSnw141292 	mutex_exit(&cache->mutex);
686c5c4113dSnw141292 }
687c5c4113dSnw141292 
688*0b10de9fSjp151216 
689c5c4113dSnw141292 void
690c5c4113dSnw141292 kidmap_sid_prefix_store_init(void)
691c5c4113dSnw141292 {
692c5c4113dSnw141292 	kidmap_sid_prefix_store = (struct sid_prefix_store *)
693c5c4113dSnw141292 	    space_fetch("SUNW,idmap_sid_prefix");
694c5c4113dSnw141292 	if (kidmap_sid_prefix_store == NULL) {
695c5c4113dSnw141292 		kidmap_sid_prefix_store = kmem_alloc(
696c5c4113dSnw141292 		    sizeof (struct sid_prefix_store), KM_SLEEP);
697c5c4113dSnw141292 		rw_init(&kidmap_sid_prefix_store->lock, NULL, RW_DRIVER, NULL);
698c5c4113dSnw141292 		avl_create(&kidmap_sid_prefix_store->tree,
699c5c4113dSnw141292 		    (avl_comp_fn)kidmap_compare_sid_prefix,
700c5c4113dSnw141292 		    sizeof (sid_prefix_node_t),
701c5c4113dSnw141292 		    offsetof(sid_prefix_node_t, avl_link));
702c5c4113dSnw141292 		(void) space_store("SUNW,idmap_sid_prefix",
703c5c4113dSnw141292 		    (uintptr_t)kidmap_sid_prefix_store);
704c5c4113dSnw141292 	} else {
705c5c4113dSnw141292 		/*
706c5c4113dSnw141292 		 * The AVL comparison function must be re-initialised on
707c5c4113dSnw141292 		 * re-load because may not be loaded into the same
708c5c4113dSnw141292 		 * address space.
709c5c4113dSnw141292 		 */
710c5c4113dSnw141292 		kidmap_sid_prefix_store->tree.avl_compar =
711c5c4113dSnw141292 		    (avl_comp_fn)kidmap_compare_sid_prefix;
712c5c4113dSnw141292 	}
713c5c4113dSnw141292 }
714c5c4113dSnw141292 
715c5c4113dSnw141292 
716c5c4113dSnw141292 const char *
717c5c4113dSnw141292 kidmap_find_sid_prefix(const char *sid_prefix) {
718c5c4113dSnw141292 	sid_prefix_node_t 	find;
719c5c4113dSnw141292 	sid_prefix_node_t	*result;
720c5c4113dSnw141292 	sid_prefix_node_t 	*new;
721c5c4113dSnw141292 	avl_index_t		where;
722c5c4113dSnw141292 
723c5c4113dSnw141292 	if (sid_prefix == NULL || *sid_prefix == '\0')
724c5c4113dSnw141292 		return (NULL);
725c5c4113dSnw141292 
726c5c4113dSnw141292 	find.sid_prefix = sid_prefix;
727c5c4113dSnw141292 
728c5c4113dSnw141292 
729c5c4113dSnw141292 	rw_enter(&kidmap_sid_prefix_store->lock, RW_READER);
730c5c4113dSnw141292 
731c5c4113dSnw141292 	result = avl_find(&kidmap_sid_prefix_store->tree, &find, &where);
732c5c4113dSnw141292 
733c5c4113dSnw141292 	if (result) {
734c5c4113dSnw141292 		rw_exit(&kidmap_sid_prefix_store->lock);
735c5c4113dSnw141292 		return (result->sid_prefix);
736c5c4113dSnw141292 	}
737c5c4113dSnw141292 
738c5c4113dSnw141292 	if (rw_tryupgrade(&kidmap_sid_prefix_store->lock) == 0) {
739c5c4113dSnw141292 		/*
740c5c4113dSnw141292 		 * Could not upgrade lock so release lock
741da6c28aaSamw 		 * and acquire the write lock
742c5c4113dSnw141292 		 */
743c5c4113dSnw141292 		rw_exit(&kidmap_sid_prefix_store->lock);
744c5c4113dSnw141292 		rw_enter(&kidmap_sid_prefix_store->lock, RW_WRITER);
745c5c4113dSnw141292 
746c5c4113dSnw141292 		result = avl_find(&kidmap_sid_prefix_store->tree,
747c5c4113dSnw141292 			&find, &where);
748c5c4113dSnw141292 		if (result) {
749c5c4113dSnw141292 			rw_exit(&kidmap_sid_prefix_store->lock);
750c5c4113dSnw141292 			return (result->sid_prefix);
751c5c4113dSnw141292 		}
752c5c4113dSnw141292 	}
753c5c4113dSnw141292 
754c5c4113dSnw141292 	new = kmem_alloc(sizeof (sid_prefix_node_t), KM_SLEEP);
755c5c4113dSnw141292 	new->sid_prefix = kidmap_strdup(sid_prefix);
756c5c4113dSnw141292 	avl_insert(&kidmap_sid_prefix_store->tree, new, where);
757c5c4113dSnw141292 	rw_exit(&kidmap_sid_prefix_store->lock);
758c5c4113dSnw141292 
759c5c4113dSnw141292 	return (new->sid_prefix);
760c5c4113dSnw141292 }
761