From e104411b82f5c4d19752c335492036abdbf5880d Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Thu, 8 Sep 2005 15:11:55 -0700 Subject: [PATCH] [XFRM]: Always release dst_entry on error in xfrm_lookup Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/ipv4/netfilter/ipt_REJECT.c | 5 +---- net/ipv6/datagram.c | 4 +--- net/ipv6/icmp.c | 5 ++--- net/ipv6/ndisc.c | 16 ++++------------ net/ipv6/netfilter/ip6t_REJECT.c | 5 +---- net/ipv6/raw.c | 4 +--- net/ipv6/tcp_ipv6.c | 15 +++------------ net/ipv6/udp.c | 4 +--- net/xfrm/xfrm_policy.c | 8 ++++---- 9 files changed, 18 insertions(+), 48 deletions(-) diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c index f115a84a4ac..f057025a719 100644 --- a/net/ipv4/netfilter/ipt_REJECT.c +++ b/net/ipv4/netfilter/ipt_REJECT.c @@ -92,10 +92,7 @@ static inline struct rtable *route_reverse(struct sk_buff *skb, fl.fl_ip_sport = tcph->dest; fl.fl_ip_dport = tcph->source; - if (xfrm_lookup((struct dst_entry **)&rt, &fl, NULL, 0)) { - dst_release(&rt->u.dst); - rt = NULL; - } + xfrm_lookup((struct dst_entry **)&rt, &fl, NULL, 0); return rt; } diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 157cec64803..cc518405b3e 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c @@ -175,10 +175,8 @@ ipv4_connected: if (final_p) ipv6_addr_copy(&fl.fl6_dst, final_p); - if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) { - dst_release(dst); + if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) goto out; - } /* source address lookup done in ip6_dst_lookup */ diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 34e99c55e85..b7185fb3377 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -374,7 +374,7 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, if (err) goto out; if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) - goto out_dst_release; + goto out; if (ipv6_addr_is_multicast(&fl.fl6_dst)) hlimit = np->mcast_hops; @@ -469,7 +469,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb) if (err) goto out; if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) - goto out_dst_release; + goto out; if (ipv6_addr_is_multicast(&fl.fl6_dst)) hlimit = np->mcast_hops; @@ -505,7 +505,6 @@ static void icmpv6_echo_reply(struct sk_buff *skb) out_put: if (likely(idev != NULL)) in6_dev_put(idev); -out_dst_release: dst_release(dst); out: icmpv6_xmit_unlock(); diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index a7eae30f455..555a31347ed 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -447,10 +447,8 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh, return; err = xfrm_lookup(&dst, &fl, NULL, 0); - if (err < 0) { - dst_release(dst); + if (err < 0) return; - } if (inc_opt) { if (dev->addr_len) @@ -539,10 +537,8 @@ void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh, return; err = xfrm_lookup(&dst, &fl, NULL, 0); - if (err < 0) { - dst_release(dst); + if (err < 0) return; - } len = sizeof(struct icmp6hdr) + sizeof(struct in6_addr); 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, return; err = xfrm_lookup(&dst, &fl, NULL, 0); - if (err < 0) { - dst_release(dst); + if (err < 0) return; - } len = sizeof(struct icmp6hdr); if (dev->addr_len) @@ -1353,10 +1347,8 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, return; err = xfrm_lookup(&dst, &fl, NULL, 0); - if (err) { - dst_release(dst); + if (err) return; - } rt = (struct rt6_info *) dst; diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c index 14316c3ebde..b03e87adca9 100644 --- a/net/ipv6/netfilter/ip6t_REJECT.c +++ b/net/ipv6/netfilter/ip6t_REJECT.c @@ -100,11 +100,8 @@ static void send_reset(struct sk_buff *oldskb) dst = ip6_route_output(NULL, &fl); if (dst == NULL) return; - if (dst->error || - xfrm_lookup(&dst, &fl, NULL, 0)) { - dst_release(dst); + if (dst->error || xfrm_lookup(&dst, &fl, NULL, 0)) return; - } hh_len = (dst->dev->hard_header_len + 15)&~15; nskb = alloc_skb(hh_len + 15 + dst->header_len + sizeof(struct ipv6hdr) diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 2ad37893334..5aa3691c578 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -782,10 +782,8 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, if (final_p) ipv6_addr_copy(&fl.fl6_dst, final_p); - if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) { - dst_release(dst); + if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) goto out; - } if (hlimit < 0) { if (ipv6_addr_is_multicast(&fl.fl6_dst)) diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 246414b27d0..80643e6b346 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -632,10 +632,8 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, if (final_p) ipv6_addr_copy(&fl.fl6_dst, final_p); - if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) { - dst_release(dst); + if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) goto failure; - } if (saddr == NULL) { saddr = &fl.fl6_src; @@ -888,7 +886,6 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req, } done: - dst_release(dst); if (opt && opt != np->opt) sock_kfree_s(sk, opt, opt->tot_len); return err; @@ -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. */ if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) { - if ((xfrm_lookup(&buff->dst, &fl, NULL, 0)) < 0) { - dst_release(buff->dst); + if ((xfrm_lookup(&buff->dst, &fl, NULL, 0)) < 0) return; - } ip6_xmit(NULL, buff, &fl, NULL, 0); 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 fl.fl_ip_sport = t1->source; if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) { - if ((xfrm_lookup(&buff->dst, &fl, NULL, 0)) < 0) { - dst_release(buff->dst); + if ((xfrm_lookup(&buff->dst, &fl, NULL, 0)) < 0) return; - } ip6_xmit(NULL, buff, &fl, NULL, 0); TCP_INC_STATS_BH(TCP_MIB_OUTSEGS); return; @@ -1733,7 +1726,6 @@ static int tcp_v6_rebuild_header(struct sock *sk) if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) { sk->sk_err_soft = -err; - dst_release(dst); return err; } @@ -1786,7 +1778,6 @@ static int tcp_v6_xmit(struct sk_buff *skb, int ipfragok) if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) { sk->sk_route_caps = 0; - dst_release(dst); return err; } diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index f5ae14810a7..69b146843a2 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -799,10 +799,8 @@ do_udp_sendmsg: if (final_p) ipv6_addr_copy(&fl->fl6_dst, final_p); - if ((err = xfrm_lookup(&dst, fl, sk, 0)) < 0) { - dst_release(dst); + if ((err = xfrm_lookup(&dst, fl, sk, 0)) < 0) goto out; - } if (hlimit < 0) { if (ipv6_addr_is_multicast(&fl->fl6_dst)) diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 83c8135e176..fda737d77ed 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -765,8 +765,8 @@ restart: switch (policy->action) { case XFRM_POLICY_BLOCK: /* Prohibit the flow */ - xfrm_pol_put(policy); - return -EPERM; + err = -EPERM; + goto error; case XFRM_POLICY_ALLOW: if (policy->xfrm_nr == 0) { @@ -782,8 +782,8 @@ restart: */ dst = xfrm_find_bundle(fl, policy, family); if (IS_ERR(dst)) { - xfrm_pol_put(policy); - return PTR_ERR(dst); + err = PTR_ERR(dst); + goto error; } if (dst) -- 2.11.4.GIT