Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

netfilter: nat: propagate errors from xfrm_me_harder()

Propagate errors from ip_xfrm_me_harder() instead of returning EPERM in
all cases.

Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

authored by

Patrick McHardy and committed by
Pablo Neira Ayuso
aaa795ad 58e35d14

+27 -16
+11 -6
net/ipv4/netfilter/iptable_nat.c
··· 176 176 #ifdef CONFIG_XFRM 177 177 const struct nf_conn *ct; 178 178 enum ip_conntrack_info ctinfo; 179 + int err; 179 180 #endif 180 181 unsigned int ret; 181 182 ··· 196 195 ct->tuplehash[!dir].tuple.dst.u3.ip) || 197 196 (ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP && 198 197 ct->tuplehash[dir].tuple.src.u.all != 199 - ct->tuplehash[!dir].tuple.dst.u.all)) 200 - if (nf_xfrm_me_harder(skb, AF_INET) < 0) 201 - ret = NF_DROP; 198 + ct->tuplehash[!dir].tuple.dst.u.all)) { 199 + err = nf_xfrm_me_harder(skb, AF_INET); 200 + if (err < 0) 201 + ret = NF_DROP_ERR(err); 202 + } 202 203 } 203 204 #endif 204 205 return ret; ··· 238 235 else if (!(IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) && 239 236 ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP && 240 237 ct->tuplehash[dir].tuple.dst.u.all != 241 - ct->tuplehash[!dir].tuple.src.u.all) 242 - if (nf_xfrm_me_harder(skb, AF_INET) < 0) 243 - ret = NF_DROP; 238 + ct->tuplehash[!dir].tuple.src.u.all) { 239 + err = nf_xfrm_me_harder(skb, AF_INET); 240 + if (err < 0) 241 + ret = NF_DROP_ERR(err); 242 + } 244 243 #endif 245 244 } 246 245 return ret;
+11 -6
net/ipv6/netfilter/ip6table_nat.c
··· 179 179 #ifdef CONFIG_XFRM 180 180 const struct nf_conn *ct; 181 181 enum ip_conntrack_info ctinfo; 182 + int err; 182 183 #endif 183 184 unsigned int ret; 184 185 ··· 198 197 &ct->tuplehash[!dir].tuple.dst.u3) || 199 198 (ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMPV6 && 200 199 ct->tuplehash[dir].tuple.src.u.all != 201 - ct->tuplehash[!dir].tuple.dst.u.all)) 202 - if (nf_xfrm_me_harder(skb, AF_INET6) < 0) 203 - ret = NF_DROP; 200 + ct->tuplehash[!dir].tuple.dst.u.all)) { 201 + err = nf_xfrm_me_harder(skb, AF_INET6); 202 + if (err < 0) 203 + ret = NF_DROP_ERR(err); 204 + } 204 205 } 205 206 #endif 206 207 return ret; ··· 239 236 else if (!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) && 240 237 ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMPV6 && 241 238 ct->tuplehash[dir].tuple.dst.u.all != 242 - ct->tuplehash[!dir].tuple.src.u.all) 243 - if (nf_xfrm_me_harder(skb, AF_INET6)) 244 - ret = NF_DROP; 239 + ct->tuplehash[!dir].tuple.src.u.all) { 240 + err = nf_xfrm_me_harder(skb, AF_INET6); 241 + if (err < 0) 242 + ret = NF_DROP_ERR(err); 243 + } 245 244 #endif 246 245 } 247 246 return ret;
+5 -4
net/netfilter/nf_nat_core.c
··· 87 87 struct flowi fl; 88 88 unsigned int hh_len; 89 89 struct dst_entry *dst; 90 + int err; 90 91 91 - if (xfrm_decode_session(skb, &fl, family) < 0) 92 - return -1; 92 + err = xfrm_decode_session(skb, &fl, family); 93 + return err; 93 94 94 95 dst = skb_dst(skb); 95 96 if (dst->xfrm) ··· 99 98 100 99 dst = xfrm_lookup(dev_net(dst->dev), dst, &fl, skb->sk, 0); 101 100 if (IS_ERR(dst)) 102 - return -1; 101 + return PTR_ERR(dst); 103 102 104 103 skb_dst_drop(skb); 105 104 skb_dst_set(skb, dst); ··· 108 107 hh_len = skb_dst(skb)->dev->hard_header_len; 109 108 if (skb_headroom(skb) < hh_len && 110 109 pskb_expand_head(skb, hh_len - skb_headroom(skb), 0, GFP_ATOMIC)) 111 - return -1; 110 + return -ENOMEM; 112 111 return 0; 113 112 } 114 113 EXPORT_SYMBOL(nf_xfrm_me_harder);