From 4e506f67cbe6cd935377da65909f0606014459aa Mon Sep 17 00:00:00 2001 From: Sergey Bugaev Date: Sat, 29 Apr 2023 23:18:19 +0300 Subject: hurd: Replace reply port with a dead name on failed interruption If we're trying to interrupt an interruptible RPC, but the server fails to respond to our __interrupt_operation () call, we instead destroy the reply port we were expecting the reply to the RPC on. Instead of deallocating the name completely, replace it with a dead name, so the name won't get reused for some other right, and deallocate it in _hurd_intr_rpc_mach_msg once we return from the signal handler. Signed-off-by: Sergey Bugaev Message-Id: <20230429201822.2605207-4-bugaevc@gmail.com> --- sysdeps/mach/hurd/mig-reply.c | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) (limited to 'sysdeps/mach') diff --git a/sysdeps/mach/hurd/mig-reply.c b/sysdeps/mach/hurd/mig-reply.c index 3fdee80e5a..7ea001df0a 100644 --- a/sysdeps/mach/hurd/mig-reply.c +++ b/sysdeps/mach/hurd/mig-reply.c @@ -69,29 +69,18 @@ __mig_dealloc_reply_port (mach_port_t arg) 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. - */ - + assert (port == arg); if (!MACH_PORT_VALID (port)) return; - assert (port == arg); err = __mach_port_mod_refs (__mach_task_self (), port, MACH_PORT_RIGHT_RECEIVE, -1); + if (err == KERN_INVALID_RIGHT) + /* It could be that during signal handling, the receive right had been + replaced with a dead name. */ + err = __mach_port_mod_refs (__mach_task_self (), port, + MACH_PORT_RIGHT_DEAD_NAME, -1); + assert_perror (err); } weak_alias (__mig_dealloc_reply_port, mig_dealloc_reply_port) -- cgit 1.4.1