diff options
author | Sergey Bugaev <bugaevc@gmail.com> | 2023-04-13 14:58:12 +0300 |
---|---|---|
committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2023-04-14 10:31:22 +0000 |
commit | ba00d787f3469b02032766b074d4df9071fa7e24 (patch) | |
tree | 2686e3886f3ade9e279c7e3cdc66192b79d4576e /sysdeps/mach/hurd/mig-reply.c | |
parent | 05fe3ecffff485032e904f0a3ea709e24d9188eb (diff) | |
download | glibc-ba00d787f3469b02032766b074d4df9071fa7e24.tar glibc-ba00d787f3469b02032766b074d4df9071fa7e24.tar.gz glibc-ba00d787f3469b02032766b074d4df9071fa7e24.tar.bz2 glibc-ba00d787f3469b02032766b074d4df9071fa7e24.zip |
hurd: Remove __hurd_local_reply_port
Now that the signal code no longer accesses it, the only real user of it
was mig-reply.c, so move the logic for managing the port there.
If we're in SHARED and outside of rtld, we know that __LIBC_NO_TLS ()
always evaluates to 0, and a TLS reply port will always be used, not
__hurd_reply_port0. Still, the compiler does not see that
__hurd_reply_port0 is never used due to its address being taken. To deal
with this, explicitly compile out __hurd_reply_port0 when we know we
won't use it.
Also, instead of accessing the port via THREAD_SELF->reply_port, this
uses THREAD_GETMEM and THREAD_SETMEM directly, avoiding possible
miscompilations.
Signed-off-by: Sergey Bugaev <bugaevc@gmail.com>
Diffstat (limited to 'sysdeps/mach/hurd/mig-reply.c')
-rw-r--r-- | sysdeps/mach/hurd/mig-reply.c | 70 |
1 files changed, 58 insertions, 12 deletions
diff --git a/sysdeps/mach/hurd/mig-reply.c b/sysdeps/mach/hurd/mig-reply.c index 33ff260e36..3fdee80e5a 100644 --- a/sysdeps/mach/hurd/mig-reply.c +++ b/sysdeps/mach/hurd/mig-reply.c @@ -17,22 +17,46 @@ #include <mach.h> #include <mach/mig_support.h> -#include <hurd/threadvar.h> +#include <tls.h> /* These functions are called by MiG-generated code. */ +#if !defined (SHARED) || IS_IN (rtld) mach_port_t __hurd_reply_port0; +#endif + +static mach_port_t +get_reply_port (void) +{ +#if !defined (SHARED) || IS_IN (rtld) + if (__LIBC_NO_TLS ()) + return __hurd_reply_port0; +#endif + return THREAD_GETMEM (THREAD_SELF, reply_port); +} + +static void +set_reply_port (mach_port_t port) +{ +#if !defined (SHARED) || IS_IN (rtld) + if (__LIBC_NO_TLS ()) + __hurd_reply_port0 = port; + else +#endif + THREAD_SETMEM (THREAD_SELF, reply_port, port); +} /* Called by MiG to get a reply port. */ mach_port_t __mig_get_reply_port (void) { - if (__hurd_local_reply_port == MACH_PORT_NULL - || (&__hurd_local_reply_port != &__hurd_reply_port0 - && __hurd_local_reply_port == __hurd_reply_port0)) - __hurd_local_reply_port = __mach_reply_port (); - - return __hurd_local_reply_port; + mach_port_t port = get_reply_port (); + if (__glibc_unlikely (port == MACH_PORT_NULL)) + { + port = __mach_reply_port (); + set_reply_port (port); + } + return port; } weak_alias (__mig_get_reply_port, mig_get_reply_port) libc_hidden_def (__mig_get_reply_port) @@ -41,12 +65,34 @@ libc_hidden_def (__mig_get_reply_port) void __mig_dealloc_reply_port (mach_port_t arg) { - mach_port_t port = __hurd_local_reply_port; - __hurd_local_reply_port = MACH_PORT_NULL; /* So the mod_refs RPC won't use it. */ + error_t err; + mach_port_t port = get_reply_port (); + + set_reply_port (MACH_PORT_NULL); /* So the mod_refs RPC won't use it. */ + + /* Normally, ARG should be the same as PORT that we store. However, if a + signal has interrupted the RPC, the stored PORT has been deallocated and + reset to MACH_PORT_NULL (or possibly MACH_PORT_DEAD). In this case the + MIG routine still has the old name, which it passes to us here. We must + not deallocate (or otherwise touch) it, since it may be already allocated + to another port right. Fortunately MIG itself doesn't do anything with + the reply port on errors either, other than immediately calling this + function. + + And so: + 1. Assert that things are sane, i.e. and PORT is either invalid or same + as ARG. + 2. Only deallocate the name if our stored PORT still names it. In that + case we're sure the right has not been deallocated / the name reused. + */ + + if (!MACH_PORT_VALID (port)) + return; + assert (port == arg); - if (MACH_PORT_VALID (port)) - __mach_port_mod_refs (__mach_task_self (), port, - MACH_PORT_RIGHT_RECEIVE, -1); + err = __mach_port_mod_refs (__mach_task_self (), port, + MACH_PORT_RIGHT_RECEIVE, -1); + assert_perror (err); } weak_alias (__mig_dealloc_reply_port, mig_dealloc_reply_port) libc_hidden_def (__mig_dealloc_reply_port) |