diff options
author | Sergey Bugaev <bugaevc@gmail.com> | 2023-03-19 18:10:08 +0300 |
---|---|---|
committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2023-04-10 23:54:28 +0200 |
commit | 747812349d42427c835aeac987aa67641d84f1ad (patch) | |
tree | e9391fe71f0f029218155bb38bac64838b8df7fb /hurd | |
parent | b37899d34d2190ef4b454283188f22519f096048 (diff) | |
download | glibc-747812349d42427c835aeac987aa67641d84f1ad.tar.gz glibc-747812349d42427c835aeac987aa67641d84f1ad.tar.xz glibc-747812349d42427c835aeac987aa67641d84f1ad.zip |
hurd: Improve reply port handling when exiting signal handlers
If we're doing signals, that means we've already got the signal thread running, and that implies TLS having been set up. So we know that __hurd_local_reply_port will resolve to THREAD_SELF->reply_port, and can access that directly using the THREAD_GETMEM and THREAD_SETMEM macros. This avoids potential miscompilations, and should also be a tiny bit faster. Also, use mach_port_mod_refs () and not mach_port_destroy () to destroy the receive right. mach_port_destroy () should *never* be used on mach_task_self (); this can easily lead to port use-after-free vulnerabilities if the task has any other references to the same port. Signed-off-by: Sergey Bugaev <bugaevc@gmail.com> Message-Id: <20230319151017.531737-26-bugaevc@gmail.com>
Diffstat (limited to 'hurd')
-rw-r--r-- | hurd/sigunwind.c | 24 |
1 files changed, 11 insertions, 13 deletions
diff --git a/hurd/sigunwind.c b/hurd/sigunwind.c index edd40b140e..399e69008e 100644 --- a/hurd/sigunwind.c +++ b/hurd/sigunwind.c @@ -18,7 +18,6 @@ #include <hurd.h> #include <thread_state.h> -#include <hurd/threadvar.h> #include <jmpbuf-unwind.h> #include <assert.h> #include <stdint.h> @@ -39,19 +38,18 @@ _hurdsig_longjmp_from_handler (void *data, jmp_buf env, int val) { /* Destroy the MiG reply port used by the signal handler, and restore the reply port in use by the thread when interrupted. */ - mach_port_t *reply_port = &__hurd_local_reply_port; - if (*reply_port) - { - mach_port_t port = *reply_port; - /* Assigning MACH_PORT_DEAD here tells libc's mig_get_reply_port - not to get another reply port, but avoids mig_dealloc_reply_port - trying to deallocate it after the receive fails (which it will, - because the reply port will be bogus, regardless). */ - *reply_port = MACH_PORT_DEAD; - __mach_port_destroy (__mach_task_self (), port); - } + mach_port_t reply_port = THREAD_GETMEM (THREAD_SELF, reply_port); + /* Assigning MACH_PORT_DEAD here tells libc's mig_get_reply_port not to + get another reply port, but avoids mig_dealloc_reply_port trying to + deallocate it after the receive fails (which it will, because the + reply port will be bogus, regardless). */ + THREAD_SETMEM (THREAD_SELF, reply_port, MACH_PORT_DEAD); + if (MACH_PORT_VALID (reply_port)) + __mach_port_mod_refs (__mach_task_self (), reply_port, + MACH_PORT_RIGHT_RECEIVE, -1); if (scp->sc_reply_port) - __mach_port_destroy (__mach_task_self (), scp->sc_reply_port); + __mach_port_mod_refs (__mach_task_self (), scp->sc_reply_port, + MACH_PORT_RIGHT_RECEIVE, -1); } __spin_lock (&ss->lock); |