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