xref: /illumos-gate/usr/src/uts/common/syscall/sidsys.c (revision 9fb67ea305c66b6a297583b9b0db6796b0dfe497)
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
allocids(int flag,int nuids,int ngids)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
idmap_reg(int did)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
idmap_unreg(int did)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
idmap_flush_kcache(void)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
sidsys(int op,int flag,int nuids,int ngids)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