diff options
author | Dan Williams <dan.j.williams@intel.com> | 2018-02-08 01:34:24 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-02-08 15:24:12 -0500 |
commit | 3968523f855050b8195134da951b87c20bd66130 (patch) | |
tree | 1bf66a780a1e70748dcbd036281015a1d510c564 /net/mpls | |
parent | ebeeb1ad9b8adcc37c2ec21a96f39e9d35199b46 (diff) |
mpls, nospec: Sanitize array index in mpls_label_ok()
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: <stable@vger.kernel.org>
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>
Diffstat (limited to 'net/mpls')
-rw-r--r-- | net/mpls/af_mpls.c | 24 |
1 files changed, 14 insertions, 10 deletions
diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c index 5dce8336d33f..e545a3c9365f 100644 --- a/net/mpls/af_mpls.c +++ b/net/mpls/af_mpls.c | |||
@@ -8,6 +8,7 @@ | |||
8 | #include <linux/ipv6.h> | 8 | #include <linux/ipv6.h> |
9 | #include <linux/mpls.h> | 9 | #include <linux/mpls.h> |
10 | #include <linux/netconf.h> | 10 | #include <linux/netconf.h> |
11 | #include <linux/nospec.h> | ||
11 | #include <linux/vmalloc.h> | 12 | #include <linux/vmalloc.h> |
12 | #include <linux/percpu.h> | 13 | #include <linux/percpu.h> |
13 | #include <net/ip.h> | 14 | #include <net/ip.h> |
@@ -935,24 +936,27 @@ errout: | |||
935 | return err; | 936 | return err; |
936 | } | 937 | } |
937 | 938 | ||
938 | static bool mpls_label_ok(struct net *net, unsigned int index, | 939 | static bool mpls_label_ok(struct net *net, unsigned int *index, |
939 | struct netlink_ext_ack *extack) | 940 | struct netlink_ext_ack *extack) |
940 | { | 941 | { |
942 | bool is_ok = true; | ||
943 | |||
941 | /* Reserved labels may not be set */ | 944 | /* Reserved labels may not be set */ |
942 | if (index < MPLS_LABEL_FIRST_UNRESERVED) { | 945 | if (*index < MPLS_LABEL_FIRST_UNRESERVED) { |
943 | NL_SET_ERR_MSG(extack, | 946 | NL_SET_ERR_MSG(extack, |
944 | "Invalid label - must be MPLS_LABEL_FIRST_UNRESERVED or higher"); | 947 | "Invalid label - must be MPLS_LABEL_FIRST_UNRESERVED or higher"); |
945 | return false; | 948 | is_ok = false; |
946 | } | 949 | } |
947 | 950 | ||
948 | /* The full 20 bit range may not be supported. */ | 951 | /* The full 20 bit range may not be supported. */ |
949 | if (index >= net->mpls.platform_labels) { | 952 | if (is_ok && *index >= net->mpls.platform_labels) { |
950 | NL_SET_ERR_MSG(extack, | 953 | NL_SET_ERR_MSG(extack, |
951 | "Label >= configured maximum in platform_labels"); | 954 | "Label >= configured maximum in platform_labels"); |
952 | return false; | 955 | is_ok = false; |
953 | } | 956 | } |
954 | 957 | ||
955 | return true; | 958 | *index = array_index_nospec(*index, net->mpls.platform_labels); |
959 | return is_ok; | ||
956 | } | 960 | } |
957 | 961 | ||
958 | static int mpls_route_add(struct mpls_route_config *cfg, | 962 | static int mpls_route_add(struct mpls_route_config *cfg, |
@@ -975,7 +979,7 @@ static int mpls_route_add(struct mpls_route_config *cfg, | |||
975 | index = find_free_label(net); | 979 | index = find_free_label(net); |
976 | } | 980 | } |
977 | 981 | ||
978 | if (!mpls_label_ok(net, index, extack)) | 982 | if (!mpls_label_ok(net, &index, extack)) |
979 | goto errout; | 983 | goto errout; |
980 | 984 | ||
981 | /* Append makes no sense with mpls */ | 985 | /* Append makes no sense with mpls */ |
@@ -1052,7 +1056,7 @@ static int mpls_route_del(struct mpls_route_config *cfg, | |||
1052 | 1056 | ||
1053 | index = cfg->rc_label; | 1057 | index = cfg->rc_label; |
1054 | 1058 | ||
1055 | if (!mpls_label_ok(net, index, extack)) | 1059 | if (!mpls_label_ok(net, &index, extack)) |
1056 | goto errout; | 1060 | goto errout; |
1057 | 1061 | ||
1058 | mpls_route_update(net, index, NULL, &cfg->rc_nlinfo); | 1062 | mpls_route_update(net, index, NULL, &cfg->rc_nlinfo); |
@@ -1810,7 +1814,7 @@ static int rtm_to_route_config(struct sk_buff *skb, | |||
1810 | goto errout; | 1814 | goto errout; |
1811 | 1815 | ||
1812 | if (!mpls_label_ok(cfg->rc_nlinfo.nl_net, | 1816 | if (!mpls_label_ok(cfg->rc_nlinfo.nl_net, |
1813 | cfg->rc_label, extack)) | 1817 | &cfg->rc_label, extack)) |
1814 | goto errout; | 1818 | goto errout; |
1815 | break; | 1819 | break; |
1816 | } | 1820 | } |
@@ -2137,7 +2141,7 @@ static int mpls_getroute(struct sk_buff *in_skb, struct nlmsghdr *in_nlh, | |||
2137 | goto errout; | 2141 | goto errout; |
2138 | } | 2142 | } |
2139 | 2143 | ||
2140 | if (!mpls_label_ok(net, in_label, extack)) { | 2144 | if (!mpls_label_ok(net, &in_label, extack)) { |
2141 | err = -EINVAL; | 2145 | err = -EINVAL; |
2142 | goto errout; | 2146 | goto errout; |
2143 | } | 2147 | } |