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