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 /* 23*f7b4b2feSjp151216 * Copyright 2008 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 560b10de9fSjp151216 #define CACHE_TRIGGER_SIZE 4096 57c5c4113dSnw141292 #define CACHE_PURGE_INTERVAL (60 * 3) 580b10de9fSjp151216 #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 { 1070b10de9fSjp151216 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 1170b10de9fSjp151216 return ((int)comp); 118c5c4113dSnw141292 } 119c5c4113dSnw141292 120c5c4113dSnw141292 121c5c4113dSnw141292 static int 122c5c4113dSnw141292 kidmap_compare_pid(const entry_t *entry1, const entry_t *entry2) 123c5c4113dSnw141292 { 1240b10de9fSjp151216 if (entry2->pid > entry1->pid) 1250b10de9fSjp151216 return (1); 1260b10de9fSjp151216 if (entry2->pid < entry1->pid) 1270b10de9fSjp151216 return (-1); 1280b10de9fSjp151216 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 { 1520b10de9fSjp151216 avl_create(&cache->uidbysid.tree, (avl_comp_fn)kidmap_compare_sid, 153c5c4113dSnw141292 sizeof (entry_t), offsetof(entry_t, avl_link)); 1540b10de9fSjp151216 mutex_init(&cache->uidbysid.mutex, NULL, MUTEX_DEFAULT, NULL); 1550b10de9fSjp151216 cache->uidbysid.purge_time = 0; 156c5c4113dSnw141292 1570b10de9fSjp151216 avl_create(&cache->gidbysid.tree, (avl_comp_fn)kidmap_compare_sid, 158c5c4113dSnw141292 sizeof (entry_t), offsetof(entry_t, avl_link)); 1590b10de9fSjp151216 mutex_init(&cache->gidbysid.mutex, NULL, MUTEX_DEFAULT, NULL); 1600b10de9fSjp151216 cache->gidbysid.purge_time = 0; 1610b10de9fSjp151216 1620b10de9fSjp151216 avl_create(&cache->pidbysid.tree, (avl_comp_fn)kidmap_compare_sid, 1630b10de9fSjp151216 sizeof (entry_t), offsetof(entry_t, avl_link)); 1640b10de9fSjp151216 mutex_init(&cache->pidbysid.mutex, NULL, MUTEX_DEFAULT, NULL); 1650b10de9fSjp151216 cache->pidbysid.purge_time = 0; 1660b10de9fSjp151216 1670b10de9fSjp151216 avl_create(&cache->sidbyuid.tree, (avl_comp_fn)kidmap_compare_pid, 1680b10de9fSjp151216 sizeof (entry_t), offsetof(entry_t, avl_link)); 1690b10de9fSjp151216 mutex_init(&cache->sidbyuid.mutex, NULL, MUTEX_DEFAULT, NULL); 1700b10de9fSjp151216 cache->sidbyuid.purge_time = 0; 1710b10de9fSjp151216 1720b10de9fSjp151216 avl_create(&cache->sidbygid.tree, (avl_comp_fn)kidmap_compare_pid, 1730b10de9fSjp151216 sizeof (entry_t), offsetof(entry_t, avl_link)); 1740b10de9fSjp151216 mutex_init(&cache->sidbygid.mutex, NULL, MUTEX_DEFAULT, NULL); 1750b10de9fSjp151216 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; 1860b10de9fSjp151216 while ((entry = avl_destroy_nodes(&cache->uidbysid.tree, &cookie)) 187c5c4113dSnw141292 != NULL) { 188c5c4113dSnw141292 kmem_free(entry, sizeof (entry_t)); 189c5c4113dSnw141292 } 1900b10de9fSjp151216 avl_destroy(&cache->uidbysid.tree); 1910b10de9fSjp151216 mutex_destroy(&cache->uidbysid.mutex); 192c5c4113dSnw141292 193c5c4113dSnw141292 cookie = NULL; 1940b10de9fSjp151216 while ((entry = avl_destroy_nodes(&cache->gidbysid.tree, &cookie)) 195c5c4113dSnw141292 != NULL) { 196c5c4113dSnw141292 kmem_free(entry, sizeof (entry_t)); 197c5c4113dSnw141292 } 1980b10de9fSjp151216 avl_destroy(&cache->gidbysid.tree); 1990b10de9fSjp151216 mutex_destroy(&cache->gidbysid.mutex); 2000b10de9fSjp151216 2010b10de9fSjp151216 cookie = NULL; 2020b10de9fSjp151216 while ((entry = avl_destroy_nodes(&cache->pidbysid.tree, &cookie)) 2030b10de9fSjp151216 != NULL) { 2040b10de9fSjp151216 kmem_free(entry, sizeof (entry_t)); 2050b10de9fSjp151216 } 2060b10de9fSjp151216 avl_destroy(&cache->pidbysid.tree); 2070b10de9fSjp151216 mutex_destroy(&cache->pidbysid.mutex); 2080b10de9fSjp151216 2090b10de9fSjp151216 cookie = NULL; 2100b10de9fSjp151216 while ((entry = avl_destroy_nodes(&cache->sidbyuid.tree, &cookie)) 2110b10de9fSjp151216 != NULL) { 2120b10de9fSjp151216 kmem_free(entry, sizeof (entry_t)); 2130b10de9fSjp151216 } 2140b10de9fSjp151216 avl_destroy(&cache->sidbyuid.tree); 2150b10de9fSjp151216 mutex_destroy(&cache->sidbyuid.mutex); 2160b10de9fSjp151216 2170b10de9fSjp151216 cookie = NULL; 2180b10de9fSjp151216 while ((entry = avl_destroy_nodes(&cache->sidbygid.tree, &cookie)) 2190b10de9fSjp151216 != NULL) { 2200b10de9fSjp151216 kmem_free(entry, sizeof (entry_t)); 2210b10de9fSjp151216 } 2220b10de9fSjp151216 avl_destroy(&cache->sidbygid.tree); 2230b10de9fSjp151216 mutex_destroy(&cache->sidbygid.mutex); 2240b10de9fSjp151216 } 2250b10de9fSjp151216 2260b10de9fSjp151216 2270b10de9fSjp151216 void 228*f7b4b2feSjp151216 kidmap_cache_get_data(idmap_cache_t *cache, size_t *uidbysid, size_t *gidbysid, 229*f7b4b2feSjp151216 size_t *pidbysid, size_t *sidbyuid, size_t *sidbygid) 230*f7b4b2feSjp151216 { 231*f7b4b2feSjp151216 mutex_enter(&cache->uidbysid.mutex); 232*f7b4b2feSjp151216 *uidbysid = avl_numnodes(&cache->uidbysid.tree); 233*f7b4b2feSjp151216 mutex_exit(&cache->uidbysid.mutex); 234*f7b4b2feSjp151216 235*f7b4b2feSjp151216 mutex_enter(&cache->gidbysid.mutex); 236*f7b4b2feSjp151216 *gidbysid = avl_numnodes(&cache->gidbysid.tree); 237*f7b4b2feSjp151216 mutex_exit(&cache->gidbysid.mutex); 238*f7b4b2feSjp151216 239*f7b4b2feSjp151216 mutex_enter(&cache->pidbysid.mutex); 240*f7b4b2feSjp151216 *pidbysid = avl_numnodes(&cache->pidbysid.tree); 241*f7b4b2feSjp151216 mutex_exit(&cache->pidbysid.mutex); 242*f7b4b2feSjp151216 243*f7b4b2feSjp151216 mutex_enter(&cache->sidbyuid.mutex); 244*f7b4b2feSjp151216 *sidbyuid = avl_numnodes(&cache->sidbyuid.tree); 245*f7b4b2feSjp151216 mutex_exit(&cache->sidbyuid.mutex); 246*f7b4b2feSjp151216 247*f7b4b2feSjp151216 mutex_enter(&cache->sidbygid.mutex); 248*f7b4b2feSjp151216 *sidbygid = avl_numnodes(&cache->sidbygid.tree); 249*f7b4b2feSjp151216 mutex_exit(&cache->sidbygid.mutex); 250*f7b4b2feSjp151216 } 251*f7b4b2feSjp151216 252*f7b4b2feSjp151216 253*f7b4b2feSjp151216 void 2540b10de9fSjp151216 kidmap_cache_purge(idmap_cache_t *cache) 2550b10de9fSjp151216 { 2560b10de9fSjp151216 entry_t *entry; 2570b10de9fSjp151216 void *cookie; 2580b10de9fSjp151216 2590b10de9fSjp151216 mutex_enter(&cache->uidbysid.mutex); 2600b10de9fSjp151216 cookie = NULL; 2610b10de9fSjp151216 while ((entry = avl_destroy_nodes(&cache->uidbysid.tree, &cookie)) 2620b10de9fSjp151216 != NULL) { 2630b10de9fSjp151216 kmem_free(entry, sizeof (entry_t)); 2640b10de9fSjp151216 } 2650b10de9fSjp151216 avl_destroy(&cache->uidbysid.tree); 2660b10de9fSjp151216 avl_create(&cache->uidbysid.tree, (avl_comp_fn)kidmap_compare_sid, 2670b10de9fSjp151216 sizeof (entry_t), offsetof(entry_t, avl_link)); 2680b10de9fSjp151216 mutex_exit(&cache->uidbysid.mutex); 2690b10de9fSjp151216 2700b10de9fSjp151216 mutex_enter(&cache->gidbysid.mutex); 2710b10de9fSjp151216 cookie = NULL; 2720b10de9fSjp151216 while ((entry = avl_destroy_nodes(&cache->gidbysid.tree, &cookie)) 2730b10de9fSjp151216 != NULL) { 2740b10de9fSjp151216 kmem_free(entry, sizeof (entry_t)); 2750b10de9fSjp151216 } 2760b10de9fSjp151216 avl_destroy(&cache->gidbysid.tree); 2770b10de9fSjp151216 avl_create(&cache->gidbysid.tree, (avl_comp_fn)kidmap_compare_sid, 2780b10de9fSjp151216 sizeof (entry_t), offsetof(entry_t, avl_link)); 2790b10de9fSjp151216 mutex_exit(&cache->gidbysid.mutex); 2800b10de9fSjp151216 2810b10de9fSjp151216 mutex_enter(&cache->pidbysid.mutex); 2820b10de9fSjp151216 cookie = NULL; 2830b10de9fSjp151216 while ((entry = avl_destroy_nodes(&cache->pidbysid.tree, &cookie)) 2840b10de9fSjp151216 != NULL) { 2850b10de9fSjp151216 kmem_free(entry, sizeof (entry_t)); 2860b10de9fSjp151216 } 2870b10de9fSjp151216 avl_destroy(&cache->pidbysid.tree); 2880b10de9fSjp151216 avl_create(&cache->pidbysid.tree, (avl_comp_fn)kidmap_compare_sid, 2890b10de9fSjp151216 sizeof (entry_t), offsetof(entry_t, avl_link)); 2900b10de9fSjp151216 mutex_exit(&cache->pidbysid.mutex); 2910b10de9fSjp151216 2920b10de9fSjp151216 mutex_enter(&cache->sidbyuid.mutex); 2930b10de9fSjp151216 cookie = NULL; 2940b10de9fSjp151216 while ((entry = avl_destroy_nodes(&cache->sidbyuid.tree, &cookie)) 2950b10de9fSjp151216 != NULL) { 2960b10de9fSjp151216 kmem_free(entry, sizeof (entry_t)); 2970b10de9fSjp151216 } 2980b10de9fSjp151216 avl_destroy(&cache->sidbyuid.tree); 2990b10de9fSjp151216 avl_create(&cache->sidbyuid.tree, (avl_comp_fn)kidmap_compare_pid, 3000b10de9fSjp151216 sizeof (entry_t), offsetof(entry_t, avl_link)); 3010b10de9fSjp151216 mutex_exit(&cache->sidbyuid.mutex); 3020b10de9fSjp151216 3030b10de9fSjp151216 mutex_enter(&cache->sidbygid.mutex); 3040b10de9fSjp151216 cookie = NULL; 3050b10de9fSjp151216 while ((entry = avl_destroy_nodes(&cache->sidbygid.tree, &cookie)) 3060b10de9fSjp151216 != NULL) { 3070b10de9fSjp151216 kmem_free(entry, sizeof (entry_t)); 3080b10de9fSjp151216 } 3090b10de9fSjp151216 avl_destroy(&cache->sidbygid.tree); 3100b10de9fSjp151216 avl_create(&cache->sidbygid.tree, (avl_comp_fn)kidmap_compare_pid, 3110b10de9fSjp151216 sizeof (entry_t), offsetof(entry_t, avl_link)); 3120b10de9fSjp151216 mutex_exit(&cache->sidbygid.mutex); 313c5c4113dSnw141292 } 314c5c4113dSnw141292 315c5c4113dSnw141292 316c5c4113dSnw141292 int 3170b10de9fSjp151216 kidmap_cache_lookup_uidbysid(idmap_cache_t *cache, const char *sid_prefix, 3180b10de9fSjp151216 uint32_t rid, uid_t *uid) 319c5c4113dSnw141292 { 320c5c4113dSnw141292 entry_t entry; 321c5c4113dSnw141292 entry_t *result; 322c5c4113dSnw141292 avl_index_t where; 323c5c4113dSnw141292 int status; 324c5c4113dSnw141292 time_t now = gethrestime_sec(); 325c5c4113dSnw141292 3260b10de9fSjp151216 entry.sid_prefix = sid_prefix; 3270b10de9fSjp151216 entry.rid = rid; 328c5c4113dSnw141292 3290b10de9fSjp151216 mutex_enter(&cache->uidbysid.mutex); 330c5c4113dSnw141292 3310b10de9fSjp151216 result = avl_find(&cache->uidbysid.tree, &entry, &where); 332c5c4113dSnw141292 333c5c4113dSnw141292 if (result && result->ttl > now) { 3340b10de9fSjp151216 *uid = result->pid; 335c5c4113dSnw141292 status = IDMAP_SUCCESS; 336c5c4113dSnw141292 } else 337c5c4113dSnw141292 status = IDMAP_ERR_NOMAPPING; 338c5c4113dSnw141292 3390b10de9fSjp151216 mutex_exit(&cache->uidbysid.mutex); 340c5c4113dSnw141292 341c5c4113dSnw141292 return (status); 342c5c4113dSnw141292 } 343c5c4113dSnw141292 344c5c4113dSnw141292 3450b10de9fSjp151216 346c5c4113dSnw141292 int 3470b10de9fSjp151216 kidmap_cache_lookup_gidbysid(idmap_cache_t *cache, const char *sid_prefix, 3480b10de9fSjp151216 uint32_t rid, gid_t *gid) 3490b10de9fSjp151216 { 3500b10de9fSjp151216 entry_t entry; 3510b10de9fSjp151216 entry_t *result; 3520b10de9fSjp151216 avl_index_t where; 3530b10de9fSjp151216 int status; 3540b10de9fSjp151216 time_t now = gethrestime_sec(); 3550b10de9fSjp151216 3560b10de9fSjp151216 entry.sid_prefix = sid_prefix; 3570b10de9fSjp151216 entry.rid = rid; 3580b10de9fSjp151216 3590b10de9fSjp151216 mutex_enter(&cache->gidbysid.mutex); 3600b10de9fSjp151216 3610b10de9fSjp151216 result = avl_find(&cache->gidbysid.tree, &entry, &where); 3620b10de9fSjp151216 3630b10de9fSjp151216 if (result && result->ttl > now) { 3640b10de9fSjp151216 *gid = result->pid; 3650b10de9fSjp151216 status = IDMAP_SUCCESS; 3660b10de9fSjp151216 } else 3670b10de9fSjp151216 status = IDMAP_ERR_NOMAPPING; 3680b10de9fSjp151216 3690b10de9fSjp151216 mutex_exit(&cache->gidbysid.mutex); 3700b10de9fSjp151216 3710b10de9fSjp151216 return (status); 3720b10de9fSjp151216 } 3730b10de9fSjp151216 3740b10de9fSjp151216 3750b10de9fSjp151216 3760b10de9fSjp151216 3770b10de9fSjp151216 int 3780b10de9fSjp151216 kidmap_cache_lookup_pidbysid(idmap_cache_t *cache, const char *sid_prefix, 379c5c4113dSnw141292 uint32_t rid, uid_t *pid, int *is_user) 380c5c4113dSnw141292 { 381c5c4113dSnw141292 entry_t entry; 382c5c4113dSnw141292 entry_t *result; 383c5c4113dSnw141292 avl_index_t where; 384c5c4113dSnw141292 int status; 385c5c4113dSnw141292 time_t now = gethrestime_sec(); 386c5c4113dSnw141292 387c5c4113dSnw141292 entry.sid_prefix = sid_prefix; 388c5c4113dSnw141292 entry.rid = rid; 389c5c4113dSnw141292 3900b10de9fSjp151216 mutex_enter(&cache->pidbysid.mutex); 391c5c4113dSnw141292 3920b10de9fSjp151216 result = avl_find(&cache->pidbysid.tree, &entry, &where); 393c5c4113dSnw141292 394c5c4113dSnw141292 if (result && result->ttl > now) { 395c5c4113dSnw141292 *pid = result->pid; 396c5c4113dSnw141292 *is_user = result->is_user; 397c5c4113dSnw141292 status = IDMAP_SUCCESS; 398c5c4113dSnw141292 } else 399c5c4113dSnw141292 status = IDMAP_ERR_NOMAPPING; 400c5c4113dSnw141292 4010b10de9fSjp151216 mutex_exit(&cache->pidbysid.mutex); 402c5c4113dSnw141292 403c5c4113dSnw141292 return (status); 404c5c4113dSnw141292 } 405c5c4113dSnw141292 406c5c4113dSnw141292 4070b10de9fSjp151216 4080b10de9fSjp151216 int 4090b10de9fSjp151216 kidmap_cache_lookup_sidbyuid(idmap_cache_t *cache, const char **sid_prefix, 4100b10de9fSjp151216 uint32_t *rid, uid_t uid) 411c5c4113dSnw141292 { 4120b10de9fSjp151216 entry_t entry; 413c5c4113dSnw141292 entry_t *result; 414c5c4113dSnw141292 avl_index_t where; 4150b10de9fSjp151216 int status; 4160b10de9fSjp151216 time_t now = gethrestime_sec(); 417c5c4113dSnw141292 4180b10de9fSjp151216 entry.pid = uid; 419c5c4113dSnw141292 4200b10de9fSjp151216 mutex_enter(&cache->sidbyuid.mutex); 421c5c4113dSnw141292 4220b10de9fSjp151216 result = avl_find(&cache->sidbyuid.tree, &entry, &where); 423c5c4113dSnw141292 4240b10de9fSjp151216 if (result && result->ttl > now) { 4250b10de9fSjp151216 *sid_prefix = result->sid_prefix; 4260b10de9fSjp151216 *rid = result->rid; 4270b10de9fSjp151216 status = IDMAP_SUCCESS; 4280b10de9fSjp151216 } else 4290b10de9fSjp151216 status = IDMAP_ERR_NOMAPPING; 4300b10de9fSjp151216 4310b10de9fSjp151216 mutex_exit(&cache->sidbyuid.mutex); 4320b10de9fSjp151216 4330b10de9fSjp151216 return (status); 434c5c4113dSnw141292 } 435c5c4113dSnw141292 4360b10de9fSjp151216 int 4370b10de9fSjp151216 kidmap_cache_lookup_sidbygid(idmap_cache_t *cache, const char **sid_prefix, 4380b10de9fSjp151216 uint32_t *rid, gid_t gid) 4390b10de9fSjp151216 { 4400b10de9fSjp151216 entry_t entry; 4410b10de9fSjp151216 entry_t *result; 4420b10de9fSjp151216 avl_index_t where; 4430b10de9fSjp151216 int status; 4440b10de9fSjp151216 time_t now = gethrestime_sec(); 445c5c4113dSnw141292 4460b10de9fSjp151216 entry.pid = gid; 4470b10de9fSjp151216 4480b10de9fSjp151216 mutex_enter(&cache->sidbygid.mutex); 4490b10de9fSjp151216 4500b10de9fSjp151216 result = avl_find(&cache->sidbygid.tree, &entry, &where); 4510b10de9fSjp151216 4520b10de9fSjp151216 if (result && result->ttl > now) { 4530b10de9fSjp151216 *sid_prefix = result->sid_prefix; 4540b10de9fSjp151216 *rid = result->rid; 4550b10de9fSjp151216 status = IDMAP_SUCCESS; 4560b10de9fSjp151216 } else 4570b10de9fSjp151216 status = IDMAP_ERR_NOMAPPING; 4580b10de9fSjp151216 4590b10de9fSjp151216 mutex_exit(&cache->sidbygid.mutex); 4600b10de9fSjp151216 4610b10de9fSjp151216 return (status); 462c5c4113dSnw141292 } 463c5c4113dSnw141292 464c5c4113dSnw141292 4650b10de9fSjp151216 4660b10de9fSjp151216 467c5c4113dSnw141292 void 4680b10de9fSjp151216 kidmap_cache_add_uidbysid(idmap_cache_t *cache, const char *sid_prefix, 4690b10de9fSjp151216 uint32_t rid, uid_t uid) 470c5c4113dSnw141292 471c5c4113dSnw141292 { 472c5c4113dSnw141292 entry_t find; 473c5c4113dSnw141292 entry_t *result; 474c5c4113dSnw141292 entry_t *new; 475c5c4113dSnw141292 avl_index_t where; 476c5c4113dSnw141292 int purge_required = FALSE; 4770b10de9fSjp151216 time_t ttl = CACHE_TTL + gethrestime_sec(); 478c5c4113dSnw141292 479c5c4113dSnw141292 find.sid_prefix = sid_prefix; 480c5c4113dSnw141292 find.rid = rid; 481c5c4113dSnw141292 4820b10de9fSjp151216 mutex_enter(&cache->uidbysid.mutex); 4830b10de9fSjp151216 result = avl_find(&cache->uidbysid.tree, &find, &where); 4840b10de9fSjp151216 4850b10de9fSjp151216 if (result) { 4860b10de9fSjp151216 result->pid = uid; 4870b10de9fSjp151216 result->ttl = ttl; 4880b10de9fSjp151216 } else { 4890b10de9fSjp151216 new = kmem_alloc(sizeof (entry_t), KM_SLEEP); 4900b10de9fSjp151216 new->pid = uid; 4910b10de9fSjp151216 new->sid_prefix = sid_prefix; 4920b10de9fSjp151216 new->rid = rid; 4930b10de9fSjp151216 new->ttl = ttl; 4940b10de9fSjp151216 4950b10de9fSjp151216 avl_insert(&cache->uidbysid.tree, new, where); 4960b10de9fSjp151216 4970b10de9fSjp151216 if ((avl_numnodes(&cache->uidbysid.tree) > 4980b10de9fSjp151216 CACHE_TRIGGER_SIZE) && 4990b10de9fSjp151216 (cache->uidbysid.purge_time + CACHE_PURGE_INTERVAL < 5000b10de9fSjp151216 gethrestime_sec())) 5010b10de9fSjp151216 purge_required = TRUE; 5020b10de9fSjp151216 } 5030b10de9fSjp151216 5040b10de9fSjp151216 mutex_exit(&cache->uidbysid.mutex); 5050b10de9fSjp151216 5060b10de9fSjp151216 if (purge_required) 5070b10de9fSjp151216 kidmap_cache_purge_avl(&cache->uidbysid); 5080b10de9fSjp151216 } 5090b10de9fSjp151216 5100b10de9fSjp151216 5110b10de9fSjp151216 void 5120b10de9fSjp151216 kidmap_cache_add_gidbysid(idmap_cache_t *cache, const char *sid_prefix, 5130b10de9fSjp151216 uint32_t rid, gid_t gid) 5140b10de9fSjp151216 5150b10de9fSjp151216 { 5160b10de9fSjp151216 entry_t find; 5170b10de9fSjp151216 entry_t *result; 5180b10de9fSjp151216 entry_t *new; 5190b10de9fSjp151216 avl_index_t where; 5200b10de9fSjp151216 int purge_required = FALSE; 5210b10de9fSjp151216 time_t ttl = CACHE_TTL + gethrestime_sec(); 5220b10de9fSjp151216 5230b10de9fSjp151216 find.sid_prefix = sid_prefix; 5240b10de9fSjp151216 find.rid = rid; 5250b10de9fSjp151216 5260b10de9fSjp151216 mutex_enter(&cache->gidbysid.mutex); 5270b10de9fSjp151216 result = avl_find(&cache->gidbysid.tree, &find, &where); 5280b10de9fSjp151216 5290b10de9fSjp151216 if (result) { 5300b10de9fSjp151216 result->pid = gid; 5310b10de9fSjp151216 result->ttl = ttl; 5320b10de9fSjp151216 } else { 5330b10de9fSjp151216 new = kmem_alloc(sizeof (entry_t), KM_SLEEP); 5340b10de9fSjp151216 new->pid = gid; 5350b10de9fSjp151216 new->sid_prefix = sid_prefix; 5360b10de9fSjp151216 new->rid = rid; 5370b10de9fSjp151216 new->ttl = ttl; 5380b10de9fSjp151216 5390b10de9fSjp151216 avl_insert(&cache->gidbysid.tree, new, where); 5400b10de9fSjp151216 5410b10de9fSjp151216 if ((avl_numnodes(&cache->gidbysid.tree) > 5420b10de9fSjp151216 CACHE_TRIGGER_SIZE) && 5430b10de9fSjp151216 (cache->gidbysid.purge_time + CACHE_PURGE_INTERVAL < 5440b10de9fSjp151216 gethrestime_sec())) 5450b10de9fSjp151216 purge_required = TRUE; 5460b10de9fSjp151216 } 5470b10de9fSjp151216 5480b10de9fSjp151216 mutex_exit(&cache->gidbysid.mutex); 5490b10de9fSjp151216 5500b10de9fSjp151216 if (purge_required) 5510b10de9fSjp151216 kidmap_cache_purge_avl(&cache->gidbysid); 5520b10de9fSjp151216 } 5530b10de9fSjp151216 5540b10de9fSjp151216 void 5550b10de9fSjp151216 kidmap_cache_add_pidbysid(idmap_cache_t *cache, const char *sid_prefix, 5560b10de9fSjp151216 uint32_t rid, uid_t pid, int is_user) 5570b10de9fSjp151216 5580b10de9fSjp151216 { 5590b10de9fSjp151216 entry_t find; 5600b10de9fSjp151216 entry_t *result; 5610b10de9fSjp151216 entry_t *new; 5620b10de9fSjp151216 avl_index_t where; 5630b10de9fSjp151216 int purge_required = FALSE; 5640b10de9fSjp151216 time_t ttl = CACHE_TTL + gethrestime_sec(); 5650b10de9fSjp151216 5660b10de9fSjp151216 find.sid_prefix = sid_prefix; 5670b10de9fSjp151216 find.rid = rid; 5680b10de9fSjp151216 5690b10de9fSjp151216 mutex_enter(&cache->pidbysid.mutex); 5700b10de9fSjp151216 result = avl_find(&cache->pidbysid.tree, &find, &where); 571c5c4113dSnw141292 572c5c4113dSnw141292 if (result) { 573c5c4113dSnw141292 result->pid = pid; 574c5c4113dSnw141292 result->is_user = is_user; 575c5c4113dSnw141292 result->ttl = ttl; 576c5c4113dSnw141292 } else { 577c5c4113dSnw141292 new = kmem_alloc(sizeof (entry_t), KM_SLEEP); 578c5c4113dSnw141292 new->pid = pid; 579c5c4113dSnw141292 new->is_user = is_user; 580c5c4113dSnw141292 new->sid_prefix = sid_prefix; 581c5c4113dSnw141292 new->rid = rid; 582c5c4113dSnw141292 new->ttl = ttl; 583c5c4113dSnw141292 5840b10de9fSjp151216 avl_insert(&cache->pidbysid.tree, new, where); 585c5c4113dSnw141292 5860b10de9fSjp151216 if ((avl_numnodes(&cache->pidbysid.tree) > 5870b10de9fSjp151216 CACHE_TRIGGER_SIZE) && 5880b10de9fSjp151216 (cache->pidbysid.purge_time + CACHE_PURGE_INTERVAL < 589c5c4113dSnw141292 gethrestime_sec())) 590c5c4113dSnw141292 purge_required = TRUE; 591c5c4113dSnw141292 } 592c5c4113dSnw141292 5930b10de9fSjp151216 mutex_exit(&cache->pidbysid.mutex); 594c5c4113dSnw141292 595c5c4113dSnw141292 if (purge_required) 5960b10de9fSjp151216 kidmap_cache_purge_avl(&cache->pidbysid); 5970b10de9fSjp151216 } 5980b10de9fSjp151216 5990b10de9fSjp151216 6000b10de9fSjp151216 6010b10de9fSjp151216 void 6020b10de9fSjp151216 kidmap_cache_add_sidbyuid(idmap_cache_t *cache, const char *sid_prefix, 6030b10de9fSjp151216 uint32_t rid, uid_t uid) 6040b10de9fSjp151216 { 6050b10de9fSjp151216 entry_t find; 6060b10de9fSjp151216 entry_t *result; 6070b10de9fSjp151216 entry_t *new; 6080b10de9fSjp151216 avl_index_t where; 6090b10de9fSjp151216 int purge_required = FALSE; 6100b10de9fSjp151216 time_t ttl = CACHE_TTL + gethrestime_sec(); 6110b10de9fSjp151216 6120b10de9fSjp151216 find.pid = uid; 6130b10de9fSjp151216 6140b10de9fSjp151216 mutex_enter(&cache->sidbyuid.mutex); 6150b10de9fSjp151216 result = avl_find(&cache->sidbyuid.tree, &find, &where); 6160b10de9fSjp151216 6170b10de9fSjp151216 if (result) { 6180b10de9fSjp151216 result->sid_prefix = sid_prefix; 6190b10de9fSjp151216 result->rid = rid; 6200b10de9fSjp151216 result->ttl = ttl; 6210b10de9fSjp151216 } else { 6220b10de9fSjp151216 new = kmem_alloc(sizeof (entry_t), KM_SLEEP); 6230b10de9fSjp151216 new->pid = uid; 6240b10de9fSjp151216 new->sid_prefix = sid_prefix; 6250b10de9fSjp151216 new->rid = rid; 6260b10de9fSjp151216 new->ttl = ttl; 6270b10de9fSjp151216 6280b10de9fSjp151216 avl_insert(&cache->sidbyuid.tree, new, where); 6290b10de9fSjp151216 if ((avl_numnodes(&cache->sidbyuid.tree) > 6300b10de9fSjp151216 CACHE_TRIGGER_SIZE) && 6310b10de9fSjp151216 (cache->sidbyuid.purge_time + CACHE_PURGE_INTERVAL < 6320b10de9fSjp151216 gethrestime_sec())) 6330b10de9fSjp151216 purge_required = TRUE; 6340b10de9fSjp151216 } 6350b10de9fSjp151216 6360b10de9fSjp151216 mutex_exit(&cache->sidbyuid.mutex); 6370b10de9fSjp151216 6380b10de9fSjp151216 if (purge_required) 6390b10de9fSjp151216 kidmap_cache_purge_avl(&cache->sidbyuid); 6400b10de9fSjp151216 } 6410b10de9fSjp151216 6420b10de9fSjp151216 6430b10de9fSjp151216 void 6440b10de9fSjp151216 kidmap_cache_add_sidbygid(idmap_cache_t *cache, const char *sid_prefix, 6450b10de9fSjp151216 uint32_t rid, gid_t gid) 6460b10de9fSjp151216 { 6470b10de9fSjp151216 entry_t find; 6480b10de9fSjp151216 entry_t *result; 6490b10de9fSjp151216 entry_t *new; 6500b10de9fSjp151216 avl_index_t where; 6510b10de9fSjp151216 int purge_required = FALSE; 6520b10de9fSjp151216 time_t ttl = CACHE_TTL + gethrestime_sec(); 6530b10de9fSjp151216 6540b10de9fSjp151216 find.pid = gid; 6550b10de9fSjp151216 6560b10de9fSjp151216 mutex_enter(&cache->sidbygid.mutex); 6570b10de9fSjp151216 result = avl_find(&cache->sidbygid.tree, &find, &where); 6580b10de9fSjp151216 6590b10de9fSjp151216 if (result) { 6600b10de9fSjp151216 result->sid_prefix = sid_prefix; 6610b10de9fSjp151216 result->rid = rid; 6620b10de9fSjp151216 result->ttl = ttl; 6630b10de9fSjp151216 } else { 6640b10de9fSjp151216 new = kmem_alloc(sizeof (entry_t), KM_SLEEP); 6650b10de9fSjp151216 new->pid = gid; 6660b10de9fSjp151216 new->sid_prefix = sid_prefix; 6670b10de9fSjp151216 new->rid = rid; 6680b10de9fSjp151216 new->ttl = ttl; 6690b10de9fSjp151216 6700b10de9fSjp151216 avl_insert(&cache->sidbygid.tree, new, where); 6710b10de9fSjp151216 if ((avl_numnodes(&cache->sidbygid.tree) > 6720b10de9fSjp151216 CACHE_TRIGGER_SIZE) && 6730b10de9fSjp151216 (cache->sidbygid.purge_time + CACHE_PURGE_INTERVAL < 6740b10de9fSjp151216 gethrestime_sec())) 6750b10de9fSjp151216 purge_required = TRUE; 6760b10de9fSjp151216 } 6770b10de9fSjp151216 6780b10de9fSjp151216 mutex_exit(&cache->sidbygid.mutex); 6790b10de9fSjp151216 6800b10de9fSjp151216 if (purge_required) 6810b10de9fSjp151216 kidmap_cache_purge_avl(&cache->sidbygid); 682c5c4113dSnw141292 } 683c5c4113dSnw141292 684c5c4113dSnw141292 685c5c4113dSnw141292 static void 686c5c4113dSnw141292 kidmap_cache_purge_avl(idmap_avl_cache_t *cache) 687c5c4113dSnw141292 { 688c5c4113dSnw141292 time_t now = gethrestime_sec(); 689c5c4113dSnw141292 entry_t *curr; 690c5c4113dSnw141292 entry_t *prev = NULL; 691c5c4113dSnw141292 692c5c4113dSnw141292 mutex_enter(&cache->mutex); 693c5c4113dSnw141292 694c5c4113dSnw141292 curr = avl_first(&cache->tree); 695c5c4113dSnw141292 while (curr != NULL) { 696c5c4113dSnw141292 if (curr->ttl < now) { 697c5c4113dSnw141292 /* Old entry to remove */ 698c5c4113dSnw141292 avl_remove(&cache->tree, curr); 699*f7b4b2feSjp151216 kmem_free(curr, sizeof (entry_t)); 700c5c4113dSnw141292 curr = prev; 701c5c4113dSnw141292 if (curr == NULL) { 702c5c4113dSnw141292 /* We removed the first entery */ 703c5c4113dSnw141292 curr = avl_first(&cache->tree); 704c5c4113dSnw141292 continue; 705c5c4113dSnw141292 } 706c5c4113dSnw141292 } 707c5c4113dSnw141292 prev = curr; 708c5c4113dSnw141292 curr = AVL_NEXT(&cache->tree, curr); 709c5c4113dSnw141292 } 710c5c4113dSnw141292 cache->purge_time = now; 7110b10de9fSjp151216 712c5c4113dSnw141292 mutex_exit(&cache->mutex); 713c5c4113dSnw141292 } 714c5c4113dSnw141292 7150b10de9fSjp151216 716c5c4113dSnw141292 void 717c5c4113dSnw141292 kidmap_sid_prefix_store_init(void) 718c5c4113dSnw141292 { 719c5c4113dSnw141292 kidmap_sid_prefix_store = (struct sid_prefix_store *) 720c5c4113dSnw141292 space_fetch("SUNW,idmap_sid_prefix"); 721c5c4113dSnw141292 if (kidmap_sid_prefix_store == NULL) { 722c5c4113dSnw141292 kidmap_sid_prefix_store = kmem_alloc( 723c5c4113dSnw141292 sizeof (struct sid_prefix_store), KM_SLEEP); 724c5c4113dSnw141292 rw_init(&kidmap_sid_prefix_store->lock, NULL, RW_DRIVER, NULL); 725c5c4113dSnw141292 avl_create(&kidmap_sid_prefix_store->tree, 726c5c4113dSnw141292 (avl_comp_fn)kidmap_compare_sid_prefix, 727c5c4113dSnw141292 sizeof (sid_prefix_node_t), 728c5c4113dSnw141292 offsetof(sid_prefix_node_t, avl_link)); 729c5c4113dSnw141292 (void) space_store("SUNW,idmap_sid_prefix", 730c5c4113dSnw141292 (uintptr_t)kidmap_sid_prefix_store); 731c5c4113dSnw141292 } else { 732c5c4113dSnw141292 /* 733c5c4113dSnw141292 * The AVL comparison function must be re-initialised on 734c5c4113dSnw141292 * re-load because may not be loaded into the same 735c5c4113dSnw141292 * address space. 736c5c4113dSnw141292 */ 737c5c4113dSnw141292 kidmap_sid_prefix_store->tree.avl_compar = 738c5c4113dSnw141292 (avl_comp_fn)kidmap_compare_sid_prefix; 739c5c4113dSnw141292 } 740c5c4113dSnw141292 } 741c5c4113dSnw141292 742c5c4113dSnw141292 743c5c4113dSnw141292 const char * 744c5c4113dSnw141292 kidmap_find_sid_prefix(const char *sid_prefix) { 745c5c4113dSnw141292 sid_prefix_node_t find; 746c5c4113dSnw141292 sid_prefix_node_t *result; 747c5c4113dSnw141292 sid_prefix_node_t *new; 748c5c4113dSnw141292 avl_index_t where; 749c5c4113dSnw141292 750c5c4113dSnw141292 if (sid_prefix == NULL || *sid_prefix == '\0') 751c5c4113dSnw141292 return (NULL); 752c5c4113dSnw141292 753c5c4113dSnw141292 find.sid_prefix = sid_prefix; 754c5c4113dSnw141292 755c5c4113dSnw141292 756c5c4113dSnw141292 rw_enter(&kidmap_sid_prefix_store->lock, RW_READER); 757c5c4113dSnw141292 758c5c4113dSnw141292 result = avl_find(&kidmap_sid_prefix_store->tree, &find, &where); 759c5c4113dSnw141292 760c5c4113dSnw141292 if (result) { 761c5c4113dSnw141292 rw_exit(&kidmap_sid_prefix_store->lock); 762c5c4113dSnw141292 return (result->sid_prefix); 763c5c4113dSnw141292 } 764c5c4113dSnw141292 765c5c4113dSnw141292 if (rw_tryupgrade(&kidmap_sid_prefix_store->lock) == 0) { 766c5c4113dSnw141292 /* 767c5c4113dSnw141292 * Could not upgrade lock so release lock 768da6c28aaSamw * and acquire the write lock 769c5c4113dSnw141292 */ 770c5c4113dSnw141292 rw_exit(&kidmap_sid_prefix_store->lock); 771c5c4113dSnw141292 rw_enter(&kidmap_sid_prefix_store->lock, RW_WRITER); 772c5c4113dSnw141292 773c5c4113dSnw141292 result = avl_find(&kidmap_sid_prefix_store->tree, 774c5c4113dSnw141292 &find, &where); 775c5c4113dSnw141292 if (result) { 776c5c4113dSnw141292 rw_exit(&kidmap_sid_prefix_store->lock); 777c5c4113dSnw141292 return (result->sid_prefix); 778c5c4113dSnw141292 } 779c5c4113dSnw141292 } 780c5c4113dSnw141292 781c5c4113dSnw141292 new = kmem_alloc(sizeof (sid_prefix_node_t), KM_SLEEP); 782c5c4113dSnw141292 new->sid_prefix = kidmap_strdup(sid_prefix); 783c5c4113dSnw141292 avl_insert(&kidmap_sid_prefix_store->tree, new, where); 784c5c4113dSnw141292 rw_exit(&kidmap_sid_prefix_store->lock); 785c5c4113dSnw141292 786c5c4113dSnw141292 return (new->sid_prefix); 787c5c4113dSnw141292 } 788