xref: /aosp_15_r20/external/ltp/testcases/kernel/sound/snd_seq01.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1*49cdfc7eSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0-or-later
2*49cdfc7eSAndroid Build Coastguard Worker /*
3*49cdfc7eSAndroid Build Coastguard Worker  * Copyright (C) 2018 SUSE LLC <[email protected]>
4*49cdfc7eSAndroid Build Coastguard Worker  * Copyright (C) 2020 SUSE LLC <[email protected]>
5*49cdfc7eSAndroid Build Coastguard Worker  *
6*49cdfc7eSAndroid Build Coastguard Worker  * CVE-2018-7566
7*49cdfc7eSAndroid Build Coastguard Worker  *
8*49cdfc7eSAndroid Build Coastguard Worker  * Test for race condition when initializing client pool on /dev/snd/seq
9*49cdfc7eSAndroid Build Coastguard Worker  * Kernel crash fixed in:
10*49cdfc7eSAndroid Build Coastguard Worker  *
11*49cdfc7eSAndroid Build Coastguard Worker  *  commit d15d662e89fc667b90cd294b0eb45694e33144da
12*49cdfc7eSAndroid Build Coastguard Worker  *  Author: Takashi Iwai <[email protected]>
13*49cdfc7eSAndroid Build Coastguard Worker  *  Date:   Mon Feb 12 15:20:51 2018 +0100
14*49cdfc7eSAndroid Build Coastguard Worker  *
15*49cdfc7eSAndroid Build Coastguard Worker  *  ALSA: seq: Fix racy pool initializations
16*49cdfc7eSAndroid Build Coastguard Worker  */
17*49cdfc7eSAndroid Build Coastguard Worker 
18*49cdfc7eSAndroid Build Coastguard Worker #include <linux/types.h>
19*49cdfc7eSAndroid Build Coastguard Worker #include <time.h>
20*49cdfc7eSAndroid Build Coastguard Worker #include <sound/asound.h>
21*49cdfc7eSAndroid Build Coastguard Worker #include <sound/asequencer.h>
22*49cdfc7eSAndroid Build Coastguard Worker 
23*49cdfc7eSAndroid Build Coastguard Worker #include "tst_test.h"
24*49cdfc7eSAndroid Build Coastguard Worker #include "tst_fuzzy_sync.h"
25*49cdfc7eSAndroid Build Coastguard Worker 
26*49cdfc7eSAndroid Build Coastguard Worker static int fd = -1;
27*49cdfc7eSAndroid Build Coastguard Worker static int client_id;
28*49cdfc7eSAndroid Build Coastguard Worker static struct snd_seq_remove_events rminfo = {
29*49cdfc7eSAndroid Build Coastguard Worker 	.remove_mode = SNDRV_SEQ_REMOVE_OUTPUT
30*49cdfc7eSAndroid Build Coastguard Worker };
31*49cdfc7eSAndroid Build Coastguard Worker static struct snd_seq_event ssev = {
32*49cdfc7eSAndroid Build Coastguard Worker 	.flags = SNDRV_SEQ_TIME_STAMP_TICK | SNDRV_SEQ_TIME_MODE_REL,
33*49cdfc7eSAndroid Build Coastguard Worker 	.queue = 0,
34*49cdfc7eSAndroid Build Coastguard Worker 	.type = SNDRV_SEQ_EVENT_USR0,
35*49cdfc7eSAndroid Build Coastguard Worker 	.time = { .tick = 10 }
36*49cdfc7eSAndroid Build Coastguard Worker };
37*49cdfc7eSAndroid Build Coastguard Worker 
38*49cdfc7eSAndroid Build Coastguard Worker static struct tst_fzsync_pair fzsync_pair;
39*49cdfc7eSAndroid Build Coastguard Worker 
reinit_pool(int pool_size)40*49cdfc7eSAndroid Build Coastguard Worker static void reinit_pool(int pool_size)
41*49cdfc7eSAndroid Build Coastguard Worker {
42*49cdfc7eSAndroid Build Coastguard Worker 	struct snd_seq_client_pool pconf = {
43*49cdfc7eSAndroid Build Coastguard Worker 		.output_pool = pool_size,
44*49cdfc7eSAndroid Build Coastguard Worker 		.client = client_id
45*49cdfc7eSAndroid Build Coastguard Worker 	};
46*49cdfc7eSAndroid Build Coastguard Worker 
47*49cdfc7eSAndroid Build Coastguard Worker 	ioctl(fd, SNDRV_SEQ_IOCTL_SET_CLIENT_POOL, &pconf);
48*49cdfc7eSAndroid Build Coastguard Worker }
49*49cdfc7eSAndroid Build Coastguard Worker 
race_ioctl(void)50*49cdfc7eSAndroid Build Coastguard Worker static void race_ioctl(void)
51*49cdfc7eSAndroid Build Coastguard Worker {
52*49cdfc7eSAndroid Build Coastguard Worker 	reinit_pool(512);
53*49cdfc7eSAndroid Build Coastguard Worker }
54*49cdfc7eSAndroid Build Coastguard Worker 
race_write(void)55*49cdfc7eSAndroid Build Coastguard Worker static void race_write(void)
56*49cdfc7eSAndroid Build Coastguard Worker {
57*49cdfc7eSAndroid Build Coastguard Worker 	TEST(write(fd, &ssev, sizeof(ssev)));
58*49cdfc7eSAndroid Build Coastguard Worker }
59*49cdfc7eSAndroid Build Coastguard Worker 
60*49cdfc7eSAndroid Build Coastguard Worker void (*testfunc_list[])(void) = {race_ioctl, race_write};
61*49cdfc7eSAndroid Build Coastguard Worker 
setup(void)62*49cdfc7eSAndroid Build Coastguard Worker static void setup(void)
63*49cdfc7eSAndroid Build Coastguard Worker {
64*49cdfc7eSAndroid Build Coastguard Worker 	struct snd_seq_queue_info qconf = { .queue = 0 };
65*49cdfc7eSAndroid Build Coastguard Worker 
66*49cdfc7eSAndroid Build Coastguard Worker 	errno = 0;
67*49cdfc7eSAndroid Build Coastguard Worker 	fd = open("/dev/snd/seq", O_RDWR);
68*49cdfc7eSAndroid Build Coastguard Worker 
69*49cdfc7eSAndroid Build Coastguard Worker 	if (fd == -1 && (errno == ENOENT || errno == EACCES))
70*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TCONF | TERRNO, "Cannot open /dev/snd/seq");
71*49cdfc7eSAndroid Build Coastguard Worker 
72*49cdfc7eSAndroid Build Coastguard Worker 	if (fd < 0)
73*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TBROK | TERRNO, "Cannot open /dev/snd/seq");
74*49cdfc7eSAndroid Build Coastguard Worker 
75*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_IOCTL(fd, SNDRV_SEQ_IOCTL_CLIENT_ID, &client_id);
76*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_IOCTL(fd, SNDRV_SEQ_IOCTL_CREATE_QUEUE, &qconf);
77*49cdfc7eSAndroid Build Coastguard Worker 	ssev.dest.client = client_id;
78*49cdfc7eSAndroid Build Coastguard Worker 
79*49cdfc7eSAndroid Build Coastguard Worker 	fzsync_pair.exec_loops = 1000000;
80*49cdfc7eSAndroid Build Coastguard Worker 	tst_fzsync_pair_init(&fzsync_pair);
81*49cdfc7eSAndroid Build Coastguard Worker }
82*49cdfc7eSAndroid Build Coastguard Worker 
cleanup(void)83*49cdfc7eSAndroid Build Coastguard Worker static void cleanup(void)
84*49cdfc7eSAndroid Build Coastguard Worker {
85*49cdfc7eSAndroid Build Coastguard Worker 	if (fd >= 0)
86*49cdfc7eSAndroid Build Coastguard Worker 		SAFE_CLOSE(fd);
87*49cdfc7eSAndroid Build Coastguard Worker 	tst_fzsync_pair_cleanup(&fzsync_pair);
88*49cdfc7eSAndroid Build Coastguard Worker }
89*49cdfc7eSAndroid Build Coastguard Worker 
thread_run(void * arg)90*49cdfc7eSAndroid Build Coastguard Worker static void *thread_run(void *arg)
91*49cdfc7eSAndroid Build Coastguard Worker {
92*49cdfc7eSAndroid Build Coastguard Worker 	while (tst_fzsync_run_b(&fzsync_pair)) {
93*49cdfc7eSAndroid Build Coastguard Worker 		tst_fzsync_start_race_b(&fzsync_pair);
94*49cdfc7eSAndroid Build Coastguard Worker 		reinit_pool(10);
95*49cdfc7eSAndroid Build Coastguard Worker 		tst_fzsync_end_race_b(&fzsync_pair);
96*49cdfc7eSAndroid Build Coastguard Worker 	}
97*49cdfc7eSAndroid Build Coastguard Worker 
98*49cdfc7eSAndroid Build Coastguard Worker 	return arg;
99*49cdfc7eSAndroid Build Coastguard Worker }
100*49cdfc7eSAndroid Build Coastguard Worker 
run(unsigned int n)101*49cdfc7eSAndroid Build Coastguard Worker static void run(unsigned int n)
102*49cdfc7eSAndroid Build Coastguard Worker {
103*49cdfc7eSAndroid Build Coastguard Worker 	tst_fzsync_pair_reset(&fzsync_pair, thread_run);
104*49cdfc7eSAndroid Build Coastguard Worker 
105*49cdfc7eSAndroid Build Coastguard Worker 	while (tst_fzsync_run_a(&fzsync_pair)) {
106*49cdfc7eSAndroid Build Coastguard Worker 		reinit_pool(5);
107*49cdfc7eSAndroid Build Coastguard Worker 		SAFE_IOCTL(fd, SNDRV_SEQ_IOCTL_REMOVE_EVENTS, &rminfo);
108*49cdfc7eSAndroid Build Coastguard Worker 		tst_fzsync_start_race_a(&fzsync_pair);
109*49cdfc7eSAndroid Build Coastguard Worker 		testfunc_list[n]();
110*49cdfc7eSAndroid Build Coastguard Worker 		tst_fzsync_end_race_a(&fzsync_pair);
111*49cdfc7eSAndroid Build Coastguard Worker 
112*49cdfc7eSAndroid Build Coastguard Worker 		if (tst_taint_check()) {
113*49cdfc7eSAndroid Build Coastguard Worker 			tst_res(TFAIL, "Kernel is vulnerable");
114*49cdfc7eSAndroid Build Coastguard Worker 			return;
115*49cdfc7eSAndroid Build Coastguard Worker 		}
116*49cdfc7eSAndroid Build Coastguard Worker 	}
117*49cdfc7eSAndroid Build Coastguard Worker 
118*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TPASS, "Nothing bad happened, probably");
119*49cdfc7eSAndroid Build Coastguard Worker }
120*49cdfc7eSAndroid Build Coastguard Worker 
121*49cdfc7eSAndroid Build Coastguard Worker static struct tst_test test = {
122*49cdfc7eSAndroid Build Coastguard Worker 	.test = run,
123*49cdfc7eSAndroid Build Coastguard Worker 	.tcnt = ARRAY_SIZE(testfunc_list),
124*49cdfc7eSAndroid Build Coastguard Worker 	.setup = setup,
125*49cdfc7eSAndroid Build Coastguard Worker 	.cleanup = cleanup,
126*49cdfc7eSAndroid Build Coastguard Worker 	.max_runtime = 60,
127*49cdfc7eSAndroid Build Coastguard Worker 	.taint_check = TST_TAINT_W | TST_TAINT_D,
128*49cdfc7eSAndroid Build Coastguard Worker 	.tags = (const struct tst_tag[]) {
129*49cdfc7eSAndroid Build Coastguard Worker 		{"linux-git", "d15d662e89fc"},
130*49cdfc7eSAndroid Build Coastguard Worker 		{"CVE", "2018-7566"},
131*49cdfc7eSAndroid Build Coastguard Worker 		{}
132*49cdfc7eSAndroid Build Coastguard Worker 	}
133*49cdfc7eSAndroid Build Coastguard Worker };
134