diff options
author | Gustavo A. R. Silva <gustavo@embeddedor.com> | 2018-05-03 14:45:58 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-05-04 12:52:47 -0400 |
commit | acf784bd0ce257fe43da7ca266f7a10b837479d2 (patch) | |
tree | 8dd84537bf4b37809868b378a7a819437db625ae /net/atm | |
parent | 2be147f7459db5bbf292e0a6f135037b55e20b39 (diff) |
net: atm: Fix potential Spectre v1
ioc_data.dev_num can be 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:
net/atm/lec.c:702 lec_vcc_attach() warn: potential spectre issue
'dev_lec'
Fix this by sanitizing ioc_data.dev_num before using it to index
dev_lec. Also, notice that there is another instance in which array
dev_lec is being indexed using ioc_data.dev_num at line 705:
lec_vcc_added(netdev_priv(dev_lec[ioc_data.dev_num]),
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: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/atm')
-rw-r--r-- | net/atm/lec.c | 9 |
1 files changed, 7 insertions, 2 deletions
diff --git a/net/atm/lec.c b/net/atm/lec.c index 01d5d20a6eb1..3138a869b5c0 100644 --- a/net/atm/lec.c +++ b/net/atm/lec.c | |||
@@ -41,6 +41,9 @@ static unsigned char bridge_ula_lec[] = { 0x01, 0x80, 0xc2, 0x00, 0x00 }; | |||
41 | #include <linux/module.h> | 41 | #include <linux/module.h> |
42 | #include <linux/init.h> | 42 | #include <linux/init.h> |
43 | 43 | ||
44 | /* Hardening for Spectre-v1 */ | ||
45 | #include <linux/nospec.h> | ||
46 | |||
44 | #include "lec.h" | 47 | #include "lec.h" |
45 | #include "lec_arpc.h" | 48 | #include "lec_arpc.h" |
46 | #include "resources.h" | 49 | #include "resources.h" |
@@ -687,8 +690,10 @@ static int lec_vcc_attach(struct atm_vcc *vcc, void __user *arg) | |||
687 | bytes_left = copy_from_user(&ioc_data, arg, sizeof(struct atmlec_ioc)); | 690 | bytes_left = copy_from_user(&ioc_data, arg, sizeof(struct atmlec_ioc)); |
688 | if (bytes_left != 0) | 691 | if (bytes_left != 0) |
689 | pr_info("copy from user failed for %d bytes\n", bytes_left); | 692 | pr_info("copy from user failed for %d bytes\n", bytes_left); |
690 | if (ioc_data.dev_num < 0 || ioc_data.dev_num >= MAX_LEC_ITF || | 693 | if (ioc_data.dev_num < 0 || ioc_data.dev_num >= MAX_LEC_ITF) |
691 | !dev_lec[ioc_data.dev_num]) | 694 | return -EINVAL; |
695 | ioc_data.dev_num = array_index_nospec(ioc_data.dev_num, MAX_LEC_ITF); | ||
696 | if (!dev_lec[ioc_data.dev_num]) | ||
692 | return -EINVAL; | 697 | return -EINVAL; |
693 | vpriv = kmalloc(sizeof(struct lec_vcc_priv), GFP_KERNEL); | 698 | vpriv = kmalloc(sizeof(struct lec_vcc_priv), GFP_KERNEL); |
694 | if (!vpriv) | 699 | if (!vpriv) |