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

applicom: Fix potential Spectre v1 vulnerabilities

IndexCard 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/applicom.c:418 ac_write() warn: potential spectre issue 'apbs' [r]
drivers/char/applicom.c:728 ac_ioctl() warn: potential spectre issue 'apbs' [r] (local cap)

Fix this by sanitizing IndexCard before using it to index apbs.

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://lore.kernel.org/lkml/20180423164740.GY17484@dhcp22.suse.cz/

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
d7ac3c6e 24d48a61

+24 -11
+24 -11
drivers/char/applicom.c
··· 32 32 #include <linux/wait.h> 33 33 #include <linux/init.h> 34 34 #include <linux/fs.h> 35 + #include <linux/nospec.h> 35 36 36 37 #include <asm/io.h> 37 38 #include <linux/uaccess.h> ··· 387 386 TicCard = st_loc.tic_des_from_pc; /* tic number to send */ 388 387 IndexCard = NumCard - 1; 389 388 390 - if((NumCard < 1) || (NumCard > MAX_BOARD) || !apbs[IndexCard].RamIO) 389 + if (IndexCard >= MAX_BOARD) 390 + return -EINVAL; 391 + IndexCard = array_index_nospec(IndexCard, MAX_BOARD); 392 + 393 + if (!apbs[IndexCard].RamIO) 391 394 return -EINVAL; 392 395 393 396 #ifdef DEBUG ··· 702 697 unsigned char IndexCard; 703 698 void __iomem *pmem; 704 699 int ret = 0; 700 + static int warncount = 10; 705 701 volatile unsigned char byte_reset_it; 706 702 struct st_ram_io *adgl; 707 703 void __user *argp = (void __user *)arg; ··· 717 711 mutex_lock(&ac_mutex); 718 712 IndexCard = adgl->num_card-1; 719 713 720 - if(cmd != 6 && ((IndexCard >= MAX_BOARD) || !apbs[IndexCard].RamIO)) { 721 - static int warncount = 10; 722 - if (warncount) { 723 - printk( KERN_WARNING "APPLICOM driver IOCTL, bad board number %d\n",(int)IndexCard+1); 724 - warncount--; 725 - } 726 - kfree(adgl); 727 - mutex_unlock(&ac_mutex); 728 - return -EINVAL; 729 - } 714 + if (cmd != 6 && IndexCard >= MAX_BOARD) 715 + goto err; 716 + IndexCard = array_index_nospec(IndexCard, MAX_BOARD); 717 + 718 + if (cmd != 6 && !apbs[IndexCard].RamIO) 719 + goto err; 730 720 731 721 switch (cmd) { 732 722 ··· 840 838 kfree(adgl); 841 839 mutex_unlock(&ac_mutex); 842 840 return 0; 841 + 842 + err: 843 + if (warncount) { 844 + pr_warn("APPLICOM driver IOCTL, bad board number %d\n", 845 + (int)IndexCard + 1); 846 + warncount--; 847 + } 848 + kfree(adgl); 849 + mutex_unlock(&ac_mutex); 850 + return -EINVAL; 851 + 843 852 } 844 853