]>
Commit | Line | Data |
---|---|---|
04277e02 | 1 | /* Copyright (C) 1991-2019 Free Software Foundation, Inc. |
c84142e8 | 2 | This file is part of the GNU C Library. |
28f540f4 | 3 | |
c84142e8 | 4 | The GNU C Library is free software; you can redistribute it and/or |
41bdb6e2 AJ |
5 | modify it under the terms of the GNU Lesser General Public |
6 | License as published by the Free Software Foundation; either | |
7 | version 2.1 of the License, or (at your option) any later version. | |
28f540f4 | 8 | |
c84142e8 UD |
9 | The GNU C Library is distributed in the hope that it will be useful, |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
41bdb6e2 | 12 | Lesser General Public License for more details. |
28f540f4 | 13 | |
41bdb6e2 | 14 | You should have received a copy of the GNU Lesser General Public |
59ba27a6 | 15 | License along with the GNU C Library; if not, see |
5a82c748 | 16 | <https://www.gnu.org/licenses/>. */ |
28f540f4 RM |
17 | |
18 | #include <hurd.h> | |
19 | #include <hurd/msg_server.h> | |
20 | #include <hurd/id.h> | |
21 | #include <string.h> | |
22 | ||
23 | int | |
24 | _hurd_refport_secure_p (mach_port_t ref) | |
25 | { | |
26 | if (ref == __mach_task_self ()) | |
27 | return 1; | |
28 | if (__USEPORT (AUTH, ref == port)) | |
29 | return 1; | |
30 | return 0; | |
31 | } | |
32 | ||
33 | kern_return_t | |
34 | _S_msg_add_auth (mach_port_t me, | |
35 | auth_t addauth) | |
36 | { | |
37 | error_t err; | |
38 | auth_t newauth; | |
1f205a47 UD |
39 | uid_t *genuids, *gengids, *auxuids, *auxgids; |
40 | mach_msg_type_number_t ngenuids, ngengids, nauxuids, nauxgids; | |
41 | uid_t *newgenuids, *newgengids, *newauxuids, *newauxgids; | |
42 | mach_msg_type_number_t nnewgenuids, nnewgengids, nnewauxuids, nnewauxgids; | |
28f540f4 | 43 | |
1f205a47 UD |
44 | /* Create a list of ids and store it in NEWLISTP, length NEWLISTLEN. |
45 | Keep all the ids in EXIST (len NEXIST), adding in those from NEW | |
46 | (len NNEW) which are not already there. */ | |
47 | error_t make_list (uid_t **newlistp, mach_msg_type_number_t *newlistlen, | |
48 | uid_t *exist, mach_msg_type_number_t nexist, | |
49 | uid_t *new, mach_msg_type_number_t nnew) | |
50 | { | |
51 | error_t urp; | |
52 | int i, j, k; | |
53 | vm_size_t offset; | |
54 | ||
dba2bdbe ST |
55 | urp = __vm_allocate (mach_task_self (), (vm_address_t *) newlistp, |
56 | nexist + nnew * sizeof (uid_t), 1); | |
1f205a47 UD |
57 | if (urp) |
58 | return urp; | |
59 | ||
60 | j = 0; | |
61 | for (i = 0; i < nexist; i++) | |
62 | (*newlistp)[j++] = exist[i]; | |
63 | ||
64 | for (i = 0; i < nnew; i++) | |
65 | { | |
66 | for (k = 0; k < nexist; k++) | |
67 | if (exist[k] == new[i]) | |
68 | break; | |
69 | if (k < nexist) | |
70 | continue; | |
71 | ||
72 | (*newlistp)[j++] = new[i]; | |
73 | } | |
74 | ||
75 | offset = (round_page (nexist + nnew * sizeof (uid_t)) | |
76 | - round_page (j * sizeof (uid_t))); | |
77 | if (offset) | |
dba2bdbe ST |
78 | __vm_deallocate (mach_task_self (), |
79 | (vm_address_t) (*newlistp | |
80 | + (nexist + nnew * sizeof (uid_t))), | |
81 | offset); | |
1f205a47 UD |
82 | *newlistlen = j; |
83 | return 0; | |
84 | } | |
85 | ||
86 | /* Find out what ids ADDAUTH refers to */ | |
87 | ||
88 | genuids = gengids = auxuids = auxgids = 0; | |
89 | ngenuids = ngengids = nauxuids = nauxgids = 0; | |
90 | err = __auth_getids (addauth, | |
91 | &genuids, &ngenuids, | |
92 | &auxuids, &nauxuids, | |
93 | &gengids, &ngengids, | |
94 | &auxgids, &nauxgids); | |
95 | if (err) | |
96 | return err; | |
97 | ||
98 | /* OR in these ids to what we already have, creating a new list. */ | |
99 | ||
100 | HURD_CRITICAL_BEGIN; | |
101 | __mutex_lock (&_hurd_id.lock); | |
102 | _hurd_check_ids (); | |
103 | ||
104 | #define MAKE(genaux,uidgid) \ | |
105 | make_list (&new ## genaux ## uidgid ## s, \ | |
106 | &nnew ## genaux ## uidgid ## s, \ | |
107 | _hurd_id.genaux.uidgid ## s, \ | |
108 | _hurd_id.genaux.n ## uidgid ## s, \ | |
109 | genaux ## uidgid ## s, \ | |
110 | n ## genaux ## uidgid ## s) | |
111 | ||
112 | err = MAKE (gen, uid); | |
113 | if (!err) | |
114 | MAKE (aux, uid); | |
115 | if (!err) | |
116 | MAKE (gen, gid); | |
117 | if (!err) | |
118 | MAKE (aux, gid); | |
119 | #undef MAKE | |
120 | ||
121 | __mutex_unlock (&_hurd_id.lock); | |
122 | HURD_CRITICAL_END; | |
123 | ||
124 | ||
125 | /* Create the new auth port */ | |
126 | ||
127 | if (!err) | |
128 | err = __USEPORT (AUTH, | |
129 | __auth_makeauth (port, | |
130 | &addauth, MACH_MSG_TYPE_MOVE_SEND, 1, | |
131 | newgenuids, nnewgenuids, | |
132 | newauxuids, nnewauxuids, | |
133 | newgengids, nnewgengids, | |
134 | newauxgids, nnewauxgids, | |
135 | &newauth)); | |
136 | ||
137 | #define freeup(array, len) \ | |
138 | if (array) \ | |
dba2bdbe ST |
139 | __vm_deallocate (mach_task_self (), (vm_address_t) array, \ |
140 | len * sizeof (uid_t)); | |
1f205a47 UD |
141 | |
142 | freeup (genuids, ngenuids); | |
143 | freeup (auxuids, nauxuids); | |
144 | freeup (gengids, ngengids); | |
145 | freeup (auxgids, nauxgids); | |
146 | freeup (newgenuids, nnewgenuids); | |
147 | freeup (newauxuids, nnewauxuids); | |
148 | freeup (newgengids, nnewgengids); | |
149 | freeup (newauxgids, nnewauxgids); | |
150 | #undef freeup | |
151 | ||
152 | if (err) | |
28f540f4 RM |
153 | return err; |
154 | ||
1f205a47 UD |
155 | /* And install it. */ |
156 | ||
28f540f4 RM |
157 | err = __setauth (newauth); |
158 | __mach_port_deallocate (__mach_task_self (), newauth); | |
159 | if (err) | |
160 | return errno; | |
161 | ||
162 | return 0; | |
163 | } | |
164 | ||
165 | kern_return_t | |
166 | _S_msg_del_auth (mach_port_t me, | |
167 | task_t task, | |
168 | intarray_t uids, mach_msg_type_number_t nuids, | |
169 | intarray_t gids, mach_msg_type_number_t ngids) | |
170 | { | |
171 | error_t err; | |
172 | auth_t newauth; | |
173 | ||
174 | if (!_hurd_refport_secure_p (task)) | |
175 | return EPERM; | |
176 | ||
177 | HURD_CRITICAL_BEGIN; | |
178 | __mutex_lock (&_hurd_id.lock); | |
179 | err = _hurd_check_ids (); | |
180 | ||
181 | if (!err) | |
182 | { | |
183 | size_t i, j; | |
184 | size_t nu = _hurd_id.gen.nuids, ng = _hurd_id.gen.ngids; | |
185 | uid_t newu[nu]; | |
186 | gid_t newg[ng]; | |
187 | ||
188 | memcpy (newu, _hurd_id.gen.uids, nu * sizeof (uid_t)); | |
189 | memcpy (newg, _hurd_id.gen.gids, ng * sizeof (gid_t)); | |
190 | ||
191 | for (j = 0; j < nuids; ++j) | |
192 | { | |
193 | const uid_t uid = uids[j]; | |
194 | for (i = 0; i < nu; ++i) | |
195 | if (newu[i] == uid) | |
196 | /* Move the last uid into this slot, and decrease the | |
197 | number of uids so the last slot is no longer used. */ | |
198 | newu[i] = newu[--nu]; | |
199 | } | |
200 | __vm_deallocate (__mach_task_self (), | |
201 | (vm_address_t) uids, nuids * sizeof (uid_t)); | |
202 | ||
203 | for (j = 0; j < ngids; ++j) | |
204 | { | |
205 | const gid_t gid = gids[j]; | |
206 | for (i = 0; i < nu; ++i) | |
207 | if (newu[i] == gid) | |
208 | /* Move the last gid into this slot, and decrease the | |
209 | number of gids so the last slot is no longer used. */ | |
210 | newu[i] = newu[--nu]; | |
211 | } | |
212 | __vm_deallocate (__mach_task_self (), | |
213 | (vm_address_t) gids, ngids * sizeof (gid_t)); | |
214 | ||
215 | err = __USEPORT (AUTH, __auth_makeauth | |
216 | (port, | |
4cca6b86 | 217 | NULL, MACH_MSG_TYPE_COPY_SEND, 0, |
28f540f4 RM |
218 | newu, nu, |
219 | _hurd_id.aux.uids, _hurd_id.aux.nuids, | |
220 | newg, ng, | |
221 | _hurd_id.aux.uids, _hurd_id.aux.ngids, | |
222 | &newauth)); | |
223 | } | |
224 | __mutex_unlock (&_hurd_id.lock); | |
225 | HURD_CRITICAL_END; | |
226 | ||
227 | if (err) | |
228 | return err; | |
229 | ||
230 | err = __setauth (newauth); | |
231 | __mach_port_deallocate (__mach_task_self (), newauth); | |
232 | if (err) | |
233 | return errno; | |
234 | ||
235 | return 0; | |
236 | } |