Update copyright dates with scripts/update-copyrights.
[platform/upstream/glibc.git] / hurd / dtable.c
1 /* Copyright (C) 1991-2015 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    <http://www.gnu.org/licenses/>.  */
17
18 #include <hurd.h>
19 #include <hurd/term.h>
20 #include <hurd/fd.h>
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <fcntl.h>
24 #include <limits.h>
25 #include <cthreads.h>           /* For `struct mutex'.  */
26 #include "set-hooks.h"
27 #include "hurdmalloc.h"         /* XXX */
28
29
30 struct mutex _hurd_dtable_lock = MUTEX_INITIALIZER; /* XXX ld bug; must init */
31 struct hurd_fd **_hurd_dtable;
32 int _hurd_dtablesize;
33
34
35 DEFINE_HOOK (_hurd_fd_subinit, (void));
36
37 /* Initialize the file descriptor table at startup.  */
38
39 static void
40 init_dtable (void)
41 {
42   int i;
43
44   __mutex_init (&_hurd_dtable_lock);
45
46   /* The initial size of the descriptor table is that of the passed-in
47      table.  It will be expanded as necessary up to _hurd_dtable_rlimit.  */
48   _hurd_dtablesize = _hurd_init_dtablesize;
49
50   /* Allocate the vector of pointers.  */
51   _hurd_dtable = malloc (_hurd_dtablesize * sizeof (*_hurd_dtable));
52   if (_hurd_dtablesize != 0 && _hurd_dtable == NULL)
53     __libc_fatal ("hurd: Can't allocate file descriptor table\n");
54
55   /* Initialize the descriptor table.  */
56   for (i = 0; (unsigned int) i < _hurd_init_dtablesize; ++i)
57     {
58       if (_hurd_init_dtable[i] == MACH_PORT_NULL)
59         /* An unused descriptor is marked by a null pointer.  */
60         _hurd_dtable[i] = NULL;
61       else
62         {
63           /* Allocate a new file descriptor structure.  */
64           struct hurd_fd *new = malloc (sizeof (struct hurd_fd));
65           if (new == NULL)
66             __libc_fatal ("hurd: Can't allocate initial file descriptors\n");
67
68           /* Initialize the port cells.  */
69           _hurd_port_init (&new->port, MACH_PORT_NULL);
70           _hurd_port_init (&new->ctty, MACH_PORT_NULL);
71
72           /* Install the port in the descriptor.
73              This sets up all the ctty magic.  */
74           _hurd_port2fd (new, _hurd_init_dtable[i], 0);
75
76           _hurd_dtable[i] = new;
77         }
78     }
79
80   /* Clear out the initial descriptor table.
81      Everything must use _hurd_dtable now.  */
82   __vm_deallocate (__mach_task_self (),
83                    (vm_address_t) _hurd_init_dtable,
84                    _hurd_init_dtablesize * sizeof (_hurd_init_dtable[0]));
85   _hurd_init_dtable = NULL;
86   _hurd_init_dtablesize = 0;
87
88   /* Initialize the remaining empty slots in the table.  */
89   for (; i < _hurd_dtablesize; ++i)
90     _hurd_dtable[i] = NULL;
91
92   /* Run things that want to run after the file descriptor table
93      is initialized.  */
94   RUN_HOOK (_hurd_fd_subinit, ());
95
96   (void) &init_dtable;          /* Avoid "defined but not used" warning.  */
97 }
98
99 text_set_element (_hurd_subinit, init_dtable);
100
101 /* XXX when the linker supports it, the following functions should all be
102    elsewhere and just have text_set_elements here.  */
103 \f
104 /* Called by `getdport' to do its work.  */
105
106 static file_t
107 get_dtable_port (int fd)
108 {
109   struct hurd_fd *d = _hurd_fd_get (fd);
110   file_t dport;
111
112   if (!d)
113     return __hurd_fail (EBADF), MACH_PORT_NULL;
114
115   HURD_CRITICAL_BEGIN;
116
117   dport = HURD_PORT_USE (&d->port,
118                          ({
119                            error_t err;
120                            mach_port_t outport;
121                            err = __mach_port_mod_refs (__mach_task_self (),
122                                                        port,
123                                                        MACH_PORT_RIGHT_SEND,
124                                                        1);
125                            if (err)
126                              {
127                                errno = err;
128                                outport = MACH_PORT_NULL;
129                              }
130                            else
131                              outport = port;
132                            outport;
133                          }));
134
135   HURD_CRITICAL_END;
136
137   return dport;
138 }
139
140 file_t (*_hurd_getdport_fn) (int fd) = get_dtable_port;
141 \f
142 #include <hurd/signal.h>
143
144 /* We are in the child fork; the dtable lock is still held.
145    The parent has inserted send rights for all the normal io ports,
146    but we must recover ctty-special ports for ourselves.  */
147 static error_t
148 fork_child_dtable (void)
149 {
150   error_t err;
151   int i;
152
153   err = 0;
154
155   for (i = 0; !err && i < _hurd_dtablesize; ++i)
156     {
157       struct hurd_fd *d = _hurd_dtable[i];
158       if (d == NULL)
159         continue;
160
161       /* No other thread is using the send rights in the child task.  */
162       d->port.users = d->ctty.users = NULL;
163
164       if (d->ctty.port != MACH_PORT_NULL)
165         {
166           /* There was a ctty-special port in the parent.
167              We need to get one for ourselves too.  */
168           __mach_port_deallocate (__mach_task_self (), d->ctty.port);
169           err = __term_open_ctty (d->port.port, _hurd_pid, _hurd_pgrp,
170                                   &d->ctty.port);
171           if (err)
172             d->ctty.port = MACH_PORT_NULL;
173         }
174
175       /* XXX for each fd with a cntlmap, reauth and re-map_cntl.  */
176     }
177   return err;
178
179   (void) &fork_child_dtable;    /* Avoid "defined but not used" warning.  */
180 }
181
182 data_set_element (_hurd_fork_locks, _hurd_dtable_lock); /* XXX ld bug: bss */
183 text_set_element (_hurd_fork_child_hook, fork_child_dtable);
184 \f
185 /* Called when our process group has changed.  */
186
187 static void
188 ctty_new_pgrp (void)
189 {
190   int i;
191
192   HURD_CRITICAL_BEGIN;
193   __mutex_lock (&_hurd_dtable_lock);
194
195   if (__USEPORT (CTTYID, port == MACH_PORT_NULL))
196     {
197       /* We have no controlling terminal.  If we haven't had one recently,
198          but our pgrp is being pointlessly diddled anyway, then we will
199          have nothing to do in the loop below because no fd will have a
200          ctty port at all.
201
202          More likely, a setsid call is responsible both for the change
203          in pgrp and for clearing the cttyid port.  In that case, setsid
204          held the dtable lock while updating the dtable to clear all the
205          ctty ports, and ergo must have finished doing so before we run here.
206          So we can be sure, again, that the loop below has no work to do.  */
207     }
208   else
209     for (i = 0; i < _hurd_dtablesize; ++i)
210       {
211         struct hurd_fd *const d = _hurd_dtable[i];
212         struct hurd_userlink ulink, ctty_ulink;
213         io_t port, ctty;
214
215         if (d == NULL)
216           /* Nothing to do for an unused descriptor cell.  */
217           continue;
218
219         port = _hurd_port_get (&d->port, &ulink);
220         ctty = _hurd_port_get (&d->ctty, &ctty_ulink);
221
222         if (ctty != MACH_PORT_NULL)
223           {
224             /* This fd has a ctty-special port.  We need a new one, to tell
225                the io server of our different process group.  */
226             io_t new;
227             if (__term_open_ctty (port, _hurd_pid, _hurd_pgrp, &new))
228               new = MACH_PORT_NULL;
229             _hurd_port_set (&d->ctty, new);
230           }
231
232         _hurd_port_free (&d->port, &ulink, port);
233         _hurd_port_free (&d->ctty, &ctty_ulink, ctty);
234       }
235
236   __mutex_unlock (&_hurd_dtable_lock);
237   HURD_CRITICAL_END;
238
239   (void) &ctty_new_pgrp;        /* Avoid "defined but not used" warning.  */
240 }
241
242 text_set_element (_hurd_pgrp_changed_hook, ctty_new_pgrp);
243 \f
244 /* Called to reauthenticate the dtable when the auth port changes.  */
245
246 static void
247 reauth_dtable (void)
248 {
249   int i;
250
251   HURD_CRITICAL_BEGIN;
252   __mutex_lock (&_hurd_dtable_lock);
253
254   for (i = 0; i < _hurd_dtablesize; ++i)
255     {
256       struct hurd_fd *const d = _hurd_dtable[i];
257       mach_port_t new, newctty, ref;
258
259       if (d == NULL)
260         /* Nothing to do for an unused descriptor cell.  */
261         continue;
262
263       ref = __mach_reply_port ();
264
265       /* Take the descriptor cell's lock.  */
266       __spin_lock (&d->port.lock);
267
268       /* Reauthenticate the descriptor's port.  */
269       if (d->port.port != MACH_PORT_NULL &&
270           ! __io_reauthenticate (d->port.port,
271                                  ref, MACH_MSG_TYPE_MAKE_SEND) &&
272           ! __USEPORT (AUTH, __auth_user_authenticate
273                        (port,
274                         ref, MACH_MSG_TYPE_MAKE_SEND,
275                         &new)))
276         {
277           /* Replace the port in the descriptor cell
278              with the newly reauthenticated port.  */
279
280           if (d->ctty.port != MACH_PORT_NULL &&
281               ! __io_reauthenticate (d->ctty.port,
282                                      ref, MACH_MSG_TYPE_MAKE_SEND) &&
283               ! __USEPORT (AUTH, __auth_user_authenticate
284                            (port,
285                             ref, MACH_MSG_TYPE_MAKE_SEND,
286                             &newctty)))
287             _hurd_port_set (&d->ctty, newctty);
288
289           _hurd_port_locked_set (&d->port, new);
290         }
291       else
292         /* Lost.  Leave this descriptor cell alone.  */
293         __spin_unlock (&d->port.lock);
294
295       __mach_port_destroy (__mach_task_self (), ref);
296     }
297
298   __mutex_unlock (&_hurd_dtable_lock);
299   HURD_CRITICAL_END;
300
301   (void) &reauth_dtable;        /* Avoid "defined but not used" warning.  */
302 }
303
304 text_set_element (_hurd_reauth_hook, reauth_dtable);