| From 4cc79c217744743077bf7a0ec5e0a4318f1e6641 Mon Sep 17 00:00:00 2001 |
| From: Nikita Popov <npv1310@gmail.com> |
| Date: Thu, 12 Aug 2021 16:09:50 +0530 |
| Subject: [PATCH] librt: add test (bug 28213) |
| |
| This test implements following logic: |
| 1) Create POSIX message queue. |
| Register a notification with mq_notify (using NULL attributes). |
| Then immediately unregister the notification with mq_notify. |
| Helper thread in a vulnerable version of glibc |
| should cause NULL pointer dereference after these steps. |
| 2) Once again, register the same notification. |
| Try to send a dummy message. |
| Test is considered successfulif the dummy message |
| is successfully received by the callback function. |
| |
| Upstream-Status: Backport [https://sourceware.org/git/?p=glibc.git;a=commit;h=4cc79c217744743077bf7a0ec5e0a4318f1e6641] |
| CVE: CVE-2021-38604 |
| |
| Signed-off-by: Nikita Popov <npv1310@gmail.com> |
| Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org> |
| Signed-off-by: Vinay Kumar <vinay.m.engg@gmail.com> |
| --- |
| rt/Makefile | 1 + |
| rt/tst-bz28213.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++ |
| 2 files changed, 102 insertions(+) |
| create mode 100644 rt/tst-bz28213.c |
| |
| diff --git a/rt/Makefile b/rt/Makefile |
| index 113cea03a5..910e775995 100644 |
| --- a/rt/Makefile |
| +++ b/rt/Makefile |
| @@ -74,6 +74,7 @@ tests := tst-shm tst-timer tst-timer2 \ |
| tst-aio7 tst-aio8 tst-aio9 tst-aio10 \ |
| tst-mqueue1 tst-mqueue2 tst-mqueue3 tst-mqueue4 \ |
| tst-mqueue5 tst-mqueue6 tst-mqueue7 tst-mqueue8 tst-mqueue9 \ |
| + tst-bz28213 \ |
| tst-timer3 tst-timer4 tst-timer5 \ |
| tst-cpuclock2 tst-cputimer1 tst-cputimer2 tst-cputimer3 \ |
| tst-shm-cancel \ |
| diff --git a/rt/tst-bz28213.c b/rt/tst-bz28213.c |
| new file mode 100644 |
| index 0000000000..0c096b5a0a |
| --- /dev/null |
| +++ b/rt/tst-bz28213.c |
| @@ -0,0 +1,101 @@ |
| +/* Bug 28213: test for NULL pointer dereference in mq_notify. |
| + Copyright (C) The GNU Toolchain Authors. |
| + This file is part of the GNU C Library. |
| + |
| + The GNU C Library is free software; you can redistribute it and/or |
| + modify it under the terms of the GNU Lesser General Public |
| + License as published by the Free Software Foundation; either |
| + version 2.1 of the License, or (at your option) any later version. |
| + |
| + The GNU C Library is distributed in the hope that it will be useful, |
| + but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + Lesser General Public License for more details. |
| + |
| + You should have received a copy of the GNU Lesser General Public |
| + License along with the GNU C Library; if not, see |
| + <https://www.gnu.org/licenses/>. */ |
| + |
| +#include <errno.h> |
| +#include <sys/types.h> |
| +#include <sys/stat.h> |
| +#include <fcntl.h> |
| +#include <unistd.h> |
| +#include <mqueue.h> |
| +#include <signal.h> |
| +#include <stdlib.h> |
| +#include <string.h> |
| +#include <support/check.h> |
| + |
| +static mqd_t m = -1; |
| +static const char msg[] = "hello"; |
| + |
| +static void |
| +check_bz28213_cb (union sigval sv) |
| +{ |
| + char buf[sizeof (msg)]; |
| + |
| + (void) sv; |
| + |
| + TEST_VERIFY_EXIT ((size_t) mq_receive (m, buf, sizeof (buf), NULL) |
| + == sizeof (buf)); |
| + TEST_VERIFY_EXIT (memcmp (buf, msg, sizeof (buf)) == 0); |
| + |
| + exit (0); |
| +} |
| + |
| +static void |
| +check_bz28213 (void) |
| +{ |
| + struct sigevent sev; |
| + |
| + memset (&sev, '\0', sizeof (sev)); |
| + sev.sigev_notify = SIGEV_THREAD; |
| + sev.sigev_notify_function = check_bz28213_cb; |
| + |
| + /* Step 1: Register & unregister notifier. |
| + Helper thread should receive NOTIFY_REMOVED notification. |
| + In a vulnerable version of glibc, NULL pointer dereference follows. */ |
| + TEST_VERIFY_EXIT (mq_notify (m, &sev) == 0); |
| + TEST_VERIFY_EXIT (mq_notify (m, NULL) == 0); |
| + |
| + /* Step 2: Once again, register notification. |
| + Try to send one message. |
| + Test is considered successful, if the callback does exit (0). */ |
| + TEST_VERIFY_EXIT (mq_notify (m, &sev) == 0); |
| + TEST_VERIFY_EXIT (mq_send (m, msg, sizeof (msg), 1) == 0); |
| + |
| + /* Wait... */ |
| + pause (); |
| +} |
| + |
| +static int |
| +do_test (void) |
| +{ |
| + static const char m_name[] = "/bz28213_queue"; |
| + struct mq_attr m_attr; |
| + |
| + memset (&m_attr, '\0', sizeof (m_attr)); |
| + m_attr.mq_maxmsg = 1; |
| + m_attr.mq_msgsize = sizeof (msg); |
| + |
| + m = mq_open (m_name, |
| + O_RDWR | O_CREAT | O_EXCL, |
| + 0600, |
| + &m_attr); |
| + |
| + if (m < 0) |
| + { |
| + if (errno == ENOSYS) |
| + FAIL_UNSUPPORTED ("POSIX message queues are not implemented\n"); |
| + FAIL_EXIT1 ("Failed to create POSIX message queue: %m\n"); |
| + } |
| + |
| + TEST_VERIFY_EXIT (mq_unlink (m_name) == 0); |
| + |
| + check_bz28213 (); |
| + |
| + return 0; |
| +} |
| + |
| +#include <support/test-driver.c> |
| -- |
| 2.31.1 |
| |