atm: iphase: Fix Spectre v1 vulnerability

board is 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/atm/iphase.c:2765 ia_ioctl() warn: potential spectre issue 'ia_dev' [r] (local cap)
drivers/atm/iphase.c:2774 ia_ioctl() warn: possible spectre second half.  'iadev'
drivers/atm/iphase.c:2782 ia_ioctl() warn: possible spectre second half.  'iadev'
drivers/atm/iphase.c:2816 ia_ioctl() warn: possible spectre second half.  'iadev'
drivers/atm/iphase.c:2823 ia_ioctl() warn: possible spectre second half.  'iadev'
drivers/atm/iphase.c:2830 ia_ioctl() warn: potential spectre issue '_ia_dev' [r] (local cap)
drivers/atm/iphase.c:2845 ia_ioctl() warn: possible spectre second half.  'iadev'
drivers/atm/iphase.c:2856 ia_ioctl() warn: possible spectre second half.  'iadev'

Fix this by sanitizing board before using it to index ia_dev and _ia_dev

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/

Signed-off-by: Gustavo A. R. Silva <gustavo@embeddedor.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Gustavo A. R. Silva 2019-07-30 22:21:41 -05:00 committed by David S. Miller
parent 685703b497
commit ea443e5e98

View File

@ -63,6 +63,7 @@
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/jiffies.h> #include <linux/jiffies.h>
#include <linux/nospec.h>
#include "iphase.h" #include "iphase.h"
#include "suni.h" #include "suni.h"
#define swap_byte_order(x) (((x & 0xff) << 8) | ((x & 0xff00) >> 8)) #define swap_byte_order(x) (((x & 0xff) << 8) | ((x & 0xff00) >> 8))
@ -2760,8 +2761,11 @@ static int ia_ioctl(struct atm_dev *dev, unsigned int cmd, void __user *arg)
} }
if (copy_from_user(&ia_cmds, arg, sizeof ia_cmds)) return -EFAULT; if (copy_from_user(&ia_cmds, arg, sizeof ia_cmds)) return -EFAULT;
board = ia_cmds.status; board = ia_cmds.status;
if ((board < 0) || (board > iadev_count))
board = 0; if ((board < 0) || (board > iadev_count))
board = 0;
board = array_index_nospec(board, iadev_count + 1);
iadev = ia_dev[board]; iadev = ia_dev[board];
switch (ia_cmds.cmd) { switch (ia_cmds.cmd) {
case MEMDUMP: case MEMDUMP: