xref: /aosp_15_r20/external/ltp/testcases/kernel/syscalls/mq_notify/mq_notify03.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
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