about summary refs log tree commit diff
path: root/hurd/hurdinit.c
blob: daa47911c381e2d9fe2bcc0b1e11a8c1f117f20a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
/* Copyright (C) 1992-2020 Free Software Foundation, Inc.
   This file is part of the GNU C Library.

   The GNU C Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   The GNU C Library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with the GNU C Library; if not, see
   <https://www.gnu.org/licenses/>.  */

#include <sys/stat.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <hurd.h>
#include <hurd/port.h>
#include <ldsodefs.h>
#include "set-hooks.h"
#include "hurdmalloc.h"		/* XXX */


int _hurd_exec_flags;
struct hurd_port *_hurd_ports;
unsigned int _hurd_nports;
mode_t _hurd_umask;
sigset_t _hurdsig_traced;

char **__libc_argv;
int __libc_argc;

static int *_hurd_intarray;
static size_t _hurd_intarraysize;
static mach_port_t *_hurd_portarray;
static size_t _hurd_portarraysize;

error_t
_hurd_ports_use (int which, error_t (*operate) (mach_port_t))
{
  if (__glibc_unlikely (_hurd_ports == NULL))
    /* This means that _hurd_init has not been called yet, which is
       normally only the case in the bootstrap filesystem, and there
       only in the early phases of booting.  */
    return EGRATUITOUS;

  return HURD_PORT_USE (&_hurd_ports[which], (*operate) (port));
}

DEFINE_HOOK (_hurd_subinit, (void));

__typeof (_hurd_proc_init) _hurd_new_proc_init;	/* below */

/* Initialize the library data structures from the
   ints and ports passed to us by the exec server.

   PORTARRAY and INTARRAY are vm_deallocate'd.  */

void
_hurd_init (int flags, char **argv,
	    mach_port_t *portarray, size_t portarraysize,
	    int *intarray, size_t intarraysize)
{
  size_t i;

  _hurd_exec_flags = flags;

  _hurd_ports = malloc (portarraysize * sizeof (*_hurd_ports));
  if (_hurd_ports == NULL)
    __libc_fatal ("Can't allocate _hurd_ports\n");
  _hurd_nports = portarraysize;

  /* See what ports we were passed.  */
  for (i = 0; i < portarraysize; ++i)
    _hurd_port_init (&_hurd_ports[i], portarray[i]);

  /* When the user asks for the bootstrap port,
     he will get the one the exec server passed us.  */
  __task_set_special_port (__mach_task_self (), TASK_BOOTSTRAP_PORT,
			   portarray[INIT_PORT_BOOTSTRAP]);

  if (intarraysize > INIT_UMASK)
    _hurd_umask = intarray[INIT_UMASK] & 0777;
  else
    _hurd_umask = CMASK;

  if (intarraysize > INIT_TRACEMASK)
    _hurdsig_traced = intarray[INIT_TRACEMASK];

  _hurd_intarray = intarray;
  _hurd_intarraysize = intarraysize;
  _hurd_portarray = portarray;
  _hurd_portarraysize = portarraysize;

  if (flags & EXEC_SECURE)
    {
      /* XXX if secure exec, elide environment variables
	 which the library uses and could be security holes.
	 CORESERVER, COREFILE
      */
    }

  /* Call other things which want to do some initialization.  These are not
     on the __libc_subinit hook because things there like to be able to
     assume the availability of the POSIX.1 services we provide.  */
  RUN_HOOK (_hurd_subinit, ());
}
libc_hidden_def (_hurd_init)

void
_hurd_libc_proc_init (char **argv)
{
  if (_hurd_portarray)
    {
      /* We will start the signal thread, so we need to initialize libpthread
       * if linked in.  */
      if (__pthread_initialize_minimal != NULL)
	__pthread_initialize_minimal ();

      /* Tell the proc server we exist, if it does.  */
      if (_hurd_portarray[INIT_PORT_PROC] != MACH_PORT_NULL)
	_hurd_new_proc_init (argv, _hurd_intarray, _hurd_intarraysize);

      /* All done with init ints and ports.  */
      __vm_deallocate (__mach_task_self (),
		       (vm_address_t) _hurd_intarray,
		       _hurd_intarraysize * sizeof (int));
      _hurd_intarray = NULL;
      _hurd_intarraysize = 0;

      __vm_deallocate (__mach_task_self (),
		       (vm_address_t) _hurd_portarray,
		       _hurd_portarraysize * sizeof (mach_port_t));
      _hurd_portarray = NULL;
      _hurd_portarraysize = 0;
    }
}
libc_hidden_def (_hurd_libc_proc_init)

#include <hurd/signal.h>

/* The user can do "int _hide_arguments = 1;" to make
   sure the arguments are never visible with `ps'.  */
int _hide_arguments, _hide_environment;

/* Hook for things which should be initialized as soon as the proc
   server is available.  */
DEFINE_HOOK (_hurd_proc_subinit, (void));

/* Do startup handshaking with the proc server just installed in _hurd_ports.
   Call _hurdsig_init to set up signal processing.  */

void
_hurd_new_proc_init (char **argv,
		     const int *intarray, size_t intarraysize)
{
  mach_port_t oldmsg;
  struct hurd_userlink ulink;
  process_t procserver;

  /* Initialize the signal code; Mach exceptions will become signals.  */
  _hurdsig_init (intarray, intarraysize);

  /* The signal thread is now prepared to receive messages.
     It is safe to give the port to the proc server.  */

  procserver = _hurd_port_get (&_hurd_ports[INIT_PORT_PROC], &ulink);

  /* Give the proc server our message port.  */
  __proc_setmsgport (procserver, _hurd_msgport, &oldmsg);
  if (oldmsg != MACH_PORT_NULL)
    /* Deallocate the old msg port we replaced.  */
    __mach_port_deallocate (__mach_task_self (), oldmsg);

  /* Tell the proc server where our args and environment are.  */
  __proc_set_arg_locations (procserver,
			    _hide_arguments ? 0 : (vm_address_t) argv,
			    _hide_environment ? 0 : (vm_address_t) __environ);

  _hurd_port_free (&_hurd_ports[INIT_PORT_PROC], &ulink, procserver);

  /* Initialize proc server-assisted fault recovery for the signal thread.  */
  _hurdsig_fault_init ();

  /* Call other things which want to do some initialization.  These are not
     on the _hurd_subinit hook because things there assume that things done
     here, like _hurd_pid, are already initialized.  */
  RUN_HOOK (_hurd_proc_subinit, ());

  /* XXX This code should probably be removed entirely at some point.  This
     conditional should make it reasonably usable with old gdb's for a
     while.  Eventually it probably makes most sense for the exec server to
     mask out EXEC_SIGTRAP so the debugged program is closer to not being
     able to tell it's being debugged.  */
  if (!__sigisemptyset (&_hurdsig_traced)
#ifdef EXEC_SIGTRAP
      && !(_hurd_exec_flags & EXEC_SIGTRAP)
#endif
      )
    /* This process is "traced", meaning it should stop on signals or exec.
       We are all set up now to handle signals.  Stop ourselves, to inform
       our parent (presumably a debugger) that the exec has completed.  */
    __msg_sig_post (_hurd_msgport, SIGTRAP, TRAP_TRACE, __mach_task_self ());
}

#include <shlib-compat.h>
versioned_symbol (libc, _hurd_new_proc_init, _hurd_proc_init, GLIBC_2_1);

/* Called when we get a message telling us to change our proc server port.  */

error_t
_hurd_setproc (process_t procserver)
{
  error_t err;
  mach_port_t oldmsg;

  /* Give the proc server our message port.  */
  if (err = __proc_setmsgport (procserver, _hurd_msgport, &oldmsg))
    return err;
  if (oldmsg != MACH_PORT_NULL)
    /* Deallocate the old msg port we replaced.  */
    __mach_port_deallocate (__mach_task_self (), oldmsg);

  /* Tell the proc server where our args and environment are.  */
  if (err = __proc_set_arg_locations (procserver,
				      _hide_arguments ? 0
				      : (vm_address_t) __libc_argv,
				      _hide_environment ? 0
				      : (vm_address_t) __environ))
    return err;

  /* Those calls worked, so the port looks good.  */
  _hurd_port_set (&_hurd_ports[INIT_PORT_PROC], procserver);

  {
    pid_t oldpgrp = _hurd_pgrp;

    /* Call these functions again so they can fetch the
       new information from the new proc server.  */
    RUN_HOOK (_hurd_proc_subinit, ());

    if (_hurd_pgrp != oldpgrp)
      {
	/* Run things that want notification of a pgrp change.  */
	DECLARE_HOOK (_hurd_pgrp_changed_hook, (pid_t));
	RUN_HOOK (_hurd_pgrp_changed_hook, (_hurd_pgrp));
      }
  }

  return 0;
}