Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

char/mwave: fix potential Spectre v1 vulnerability

ipcnum is indirectly controlled by user-space, hence leading to
a potential exploitation of the Spectre variant 1 vulnerability.

This issue was detected with the help of Smatch:

drivers/char/mwave/mwavedd.c:299 mwave_ioctl() warn: potential spectre issue 'pDrvData->IPCs' [w] (local cap)

Fix this by sanitizing ipcnum before using it to index pDrvData->IPCs.

Notice that given that speculation windows are large, the policy is
to kill the speculation on the first load and not worry if it can be
completed with a dependent load/store [1].

[1] https://marc.info/?l=linux-kernel&m=152449131114778&w=2

Cc: stable@vger.kernel.org
Signed-off-by: Gustavo A. R. Silva <gustavo@embeddedor.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Gustavo A. R. Silva and committed by
Greg Kroah-Hartman
701956d4 e25df781

+7
+7
drivers/char/mwave/mwavedd.c
··· 59 59 #include <linux/mutex.h> 60 60 #include <linux/delay.h> 61 61 #include <linux/serial_8250.h> 62 + #include <linux/nospec.h> 62 63 #include "smapi.h" 63 64 #include "mwavedd.h" 64 65 #include "3780i.h" ··· 290 289 ipcnum); 291 290 return -EINVAL; 292 291 } 292 + ipcnum = array_index_nospec(ipcnum, 293 + ARRAY_SIZE(pDrvData->IPCs)); 293 294 PRINTK_3(TRACE_MWAVE, 294 295 "mwavedd::mwave_ioctl IOCTL_MW_REGISTER_IPC" 295 296 " ipcnum %x entry usIntCount %x\n", ··· 320 317 " Invalid ipcnum %x\n", ipcnum); 321 318 return -EINVAL; 322 319 } 320 + ipcnum = array_index_nospec(ipcnum, 321 + ARRAY_SIZE(pDrvData->IPCs)); 323 322 PRINTK_3(TRACE_MWAVE, 324 323 "mwavedd::mwave_ioctl IOCTL_MW_GET_IPC" 325 324 " ipcnum %x, usIntCount %x\n", ··· 388 383 ipcnum); 389 384 return -EINVAL; 390 385 } 386 + ipcnum = array_index_nospec(ipcnum, 387 + ARRAY_SIZE(pDrvData->IPCs)); 391 388 mutex_lock(&mwave_mutex); 392 389 if (pDrvData->IPCs[ipcnum].bIsEnabled == true) { 393 390 pDrvData->IPCs[ipcnum].bIsEnabled = false;