net/openvswitch: check Ethernet header length before key_extract()
Subsystems (3)
PATCH 1/1 net/openvswitch: check Ethernet header length before key_extract()
When a packet arrives on an ARPHRD_NONE device (e.g. TUN), ovs_flow_key_extract() trusts the user-provided skb->protocol field: if it is ETH_P_TEB, the packet is classified as MAC_PROTO_ETHERNET and key_extract() is called without ensuring the skb has ETH_HLEN (14) bytes of linear data. key_extract() unconditionally pulls 2 * ETH_ALEN bytes for MAC addresses and parse_ethertype() pulls 2 more, either of which triggers a kernel BUG in __skb_pull() when the linear area is too small.
kernel BUG at include/linux/skbuff.h:2848!
RIP: 0010:key_extract+0xa7e/0xd90 net/openvswitch/flow.c:933 ovs_flow_key_extract+0x419/0xa70 ovs_vport_receive+0x222/0x390 netdev_frame_hook+0x3e0/0x630 tun_get_user+0x2d0c/0x38e0
Fixed by adding check_header(skb, ETH_HLEN) in ovs_flow_key_extract() before calling key_extract().
--- net/openvswitch/flow.c | 7 +++++++ 1 file changed, 7 insertions(+)
net/openvswitch/flow.c +7 -0
@@ -1035,6 +1035,13 @@ int ovs_flow_key_extract(const struct ip_tunnel_info *tun_info,return res; key->mac_proto = res; +if (res ==MAC_PROTO_ETHERNET ) { +int err =check_header (skb,ETH_HLEN ); + +if (unlikely (err)) +return err; + } +#if IS_ENABLED (CONFIG_NET_TC_SKB_EXT )if (tc_skb_ext_tc_enabled ()) { tc_ext =skb_ext_find (skb,TC_SKB_EXT );
Signature · 1 line
2.53.0
Ilya Maximets
maintainerQuoted 30 lines · Cen Zhang (Microsoft)
When a packet arrives on an
ARPHRD_NONEdevice (e.g. TUN),ovs_flow_key_extract()trusts the user-providedskb->protocolfield: if it isETH_P_TEB, the packet is classified asMAC_PROTO_ETHERNETandkey_extract()is called without ensuring the skb hasETH_HLEN(14) bytes of linear data.key_extract()unconditionally pulls 2 *ETH_ALENbytes for MAC addresses andparse_ethertype()pulls 2 more, either of which triggers a kernel BUG in__skb_pull()when the linear area is too small.kernel BUG at
include/linux/skbuff.h:2848!RIP: 0010:key_extract+0xa7e/0xd90 net/openvswitch/flow.c:933 ovs_flow_key_extract+0x419/0xa70 ovs_vport_receive+0x222/0x390 netdev_frame_hook+0x3e0/0x630 tun_get_user+0x2d0c/0x38e0Fixed by adding
check_header(skb, ETH_HLEN)inovs_flow_key_extract()before callingkey_extract().Fixes 217ac77a3c25 ("openvswitch: allow L3 netdev ports")Reported-by [email protected]Signed-off-by Cen Zhang (Microsoft) <[email protected]>--- net/openvswitch/flow.c | 7 +++++++ 1 file changed, 7 insertions(+)net/openvswitch/flow.c +0
-0
net/openvswitch/flow.c int ovs_flow_key_extract(const struct ip_tunnel_info *tun_info, · line 1043
Quoted 9 lines
net/openvswitch/flow.c +6
-0@@ -1035,6 +1035,13 @@ int ovs_flow_key_extract(const struct ip_tunnel_info *tun_info,return res; key->mac_proto = res; +if (res ==MAC_PROTO_ETHERNET ) { +int err =check_header (skb,ETH_HLEN ); + +if (unlikely (err)) +return err; + }
I'd suggest moving this check closer to the place where we're pulling the header, i.e. into the key_extract() function itself.
Best regards, Ilya Maximets.