Commit 61622cc6 authored by Steffen Klassert's avatar Steffen Klassert

xfrm4: Properly handle unsupported protocols

We don't catch the case if an unsupported protocol is submitted
to the xfrm4 protocol handlers, this can lead to NULL pointer
dereferences. Fix this by adding the appropriate checks.

Fixes: 3328715e ("xfrm4: Add IPsec protocol multiplexer")
Signed-off-by: default avatarSteffen Klassert <steffen.klassert@secunet.com>
parent a3245236
...@@ -50,8 +50,12 @@ int xfrm4_rcv_cb(struct sk_buff *skb, u8 protocol, int err) ...@@ -50,8 +50,12 @@ int xfrm4_rcv_cb(struct sk_buff *skb, u8 protocol, int err)
{ {
int ret; int ret;
struct xfrm4_protocol *handler; struct xfrm4_protocol *handler;
struct xfrm4_protocol __rcu **head = proto_handlers(protocol);
for_each_protocol_rcu(*proto_handlers(protocol), handler) if (!head)
return 0;
for_each_protocol_rcu(*head, handler)
if ((ret = handler->cb_handler(skb, err)) <= 0) if ((ret = handler->cb_handler(skb, err)) <= 0)
return ret; return ret;
...@@ -64,15 +68,20 @@ int xfrm4_rcv_encap(struct sk_buff *skb, int nexthdr, __be32 spi, ...@@ -64,15 +68,20 @@ int xfrm4_rcv_encap(struct sk_buff *skb, int nexthdr, __be32 spi,
{ {
int ret; int ret;
struct xfrm4_protocol *handler; struct xfrm4_protocol *handler;
struct xfrm4_protocol __rcu **head = proto_handlers(nexthdr);
XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4 = NULL; XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4 = NULL;
XFRM_SPI_SKB_CB(skb)->family = AF_INET; XFRM_SPI_SKB_CB(skb)->family = AF_INET;
XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct iphdr, daddr); XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct iphdr, daddr);
for_each_protocol_rcu(*proto_handlers(nexthdr), handler) if (!head)
goto out;
for_each_protocol_rcu(*head, handler)
if ((ret = handler->input_handler(skb, nexthdr, spi, encap_type)) != -EINVAL) if ((ret = handler->input_handler(skb, nexthdr, spi, encap_type)) != -EINVAL)
return ret; return ret;
out:
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
kfree_skb(skb); kfree_skb(skb);
...@@ -208,6 +217,9 @@ int xfrm4_protocol_register(struct xfrm4_protocol *handler, ...@@ -208,6 +217,9 @@ int xfrm4_protocol_register(struct xfrm4_protocol *handler,
int ret = -EEXIST; int ret = -EEXIST;
int priority = handler->priority; int priority = handler->priority;
if (!proto_handlers(protocol) || !netproto(protocol))
return -EINVAL;
mutex_lock(&xfrm4_protocol_mutex); mutex_lock(&xfrm4_protocol_mutex);
if (!rcu_dereference_protected(*proto_handlers(protocol), if (!rcu_dereference_protected(*proto_handlers(protocol),
...@@ -250,6 +262,9 @@ int xfrm4_protocol_deregister(struct xfrm4_protocol *handler, ...@@ -250,6 +262,9 @@ int xfrm4_protocol_deregister(struct xfrm4_protocol *handler,
struct xfrm4_protocol *t; struct xfrm4_protocol *t;
int ret = -ENOENT; int ret = -ENOENT;
if (!proto_handlers(protocol) || !netproto(protocol))
return -EINVAL;
mutex_lock(&xfrm4_protocol_mutex); mutex_lock(&xfrm4_protocol_mutex);
for (pprev = proto_handlers(protocol); for (pprev = proto_handlers(protocol);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment