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 2010 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * SID system call. 29 */ 30 31 #include <sys/sid.h> 32 #include <sys/cred.h> 33 #include <sys/errno.h> 34 #include <sys/systm.h> 35 #include <sys/policy.h> 36 #include <sys/door.h> 37 #include <sys/kidmap.h> 38 #include <sys/proc.h> 39 40 static uint64_t 41 allocids(int flag, int nuids, int ngids) 42 { 43 rval_t r; 44 uid_t su = 0; 45 gid_t sg = 0; 46 struct door_info di; 47 door_handle_t dh; 48 int err; 49 zone_t *zone = crgetzone(CRED()); 50 51 dh = idmap_get_door(zone); 52 53 if (dh == NULL) 54 return (set_errno(EPERM)); 55 56 if ((err = door_ki_info(dh, &di)) != 0) { 57 door_ki_rele(dh); 58 return (set_errno(err)); 59 } 60 61 door_ki_rele(dh); 62 63 if (curproc->p_pid != di.di_target) 64 return (set_errno(EPERM)); 65 66 if (flag) 67 idmap_purge_cache(zone); 68 69 if (nuids < 0 || ngids < 0) 70 return (set_errno(EINVAL)); 71 72 if (flag != 0 || nuids > 0) 73 err = eph_uid_alloc(zone, flag, &su, nuids); 74 if (err == 0 && (flag != 0 || ngids > 0)) 75 err = eph_gid_alloc(zone, flag, &sg, ngids); 76 77 if (err != 0) 78 return (set_errno(EOVERFLOW)); 79 80 r.r_val1 = su; 81 r.r_val2 = sg; 82 return (r.r_vals); 83 } 84 85 static int 86 idmap_reg(int did) 87 { 88 door_handle_t dh; 89 int err; 90 cred_t *cr = CRED(); 91 92 if ((err = secpolicy_idmap(cr)) != 0) 93 return (set_errno(err)); 94 95 dh = door_ki_lookup(did); 96 97 if (dh == NULL) 98 return (set_errno(EBADF)); 99 100 if ((err = idmap_reg_dh(crgetzone(cr), dh)) != 0) 101 return (set_errno(err)); 102 103 return (0); 104 } 105 106 static int 107 idmap_unreg(int did) 108 { 109 door_handle_t dh = door_ki_lookup(did); 110 int res; 111 zone_t *zone; 112 113 if (dh == NULL) 114 return (set_errno(EINVAL)); 115 116 zone = crgetzone(CRED()); 117 res = idmap_unreg_dh(zone, dh); 118 door_ki_rele(dh); 119 120 if (res != 0) 121 return (set_errno(res)); 122 return (0); 123 } 124 125 static uint64_t 126 idmap_flush_kcache(void) 127 { 128 struct door_info di; 129 door_handle_t dh; 130 int err; 131 zone_t *zone = crgetzone(CRED()); 132 133 dh = idmap_get_door(zone); 134 135 if (dh == NULL) 136 return (set_errno(EPERM)); 137 138 if ((err = door_ki_info(dh, &di)) != 0) { 139 door_ki_rele(dh); 140 return (set_errno(err)); 141 } 142 143 door_ki_rele(dh); 144 145 if (curproc->p_pid != di.di_target) 146 return (set_errno(EPERM)); 147 148 idmap_purge_cache(zone); 149 150 return (0); 151 } 152 153 uint64_t 154 sidsys(int op, int flag, int nuids, int ngids) 155 { 156 switch (op) { 157 case SIDSYS_ALLOC_IDS: 158 return (allocids(flag, nuids, ngids)); 159 case SIDSYS_IDMAP_REG: 160 return (idmap_reg(flag)); 161 case SIDSYS_IDMAP_UNREG: 162 return (idmap_unreg(flag)); 163 case SIDSYS_IDMAP_FLUSH_KCACHE: 164 return (idmap_flush_kcache()); 165 default: 166 return (set_errno(EINVAL)); 167 } 168 } 169