>From 70dea58630dedb26b2fbf03422ad7a36f8e95c92 Mon Sep 17 00:00:00 2001
From: Rich Felker <dalias@aerifal.cx>
Date: Fri, 10 Feb 2023 11:22:45 -0500
Subject: [PATCH 2/3] mq_notify: fix use-after-close/double-close bug in error
 path

in the error path where the mq_notify syscall fails, the initiating
thread may close the socket before the worker thread calls recv on it.
even if this does not happen, both threads perform the close
operation, resulting in double-close.

move the close to a cancellation cleanup handler so this cannot
happen. this fix is based on one of the alternate proposals in Alexey
Izbyshev's original report of the bug.
---
 src/mq/mq_notify.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/src/mq/mq_notify.c b/src/mq/mq_notify.c
index 7d3dff5f..a42e6afc 100644
--- a/src/mq/mq_notify.c
+++ b/src/mq/mq_notify.c
@@ -13,6 +13,11 @@ struct args {
 	const struct sigevent *sev;
 };
 
+static void cleanup(void *p)
+{
+	__syscall(SYS_close, *(int *)p);
+}
+
 static void *start(void *p)
 {
 	struct args *args = p;
@@ -23,8 +28,9 @@ static void *start(void *p)
 	union sigval val = args->sev->sigev_value;
 
 	sem_post(&args->sem);
+	pthread_cleanup_push(cleanup, &s);
 	n = recv(s, buf, sizeof(buf), MSG_NOSIGNAL|MSG_WAITALL);
-	close(s);
+	pthread_cleanup_pop(1);
 	if (n==sizeof buf && buf[sizeof buf - 1] == 1)
 		func(val);
 	return 0;
@@ -66,7 +72,6 @@ int mq_notify(mqd_t mqd, const struct sigevent *sev)
 
 	if (syscall(SYS_mq_notify, mqd, &sev2) < 0) {
 		pthread_cancel(td);
-		__syscall(SYS_close, s);
 		return -1;
 	}
 
-- 
2.21.0