(root)/
glibc-2.38/
hurd/
hurdinit.c
       1  /* Copyright (C) 1992-2023 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 <sys/stat.h>
      19  #include <stdlib.h>
      20  #include <stdio.h>
      21  #include <unistd.h>
      22  #include <hurd.h>
      23  #include <hurd/port.h>
      24  #include <ldsodefs.h>
      25  #include "set-hooks.h"
      26  #include "hurdmalloc.h"		/* XXX */
      27  
      28  
      29  int _hurd_exec_flags;
      30  struct hurd_port *_hurd_ports;
      31  unsigned int _hurd_nports;
      32  mode_t _hurd_umask;
      33  sigset_t _hurdsig_traced;
      34  
      35  char **__libc_argv;
      36  int __libc_argc;
      37  
      38  static int *_hurd_intarray;
      39  static size_t _hurd_intarraysize;
      40  static mach_port_t *_hurd_portarray;
      41  static size_t _hurd_portarraysize;
      42  
      43  error_t
      44  _hurd_ports_use (int which, error_t (*operate) (mach_port_t))
      45  {
      46    if (__glibc_unlikely (_hurd_ports == NULL))
      47      /* This means that _hurd_init has not been called yet, which is
      48         normally only the case in the bootstrap filesystem, and there
      49         only in the early phases of booting.  */
      50      return EGRATUITOUS;
      51  
      52    return HURD_PORT_USE (&_hurd_ports[which], (*operate) (port));
      53  }
      54  
      55  DEFINE_HOOK (_hurd_subinit, (void));
      56  
      57  /* Hook for things which should be initialized as soon as the proc
      58     server is available.  */
      59  DEFINE_HOOK (_hurd_proc_subinit, (void));
      60  
      61  __typeof (_hurd_proc_init) _hurd_new_proc_init;	/* below */
      62  
      63  /* Initialize the library data structures from the
      64     ints and ports passed to us by the exec server.
      65  
      66     PORTARRAY and INTARRAY are vm_deallocate'd.  */
      67  
      68  void
      69  _hurd_init (int flags, char **argv,
      70  	    mach_port_t *portarray, size_t portarraysize,
      71  	    int *intarray, size_t intarraysize)
      72  {
      73    size_t i;
      74  
      75    _hurd_exec_flags = flags;
      76  
      77    _hurd_ports = malloc (portarraysize * sizeof (*_hurd_ports));
      78    if (_hurd_ports == NULL)
      79      __libc_fatal ("Can't allocate _hurd_ports\n");
      80    _hurd_nports = portarraysize;
      81  
      82    /* See what ports we were passed.  */
      83    for (i = 0; i < portarraysize; ++i)
      84      _hurd_port_init (&_hurd_ports[i], portarray[i]);
      85  
      86    /* When the user asks for the bootstrap port,
      87       he will get the one the exec server passed us.  */
      88    __task_set_special_port (__mach_task_self (), TASK_BOOTSTRAP_PORT,
      89  			   portarray[INIT_PORT_BOOTSTRAP]);
      90  
      91    if (intarraysize > INIT_UMASK)
      92      _hurd_umask = intarray[INIT_UMASK] & 0777;
      93    else
      94      _hurd_umask = CMASK;
      95  
      96    if (intarraysize > INIT_TRACEMASK)
      97      _hurdsig_traced = intarray[INIT_TRACEMASK];
      98  
      99    _hurd_intarray = intarray;
     100    _hurd_intarraysize = intarraysize;
     101    _hurd_portarray = portarray;
     102    _hurd_portarraysize = portarraysize;
     103  
     104    if (flags & EXEC_SECURE)
     105      {
     106        /* XXX if secure exec, elide environment variables
     107  	 which the library uses and could be security holes.
     108  	 CORESERVER, COREFILE
     109        */
     110      }
     111  
     112    /* Call other things which want to do some initialization.  These are not
     113       on the _hurd_subinit hook because things there assume that things done
     114       here, like _hurd_pid, are already initialized.  */
     115    RUN_RELHOOK (_hurd_proc_subinit, ());
     116  
     117    /* Call other things which want to do some initialization.  These are not
     118       on the __libc_subinit hook because things there like to be able to
     119       assume the availability of the POSIX.1 services we provide.  */
     120    RUN_RELHOOK (_hurd_subinit, ());
     121  }
     122  libc_hidden_def (_hurd_init)
     123  
     124  void
     125  _hurd_libc_proc_init (char **argv)
     126  {
     127    if (_hurd_portarray)
     128      {
     129        /* We will start the signal thread, so we need to initialize libpthread
     130         * if linked in.  */
     131        if (__pthread_initialize_minimal != NULL)
     132  	__pthread_initialize_minimal ();
     133  
     134        /* Tell the proc server we exist, if it does.  */
     135        if (_hurd_portarray[INIT_PORT_PROC] != MACH_PORT_NULL)
     136  	_hurd_new_proc_init (argv, _hurd_intarray, _hurd_intarraysize);
     137  
     138        /* All done with init ints and ports.  */
     139        __vm_deallocate (__mach_task_self (),
     140  		       (vm_address_t) _hurd_intarray,
     141  		       _hurd_intarraysize * sizeof (int));
     142        _hurd_intarray = NULL;
     143        _hurd_intarraysize = 0;
     144  
     145        __vm_deallocate (__mach_task_self (),
     146  		       (vm_address_t) _hurd_portarray,
     147  		       _hurd_portarraysize * sizeof (mach_port_t));
     148        _hurd_portarray = NULL;
     149        _hurd_portarraysize = 0;
     150      }
     151  }
     152  libc_hidden_def (_hurd_libc_proc_init)
     153  
     154  #include <hurd/signal.h>
     155  
     156  /* The user can do "int _hide_arguments = 1;" to make
     157     sure the arguments are never visible with `ps'.  */
     158  int _hide_arguments, _hide_environment;
     159  
     160  /* Do startup handshaking with the proc server just installed in _hurd_ports.
     161     Call _hurdsig_init to set up signal processing.  */
     162  
     163  void
     164  _hurd_new_proc_init (char **argv,
     165  		     const int *intarray, size_t intarraysize)
     166  {
     167    mach_port_t oldmsg;
     168    struct hurd_userlink ulink;
     169    process_t procserver;
     170  
     171    /* Initialize the signal code; Mach exceptions will become signals.  */
     172    _hurdsig_init (intarray, intarraysize);
     173  
     174    /* The signal thread is now prepared to receive messages.
     175       It is safe to give the port to the proc server.  */
     176  
     177    procserver = _hurd_port_get (&_hurd_ports[INIT_PORT_PROC], &ulink);
     178  
     179    /* Give the proc server our message port.  */
     180    __proc_setmsgport (procserver, _hurd_msgport, &oldmsg);
     181    if (oldmsg != MACH_PORT_NULL)
     182      /* Deallocate the old msg port we replaced.  */
     183      __mach_port_deallocate (__mach_task_self (), oldmsg);
     184  
     185    /* Tell the proc server where our args and environment are.  */
     186    __proc_set_arg_locations (procserver,
     187  			    _hide_arguments ? 0 : (vm_address_t) argv,
     188  			    _hide_environment ? 0 : (vm_address_t) __environ);
     189  
     190    _hurd_port_free (&_hurd_ports[INIT_PORT_PROC], &ulink, procserver);
     191  
     192    /* Initialize proc server-assisted fault recovery for the signal thread.  */
     193    _hurdsig_fault_init ();
     194  
     195    /* XXX This code should probably be removed entirely at some point.  This
     196       conditional should make it reasonably usable with old gdb's for a
     197       while.  Eventually it probably makes most sense for the exec server to
     198       mask out EXEC_SIGTRAP so the debugged program is closer to not being
     199       able to tell it's being debugged.  */
     200    if (!__sigisemptyset (&_hurdsig_traced)
     201  #ifdef EXEC_SIGTRAP
     202        && !(_hurd_exec_flags & EXEC_SIGTRAP)
     203  #endif
     204        )
     205      /* This process is "traced", meaning it should stop on signals or exec.
     206         We are all set up now to handle signals.  Stop ourselves, to inform
     207         our parent (presumably a debugger) that the exec has completed.  */
     208      __msg_sig_post (_hurd_msgport, SIGTRAP, TRAP_TRACE, __mach_task_self ());
     209  }
     210  
     211  #include <shlib-compat.h>
     212  versioned_symbol (libc, _hurd_new_proc_init, _hurd_proc_init, GLIBC_2_1);
     213  
     214  /* Called when we get a message telling us to change our proc server port.  */
     215  
     216  error_t
     217  _hurd_setproc (process_t procserver)
     218  {
     219    error_t err;
     220    mach_port_t oldmsg;
     221  
     222    /* Give the proc server our message port.  */
     223    if (err = __proc_setmsgport (procserver, _hurd_msgport, &oldmsg))
     224      return err;
     225    if (oldmsg != MACH_PORT_NULL)
     226      /* Deallocate the old msg port we replaced.  */
     227      __mach_port_deallocate (__mach_task_self (), oldmsg);
     228  
     229    /* Tell the proc server where our args and environment are.  */
     230    if (err = __proc_set_arg_locations (procserver,
     231  				      _hide_arguments ? 0
     232  				      : (vm_address_t) __libc_argv,
     233  				      _hide_environment ? 0
     234  				      : (vm_address_t) __environ))
     235      return err;
     236  
     237    /* Those calls worked, so the port looks good.  */
     238    _hurd_port_set (&_hurd_ports[INIT_PORT_PROC], procserver);
     239  
     240    {
     241      pid_t oldpgrp = _hurd_pgrp;
     242  
     243      /* Call these functions again so they can fetch the
     244         new information from the new proc server.  */
     245      RUN_RELHOOK (_hurd_proc_subinit, ());
     246  
     247      if (_hurd_pgrp != oldpgrp)
     248        {
     249  	/* Run things that want notification of a pgrp change.  */
     250  	DECLARE_HOOK (_hurd_pgrp_changed_hook, (pid_t));
     251  	RUN_HOOK (_hurd_pgrp_changed_hook, (_hurd_pgrp));
     252        }
     253    }
     254  
     255    return 0;
     256  }