summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2018-03-08 18:39:24 +0000
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2018-03-11 16:21:34 +0100
commit93f3aff1d910c5363a42c2c18dec9939cb0d58c2 (patch)
tree23ad162a5b5474d79e675955d9ea4132d9ab2568 /net
parentd77763dc70c4afa451b33f80013910d502bf3bb7 (diff)
mpls, nospec: Sanitize array index in mpls_label_ok()
commit 3968523f855050b8195134da951b87c20bd66130 upstream. mpls_label_ok() validates that the 'platform_label' array index from a userspace netlink message payload is valid. Under speculation the mpls_label_ok() result may not resolve in the CPU pipeline until after the index is used to access an array element. Sanitize the index to zero to prevent userspace-controlled arbitrary out-of-bounds speculation, a precursor for a speculative execution side channel vulnerability. Cc: "David S. Miller" <davem@davemloft.net> Cc: Eric W. Biederman <ebiederm@xmission.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net> [bwh: Backported to 4.4: - mpls_label_ok() doesn't take an extack parameter - Drop change in mpls_getroute()] Signed-off-by: Ben Hutchings <ben.hutchings@codethink.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'net')
-rw-r--r--net/mpls/af_mpls.c22
1 files changed, 13 insertions, 9 deletions
diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c
index 3e8d1f6ac907..ffab94d61e1d 100644
--- a/net/mpls/af_mpls.c
+++ b/net/mpls/af_mpls.c
@@ -7,6 +7,7 @@
#include <linux/if_arp.h>
#include <linux/ipv6.h>
#include <linux/mpls.h>
+#include <linux/nospec.h>
#include <linux/vmalloc.h>
#include <net/ip.h>
#include <net/dst.h>
@@ -756,17 +757,20 @@ errout:
return err;
}
-static bool mpls_label_ok(struct net *net, unsigned int index)
+static bool mpls_label_ok(struct net *net, unsigned int *index)
{
+ bool is_ok = true;
+
/* Reserved labels may not be set */
- if (index < MPLS_LABEL_FIRST_UNRESERVED)
- return false;
+ if (*index < MPLS_LABEL_FIRST_UNRESERVED)
+ is_ok = false;
/* The full 20 bit range may not be supported. */
- if (index >= net->mpls.platform_labels)
- return false;
+ if (is_ok && *index >= net->mpls.platform_labels)
+ is_ok = false;
- return true;
+ *index = array_index_nospec(*index, net->mpls.platform_labels);
+ return is_ok;
}
static int mpls_route_add(struct mpls_route_config *cfg)
@@ -787,7 +791,7 @@ static int mpls_route_add(struct mpls_route_config *cfg)
index = find_free_label(net);
}
- if (!mpls_label_ok(net, index))
+ if (!mpls_label_ok(net, &index))
goto errout;
/* Append makes no sense with mpls */
@@ -848,7 +852,7 @@ static int mpls_route_del(struct mpls_route_config *cfg)
index = cfg->rc_label;
- if (!mpls_label_ok(net, index))
+ if (!mpls_label_ok(net, &index))
goto errout;
mpls_route_update(net, index, NULL, &cfg->rc_nlinfo);
@@ -1283,7 +1287,7 @@ static int rtm_to_route_config(struct sk_buff *skb, struct nlmsghdr *nlh,
goto errout;
if (!mpls_label_ok(cfg->rc_nlinfo.nl_net,
- cfg->rc_label))
+ &cfg->rc_label))
goto errout;
break;
}