Home | History | Annotate | Download | only in os
      1  4321    casper /*
      2  4321    casper  * CDDL HEADER START
      3  4321    casper  *
      4  4321    casper  * The contents of this file are subject to the terms of the
      5  4321    casper  * Common Development and Distribution License (the "License").
      6  4321    casper  * You may not use this file except in compliance with the License.
      7  4321    casper  *
      8  4321    casper  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  4321    casper  * or http://www.opensolaris.org/os/licensing.
     10  4321    casper  * See the License for the specific language governing permissions
     11  4321    casper  * and limitations under the License.
     12  4321    casper  *
     13  4321    casper  * When distributing Covered Code, include this CDDL HEADER in each
     14  4321    casper  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  4321    casper  * If applicable, add the following below this CDDL HEADER, with the
     16  4321    casper  * fields enclosed by brackets "[]" replaced with your own identifying
     17  4321    casper  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  4321    casper  *
     19  4321    casper  * CDDL HEADER END
     20  4321    casper  */
     21  4321    casper 
     22  4321    casper /*
     23  5771  jp151216  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     24  4321    casper  * Use is subject to license terms.
     25  4321    casper  */
     26  4321    casper 
     27  4321    casper /*
     28  4321    casper  * Sid manipulation (stubs).
     29  4321    casper  */
     30  4321    casper 
     31  4321    casper #include <sys/atomic.h>
     32  4321    casper #include <sys/avl.h>
     33  4321    casper #include <sys/cmn_err.h>
     34  4321    casper #include <sys/kmem.h>
     35  4321    casper #include <sys/mutex.h>
     36  4321    casper #include <sys/sid.h>
     37  4321    casper #include <sys/sysmacros.h>
     38  4321    casper #include <sys/systm.h>
     39  4520  nw141292 #include <sys/kidmap.h>
     40  4520  nw141292 #include <sys/idmap.h>
     41  4321    casper 
     42  4321    casper static kmutex_t sid_lock;
     43  4321    casper static avl_tree_t sid_tree;
     44  4321    casper static boolean_t sid_inited = B_FALSE;
     45  4321    casper 
     46  4321    casper static ksiddomain_t
     47  4321    casper *ksid_enterdomain(const char *dom)
     48  4321    casper {
     49  4321    casper 	size_t len = strlen(dom) + 1;
     50  4321    casper 	ksiddomain_t *res;
     51  4321    casper 
     52  4321    casper 	ASSERT(MUTEX_HELD(&sid_lock));
     53  4321    casper 	res = kmem_alloc(sizeof (ksiddomain_t), KM_SLEEP);
     54  4321    casper 	res->kd_len = (uint_t)len;
     55  4321    casper 	res->kd_name = kmem_alloc(len, KM_SLEEP);
     56  4321    casper 	bcopy(dom, res->kd_name, len);
     57  4321    casper 
     58  4321    casper 	res->kd_ref = 1;
     59  4321    casper 
     60  4321    casper 	avl_add(&sid_tree, res);
     61  4321    casper 
     62  4321    casper 	return (res);
     63  4321    casper }
     64  4321    casper 
     65  4321    casper void
     66  4321    casper ksid_hold(ksid_t *ks)
     67  4321    casper {
     68  4321    casper 	if (ks->ks_domain != NULL)
     69  4321    casper 		ksiddomain_hold(ks->ks_domain);
     70  4321    casper }
     71  4321    casper 
     72  4321    casper void
     73  4321    casper ksid_rele(ksid_t *ks)
     74  4321    casper {
     75  4321    casper 	if (ks->ks_domain != NULL)
     76  4321    casper 		ksiddomain_rele(ks->ks_domain);
     77  4321    casper }
     78  4321    casper 
     79  4321    casper void
     80  4321    casper ksiddomain_hold(ksiddomain_t *kd)
     81  4321    casper {
     82  4321    casper 	atomic_add_32(&kd->kd_ref, 1);
     83  4321    casper }
     84  4321    casper 
     85  4321    casper void
     86  4321    casper ksiddomain_rele(ksiddomain_t *kd)
     87  4321    casper {
     88  4321    casper 	if (atomic_add_32_nv(&kd->kd_ref, -1) == 0) {
     89  4321    casper 		/*
     90  4321    casper 		 * The kd reference can only be incremented from 0 when
     91  4321    casper 		 * the sid_lock is held; so we lock and then check need to
     92  4321    casper 		 * check for 0 again.
     93  4321    casper 		 */
     94  4321    casper 		mutex_enter(&sid_lock);
     95  4321    casper 		if (kd->kd_ref == 0) {
     96  4321    casper 			avl_remove(&sid_tree, kd);
     97  4321    casper 			kmem_free(kd->kd_name, kd->kd_len);
     98  4321    casper 			kmem_free(kd, sizeof (*kd));
     99  4321    casper 		}
    100  4321    casper 		mutex_exit(&sid_lock);
    101  4321    casper 	}
    102  4321    casper }
    103  4321    casper 
    104  4321    casper void
    105  4321    casper ksidlist_hold(ksidlist_t *ksl)
    106  4321    casper {
    107  4321    casper 	atomic_add_32(&ksl->ksl_ref, 1);
    108  4321    casper }
    109  4321    casper 
    110  4321    casper void
    111  4321    casper ksidlist_rele(ksidlist_t *ksl)
    112  4321    casper {
    113  4321    casper 	if (atomic_add_32_nv(&ksl->ksl_ref, -1) == 0) {
    114  4321    casper 		int i;
    115  4321    casper 
    116  4321    casper 		for (i = 0; i < ksl->ksl_nsid; i++)
    117  4321    casper 			ksid_rele(&ksl->ksl_sids[i]);
    118  4321    casper 
    119  4321    casper 		kmem_free(ksl, KSIDLIST_MEM(ksl->ksl_nsid));
    120  4321    casper 	}
    121  4321    casper }
    122  4321    casper 
    123  4321    casper static int
    124  4321    casper ksid_cmp(const void *a, const void *b)
    125  4321    casper {
    126  4321    casper 	const ksiddomain_t *ap = a;
    127  4321    casper 	const ksiddomain_t *bp = b;
    128  4321    casper 	int res;
    129  4321    casper 
    130  4321    casper 	res = strcmp(ap->kd_name, bp->kd_name);
    131  4321    casper 	if (res > 0)
    132  4321    casper 		return (1);
    133  4321    casper 	if (res != 0)
    134  4321    casper 		return (-1);
    135  4321    casper 	return (0);
    136  4321    casper }
    137  4321    casper 
    138  4321    casper /*
    139  4321    casper  * Lookup the named domain in the AVL tree.
    140  4321    casper  * If no entry is found, add the domain to the AVL tree.
    141  4321    casper  * The domain is returned held and needs to be released
    142  4321    casper  * when done.
    143  4321    casper  */
    144  4321    casper ksiddomain_t
    145  4321    casper *ksid_lookupdomain(const char *dom)
    146  4321    casper {
    147  4321    casper 	ksiddomain_t *res;
    148  4321    casper 	ksiddomain_t tmpl;
    149  4321    casper 
    150  4321    casper 	mutex_enter(&sid_lock);
    151  4321    casper 
    152  4321    casper 	if (!sid_inited) {
    153  4321    casper 		avl_create(&sid_tree, ksid_cmp, sizeof (ksiddomain_t),
    154  4321    casper 		    offsetof(ksiddomain_t, kd_link));
    155  4321    casper 
    156  4321    casper 		res = ksid_enterdomain(dom);
    157  4321    casper 		sid_inited = B_TRUE;
    158  4321    casper 		mutex_exit(&sid_lock);
    159  4321    casper 		return (res);
    160  4321    casper 	}
    161  4321    casper 
    162  4321    casper 	tmpl.kd_name = (char *)dom;
    163  4321    casper 
    164  4321    casper 	res = avl_find(&sid_tree, &tmpl, NULL);
    165  4321    casper 	if (res == NULL) {
    166  4321    casper 		res = ksid_enterdomain(dom);
    167  4321    casper 	} else {
    168  4321    casper 		ksiddomain_hold(res);
    169  4321    casper 	}
    170  4321    casper 
    171  4321    casper 	mutex_exit(&sid_lock);
    172  4321    casper 	return (res);
    173  4321    casper }
    174  4321    casper 
    175  4321    casper const char *
    176  4321    casper ksid_getdomain(ksid_t *ks)
    177  4321    casper {
    178  4321    casper 	return (ks->ks_domain->kd_name);
    179  4321    casper }
    180  4321    casper 
    181  4321    casper uint_t
    182  4321    casper ksid_getrid(ksid_t *ks)
    183  4321    casper {
    184  4321    casper 	return (ks->ks_rid);
    185  7847      Mark }
    186  7847      Mark 
    187  7847      Mark uid_t
    188  7847      Mark ksid_getid(ksid_t *ks)
    189  7847      Mark {
    190  7847      Mark 	return (ks->ks_id);
    191  4321    casper }
    192  4321    casper 
    193  4321    casper int
    194  5771  jp151216 ksid_lookupbyuid(zone_t *zone, uid_t id, ksid_t *res)
    195  4321    casper {
    196  4520  nw141292 	const char *sid_prefix;
    197  4321    casper 
    198  5771  jp151216 	if (kidmap_getsidbyuid(zone, id, &sid_prefix, &res->ks_rid)
    199  5771  jp151216 	    != IDMAP_SUCCESS)
    200  4321    casper 		return (-1);
    201  4321    casper 
    202  4520  nw141292 	res->ks_domain = ksid_lookupdomain(sid_prefix);
    203  4520  nw141292 
    204  4520  nw141292 	res->ks_id = id;
    205  4520  nw141292 
    206  4520  nw141292 	return (0);
    207  4520  nw141292 }
    208  4520  nw141292 
    209  4520  nw141292 int
    210  5771  jp151216 ksid_lookupbygid(zone_t *zone, gid_t id, ksid_t *res)
    211  4520  nw141292 {
    212  4520  nw141292 	const char *sid_prefix;
    213  4520  nw141292 
    214  5771  jp151216 	if (kidmap_getsidbygid(zone, id, &sid_prefix, &res->ks_rid)
    215  5771  jp151216 	    != IDMAP_SUCCESS)
    216  4520  nw141292 		return (-1);
    217  4520  nw141292 
    218  4520  nw141292 	res->ks_domain = ksid_lookupdomain(sid_prefix);
    219  4520  nw141292 
    220  4321    casper 	res->ks_id = id;
    221  4321    casper 
    222  4321    casper 	return (0);
    223  4321    casper }
    224  4321    casper 
    225  4321    casper credsid_t *
    226  4321    casper kcrsid_alloc(void)
    227  4321    casper {
    228  4321    casper 	credsid_t *kcr = kmem_zalloc(sizeof (*kcr), KM_SLEEP);
    229  4321    casper 	kcr->kr_ref = 1;
    230  4321    casper 	return (kcr);
    231  4321    casper }
    232  4321    casper 
    233  4321    casper /*
    234  4321    casper  * Returns a credsid_t with a refcount of 1.
    235  4321    casper  */
    236  4321    casper static credsid_t *
    237  4321    casper kcrsid_dup(credsid_t *org)
    238  4321    casper {
    239  4321    casper 	credsid_t *new;
    240  4321    casper 	ksid_index_t ki;
    241  4321    casper 
    242  4321    casper 	if (org == NULL)
    243  4321    casper 		return (kcrsid_alloc());
    244  4321    casper 	if (org->kr_ref == 1)
    245  4321    casper 		return (org);
    246  4321    casper 	new = kcrsid_alloc();
    247  4321    casper 
    248  4321    casper 	/* Copy, then update reference counts */
    249  4321    casper 	*new = *org;
    250  4321    casper 	new->kr_ref = 1;
    251  4321    casper 	for (ki = 0; ki < KSID_COUNT; ki++)
    252  4321    casper 		ksid_hold(&new->kr_sidx[ki]);
    253  4321    casper 
    254  4321    casper 	if (new->kr_sidlist != NULL)
    255  4321    casper 		ksidlist_hold(new->kr_sidlist);
    256  4321    casper 
    257  4321    casper 	kcrsid_rele(org);
    258  4321    casper 	return (new);
    259  4321    casper }
    260  4321    casper 
    261  4321    casper void
    262  4321    casper kcrsid_hold(credsid_t *kcr)
    263  4321    casper {
    264  4321    casper 	atomic_add_32(&kcr->kr_ref, 1);
    265  4321    casper }
    266  4321    casper 
    267  4321    casper void
    268  4321    casper kcrsid_rele(credsid_t *kcr)
    269  4321    casper {
    270  4321    casper 	if (atomic_add_32_nv(&kcr->kr_ref, -1) == 0) {
    271  4321    casper 		ksid_index_t i;
    272  4321    casper 
    273  4321    casper 		for (i = 0; i < KSID_COUNT; i++)
    274  4321    casper 			ksid_rele(&kcr->kr_sidx[i]);
    275  4321    casper 
    276  4321    casper 		if (kcr->kr_sidlist != NULL)
    277  4321    casper 			ksidlist_rele(kcr->kr_sidlist);
    278  4321    casper 
    279  4321    casper 		kmem_free(kcr, sizeof (*kcr));
    280  4321    casper 	}
    281  4321    casper }
    282  4321    casper 
    283  4321    casper /*
    284  4321    casper  * Copy the SID credential into a previously allocated piece of memory.
    285  4321    casper  */
    286  4321    casper void
    287  4321    casper kcrsidcopy_to(const credsid_t *okcr, credsid_t *nkcr)
    288  4321    casper {
    289  4321    casper 	int i;
    290  4321    casper 
    291  4321    casper 	ASSERT(nkcr->kr_ref == 1);
    292  4321    casper 
    293  4321    casper 	if (okcr == NULL)
    294  4321    casper 		return;
    295  4321    casper 	*nkcr = *okcr;
    296  4321    casper 	for (i = 0; i < KSID_COUNT; i++)
    297  4321    casper 		ksid_hold(&nkcr->kr_sidx[i]);
    298  4321    casper 	if (nkcr->kr_sidlist != NULL)
    299  4321    casper 		ksidlist_hold(nkcr->kr_sidlist);
    300  4321    casper 	nkcr->kr_ref = 1;
    301  4321    casper }
    302  4321    casper 
    303  4321    casper static int
    304  4321    casper kcrsid_sidcount(const credsid_t *kcr)
    305  4321    casper {
    306  4321    casper 	int cnt = 0;
    307  4321    casper 	int i;
    308  4321    casper 
    309  4321    casper 	if (kcr == NULL)
    310  4321    casper 		return (0);
    311  4321    casper 
    312  4321    casper 	for (i = 0; i < KSID_COUNT; i++)
    313  4321    casper 		if (kcr->kr_sidx[i].ks_domain != NULL)
    314  4321    casper 			cnt++;
    315  4321    casper 
    316  4321    casper 	if (kcr->kr_sidlist != NULL)
    317  4321    casper 		cnt += kcr->kr_sidlist->ksl_nsid;
    318  4321    casper 	return (cnt);
    319  4321    casper }
    320  4321    casper 
    321  4321    casper /*
    322  4321    casper  * Argument needs to be a ksid_t with a properly held ks_domain reference.
    323  4321    casper  */
    324  4321    casper credsid_t *
    325  4321    casper kcrsid_setsid(credsid_t *okcr, ksid_t *ksp, ksid_index_t i)
    326  4321    casper {
    327  4321    casper 	int ocnt = kcrsid_sidcount(okcr);
    328  4321    casper 	credsid_t *nkcr;
    329  4321    casper 
    330  4321    casper 	/*
    331  4321    casper 	 * Unset the particular ksid; if there are no other SIDs or if this
    332  4321    casper 	 * is the last SID, remove the auxilary data structure.
    333  4321    casper 	 */
    334  4321    casper 	if (ksp == NULL) {
    335  4321    casper 		if (ocnt == 0 ||
    336  4321    casper 		    (ocnt == 1 && okcr->kr_sidx[i].ks_domain != NULL)) {
    337  4321    casper 			if (okcr != NULL)
    338  4321    casper 				kcrsid_rele(okcr);
    339  4321    casper 			return (NULL);
    340  4321    casper 		}
    341  4321    casper 	}
    342  4321    casper 	nkcr = kcrsid_dup(okcr);
    343  4321    casper 	ksid_rele(&nkcr->kr_sidx[i]);
    344  4321    casper 	if (ksp == NULL)
    345  4321    casper 		bzero(&nkcr->kr_sidx[i], sizeof (ksid_t));
    346  4321    casper 	else
    347  4321    casper 		nkcr->kr_sidx[i] = *ksp;
    348  4321    casper 
    349  4321    casper 	return (nkcr);
    350  4321    casper }
    351  4321    casper 
    352  4321    casper /*
    353  4321    casper  * Argument needs to be a ksidlist_t with properly held ks_domain references
    354  4321    casper  * and a reference count taking the new reference into account.
    355  4321    casper  */
    356  4321    casper credsid_t *
    357  4321    casper kcrsid_setsidlist(credsid_t *okcr, ksidlist_t *ksl)
    358  4321    casper {
    359  4321    casper 	int ocnt = kcrsid_sidcount(okcr);
    360  4321    casper 	credsid_t *nkcr;
    361  4321    casper 
    362  4321    casper 	/*
    363  4321    casper 	 * Unset the sidlist; if there are no further SIDs, remove the
    364  4321    casper 	 * auxilary data structure.
    365  4321    casper 	 */
    366  4321    casper 	if (ksl == NULL) {
    367  4321    casper 		if (ocnt == 0 || (okcr->kr_sidlist != NULL &&
    368  4321    casper 		    ocnt == okcr->kr_sidlist->ksl_nsid)) {
    369  4321    casper 			if (okcr != NULL)
    370  4321    casper 				kcrsid_rele(okcr);
    371  4321    casper 			return (NULL);
    372  4321    casper 		}
    373  4321    casper 	}
    374  4321    casper 	nkcr = kcrsid_dup(okcr);
    375  4321    casper 	if (nkcr->kr_sidlist != NULL)
    376  4321    casper 		ksidlist_rele(nkcr->kr_sidlist);
    377  4321    casper 
    378  4321    casper 	nkcr->kr_sidlist = ksl;
    379  4321    casper 	return (nkcr);
    380  4321    casper }
    381  4321    casper 
    382  4321    casper ksidlist_t *
    383  5771  jp151216 kcrsid_gidstosids(zone_t *zone, int ngrp, gid_t *grp)
    384  4321    casper {
    385  4321    casper 	int i;
    386  4321    casper 	ksidlist_t *list;
    387  4321    casper 	int cnt;
    388  4321    casper 
    389  4321    casper 	if (ngrp == 0)
    390  4321    casper 		return (NULL);
    391  4321    casper 
    392  4321    casper 	cnt = 0;
    393  4321    casper 	list = kmem_zalloc(KSIDLIST_MEM(ngrp), KM_SLEEP);
    394  4321    casper 
    395  4321    casper 	list->ksl_nsid = ngrp;
    396  4321    casper 	list->ksl_ref = 1;
    397  4321    casper 
    398  4321    casper 	for (i = 0; i < ngrp; i++) {
    399  4321    casper 		if (grp[i] > MAXUID) {
    400  4321    casper 			list->ksl_neid++;
    401  5771  jp151216 			if (ksid_lookupbygid(zone,
    402  5771  jp151216 			    grp[i], &list->ksl_sids[i]) != 0) {
    403  4321    casper 				while (--i >= 0)
    404  4321    casper 					ksid_rele(&list->ksl_sids[i]);
    405  4321    casper 				cnt = 0;
    406  4321    casper 				break;
    407  4321    casper 			}
    408  4321    casper 			cnt++;
    409  4321    casper 		} else {
    410  4321    casper 			list->ksl_sids[i].ks_id = grp[i];
    411  4321    casper 		}
    412  4321    casper 	}
    413  4321    casper 	if (cnt == 0) {
    414  4321    casper 		kmem_free(list, KSIDLIST_MEM(ngrp));
    415  4321    casper 		return (NULL);
    416  4321    casper 	}
    417  4321    casper 	return (list);
    418  4321    casper }
    419