hurdinit.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. /* Copyright (C) 1992-2026 Free Software Foundation, Inc.
  2. This file is part of the GNU C Library.
  3. The GNU C Library is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU Lesser General Public
  5. License as published by the Free Software Foundation; either
  6. version 2.1 of the License, or (at your option) any later version.
  7. The GNU C Library is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  10. Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser General Public
  12. License along with the GNU C Library; if not, see
  13. <https://www.gnu.org/licenses/>. */
  14. #include <sys/stat.h>
  15. #include <stdlib.h>
  16. #include <stdio.h>
  17. #include <unistd.h>
  18. #include <hurd.h>
  19. #include <hurd/port.h>
  20. #include <ldsodefs.h>
  21. #include "set-hooks.h"
  22. #include "hurdmalloc.h" /* XXX */
  23. int _hurd_exec_flags;
  24. struct hurd_port *_hurd_ports;
  25. unsigned int _hurd_nports;
  26. mode_t _hurd_umask;
  27. sigset_t _hurdsig_traced;
  28. char **__libc_argv;
  29. int __libc_argc;
  30. static int *_hurd_intarray;
  31. static size_t _hurd_intarraysize;
  32. static mach_port_t *_hurd_portarray;
  33. static size_t _hurd_portarraysize;
  34. error_t
  35. _hurd_ports_use (int which, error_t (*operate) (mach_port_t))
  36. {
  37. if (__glibc_unlikely (_hurd_ports == NULL))
  38. /* This means that _hurd_init has not been called yet, which is
  39. normally only the case in the bootstrap filesystem, and there
  40. only in the early phases of booting. */
  41. return EGRATUITOUS;
  42. return HURD_PORT_USE (&_hurd_ports[which], (*operate) (port));
  43. }
  44. DEFINE_HOOK (_hurd_subinit, (void));
  45. /* Hook for things which should be initialized as soon as the proc
  46. server is available. */
  47. DEFINE_HOOK (_hurd_proc_subinit, (void));
  48. __typeof (_hurd_proc_init) _hurd_new_proc_init; /* below */
  49. /* Initialize the library data structures from the
  50. ints and ports passed to us by the exec server.
  51. PORTARRAY and INTARRAY are vm_deallocate'd. */
  52. void
  53. _hurd_init (int flags, char **argv,
  54. mach_port_t *portarray, size_t portarraysize,
  55. int *intarray, size_t intarraysize)
  56. {
  57. size_t i;
  58. _hurd_exec_flags = flags;
  59. _hurd_ports = malloc (portarraysize * sizeof (*_hurd_ports));
  60. if (_hurd_ports == NULL)
  61. __libc_fatal ("Can't allocate _hurd_ports\n");
  62. _hurd_nports = portarraysize;
  63. /* See what ports we were passed. */
  64. for (i = 0; i < portarraysize; ++i)
  65. _hurd_port_init (&_hurd_ports[i], portarray[i]);
  66. /* When the user asks for the bootstrap port,
  67. he will get the one the exec server passed us. */
  68. __task_set_special_port (__mach_task_self (), TASK_BOOTSTRAP_PORT,
  69. portarray[INIT_PORT_BOOTSTRAP]);
  70. if (intarraysize > INIT_UMASK)
  71. _hurd_umask = intarray[INIT_UMASK] & 0777;
  72. else
  73. _hurd_umask = CMASK;
  74. if (intarraysize > INIT_TRACEMASK)
  75. _hurdsig_traced = intarray[INIT_TRACEMASK];
  76. _hurd_intarray = intarray;
  77. _hurd_intarraysize = intarraysize;
  78. _hurd_portarray = portarray;
  79. _hurd_portarraysize = portarraysize;
  80. if (flags & EXEC_SECURE)
  81. {
  82. /* XXX if secure exec, elide environment variables
  83. which the library uses and could be security holes.
  84. CORESERVER, COREFILE
  85. */
  86. }
  87. /* Call other things which want to do some initialization. These are not
  88. on the _hurd_subinit hook because things there assume that things done
  89. here, like _hurd_pid, are already initialized. */
  90. RUN_RELHOOK (_hurd_proc_subinit, ());
  91. /* Call other things which want to do some initialization. These are not
  92. on the __libc_subinit hook because things there like to be able to
  93. assume the availability of the POSIX.1 services we provide. */
  94. RUN_RELHOOK (_hurd_subinit, ());
  95. }
  96. libc_hidden_def (_hurd_init)
  97. void
  98. _hurd_libc_proc_init (char **argv)
  99. {
  100. if (_hurd_portarray)
  101. {
  102. /* We will start the signal thread, so we need to initialize libpthread
  103. * if linked in. */
  104. if (__pthread_initialize_minimal != NULL)
  105. __pthread_initialize_minimal ();
  106. /* Tell the proc server we exist, if it does. */
  107. if (_hurd_portarray[INIT_PORT_PROC] != MACH_PORT_NULL)
  108. _hurd_new_proc_init (argv, _hurd_intarray, _hurd_intarraysize);
  109. /* All done with init ints and ports. */
  110. __vm_deallocate (__mach_task_self (),
  111. (vm_address_t) _hurd_intarray,
  112. _hurd_intarraysize * sizeof (int));
  113. _hurd_intarray = NULL;
  114. _hurd_intarraysize = 0;
  115. __vm_deallocate (__mach_task_self (),
  116. (vm_address_t) _hurd_portarray,
  117. _hurd_portarraysize * sizeof (mach_port_t));
  118. _hurd_portarray = NULL;
  119. _hurd_portarraysize = 0;
  120. }
  121. }
  122. libc_hidden_def (_hurd_libc_proc_init)
  123. #include <hurd/signal.h>
  124. /* The user can do "int _hide_arguments = 1;" to make
  125. sure the arguments are never visible with `ps'. */
  126. int _hide_arguments, _hide_environment;
  127. /* Do startup handshaking with the proc server just installed in _hurd_ports.
  128. Call _hurdsig_init to set up signal processing. */
  129. void
  130. _hurd_new_proc_init (char **argv,
  131. const int *intarray, size_t intarraysize)
  132. {
  133. mach_port_t oldmsg;
  134. struct hurd_userlink ulink;
  135. process_t procserver;
  136. /* Initialize the signal code; Mach exceptions will become signals. */
  137. _hurdsig_init (intarray, intarraysize);
  138. /* The signal thread is now prepared to receive messages.
  139. It is safe to give the port to the proc server. */
  140. procserver = _hurd_port_get (&_hurd_ports[INIT_PORT_PROC], &ulink);
  141. /* Give the proc server our message port. */
  142. __proc_setmsgport (procserver, _hurd_msgport, &oldmsg);
  143. if (oldmsg != MACH_PORT_NULL)
  144. /* Deallocate the old msg port we replaced. */
  145. __mach_port_deallocate (__mach_task_self (), oldmsg);
  146. /* Tell the proc server where our args and environment are. */
  147. __proc_set_arg_locations (procserver,
  148. _hide_arguments ? 0 : (vm_address_t) argv,
  149. _hide_environment ? 0 : (vm_address_t) __environ);
  150. _hurd_port_free (&_hurd_ports[INIT_PORT_PROC], &ulink, procserver);
  151. /* Initialize proc server-assisted fault recovery for the signal thread. */
  152. _hurdsig_fault_init ();
  153. /* XXX This code should probably be removed entirely at some point. This
  154. conditional should make it reasonably usable with old gdb's for a
  155. while. Eventually it probably makes most sense for the exec server to
  156. mask out EXEC_SIGTRAP so the debugged program is closer to not being
  157. able to tell it's being debugged. */
  158. if (!__sigisemptyset (&_hurdsig_traced)
  159. #ifdef EXEC_SIGTRAP
  160. && !(_hurd_exec_flags & EXEC_SIGTRAP)
  161. #endif
  162. )
  163. /* This process is "traced", meaning it should stop on signals or exec.
  164. We are all set up now to handle signals. Stop ourselves, to inform
  165. our parent (presumably a debugger) that the exec has completed. */
  166. __msg_sig_post (_hurd_msgport, SIGTRAP, TRAP_TRACE, __mach_task_self ());
  167. }
  168. #include <shlib-compat.h>
  169. versioned_symbol (libc, _hurd_new_proc_init, _hurd_proc_init, GLIBC_2_1);
  170. /* Called when we get a message telling us to change our proc server port. */
  171. error_t
  172. _hurd_setproc (process_t procserver)
  173. {
  174. error_t err;
  175. mach_port_t oldmsg;
  176. /* Give the proc server our message port. */
  177. if (err = __proc_setmsgport (procserver, _hurd_msgport, &oldmsg))
  178. return err;
  179. if (oldmsg != MACH_PORT_NULL)
  180. /* Deallocate the old msg port we replaced. */
  181. __mach_port_deallocate (__mach_task_self (), oldmsg);
  182. /* Tell the proc server where our args and environment are. */
  183. if (err = __proc_set_arg_locations (procserver,
  184. _hide_arguments ? 0
  185. : (vm_address_t) __libc_argv,
  186. _hide_environment ? 0
  187. : (vm_address_t) __environ))
  188. return err;
  189. /* Those calls worked, so the port looks good. */
  190. _hurd_port_set (&_hurd_ports[INIT_PORT_PROC], procserver);
  191. {
  192. pid_t oldpgrp = _hurd_pgrp;
  193. /* Call these functions again so they can fetch the
  194. new information from the new proc server. */
  195. RUN_RELHOOK (_hurd_proc_subinit, ());
  196. if (_hurd_pgrp != oldpgrp)
  197. {
  198. /* Run things that want notification of a pgrp change. */
  199. DECLARE_HOOK (_hurd_pgrp_changed_hook, (pid_t));
  200. RUN_HOOK (_hurd_pgrp_changed_hook, (_hurd_pgrp));
  201. }
  202. }
  203. return 0;
  204. }