4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
28 * Sid manipulation (stubs).
31 #include <sys/atomic.h>
33 #include <sys/cmn_err.h>
35 #include <sys/mutex.h>
37 #include <sys/sysmacros.h>
38 #include <sys/systm.h>
39 #include <sys/kidmap.h>
40 #include <sys/idmap.h>
42 static kmutex_t sid_lock
;
43 static avl_tree_t sid_tree
;
44 static boolean_t sid_inited
= B_FALSE
;
47 *ksid_enterdomain(const char *dom
)
49 size_t len
= strlen(dom
) + 1;
52 ASSERT(MUTEX_HELD(&sid_lock
));
53 res
= kmem_alloc(sizeof (ksiddomain_t
), KM_SLEEP
);
54 res
->kd_len
= (uint_t
)len
;
55 res
->kd_name
= kmem_alloc(len
, KM_SLEEP
);
56 bcopy(dom
, res
->kd_name
, len
);
60 avl_add(&sid_tree
, res
);
68 if (ks
->ks_domain
!= NULL
)
69 ksiddomain_hold(ks
->ks_domain
);
75 if (ks
->ks_domain
!= NULL
)
76 ksiddomain_rele(ks
->ks_domain
);
80 ksiddomain_hold(ksiddomain_t
*kd
)
82 atomic_inc_32(&kd
->kd_ref
);
86 ksiddomain_rele(ksiddomain_t
*kd
)
88 if (atomic_dec_32_nv(&kd
->kd_ref
) == 0) {
90 * The kd reference can only be incremented from 0 when
91 * the sid_lock is held; so we lock and then check need to
94 mutex_enter(&sid_lock
);
95 if (kd
->kd_ref
== 0) {
96 avl_remove(&sid_tree
, kd
);
97 kmem_free(kd
->kd_name
, kd
->kd_len
);
98 kmem_free(kd
, sizeof (*kd
));
100 mutex_exit(&sid_lock
);
105 ksidlist_hold(ksidlist_t
*ksl
)
107 atomic_inc_32(&ksl
->ksl_ref
);
111 ksidlist_rele(ksidlist_t
*ksl
)
113 if (atomic_dec_32_nv(&ksl
->ksl_ref
) == 0) {
116 for (i
= 0; i
< ksl
->ksl_nsid
; i
++)
117 ksid_rele(&ksl
->ksl_sids
[i
]);
119 kmem_free(ksl
, KSIDLIST_MEM(ksl
->ksl_nsid
));
124 ksid_cmp(const void *a
, const void *b
)
126 const ksiddomain_t
*ap
= a
;
127 const ksiddomain_t
*bp
= b
;
130 res
= strcmp(ap
->kd_name
, bp
->kd_name
);
139 * Lookup the named domain in the AVL tree.
140 * If no entry is found, add the domain to the AVL tree.
141 * The domain is returned held and needs to be released
145 *ksid_lookupdomain(const char *dom
)
150 mutex_enter(&sid_lock
);
153 avl_create(&sid_tree
, ksid_cmp
, sizeof (ksiddomain_t
),
154 offsetof(ksiddomain_t
, kd_link
));
156 res
= ksid_enterdomain(dom
);
158 mutex_exit(&sid_lock
);
162 tmpl
.kd_name
= (char *)dom
;
164 res
= avl_find(&sid_tree
, &tmpl
, NULL
);
166 res
= ksid_enterdomain(dom
);
168 ksiddomain_hold(res
);
171 mutex_exit(&sid_lock
);
176 ksid_getdomain(ksid_t
*ks
)
178 return (ks
->ks_domain
->kd_name
);
182 ksid_getrid(ksid_t
*ks
)
188 ksid_getid(ksid_t
*ks
)
194 ksid_lookupbyuid(zone_t
*zone
, uid_t id
, ksid_t
*res
)
196 const char *sid_prefix
;
198 if (kidmap_getsidbyuid(zone
, id
, &sid_prefix
, &res
->ks_rid
)
202 res
->ks_domain
= ksid_lookupdomain(sid_prefix
);
210 ksid_lookupbygid(zone_t
*zone
, gid_t id
, ksid_t
*res
)
212 const char *sid_prefix
;
214 if (kidmap_getsidbygid(zone
, id
, &sid_prefix
, &res
->ks_rid
)
218 res
->ks_domain
= ksid_lookupdomain(sid_prefix
);
228 credsid_t
*kcr
= kmem_zalloc(sizeof (*kcr
), KM_SLEEP
);
234 * Returns a credsid_t with a refcount of 1.
237 kcrsid_dup(credsid_t
*org
)
243 return (kcrsid_alloc());
244 if (org
->kr_ref
== 1)
246 new = kcrsid_alloc();
248 /* Copy, then update reference counts */
251 for (ki
= 0; ki
< KSID_COUNT
; ki
++)
252 ksid_hold(&new->kr_sidx
[ki
]);
254 if (new->kr_sidlist
!= NULL
)
255 ksidlist_hold(new->kr_sidlist
);
262 kcrsid_hold(credsid_t
*kcr
)
264 atomic_inc_32(&kcr
->kr_ref
);
268 kcrsid_rele(credsid_t
*kcr
)
270 if (atomic_dec_32_nv(&kcr
->kr_ref
) == 0) {
273 for (i
= 0; i
< KSID_COUNT
; i
++)
274 ksid_rele(&kcr
->kr_sidx
[i
]);
276 if (kcr
->kr_sidlist
!= NULL
)
277 ksidlist_rele(kcr
->kr_sidlist
);
279 kmem_free(kcr
, sizeof (*kcr
));
284 * Copy the SID credential into a previously allocated piece of memory.
287 kcrsidcopy_to(const credsid_t
*okcr
, credsid_t
*nkcr
)
291 ASSERT(nkcr
->kr_ref
== 1);
296 for (i
= 0; i
< KSID_COUNT
; i
++)
297 ksid_hold(&nkcr
->kr_sidx
[i
]);
298 if (nkcr
->kr_sidlist
!= NULL
)
299 ksidlist_hold(nkcr
->kr_sidlist
);
304 kcrsid_sidcount(const credsid_t
*kcr
)
312 for (i
= 0; i
< KSID_COUNT
; i
++)
313 if (kcr
->kr_sidx
[i
].ks_domain
!= NULL
)
316 if (kcr
->kr_sidlist
!= NULL
)
317 cnt
+= kcr
->kr_sidlist
->ksl_nsid
;
322 * Argument needs to be a ksid_t with a properly held ks_domain reference.
325 kcrsid_setsid(credsid_t
*okcr
, ksid_t
*ksp
, ksid_index_t i
)
327 int ocnt
= kcrsid_sidcount(okcr
);
331 * Unset the particular ksid; if there are no other SIDs or if this
332 * is the last SID, remove the auxilary data structure.
336 (ocnt
== 1 && okcr
->kr_sidx
[i
].ks_domain
!= NULL
)) {
342 nkcr
= kcrsid_dup(okcr
);
343 ksid_rele(&nkcr
->kr_sidx
[i
]);
345 bzero(&nkcr
->kr_sidx
[i
], sizeof (ksid_t
));
347 nkcr
->kr_sidx
[i
] = *ksp
;
353 * Argument needs to be a ksidlist_t with properly held ks_domain references
354 * and a reference count taking the new reference into account.
357 kcrsid_setsidlist(credsid_t
*okcr
, ksidlist_t
*ksl
)
359 int ocnt
= kcrsid_sidcount(okcr
);
363 * Unset the sidlist; if there are no further SIDs, remove the
364 * auxilary data structure.
367 if (ocnt
== 0 || (okcr
->kr_sidlist
!= NULL
&&
368 ocnt
== okcr
->kr_sidlist
->ksl_nsid
)) {
374 nkcr
= kcrsid_dup(okcr
);
375 if (nkcr
->kr_sidlist
!= NULL
)
376 ksidlist_rele(nkcr
->kr_sidlist
);
378 nkcr
->kr_sidlist
= ksl
;
383 kcrsid_gidstosids(zone_t
*zone
, int ngrp
, gid_t
*grp
)
393 list
= kmem_zalloc(KSIDLIST_MEM(ngrp
), KM_SLEEP
);
395 list
->ksl_nsid
= ngrp
;
398 for (i
= 0; i
< ngrp
; i
++) {
399 if (grp
[i
] > MAXUID
) {
401 if (ksid_lookupbygid(zone
,
402 grp
[i
], &list
->ksl_sids
[i
]) != 0) {
404 ksid_rele(&list
->ksl_sids
[i
]);
410 list
->ksl_sids
[i
].ks_id
= grp
[i
];
414 kmem_free(list
, KSIDLIST_MEM(ngrp
));