From mboxrd@z Thu Jan 1 00:00:00 1970 From: Cyril Hrubis Date: Thu, 11 Jul 2019 15:18:42 +0200 Subject: [LTP] [PATCH v2] Add a regression test for CVE-2017-1000380 In-Reply-To: <20190711125055.9289-1-mmoese@suse.de> References: <20190711125055.9289-1-mmoese@suse.de> Message-ID: <20190711131842.GC8709@rei> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: ltp@lists.linux.it Hi! > +LDLIBS += -pthread ^ Space before tabs > + > +include $(top_srcdir)/include/mk/generic_leaf_target.mk > diff --git a/testcases/kernel/sound/snd_timer01.c b/testcases/kernel/sound/snd_timer01.c > new file mode 100644 > index 000000000..80b03022a > --- /dev/null > +++ b/testcases/kernel/sound/snd_timer01.c > @@ -0,0 +1,140 @@ > +// SPDX-License-Identifier: GPL-2.0-or-later > + > +/* Copyright (c) 2019 Michael Moese > + * Regression test for CVE-2017-1000380 based on the original PoC exploit > + * by Alexander Potapenko > + * > + * Be careful! This test may crash your kernel! > + * > + * The test performs several ioctl() parallel with readv() on the same > + * file descriptor to /dev/snd/timer. A buggy kernel will leak memory > + * to the process, which may contain information from the the kernel or > + * any other process on the system. > + * > + * The issue was fixed with > + * http://git.kernel.org/linus/d11662f4f798b50d8c8743f433842c3e40fe3378 > + * http://git.kernel.org/linus/ba3021b2c79b2fa9114f92790a99deb27a65b728 > + */ > + > +#include "config.h" > +#include "tst_test.h" > +#include "tst_taint.h" > +#include "tst_fuzzy_sync.h" > +#include "tst_safe_macros.h" > +#include "tst_safe_pthread.h" > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#define MAX_BUFSIZE 1024 > + > +static int snd_fd; > +static struct tst_fzsync_pair fzsync_pair; > + > +static void *ioctl_thread(void *unused) > +{ > + (void) unused; ^ Leftover? > + int tread_arg = 1; > + struct snd_timer_select ts; > + struct snd_timer_params tp; > + > + memset(&ts, 0, sizeof(ts)); > + ts.id.dev_class = 1; > + > + memset(&tp, 0, sizeof(tp)); > + tp.ticks = 1; > + tp.filter = 0xf; > + > + while (tst_fzsync_run_b(&fzsync_pair)) { > + > + ioctl(snd_fd, SNDRV_TIMER_IOCTL_TREAD, &tread_arg); > + > + ioctl(snd_fd, SNDRV_TIMER_IOCTL_SELECT, &ts); > + > + ioctl(snd_fd, SNDRV_TIMER_IOCTL_PARAMS, &tp); > + > + ioctl(snd_fd, SNDRV_TIMER_IOCTL_START, 0); > + > + tst_fzsync_end_race_b(&fzsync_pair); > + } > + return unused; > +} > + > +static void setup(void) > +{ > + tst_fzsync_pair_init(&fzsync_pair); > + tst_taint_init(TST_TAINT_W | TST_TAINT_D); > + snd_fd = SAFE_OPEN("/dev/snd/timer", > + O_RDONLY|O_CREAT|O_NOCTTY|O_SYNC|O_LARGEFILE, 0); > +} > + > +static void cleanup(void) > +{ > + tst_fzsync_pair_cleanup(&fzsync_pair); > + SAFE_CLOSE(snd_fd); > +} > + > +static void run(void) > +{ > + size_t len; > + int size; > + struct iovec iov; > + pthread_t th; > + char read_buf[MAX_BUFSIZE]; > + int i, nz; > + pthread_attr_t thread_attr; > + > + pthread_attr_init(&thread_attr); > + pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED); > + SAFE_PTHREAD_CREATE(&th, &thread_attr, ioctl_thread, NULL); > + > + iov.iov_base = read_buf; > + iov.iov_len = sizeof(read_buf); > + > + while (tst_fzsync_run_a(&fzsync_pair)) { > + nz = 0; > + memset(read_buf, 0, sizeof(read_buf)); > + size = readv(snd_fd, &iov, 1); > + > + tst_fzsync_end_race_a(&fzsync_pair); > + > + /* check if it could be a valid ioctl result */ > + if (size == 0) > + continue; > + > + /* check if the buffer is non-empty */ > + for (i = 0; i < size; i++) { > + if (read_buf[i]) { > + nz = 1; > + break; > + } > + } > + if (!nz) > + continue; > + > + len = strlen(read_buf); The point still stands, strlen() on random buffer here is not safe. I guess that the easies option would be shortening the iov_len by 1 since we do memset() for the buffer it will be guaranteed that it's null-terminated. > + /* the kernel's struct snd_timer_read is two unsigned integers*/ > + if (len <= 2 * sizeof(unsigned int)) > + continue; > + > + tst_res(TFAIL, "kernel seems vulnerable"); > + return; > + } > + > + if (tst_taint_check() != 0) > + tst_res(TFAIL, "kernel seems vulnerable"); > + else > + tst_res(TPASS, "kernel seems not vulnerable"); > +} > + > +static struct tst_test test = { > + .test_all = run, > + .setup = setup, > + .cleanup = cleanup, > +}; > -- > 2.22.0 > > > -- > Mailing list info: https://lists.linux.it/listinfo/ltp -- Cyril Hrubis chrubis@suse.cz