1/* Copyright (C) 1991-2024 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
4 The GNU C Library is free software; you can redistribute it and/or
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.
8
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
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, see
16 <https://www.gnu.org/licenses/>. */
17
18#include <hurd.h>
19#include <hurd/msg_server.h>
20#include <hurd/id.h>
21#include <string.h>
22
23int
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
33kern_return_t
34_S_msg_add_auth (mach_port_t me,
35 auth_t addauth)
36{
37 error_t err;
38 auth_t newauth;
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;
43
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
55 urp = __vm_allocate (mach_task_self (), (vm_address_t *) newlistp,
56 nexist + nnew * sizeof (uid_t), 1);
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)
78 __vm_deallocate (mach_task_self (),
79 (vm_address_t) (*newlistp
80 + (nexist + nnew * sizeof (uid_t))),
81 offset);
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 new ## genaux ## uidgid ## s = 0; \
106 nnew ## genaux ## uidgid ## s = 0; \
107 make_list (&new ## genaux ## uidgid ## s, \
108 &nnew ## genaux ## uidgid ## s, \
109 _hurd_id.genaux.uidgid ## s, \
110 _hurd_id.genaux.n ## uidgid ## s, \
111 genaux ## uidgid ## s, \
112 n ## genaux ## uidgid ## s); \
113})
114
115 err = MAKE (gen, uid);
116 if (!err)
117 err = MAKE (aux, uid);
118 if (!err)
119 err = MAKE (gen, gid);
120 if (!err)
121 err = MAKE (aux, gid);
122#undef MAKE
123
124 __mutex_unlock (&_hurd_id.lock);
125 HURD_CRITICAL_END;
126
127
128 /* Create the new auth port */
129
130 if (!err)
131 err = __USEPORT (AUTH,
132 __auth_makeauth (port,
133 &addauth, MACH_MSG_TYPE_MOVE_SEND, 1,
134 newgenuids, nnewgenuids,
135 newauxuids, nnewauxuids,
136 newgengids, nnewgengids,
137 newauxgids, nnewauxgids,
138 &newauth));
139
140#define freeup(array, len) \
141 if (array) \
142 __vm_deallocate (mach_task_self (), (vm_address_t) array, \
143 len * sizeof (uid_t));
144
145 freeup (genuids, ngenuids);
146 freeup (auxuids, nauxuids);
147 freeup (gengids, ngengids);
148 freeup (auxgids, nauxgids);
149 freeup (newgenuids, nnewgenuids);
150 freeup (newauxuids, nnewauxuids);
151 freeup (newgengids, nnewgengids);
152 freeup (newauxgids, nnewauxgids);
153#undef freeup
154
155 if (err)
156 return err;
157
158 /* And install it. */
159
160 err = __setauth (newauth);
161 __mach_port_deallocate (__mach_task_self (), newauth);
162 if (err)
163 return errno;
164
165 return 0;
166}
167
168kern_return_t
169_S_msg_del_auth (mach_port_t me,
170 task_t task,
171 const_intarray_t uids, mach_msg_type_number_t nuids,
172 const_intarray_t gids, mach_msg_type_number_t ngids)
173{
174 error_t err;
175 auth_t newauth;
176
177 if (!_hurd_refport_secure_p (task))
178 return EPERM;
179
180 HURD_CRITICAL_BEGIN;
181 __mutex_lock (&_hurd_id.lock);
182 err = _hurd_check_ids ();
183
184 if (!err)
185 {
186 size_t i, j;
187 size_t nu = _hurd_id.gen.nuids, ng = _hurd_id.gen.ngids;
188 uid_t newu[nu];
189 gid_t newg[ng];
190
191 memcpy (dest: newu, src: _hurd_id.gen.uids, n: nu * sizeof (uid_t));
192 memcpy (dest: newg, src: _hurd_id.gen.gids, n: ng * sizeof (gid_t));
193
194 for (j = 0; j < nuids; ++j)
195 {
196 const uid_t uid = uids[j];
197 for (i = 0; i < nu; ++i)
198 if (newu[i] == uid)
199 /* Move the last uid into this slot, and decrease the
200 number of uids so the last slot is no longer used. */
201 newu[i] = newu[--nu];
202 }
203 __vm_deallocate (__mach_task_self (),
204 (vm_address_t) uids, nuids * sizeof (uid_t));
205
206 for (j = 0; j < ngids; ++j)
207 {
208 const gid_t gid = gids[j];
209 for (i = 0; i < nu; ++i)
210 if (newu[i] == gid)
211 /* Move the last gid into this slot, and decrease the
212 number of gids so the last slot is no longer used. */
213 newu[i] = newu[--nu];
214 }
215 __vm_deallocate (__mach_task_self (),
216 (vm_address_t) gids, ngids * sizeof (gid_t));
217
218 err = __USEPORT (AUTH, __auth_makeauth
219 (port,
220 NULL, MACH_MSG_TYPE_COPY_SEND, 0,
221 newu, nu,
222 _hurd_id.aux.uids, _hurd_id.aux.nuids,
223 newg, ng,
224 _hurd_id.aux.uids, _hurd_id.aux.ngids,
225 &newauth));
226 }
227 __mutex_unlock (&_hurd_id.lock);
228 HURD_CRITICAL_END;
229
230 if (err)
231 return err;
232
233 err = __setauth (newauth);
234 __mach_port_deallocate (__mach_task_self (), newauth);
235 if (err)
236 return errno;
237
238 return 0;
239}
240

source code of glibc/hurd/hurdauth.c