1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (c) The GNU Toolchain Authors. 4f08c3bdfSopenharmony_ci * Copyright (c) 2023 Wei Gao <wegao@suse.com> 5f08c3bdfSopenharmony_ci * 6f08c3bdfSopenharmony_ci */ 7f08c3bdfSopenharmony_ci 8f08c3bdfSopenharmony_ci/*\ 9f08c3bdfSopenharmony_ci * [Description] 10f08c3bdfSopenharmony_ci * 11f08c3bdfSopenharmony_ci * Test for NULL pointer dereference in mq_notify(CVE-2021-38604) 12f08c3bdfSopenharmony_ci * 13f08c3bdfSopenharmony_ci * References links: 14f08c3bdfSopenharmony_ci * - https://sourceware.org/bugzilla/show_bug.cgi?id=28213 15f08c3bdfSopenharmony_ci */ 16f08c3bdfSopenharmony_ci 17f08c3bdfSopenharmony_ci#include <errno.h> 18f08c3bdfSopenharmony_ci#include <sys/types.h> 19f08c3bdfSopenharmony_ci#include <sys/stat.h> 20f08c3bdfSopenharmony_ci#include <fcntl.h> 21f08c3bdfSopenharmony_ci#include <unistd.h> 22f08c3bdfSopenharmony_ci#include <mqueue.h> 23f08c3bdfSopenharmony_ci#include <signal.h> 24f08c3bdfSopenharmony_ci#include <stdlib.h> 25f08c3bdfSopenharmony_ci#include <string.h> 26f08c3bdfSopenharmony_ci#include "tst_test.h" 27f08c3bdfSopenharmony_ci#include "tst_safe_posix_ipc.h" 28f08c3bdfSopenharmony_ci 29f08c3bdfSopenharmony_cistatic mqd_t m = -1; 30f08c3bdfSopenharmony_cistatic const char msg[] = "hello"; 31f08c3bdfSopenharmony_ci 32f08c3bdfSopenharmony_cistatic void try_null_dereference_cb(union sigval sv) 33f08c3bdfSopenharmony_ci{ 34f08c3bdfSopenharmony_ci char buf[sizeof(msg)]; 35f08c3bdfSopenharmony_ci 36f08c3bdfSopenharmony_ci (void)sv; 37f08c3bdfSopenharmony_ci 38f08c3bdfSopenharmony_ci TST_EXP_VAL((size_t) mq_receive(m, buf, sizeof(buf), NULL), 39f08c3bdfSopenharmony_ci sizeof(buf)); 40f08c3bdfSopenharmony_ci TST_EXP_PASS(memcmp(buf, msg, sizeof(buf))); 41f08c3bdfSopenharmony_ci 42f08c3bdfSopenharmony_ci exit(0); 43f08c3bdfSopenharmony_ci} 44f08c3bdfSopenharmony_ci 45f08c3bdfSopenharmony_cistatic void try_null_dereference(void) 46f08c3bdfSopenharmony_ci{ 47f08c3bdfSopenharmony_ci struct sigevent sev; 48f08c3bdfSopenharmony_ci 49f08c3bdfSopenharmony_ci memset(&sev, '\0', sizeof(sev)); 50f08c3bdfSopenharmony_ci sev.sigev_notify = SIGEV_THREAD; 51f08c3bdfSopenharmony_ci sev.sigev_notify_function = try_null_dereference_cb; 52f08c3bdfSopenharmony_ci 53f08c3bdfSopenharmony_ci /* Step 1: Register & unregister notifier. 54f08c3bdfSopenharmony_ci * Helper thread should receive NOTIFY_REMOVED notification. 55f08c3bdfSopenharmony_ci * In a vulnerable version of glibc, NULL pointer dereference follows. 56f08c3bdfSopenharmony_ci */ 57f08c3bdfSopenharmony_ci TST_EXP_PASS(mq_notify(m, &sev)); 58f08c3bdfSopenharmony_ci TST_EXP_PASS(mq_notify(m, NULL)); 59f08c3bdfSopenharmony_ci 60f08c3bdfSopenharmony_ci /* Step 2: Once again, register notification. 61f08c3bdfSopenharmony_ci * Try to send one message. 62f08c3bdfSopenharmony_ci * Test is considered successful, if the callback does exit (0). 63f08c3bdfSopenharmony_ci */ 64f08c3bdfSopenharmony_ci TST_EXP_PASS(mq_notify(m, &sev)); 65f08c3bdfSopenharmony_ci TST_EXP_PASS(mq_send(m, msg, sizeof(msg), 1)); 66f08c3bdfSopenharmony_ci 67f08c3bdfSopenharmony_ci /* Wait... */ 68f08c3bdfSopenharmony_ci pause(); 69f08c3bdfSopenharmony_ci} 70f08c3bdfSopenharmony_ci 71f08c3bdfSopenharmony_cistatic void do_test(void) 72f08c3bdfSopenharmony_ci{ 73f08c3bdfSopenharmony_ci static const char m_name[] = "/ltp_mq_notify03"; 74f08c3bdfSopenharmony_ci struct mq_attr m_attr; 75f08c3bdfSopenharmony_ci 76f08c3bdfSopenharmony_ci memset(&m_attr, '\0', sizeof(m_attr)); 77f08c3bdfSopenharmony_ci m_attr.mq_maxmsg = 1; 78f08c3bdfSopenharmony_ci m_attr.mq_msgsize = sizeof(msg); 79f08c3bdfSopenharmony_ci 80f08c3bdfSopenharmony_ci m = SAFE_MQ_OPEN(m_name, 81f08c3bdfSopenharmony_ci O_RDWR | O_CREAT | O_EXCL, 82f08c3bdfSopenharmony_ci 0600, 83f08c3bdfSopenharmony_ci &m_attr); 84f08c3bdfSopenharmony_ci 85f08c3bdfSopenharmony_ci TST_EXP_PASS(mq_unlink(m_name)); 86f08c3bdfSopenharmony_ci 87f08c3bdfSopenharmony_ci try_null_dereference(); 88f08c3bdfSopenharmony_ci} 89f08c3bdfSopenharmony_ci 90f08c3bdfSopenharmony_ci 91f08c3bdfSopenharmony_cistatic struct tst_test test = { 92f08c3bdfSopenharmony_ci .test_all = do_test, 93f08c3bdfSopenharmony_ci .tags = (const struct tst_tag[]) { 94f08c3bdfSopenharmony_ci {"glibc-git", "b805aebd42"}, 95f08c3bdfSopenharmony_ci {"CVE", "2021-38604"}, 96f08c3bdfSopenharmony_ci {} 97f08c3bdfSopenharmony_ci }, 98f08c3bdfSopenharmony_ci .needs_root = 1, 99f08c3bdfSopenharmony_ci}; 100