| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501 |
- /* Copyright (C) 1992-2026 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 <hurd.h>
- #include <hurd/msg_server.h>
- #include <hurd/fd.h>
- #include <unistd.h>
- #include <limits.h>
- #include <string.h>
- #include <argz.h>
- #define AUTHCHECK \
- if (auth != mach_task_self () && ! __USEPORT (AUTH, port == auth)) \
- return EPERM
- /* Snarfing and frobbing the init ports. */
- kern_return_t
- _S_msg_get_init_port (mach_port_t msgport, mach_port_t auth, int which,
- mach_port_t *result, mach_msg_type_name_t *result_type)
- {
- error_t err;
- AUTHCHECK;
- *result_type = MACH_MSG_TYPE_MOVE_SEND;
- /* This function adds a new user reference for the *RESULT it gives back.
- Our reply message uses a move-send right that consumes this reference. */
- err = _hurd_ports_get (which, result);
- if (!err && MACH_PORT_VALID (auth))
- __mach_port_deallocate (__mach_task_self (), auth);
- return err;
- }
- kern_return_t
- _S_msg_set_init_port (mach_port_t msgport, mach_port_t auth,
- int which, mach_port_t port)
- {
- error_t err;
- AUTHCHECK;
- err = _hurd_ports_set (which, port);
- if (!err && MACH_PORT_VALID (port))
- __mach_port_deallocate (__mach_task_self (), port);
- if (!err && MACH_PORT_VALID (auth))
- __mach_port_deallocate (__mach_task_self (), auth);
- return err;
- }
- kern_return_t
- _S_msg_get_init_ports (mach_port_t msgport, mach_port_t auth,
- mach_port_t **ports,
- mach_msg_type_name_t *ports_type,
- mach_msg_type_number_t *nports)
- {
- mach_msg_type_number_t i;
- error_t err;
- AUTHCHECK;
- if (err = __vm_allocate (__mach_task_self (), (vm_address_t *) ports,
- _hurd_nports * sizeof (mach_port_t), 1))
- return err;
- *nports = _hurd_nports;
- for (i = 0; i < _hurd_nports; ++i)
- /* This function adds a new user ref for the *RESULT it gives back.
- Our reply message uses move-send rights that consumes this ref. */
- if (err = _hurd_ports_get (i, &(*ports)[i]))
- {
- /* Died part way through. Deallocate the ports already fetched. */
- while (i-- > 0)
- __mach_port_deallocate (__mach_task_self (), (*ports)[i]);
- __vm_deallocate (__mach_task_self (),
- (vm_address_t) *ports,
- *nports * sizeof (mach_port_t));
- return err;
- }
- *ports_type = MACH_MSG_TYPE_MOVE_SEND;
- if (MACH_PORT_VALID (auth))
- __mach_port_deallocate (__mach_task_self (), auth);
- return 0;
- }
- kern_return_t
- _S_msg_set_init_ports (mach_port_t msgport, mach_port_t auth,
- const mach_port_t *ports, mach_msg_type_number_t nports)
- {
- mach_msg_type_number_t i;
- error_t err;
- AUTHCHECK;
- for (i = 0; i < _hurd_nports; ++i)
- {
- if (err = _hurd_ports_set (i, ports[i]))
- return err;
- else
- __mach_port_deallocate (__mach_task_self (), ports[i]);
- }
- if (MACH_PORT_VALID (auth))
- __mach_port_deallocate (__mach_task_self (), auth);
- return 0;
- }
- /* Snarfing and frobbing the init ints. */
- static kern_return_t
- get_int (int which, int *value)
- {
- switch (which)
- {
- case INIT_UMASK:
- *value = _hurd_umask;
- return 0;
- case INIT_SIGPENDING:
- {
- struct hurd_sigstate *ss = _hurd_global_sigstate;
- __spin_lock (&ss->lock);
- *value = ss->pending;
- __spin_unlock (&ss->lock);
- return 0;
- }
- case INIT_SIGIGN:
- {
- struct hurd_sigstate *ss = _hurd_global_sigstate;
- sigset_t ign;
- int sig;
- __spin_lock (&ss->lock);
- __sigemptyset (&ign);
- for (sig = 1; sig < NSIG; ++sig)
- if (ss->actions[sig].sa_handler == SIG_IGN)
- __sigaddset (&ign, sig);
- __spin_unlock (&ss->lock);
- *value = ign;
- return 0;
- }
- default:
- return EINVAL;
- }
- }
- kern_return_t
- _S_msg_get_init_int (mach_port_t msgport, mach_port_t auth,
- int which, int *value)
- {
- error_t err;
- AUTHCHECK;
- err = get_int (which, value);
- if (err)
- return err;
- if (MACH_PORT_VALID (auth))
- __mach_port_deallocate (__mach_task_self (), auth);
- return 0;
- }
- kern_return_t
- _S_msg_get_init_ints (mach_port_t msgport, mach_port_t auth,
- int **values, mach_msg_type_number_t *nvalues)
- {
- error_t err;
- mach_msg_type_number_t i;
- AUTHCHECK;
- if (err = __vm_allocate (__mach_task_self (), (vm_address_t *) values,
- INIT_INT_MAX * sizeof (int), 1))
- return err;
- *nvalues = INIT_INT_MAX;
- for (i = 0; i < INIT_INT_MAX; ++i)
- switch (err = get_int (i, &(*values)[i]))
- {
- case 0: /* Success. */
- break;
- case EINVAL: /* Unknown index. */
- (*values)[i] = 0;
- break;
- default: /* Lossage. */
- __vm_deallocate (__mach_task_self (),
- (vm_address_t) *values, INIT_INT_MAX * sizeof (int));
- return err;
- }
- if (MACH_PORT_VALID (auth))
- __mach_port_deallocate (__mach_task_self (), auth);
- return 0;
- }
- static kern_return_t
- set_int (int which, int value)
- {
- switch (which)
- {
- case INIT_UMASK:
- _hurd_umask = value;
- return 0;
- /* These are pretty odd things to do. But you asked for it. */
- case INIT_SIGPENDING:
- {
- struct hurd_sigstate *ss = _hurd_global_sigstate;
- __spin_lock (&ss->lock);
- ss->pending = value;
- __spin_unlock (&ss->lock);
- return 0;
- }
- case INIT_SIGIGN:
- {
- struct hurd_sigstate *ss = _hurd_global_sigstate;
- int sig;
- const sigset_t ign = value;
- __spin_lock (&ss->lock);
- for (sig = 1; sig < NSIG; ++sig)
- {
- if (__sigismember (&ign, sig))
- ss->actions[sig].sa_handler = SIG_IGN;
- else if (ss->actions[sig].sa_handler == SIG_IGN)
- ss->actions[sig].sa_handler = SIG_DFL;
- }
- __spin_unlock (&ss->lock);
- return 0;
- case INIT_TRACEMASK:
- _hurdsig_traced = value;
- return 0;
- }
- default:
- return EINVAL;
- }
- }
- kern_return_t
- _S_msg_set_init_int (mach_port_t msgport, mach_port_t auth,
- int which, int value)
- {
- error_t err;
- AUTHCHECK;
- err = set_int (which, value);
- if (err)
- return err;
- if (MACH_PORT_VALID (auth))
- __mach_port_deallocate (__mach_task_self (), auth);
- return 0;
- }
- kern_return_t
- _S_msg_set_init_ints (mach_port_t msgport, mach_port_t auth,
- const int *values, mach_msg_type_number_t nvalues)
- {
- error_t err;
- mach_msg_type_number_t i;
- AUTHCHECK;
- for (i = 0; i < INIT_INT_MAX; ++i)
- switch (err = set_int (i, values[i]))
- {
- case 0: /* Success. */
- break;
- case EINVAL: /* Unknown index. */
- break;
- default: /* Lossage. */
- return err;
- }
- if (MACH_PORT_VALID (auth))
- __mach_port_deallocate (__mach_task_self (), auth);
- return 0;
- }
- kern_return_t
- _S_msg_get_fd (mach_port_t msgport, mach_port_t auth, int which,
- mach_port_t *result, mach_msg_type_name_t *result_type)
- {
- AUTHCHECK;
- /* This creates a new user reference for the send right.
- Our reply message will move that reference to the caller. */
- *result = __getdport (which);
- if (*result == MACH_PORT_NULL)
- return errno;
- *result_type = MACH_MSG_TYPE_MOVE_SEND;
- if (MACH_PORT_VALID (auth))
- __mach_port_deallocate (__mach_task_self (), auth);
- return 0;
- }
- kern_return_t
- _S_msg_set_fd (mach_port_t msgport, mach_port_t auth,
- int which, mach_port_t port)
- {
- error_t err;
- AUTHCHECK;
- /* We consume the reference if successful. */
- err = HURD_FD_USE (which,
- ({
- int flags = (descriptor->flags & FD_CLOEXEC)
- ? O_CLOEXEC : 0;
- _hurd_port2fd (descriptor, port, flags);
- 0;
- }));
- if (err)
- return err;
- if (MACH_PORT_VALID (auth))
- __mach_port_deallocate (__mach_task_self (), auth);
- return 0;
- }
- /* Snarfing and frobbing environment variables. */
- kern_return_t
- _S_msg_get_env_variable (mach_port_t msgport,
- const_string_t variable,
- char **data, mach_msg_type_number_t *datalen)
- {
- error_t err;
- mach_msg_type_number_t valuelen;
- const char *value = getenv (variable);
- if (value == NULL)
- return ENOENT;
- valuelen = strlen (value);
- if (valuelen > *datalen)
- {
- if (err = __vm_allocate (__mach_task_self (),
- (vm_address_t *) data, valuelen, 1))
- return err;
- }
- memcpy (*data, value, valuelen);
- *datalen = valuelen;
- return 0;
- }
- kern_return_t
- _S_msg_set_env_variable (mach_port_t msgport, mach_port_t auth,
- const_string_t variable,
- const_string_t value,
- int replace)
- {
- AUTHCHECK;
- if (__setenv (variable, value, replace)) /* XXX name space */
- return errno;
- if (MACH_PORT_VALID (auth))
- __mach_port_deallocate (__mach_task_self (), auth);
- return 0;
- }
- kern_return_t
- _S_msg_get_environment (mach_port_t msgport,
- char **data, mach_msg_type_number_t *datalen)
- {
- /* Pack the environment into an array with nulls separating elements. */
- if (__environ != NULL)
- {
- char *ap, **p;
- size_t envlen = 0;
- for (p = __environ; *p != NULL; ++p)
- envlen += strlen (*p) + 1;
- if (envlen > *datalen)
- {
- if (__vm_allocate (__mach_task_self (),
- (vm_address_t *) data, envlen, 1))
- return ENOMEM;
- }
- ap = *data;
- for (p = __environ; *p != NULL; ++p)
- ap = __memccpy (ap, *p, '\0', ULONG_MAX);
- *datalen = envlen;
- }
- else
- *datalen = 0;
- return 0;
- }
- kern_return_t
- _S_msg_set_environment (mach_port_t msgport, mach_port_t auth,
- const char *data, mach_msg_type_number_t datalen)
- {
- int _hurd_split_args (char *, mach_msg_type_number_t, char **);
- int envc;
- char **envp;
- AUTHCHECK;
- envc = __argz_count (data, datalen);
- envp = malloc ((envc + 1) * sizeof (char *));
- if (envp == NULL)
- return errno;
- __argz_extract (data, datalen, envp);
- __environ = envp; /* XXX cooperate with loadenv et al */
- if (MACH_PORT_VALID (auth))
- __mach_port_deallocate (__mach_task_self (), auth);
- return 0;
- }
- kern_return_t
- _S_msg_get_dtable (mach_port_t process,
- mach_port_t auth,
- portarray_t *dtable,
- mach_msg_type_name_t *dtablePoly,
- mach_msg_type_number_t *dtableCnt)
- {
- mach_port_t *ports;
- mach_msg_type_number_t i;
- error_t err;
- AUTHCHECK;
- HURD_CRITICAL_BEGIN;
- __mutex_lock (&_hurd_dtable_lock);
- if (err = __vm_allocate (__mach_task_self (), (vm_address_t *) &ports,
- _hurd_dtablesize * sizeof(mach_port_t), 1))
- goto out;
- for (i = 0; i < _hurd_dtablesize; i++)
- {
- struct hurd_fd *cell = _hurd_dtable[i];
- if (cell == NULL)
- ports[i] = MACH_PORT_NULL;
- else
- {
- __spin_lock (&cell->port.lock);
- if (cell->port.port == MACH_PORT_NULL)
- ports[i] = MACH_PORT_NULL;
- else
- {
- ports[i] = cell->port.port;
- /* We will move this send right. */
- __mach_port_mod_refs (__mach_task_self (), ports[i],
- MACH_PORT_RIGHT_SEND, +1);
- }
- __spin_unlock (&cell->port.lock);
- }
- }
- *dtable = ports;
- *dtablePoly = MACH_MSG_TYPE_MOVE_SEND;
- *dtableCnt = _hurd_dtablesize;
- out:
- __mutex_unlock (&_hurd_dtable_lock);
- HURD_CRITICAL_END;
- if (!err && MACH_PORT_VALID (auth))
- __mach_port_deallocate (__mach_task_self (), auth);
- return err;
- }
- /* XXX */
- kern_return_t
- _S_msg_set_dtable (mach_port_t process,
- mach_port_t refport,
- const_portarray_t dtable,
- mach_msg_type_number_t dtableCnt)
- { return EOPNOTSUPP; }
|