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