bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [RFC PATCH glibc v2 26/34] hurd: Remove __hurd_local_reply_port


From: Samuel Thibault
Subject: Re: [RFC PATCH glibc v2 26/34] hurd: Remove __hurd_local_reply_port
Date: Fri, 14 Apr 2023 19:33:32 +0200
User-agent: NeoMutt/20170609 (1.8.3)

Applied with fixing the __mig_dealloc_reply_port(NULL) cases, thanks!

Sergey Bugaev, le jeu. 13 avril 2023 14:58:12 +0300, a ecrit:
> 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>
> ---
> Changes since v1:
> * Only deallocate the port in __mig_dealloc_reply_port if it's the same
>   as the stored port, because of signals.
> * Add a comment detailing the reasoning.
> * Add two assertions: that ARG and PORT are exactly the same (unless PORT
>    has been invalidated), and that we succeed deallocating PORT.
> 
> NOTE: Completely untested! Do your own testing! You have been warned!
> 
>  hurd/hurd/threadvar.h         |  7 ----
>  sysdeps/mach/hurd/mig-reply.c | 70 +++++++++++++++++++++++++++++------
>  2 files changed, 58 insertions(+), 19 deletions(-)
> 
> diff --git a/hurd/hurd/threadvar.h b/hurd/hurd/threadvar.h
> index f5c6a278..c476d988 100644
> --- a/hurd/hurd/threadvar.h
> +++ b/hurd/hurd/threadvar.h
> @@ -29,11 +29,4 @@
>  extern unsigned long int __hurd_sigthread_stack_base;
>  extern unsigned long int __hurd_sigthread_stack_end;
>  
> -/* Store the MiG reply port reply port until we enable TLS.  */
> -extern mach_port_t __hurd_reply_port0;
> -
> -/* This returns either the TLS reply port variable, or a single-thread 
> variable
> -   when TLS is not initialized yet.  */
> -#define __hurd_local_reply_port (*(__LIBC_NO_TLS () ? &__hurd_reply_port0 : 
> &THREAD_SELF->reply_port))
> -
>  #endif       /* hurd/threadvar.h */
> diff --git a/sysdeps/mach/hurd/mig-reply.c b/sysdeps/mach/hurd/mig-reply.c
> index 33ff260e..3fdee80e 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)
> -- 
> 2.39.2
> 

-- 
Samuel
---
Pour une évaluation indépendante, transparente et rigoureuse !
Je soutiens la Commission d'Évaluation de l'Inria.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]