Commit e104411b authored by Patrick McHardy's avatar Patrick McHardy Committed by David S. Miller

[XFRM]: Always release dst_entry on error in xfrm_lookup

Signed-off-by: default avatarPatrick McHardy <kaber@trash.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent cf0b450c
...@@ -92,10 +92,7 @@ static inline struct rtable *route_reverse(struct sk_buff *skb, ...@@ -92,10 +92,7 @@ static inline struct rtable *route_reverse(struct sk_buff *skb,
fl.fl_ip_sport = tcph->dest; fl.fl_ip_sport = tcph->dest;
fl.fl_ip_dport = tcph->source; fl.fl_ip_dport = tcph->source;
if (xfrm_lookup((struct dst_entry **)&rt, &fl, NULL, 0)) { xfrm_lookup((struct dst_entry **)&rt, &fl, NULL, 0);
dst_release(&rt->u.dst);
rt = NULL;
}
return rt; return rt;
} }
......
...@@ -175,10 +175,8 @@ int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) ...@@ -175,10 +175,8 @@ int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
if (final_p) if (final_p)
ipv6_addr_copy(&fl.fl6_dst, final_p); ipv6_addr_copy(&fl.fl6_dst, final_p);
if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) { if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0)
dst_release(dst);
goto out; goto out;
}
/* source address lookup done in ip6_dst_lookup */ /* source address lookup done in ip6_dst_lookup */
......
...@@ -374,7 +374,7 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, ...@@ -374,7 +374,7 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info,
if (err) if (err)
goto out; goto out;
if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0)
goto out_dst_release; goto out;
if (ipv6_addr_is_multicast(&fl.fl6_dst)) if (ipv6_addr_is_multicast(&fl.fl6_dst))
hlimit = np->mcast_hops; hlimit = np->mcast_hops;
...@@ -469,7 +469,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb) ...@@ -469,7 +469,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
if (err) if (err)
goto out; goto out;
if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0)
goto out_dst_release; goto out;
if (ipv6_addr_is_multicast(&fl.fl6_dst)) if (ipv6_addr_is_multicast(&fl.fl6_dst))
hlimit = np->mcast_hops; hlimit = np->mcast_hops;
...@@ -505,7 +505,6 @@ static void icmpv6_echo_reply(struct sk_buff *skb) ...@@ -505,7 +505,6 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
out_put: out_put:
if (likely(idev != NULL)) if (likely(idev != NULL))
in6_dev_put(idev); in6_dev_put(idev);
out_dst_release:
dst_release(dst); dst_release(dst);
out: out:
icmpv6_xmit_unlock(); icmpv6_xmit_unlock();
......
...@@ -447,10 +447,8 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh, ...@@ -447,10 +447,8 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
return; return;
err = xfrm_lookup(&dst, &fl, NULL, 0); err = xfrm_lookup(&dst, &fl, NULL, 0);
if (err < 0) { if (err < 0)
dst_release(dst);
return; return;
}
if (inc_opt) { if (inc_opt) {
if (dev->addr_len) if (dev->addr_len)
...@@ -539,10 +537,8 @@ void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh, ...@@ -539,10 +537,8 @@ void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh,
return; return;
err = xfrm_lookup(&dst, &fl, NULL, 0); err = xfrm_lookup(&dst, &fl, NULL, 0);
if (err < 0) { if (err < 0)
dst_release(dst);
return; return;
}
len = sizeof(struct icmp6hdr) + sizeof(struct in6_addr); len = sizeof(struct icmp6hdr) + sizeof(struct in6_addr);
send_llinfo = dev->addr_len && !ipv6_addr_any(saddr); send_llinfo = dev->addr_len && !ipv6_addr_any(saddr);
...@@ -616,10 +612,8 @@ void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr, ...@@ -616,10 +612,8 @@ void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr,
return; return;
err = xfrm_lookup(&dst, &fl, NULL, 0); err = xfrm_lookup(&dst, &fl, NULL, 0);
if (err < 0) { if (err < 0)
dst_release(dst);
return; return;
}
len = sizeof(struct icmp6hdr); len = sizeof(struct icmp6hdr);
if (dev->addr_len) if (dev->addr_len)
...@@ -1353,10 +1347,8 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, ...@@ -1353,10 +1347,8 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
return; return;
err = xfrm_lookup(&dst, &fl, NULL, 0); err = xfrm_lookup(&dst, &fl, NULL, 0);
if (err) { if (err)
dst_release(dst);
return; return;
}
rt = (struct rt6_info *) dst; rt = (struct rt6_info *) dst;
......
...@@ -100,11 +100,8 @@ static void send_reset(struct sk_buff *oldskb) ...@@ -100,11 +100,8 @@ static void send_reset(struct sk_buff *oldskb)
dst = ip6_route_output(NULL, &fl); dst = ip6_route_output(NULL, &fl);
if (dst == NULL) if (dst == NULL)
return; return;
if (dst->error || if (dst->error || xfrm_lookup(&dst, &fl, NULL, 0))
xfrm_lookup(&dst, &fl, NULL, 0)) {
dst_release(dst);
return; return;
}
hh_len = (dst->dev->hard_header_len + 15)&~15; hh_len = (dst->dev->hard_header_len + 15)&~15;
nskb = alloc_skb(hh_len + 15 + dst->header_len + sizeof(struct ipv6hdr) nskb = alloc_skb(hh_len + 15 + dst->header_len + sizeof(struct ipv6hdr)
......
...@@ -782,10 +782,8 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, ...@@ -782,10 +782,8 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
if (final_p) if (final_p)
ipv6_addr_copy(&fl.fl6_dst, final_p); ipv6_addr_copy(&fl.fl6_dst, final_p);
if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) { if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0)
dst_release(dst);
goto out; goto out;
}
if (hlimit < 0) { if (hlimit < 0) {
if (ipv6_addr_is_multicast(&fl.fl6_dst)) if (ipv6_addr_is_multicast(&fl.fl6_dst))
......
...@@ -632,10 +632,8 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, ...@@ -632,10 +632,8 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
if (final_p) if (final_p)
ipv6_addr_copy(&fl.fl6_dst, final_p); ipv6_addr_copy(&fl.fl6_dst, final_p);
if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) { if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0)
dst_release(dst);
goto failure; goto failure;
}
if (saddr == NULL) { if (saddr == NULL) {
saddr = &fl.fl6_src; saddr = &fl.fl6_src;
...@@ -888,7 +886,6 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req, ...@@ -888,7 +886,6 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req,
} }
done: done:
dst_release(dst);
if (opt && opt != np->opt) if (opt && opt != np->opt)
sock_kfree_s(sk, opt, opt->tot_len); sock_kfree_s(sk, opt, opt->tot_len);
return err; return err;
...@@ -1000,10 +997,8 @@ static void tcp_v6_send_reset(struct sk_buff *skb) ...@@ -1000,10 +997,8 @@ static void tcp_v6_send_reset(struct sk_buff *skb)
/* sk = NULL, but it is safe for now. RST socket required. */ /* sk = NULL, but it is safe for now. RST socket required. */
if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) { if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) {
if ((xfrm_lookup(&buff->dst, &fl, NULL, 0)) < 0) { if ((xfrm_lookup(&buff->dst, &fl, NULL, 0)) < 0)
dst_release(buff->dst);
return; return;
}
ip6_xmit(NULL, buff, &fl, NULL, 0); ip6_xmit(NULL, buff, &fl, NULL, 0);
TCP_INC_STATS_BH(TCP_MIB_OUTSEGS); TCP_INC_STATS_BH(TCP_MIB_OUTSEGS);
...@@ -1067,10 +1062,8 @@ static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ...@@ -1067,10 +1062,8 @@ static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32
fl.fl_ip_sport = t1->source; fl.fl_ip_sport = t1->source;
if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) { if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) {
if ((xfrm_lookup(&buff->dst, &fl, NULL, 0)) < 0) { if ((xfrm_lookup(&buff->dst, &fl, NULL, 0)) < 0)
dst_release(buff->dst);
return; return;
}
ip6_xmit(NULL, buff, &fl, NULL, 0); ip6_xmit(NULL, buff, &fl, NULL, 0);
TCP_INC_STATS_BH(TCP_MIB_OUTSEGS); TCP_INC_STATS_BH(TCP_MIB_OUTSEGS);
return; return;
...@@ -1733,7 +1726,6 @@ static int tcp_v6_rebuild_header(struct sock *sk) ...@@ -1733,7 +1726,6 @@ static int tcp_v6_rebuild_header(struct sock *sk)
if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) { if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
sk->sk_err_soft = -err; sk->sk_err_soft = -err;
dst_release(dst);
return err; return err;
} }
...@@ -1786,7 +1778,6 @@ static int tcp_v6_xmit(struct sk_buff *skb, int ipfragok) ...@@ -1786,7 +1778,6 @@ static int tcp_v6_xmit(struct sk_buff *skb, int ipfragok)
if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) { if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
sk->sk_route_caps = 0; sk->sk_route_caps = 0;
dst_release(dst);
return err; return err;
} }
......
...@@ -799,10 +799,8 @@ static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, ...@@ -799,10 +799,8 @@ static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk,
if (final_p) if (final_p)
ipv6_addr_copy(&fl->fl6_dst, final_p); ipv6_addr_copy(&fl->fl6_dst, final_p);
if ((err = xfrm_lookup(&dst, fl, sk, 0)) < 0) { if ((err = xfrm_lookup(&dst, fl, sk, 0)) < 0)
dst_release(dst);
goto out; goto out;
}
if (hlimit < 0) { if (hlimit < 0) {
if (ipv6_addr_is_multicast(&fl->fl6_dst)) if (ipv6_addr_is_multicast(&fl->fl6_dst))
......
...@@ -765,8 +765,8 @@ int xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl, ...@@ -765,8 +765,8 @@ int xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl,
switch (policy->action) { switch (policy->action) {
case XFRM_POLICY_BLOCK: case XFRM_POLICY_BLOCK:
/* Prohibit the flow */ /* Prohibit the flow */
xfrm_pol_put(policy); err = -EPERM;
return -EPERM; goto error;
case XFRM_POLICY_ALLOW: case XFRM_POLICY_ALLOW:
if (policy->xfrm_nr == 0) { if (policy->xfrm_nr == 0) {
...@@ -782,8 +782,8 @@ int xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl, ...@@ -782,8 +782,8 @@ int xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl,
*/ */
dst = xfrm_find_bundle(fl, policy, family); dst = xfrm_find_bundle(fl, policy, family);
if (IS_ERR(dst)) { if (IS_ERR(dst)) {
xfrm_pol_put(policy); err = PTR_ERR(dst);
return PTR_ERR(dst); goto error;
} }
if (dst) if (dst)
......
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