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