Home | History | Annotate | Download | only in syscall
      1 /*
      2  * CDDL HEADER START
      3  *
      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.
      7  *
      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.
     12  *
     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]
     18  *
     19  * CDDL HEADER END
     20  */
     21 
     22 /*
     23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     28 
     29 /*
     30  * SID system call.
     31  */
     32 
     33 #include <sys/sid.h>
     34 #include <sys/cred.h>
     35 #include <sys/errno.h>
     36 #include <sys/systm.h>
     37 #include <sys/policy.h>
     38 #include <sys/door.h>
     39 #include <sys/kidmap.h>
     40 #include <sys/proc.h>
     41 
     42 static uint64_t
     43 allocids(int flag, int nuids, int ngids)
     44 {
     45 	rval_t r;
     46 	uid_t su = 0;
     47 	gid_t sg = 0;
     48 	struct door_info di;
     49 	door_handle_t dh;
     50 	int err;
     51 	zone_t *zone = crgetzone(CRED());
     52 
     53 	dh = idmap_get_door(zone);
     54 
     55 	if (dh == NULL)
     56 		return (set_errno(EPERM));
     57 
     58 	if ((err = door_ki_info(dh, &di)) != 0) {
     59 		door_ki_rele(dh);
     60 		return (set_errno(err));
     61 	}
     62 
     63 	door_ki_rele(dh);
     64 
     65 	if (curproc->p_pid != di.di_target)
     66 		return (set_errno(EPERM));
     67 
     68 	if (flag)
     69 		idmap_purge_cache(zone);
     70 
     71 	if (nuids < 0 || ngids < 0)
     72 		return (set_errno(EINVAL));
     73 
     74 	if (flag != 0 || nuids > 0)
     75 		err = eph_uid_alloc(zone, flag, &su, nuids);
     76 	if (err == 0 && (flag != 0 || ngids > 0))
     77 		err = eph_gid_alloc(zone, flag, &sg, ngids);
     78 
     79 	if (err != 0)
     80 		return (set_errno(EOVERFLOW));
     81 
     82 	r.r_val1 = su;
     83 	r.r_val2 = sg;
     84 	return (r.r_vals);
     85 }
     86 
     87 static int
     88 idmap_reg(int did)
     89 {
     90 	door_handle_t dh;
     91 	int err;
     92 	cred_t *cr = CRED();
     93 
     94 	if ((err = secpolicy_idmap(cr)) != 0)
     95 		return (set_errno(err));
     96 
     97 	dh = door_ki_lookup(did);
     98 
     99 	if (dh == NULL)
    100 		return (set_errno(EBADF));
    101 
    102 	if ((err = idmap_reg_dh(crgetzone(cr), dh)) != 0)
    103 		return (set_errno(err));
    104 
    105 	return (0);
    106 }
    107 
    108 static int
    109 idmap_unreg(int did)
    110 {
    111 	door_handle_t dh = door_ki_lookup(did);
    112 	int res;
    113 	zone_t *zone;
    114 
    115 	if (dh == NULL)
    116 		return (set_errno(EINVAL));
    117 
    118 	zone = crgetzone(CRED());
    119 	res = idmap_unreg_dh(zone, dh);
    120 	door_ki_rele(dh);
    121 
    122 	if (res != 0)
    123 		return (set_errno(res));
    124 	return (0);
    125 }
    126 
    127 uint64_t
    128 sidsys(int op, int flag, int nuids, int ngids)
    129 {
    130 	switch (op) {
    131 	case SIDSYS_ALLOC_IDS:
    132 		return (allocids(flag, nuids, ngids));
    133 	case SIDSYS_IDMAP_REG:
    134 		return (idmap_reg(flag));
    135 	case SIDSYS_IDMAP_UNREG:
    136 		return (idmap_unreg(flag));
    137 	default:
    138 		return (set_errno(EINVAL));
    139 	}
    140 }
    141