1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20: #include <errno.h>
21: #include <unistd.h>
22: #include <fcntl.h>
23: #include <limits.h>
24: #include <stdlib.h>
25: #include <string.h>
26: #include <hurd.h>
27: #include <hurd/fd.h>
28: #include <hurd/signal.h>
29: #include <hurd/id.h>
30: #include <assert.h>
31: #include <argz.h>
32:
33:
34:
35:
36: error_t
37: _hurd_exec (task_t task, file_t file,
38: char *const argv[], char *const envp[])
39: {
40: error_t err;
41: char *args, *env;
42: size_t argslen, envlen;
43: int ints[INIT_INT_MAX];
44: mach_port_t ports[_hurd_nports];
45: struct hurd_userlink ulink_ports[_hurd_nports];
46: inline void free_port (unsigned int i)
47: {
48: _hurd_port_free (&_hurd_ports[i], &ulink_ports[i], ports[i]);
49: }
50: file_t *dtable;
51: unsigned int dtablesize, i;
52: struct hurd_port **dtable_cells;
53: struct hurd_userlink *ulink_dtable;
54: struct hurd_sigstate *ss;
55: mach_port_t *please_dealloc, *pdp;
56: int reauth = 0;
57:
58:
59: if (argv == NULL)
60: args = NULL, argslen = 0;
61: else if (err = __argz_create (argv, &args, &argslen))
62: return err;
63: if (envp == NULL)
64: env = NULL, envlen = 0;
65: else if (err = __argz_create (envp, &env, &envlen))
66: goto outargs;
67:
68:
69: for (i = 0; i < _hurd_nports; ++i)
70: if (i == INIT_PORT_PROC && task != __mach_task_self ())
71: {
72:
73:
74: if (err = __USEPORT (PROC, __proc_task2proc (port, task, &ports[i])))
75: {
76: while (--i > 0)
77: free_port (i);
78: goto outenv;
79: }
80: }
81: else
82: ports[i] = _hurd_port_get (&_hurd_ports[i], &ulink_ports[i]);
83:
84:
85:
86: for (i = 0; i < INIT_INT_MAX; ++i)
87: switch (i)
88: {
89: case INIT_UMASK:
90: ints[i] = _hurd_umask;
91: break;
92:
93: case INIT_SIGMASK:
94: case INIT_SIGIGN:
95: case INIT_SIGPENDING:
96:
97: break;
98:
99: case INIT_TRACEMASK:
100: ints[i] = _hurdsig_traced;
101: break;
102:
103: default:
104: ints[i] = 0;
105: }
106:
107: ss = _hurd_self_sigstate ();
108:
109: assert (! __spin_lock_locked (&ss->critical_section_lock));
110: __spin_lock (&ss->critical_section_lock);
111:
112: __spin_lock (&ss->lock);
113: ints[INIT_SIGMASK] = ss->blocked;
114: ints[INIT_SIGPENDING] = ss->pending;
115: ints[INIT_SIGIGN] = 0;
116: for (i = 1; i < NSIG; ++i)
117: if (ss->actions[i].sa_handler == SIG_IGN)
118: ints[INIT_SIGIGN] |= __sigmask (i);
119:
120:
121:
122:
123:
124:
125:
126:
127:
128: __spin_unlock (&ss->lock);
129:
130:
131: __mutex_lock (&_hurd_dtable_lock);
132:
133: dtablesize = _hurd_dtable ? _hurd_dtablesize : _hurd_init_dtablesize;
134:
135: if (task == __mach_task_self ())
136:
137:
138:
139:
140:
141:
142: please_dealloc = __alloca ((_hurd_nports + 3 + (3 * dtablesize))
143: * sizeof (mach_port_t));
144: else
145: please_dealloc = NULL;
146: pdp = please_dealloc;
147:
148: if (_hurd_dtable != NULL)
149: {
150: dtable = __alloca (dtablesize * sizeof (dtable[0]));
151: ulink_dtable = __alloca (dtablesize * sizeof (ulink_dtable[0]));
152: dtable_cells = __alloca (dtablesize * sizeof (dtable_cells[0]));
153: for (i = 0; i < dtablesize; ++i)
154: {
155: struct hurd_fd *const d = _hurd_dtable[i];
156: if (d == NULL)
157: {
158: dtable[i] = MACH_PORT_NULL;
159: continue;
160: }
161: __spin_lock (&d->port.lock);
162: if (d->flags & FD_CLOEXEC)
163: {
164:
165:
166: dtable[i] = MACH_PORT_NULL;
167: if (pdp && d->port.port != MACH_PORT_NULL)
168: {
169:
170: *pdp++ = d->port.port;
171: if (d->ctty.port != MACH_PORT_NULL)
172: *pdp++ = d->ctty.port;
173: }
174: __spin_unlock (&d->port.lock);
175: }
176: else
177: {
178: if (pdp && d->ctty.port != MACH_PORT_NULL)
179:
180:
181:
182:
183: *pdp++ = d->ctty.port;
184: dtable[i] = _hurd_port_locked_get (&d->port, &ulink_dtable[i]);
185: dtable_cells[i] = &d->port;
186: }
187: }
188: }
189: else
190: {
191: dtable = _hurd_init_dtable;
192: ulink_dtable = NULL;
193: dtable_cells = NULL;
194: }
195:
196:
197: while (dtablesize > 0 && dtable[dtablesize - 1] == MACH_PORT_NULL)
198: --dtablesize;
199:
200:
201:
202:
203:
204:
205:
206:
207:
208:
209:
210:
211: __mutex_lock (&_hurd_id.lock);
212: err = _hurd_check_ids ();
213: if (err == 0 && ((_hurd_id.aux.nuids >= 2 && _hurd_id.gen.nuids >= 1
214: && _hurd_id.aux.uids[1] != _hurd_id.gen.uids[0])
215: || (_hurd_id.aux.ngids >= 2 && _hurd_id.gen.ngids >= 1
216: && _hurd_id.aux.gids[1] != _hurd_id.gen.gids[0])))
217: {
218:
219:
220:
221:
222:
223: auth_t newauth;
224:
225: _hurd_id.aux.uids[1] = _hurd_id.gen.uids[0];
226: _hurd_id.aux.gids[1] = _hurd_id.gen.gids[0];
227: _hurd_id.valid = 0;
228: if (_hurd_id.rid_auth != MACH_PORT_NULL)
229: {
230: __mach_port_deallocate (__mach_task_self (), _hurd_id.rid_auth);
231: _hurd_id.rid_auth = MACH_PORT_NULL;
232: }
233:
234: err = __auth_makeauth (ports[INIT_PORT_AUTH],
235: NULL, MACH_MSG_TYPE_COPY_SEND, 0,
236: _hurd_id.gen.uids, _hurd_id.gen.nuids,
237: _hurd_id.aux.uids, _hurd_id.aux.nuids,
238: _hurd_id.gen.gids, _hurd_id.gen.ngids,
239: _hurd_id.aux.gids, _hurd_id.aux.ngids,
240: &newauth);
241: if (err == 0)
242: {
243:
244:
245:
246: inline error_t reauth_io (io_t port, io_t *newport)
247: {
248: mach_port_t ref = __mach_reply_port ();
249: *newport = MACH_PORT_NULL;
250: error_t err = __io_reauthenticate (port,
251: ref, MACH_MSG_TYPE_MAKE_SEND);
252: if (!err)
253: err = __auth_user_authenticate (newauth,
254: ref, MACH_MSG_TYPE_MAKE_SEND,
255: newport);
256: __mach_port_destroy (__mach_task_self (), ref);
257: return err;
258: }
259: inline void reauth_port (unsigned int idx)
260: {
261: io_t newport;
262: err = reauth_io (ports[idx], &newport) ?: err;
263: if (pdp)
264: *pdp++ = ports[idx];
265: free_port (idx);
266: ports[idx] = newport;
267: }
268:
269: if (pdp)
270: *pdp++ = ports[INIT_PORT_AUTH];
271: free_port (INIT_PORT_AUTH);
272: ports[INIT_PORT_AUTH] = newauth;
273:
274: reauth_port (INIT_PORT_CRDIR);
275: reauth_port (INIT_PORT_CWDIR);
276:
277: if (!err)
278: {
279:
280: if (ulink_dtable == NULL)
281: {
282: assert (dtable == _hurd_init_dtable);
283: dtable = __alloca (dtablesize * sizeof (dtable[0]));
284: for (i = 0; i < dtablesize; ++i)
285: if (_hurd_init_dtable[i] != MACH_PORT_NULL)
286: {
287: if (pdp)
288: *pdp++ = _hurd_init_dtable[i];
289: err = reauth_io (_hurd_init_dtable[i], &dtable[i]);
290: if (err)
291: {
292: while (++i < dtablesize)
293: dtable[i] = MACH_PORT_NULL;
294: break;
295: }
296: }
297: else
298: dtable[i] = MACH_PORT_NULL;
299: }
300: else
301: {
302: if (pdp)
303: {
304:
305:
306: memcpy (pdp, dtable, dtablesize * sizeof pdp[0]);
307: pdp += dtablesize;
308: }
309: for (i = 0; i < dtablesize; ++i)
310: if (dtable[i] != MACH_PORT_NULL)
311: {
312: io_t newport;
313: err = reauth_io (dtable[i], &newport);
314: _hurd_port_free (dtable_cells[i], &ulink_dtable[i],
315: dtable[i]);
316: dtable[i] = newport;
317: if (err)
318: {
319: while (++i < dtablesize)
320: _hurd_port_free (dtable_cells[i],
321: &ulink_dtable[i], dtable[i]);
322: break;
323: }
324: }
325: ulink_dtable = NULL;
326: dtable_cells = NULL;
327: }
328: }
329: }
330:
331: reauth = 1;
332: }
333: __mutex_unlock (&_hurd_id.lock);
334:
335:
336: if (!err)
337: {
338: int flags;
339:
340: if (pdp)
341: {
342:
343:
344:
345:
346:
347:
348:
349:
350: for (i = 0; i < _hurd_nports; ++i)
351: *pdp++ = ports[i];
352: for (i = 0; i < dtablesize; ++i)
353: *pdp++ = dtable[i];
354: }
355:
356: flags = 0;
357: #ifdef EXEC_SIGTRAP
358:
359:
360:
361:
362: if (__sigismember (&_hurdsig_traced, SIGKILL))
363: flags |= EXEC_SIGTRAP;
364: #endif
365: err = __file_exec (file, task, flags,
366: args, argslen, env, envlen,
367: dtable, MACH_MSG_TYPE_COPY_SEND, dtablesize,
368: ports, MACH_MSG_TYPE_COPY_SEND, _hurd_nports,
369: ints, INIT_INT_MAX,
370: please_dealloc, pdp - please_dealloc,
371: &_hurd_msgport, task == __mach_task_self () ? 1 : 0);
372: }
373:
374:
375: for (i = 0; i < _hurd_nports; ++i)
376: if ((i == INIT_PORT_PROC && task != __mach_task_self ())
377: || (reauth && (i == INIT_PORT_AUTH
378: || i == INIT_PORT_CRDIR || i == INIT_PORT_CWDIR)))
379: __mach_port_deallocate (__mach_task_self (), ports[i]);
380: else
381: free_port (i);
382:
383:
384: if (ulink_dtable != NULL)
385: {
386: for (i = 0; i < dtablesize; ++i)
387: if (dtable[i] != MACH_PORT_NULL)
388: _hurd_port_free (dtable_cells[i], &ulink_dtable[i], dtable[i]);
389: }
390: else if (dtable && dtable != _hurd_init_dtable)
391: for (i = 0; i < dtablesize; ++i)
392: __mach_port_deallocate (__mach_task_self (), dtable[i]);
393:
394:
395: __mutex_unlock (&_hurd_dtable_lock);
396:
397:
398: _hurd_critical_section_unlock (ss);
399:
400: outargs:
401: free (args);
402: outenv:
403: free (env);
404: return err;
405: }