* [PATCH 0/3] netfilter: propagate routing and XFRM errors
@ 2013-04-05 16:41 Patrick McHardy
2013-04-05 16:41 ` [PATCH 1/3] netfilter: ipv4: propagate routing errors from ip_route_me_harder() Patrick McHardy
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Patrick McHardy @ 2013-04-05 16:41 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, netdev
These patches fix a long standing annoyance: netfilter will return
EPERM for all errors during rerouting or XFRM policy lookups.
These patches change {ip,ip6}_route_me_harder() and nf_xfrm_me_harder()
to return errno codes and use NF_DROP_ERR() to propagate those back
to userspace.
Please apply.
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/3] netfilter: ipv4: propagate routing errors from ip_route_me_harder()
2013-04-05 16:41 [PATCH 0/3] netfilter: propagate routing and XFRM errors Patrick McHardy
@ 2013-04-05 16:41 ` Patrick McHardy
2013-04-05 16:41 ` [PATCH 2/3] netfilter: ipv6: propagate routing errors from ip6_route_me_harder() Patrick McHardy
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Patrick McHardy @ 2013-04-05 16:41 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, netdev
Propagate routing errors from ip_route_me_harder() when dropping a packet
using NF_DROP_ERR(). This makes userspace get the proper error instead of
EPERM for everything.
Example:
# ip r a unreachable default table 100
# ip ru add fwmark 0x1 lookup 100
# iptables -t mangle -A OUTPUT -d 8.8.8.8 -j MARK --set-mark 0x1
Current behaviour:
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
ping: sendmsg: Operation not permitted
ping: sendmsg: Operation not permitted
ping: sendmsg: Operation not permitted
New behaviour:
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
ping: sendmsg: Network is unreachable
ping: sendmsg: Network is unreachable
ping: sendmsg: Network is unreachable
ping: sendmsg: Network is unreachable
Signed-off-by: Patrick McHardy <kaber@trash.net>
---
net/ipv4/netfilter.c | 8 ++++----
net/ipv4/netfilter/iptable_mangle.c | 9 ++++++---
net/ipv4/netfilter/iptable_nat.c | 6 ++++--
3 files changed, 14 insertions(+), 9 deletions(-)
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c
index 4c0cf63..8b201e8 100644
--- a/net/ipv4/netfilter.c
+++ b/net/ipv4/netfilter.c
@@ -40,14 +40,14 @@ int ip_route_me_harder(struct sk_buff *skb, unsigned int addr_type)
fl4.flowi4_flags = flags;
rt = ip_route_output_key(net, &fl4);
if (IS_ERR(rt))
- return -1;
+ return PTR_ERR(rt);
/* Drop old route. */
skb_dst_drop(skb);
skb_dst_set(skb, &rt->dst);
if (skb_dst(skb)->error)
- return -1;
+ return skb_dst(skb)->error;
#ifdef CONFIG_XFRM
if (!(IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) &&
@@ -56,7 +56,7 @@ int ip_route_me_harder(struct sk_buff *skb, unsigned int addr_type)
skb_dst_set(skb, NULL);
dst = xfrm_lookup(net, dst, flowi4_to_flowi(&fl4), skb->sk, 0);
if (IS_ERR(dst))
- return -1;
+ return PTR_ERR(dst);;
skb_dst_set(skb, dst);
}
#endif
@@ -66,7 +66,7 @@ int ip_route_me_harder(struct sk_buff *skb, unsigned int addr_type)
if (skb_headroom(skb) < hh_len &&
pskb_expand_head(skb, HH_DATA_ALIGN(hh_len - skb_headroom(skb)),
0, GFP_ATOMIC))
- return -1;
+ return -ENOMEM;
return 0;
}
diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c
index 85d88f2..cba5658 100644
--- a/net/ipv4/netfilter/iptable_mangle.c
+++ b/net/ipv4/netfilter/iptable_mangle.c
@@ -44,6 +44,7 @@ ipt_mangle_out(struct sk_buff *skb, const struct net_device *out)
u_int8_t tos;
__be32 saddr, daddr;
u_int32_t mark;
+ int err;
/* root is playing with raw sockets. */
if (skb->len < sizeof(struct iphdr) ||
@@ -66,9 +67,11 @@ ipt_mangle_out(struct sk_buff *skb, const struct net_device *out)
if (iph->saddr != saddr ||
iph->daddr != daddr ||
skb->mark != mark ||
- iph->tos != tos)
- if (ip_route_me_harder(skb, RTN_UNSPEC))
- ret = NF_DROP;
+ iph->tos != tos) {
+ err = ip_route_me_harder(skb, RTN_UNSPEC);
+ if (err < 0)
+ ret = NF_DROP_ERR(err);
+ }
}
return ret;
diff --git a/net/ipv4/netfilter/iptable_nat.c b/net/ipv4/netfilter/iptable_nat.c
index eeaff7e..c2937c8 100644
--- a/net/ipv4/netfilter/iptable_nat.c
+++ b/net/ipv4/netfilter/iptable_nat.c
@@ -213,6 +213,7 @@ nf_nat_ipv4_local_fn(unsigned int hooknum,
const struct nf_conn *ct;
enum ip_conntrack_info ctinfo;
unsigned int ret;
+ int err;
/* root is playing with raw sockets. */
if (skb->len < sizeof(struct iphdr) ||
@@ -226,8 +227,9 @@ nf_nat_ipv4_local_fn(unsigned int hooknum,
if (ct->tuplehash[dir].tuple.dst.u3.ip !=
ct->tuplehash[!dir].tuple.src.u3.ip) {
- if (ip_route_me_harder(skb, RTN_UNSPEC))
- ret = NF_DROP;
+ err = ip_route_me_harder(skb, RTN_UNSPEC);
+ if (err < 0)
+ ret = NF_DROP_ERR(err);
}
#ifdef CONFIG_XFRM
else if (!(IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) &&
--
1.8.1.4
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 2/3] netfilter: ipv6: propagate routing errors from ip6_route_me_harder()
2013-04-05 16:41 [PATCH 0/3] netfilter: propagate routing and XFRM errors Patrick McHardy
2013-04-05 16:41 ` [PATCH 1/3] netfilter: ipv4: propagate routing errors from ip_route_me_harder() Patrick McHardy
@ 2013-04-05 16:41 ` Patrick McHardy
2013-04-05 16:41 ` [PATCH 3/3] netfilter: nat: propagate errors from xfrm_me_harder() Patrick McHardy
2013-04-06 12:02 ` [PATCH 0/3] netfilter: propagate routing and XFRM errors Pablo Neira Ayuso
3 siblings, 0 replies; 5+ messages in thread
From: Patrick McHardy @ 2013-04-05 16:41 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, netdev
Propagate routing errors from ip_route_me_harder() when dropping a packet
using NF_DROP_ERR(). This makes userspace get the proper error instead of
EPERM for everything.
# ip -6 r a unreachable default table 100
# ip -6 ru add fwmark 0x1 lookup 100
# ip6tables -t mangle -A OUTPUT -d 2001:4860:4860::8888 -j MARK --set-mark 0x1
Old behaviour:
PING 2001:4860:4860::8888(2001:4860:4860::8888) 56 data bytes
ping: sendmsg: Operation not permitted
ping: sendmsg: Operation not permitted
ping: sendmsg: Operation not permitted
New behaviour:
PING 2001:4860:4860::8888(2001:4860:4860::8888) 56 data bytes
ping: sendmsg: Network is unreachable
ping: sendmsg: Network is unreachable
ping: sendmsg: Network is unreachable
Signed-off-by: Patrick McHardy <kaber@trash.net>
---
net/ipv6/netfilter.c | 6 +++---
net/ipv6/netfilter/ip6table_mangle.c | 9 ++++++---
net/ipv6/netfilter/ip6table_nat.c | 6 ++++--
3 files changed, 13 insertions(+), 8 deletions(-)
diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c
index 429089c..fc5fbd7 100644
--- a/net/ipv6/netfilter.c
+++ b/net/ipv6/netfilter.c
@@ -29,7 +29,7 @@ int ip6_route_me_harder(struct sk_buff *skb)
IP6_INC_STATS(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES);
LIMIT_NETDEBUG(KERN_DEBUG "ip6_route_me_harder: No more route.\n");
dst_release(dst);
- return -EINVAL;
+ return dst->error;
}
/* Drop old route. */
@@ -43,7 +43,7 @@ int ip6_route_me_harder(struct sk_buff *skb)
skb_dst_set(skb, NULL);
dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), skb->sk, 0);
if (IS_ERR(dst))
- return -1;
+ return PTR_ERR(dst);
skb_dst_set(skb, dst);
}
#endif
@@ -53,7 +53,7 @@ int ip6_route_me_harder(struct sk_buff *skb)
if (skb_headroom(skb) < hh_len &&
pskb_expand_head(skb, HH_DATA_ALIGN(hh_len - skb_headroom(skb)),
0, GFP_ATOMIC))
- return -1;
+ return -ENOMEM;
return 0;
}
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c
index 6134a1e..e075399 100644
--- a/net/ipv6/netfilter/ip6table_mangle.c
+++ b/net/ipv6/netfilter/ip6table_mangle.c
@@ -38,7 +38,7 @@ ip6t_mangle_out(struct sk_buff *skb, const struct net_device *out)
struct in6_addr saddr, daddr;
u_int8_t hop_limit;
u_int32_t flowlabel, mark;
-
+ int err;
#if 0
/* root is playing with raw sockets. */
if (skb->len < sizeof(struct iphdr) ||
@@ -65,8 +65,11 @@ ip6t_mangle_out(struct sk_buff *skb, const struct net_device *out)
!ipv6_addr_equal(&ipv6_hdr(skb)->daddr, &daddr) ||
skb->mark != mark ||
ipv6_hdr(skb)->hop_limit != hop_limit ||
- flowlabel != *((u_int32_t *)ipv6_hdr(skb))))
- return ip6_route_me_harder(skb) == 0 ? ret : NF_DROP;
+ flowlabel != *((u_int32_t *)ipv6_hdr(skb)))) {
+ err = ip6_route_me_harder(skb);
+ if (err < 0)
+ ret = NF_DROP_ERR(err);
+ }
return ret;
}
diff --git a/net/ipv6/netfilter/ip6table_nat.c b/net/ipv6/netfilter/ip6table_nat.c
index e0e788d..97e2edd 100644
--- a/net/ipv6/netfilter/ip6table_nat.c
+++ b/net/ipv6/netfilter/ip6table_nat.c
@@ -215,6 +215,7 @@ nf_nat_ipv6_local_fn(unsigned int hooknum,
const struct nf_conn *ct;
enum ip_conntrack_info ctinfo;
unsigned int ret;
+ int err;
/* root is playing with raw sockets. */
if (skb->len < sizeof(struct ipv6hdr))
@@ -227,8 +228,9 @@ nf_nat_ipv6_local_fn(unsigned int hooknum,
if (!nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.dst.u3,
&ct->tuplehash[!dir].tuple.src.u3)) {
- if (ip6_route_me_harder(skb))
- ret = NF_DROP;
+ err = ip6_route_me_harder(skb);
+ if (err < 0)
+ ret = NF_DROP_ERR(err);
}
#ifdef CONFIG_XFRM
else if (!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) &&
--
1.8.1.4
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 3/3] netfilter: nat: propagate errors from xfrm_me_harder()
2013-04-05 16:41 [PATCH 0/3] netfilter: propagate routing and XFRM errors Patrick McHardy
2013-04-05 16:41 ` [PATCH 1/3] netfilter: ipv4: propagate routing errors from ip_route_me_harder() Patrick McHardy
2013-04-05 16:41 ` [PATCH 2/3] netfilter: ipv6: propagate routing errors from ip6_route_me_harder() Patrick McHardy
@ 2013-04-05 16:41 ` Patrick McHardy
2013-04-06 12:02 ` [PATCH 0/3] netfilter: propagate routing and XFRM errors Pablo Neira Ayuso
3 siblings, 0 replies; 5+ messages in thread
From: Patrick McHardy @ 2013-04-05 16:41 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, netdev
Propagate errors from ip_xfrm_me_harder() instead of returning EPERM in
all cases.
Signed-off-by: Patrick McHardy <kaber@trash.net>
---
net/ipv4/netfilter/iptable_nat.c | 17 +++++++++++------
net/ipv6/netfilter/ip6table_nat.c | 17 +++++++++++------
net/netfilter/nf_nat_core.c | 9 +++++----
3 files changed, 27 insertions(+), 16 deletions(-)
diff --git a/net/ipv4/netfilter/iptable_nat.c b/net/ipv4/netfilter/iptable_nat.c
index c2937c8..6383273 100644
--- a/net/ipv4/netfilter/iptable_nat.c
+++ b/net/ipv4/netfilter/iptable_nat.c
@@ -176,6 +176,7 @@ nf_nat_ipv4_out(unsigned int hooknum,
#ifdef CONFIG_XFRM
const struct nf_conn *ct;
enum ip_conntrack_info ctinfo;
+ int err;
#endif
unsigned int ret;
@@ -195,9 +196,11 @@ nf_nat_ipv4_out(unsigned int hooknum,
ct->tuplehash[!dir].tuple.dst.u3.ip) ||
(ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP &&
ct->tuplehash[dir].tuple.src.u.all !=
- ct->tuplehash[!dir].tuple.dst.u.all))
- if (nf_xfrm_me_harder(skb, AF_INET) < 0)
- ret = NF_DROP;
+ ct->tuplehash[!dir].tuple.dst.u.all)) {
+ err = nf_xfrm_me_harder(skb, AF_INET);
+ if (err < 0)
+ ret = NF_DROP_ERR(err);
+ }
}
#endif
return ret;
@@ -235,9 +238,11 @@ nf_nat_ipv4_local_fn(unsigned int hooknum,
else if (!(IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) &&
ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP &&
ct->tuplehash[dir].tuple.dst.u.all !=
- ct->tuplehash[!dir].tuple.src.u.all)
- if (nf_xfrm_me_harder(skb, AF_INET) < 0)
- ret = NF_DROP;
+ ct->tuplehash[!dir].tuple.src.u.all) {
+ err = nf_xfrm_me_harder(skb, AF_INET);
+ if (err < 0)
+ ret = NF_DROP_ERR(err);
+ }
#endif
}
return ret;
diff --git a/net/ipv6/netfilter/ip6table_nat.c b/net/ipv6/netfilter/ip6table_nat.c
index 97e2edd..6383f90 100644
--- a/net/ipv6/netfilter/ip6table_nat.c
+++ b/net/ipv6/netfilter/ip6table_nat.c
@@ -179,6 +179,7 @@ nf_nat_ipv6_out(unsigned int hooknum,
#ifdef CONFIG_XFRM
const struct nf_conn *ct;
enum ip_conntrack_info ctinfo;
+ int err;
#endif
unsigned int ret;
@@ -197,9 +198,11 @@ nf_nat_ipv6_out(unsigned int hooknum,
&ct->tuplehash[!dir].tuple.dst.u3) ||
(ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMPV6 &&
ct->tuplehash[dir].tuple.src.u.all !=
- ct->tuplehash[!dir].tuple.dst.u.all))
- if (nf_xfrm_me_harder(skb, AF_INET6) < 0)
- ret = NF_DROP;
+ ct->tuplehash[!dir].tuple.dst.u.all)) {
+ err = nf_xfrm_me_harder(skb, AF_INET6);
+ if (err < 0)
+ ret = NF_DROP_ERR(err);
+ }
}
#endif
return ret;
@@ -236,9 +239,11 @@ nf_nat_ipv6_local_fn(unsigned int hooknum,
else if (!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) &&
ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMPV6 &&
ct->tuplehash[dir].tuple.dst.u.all !=
- ct->tuplehash[!dir].tuple.src.u.all)
- if (nf_xfrm_me_harder(skb, AF_INET6))
- ret = NF_DROP;
+ ct->tuplehash[!dir].tuple.src.u.all) {
+ err = nf_xfrm_me_harder(skb, AF_INET6);
+ if (err < 0)
+ ret = NF_DROP_ERR(err);
+ }
#endif
}
return ret;
diff --git a/net/netfilter/nf_nat_core.c b/net/netfilter/nf_nat_core.c
index 8d5769c..346f871 100644
--- a/net/netfilter/nf_nat_core.c
+++ b/net/netfilter/nf_nat_core.c
@@ -87,9 +87,10 @@ int nf_xfrm_me_harder(struct sk_buff *skb, unsigned int family)
struct flowi fl;
unsigned int hh_len;
struct dst_entry *dst;
+ int err;
- if (xfrm_decode_session(skb, &fl, family) < 0)
- return -1;
+ err = xfrm_decode_session(skb, &fl, family);
+ return err;
dst = skb_dst(skb);
if (dst->xfrm)
@@ -98,7 +99,7 @@ int nf_xfrm_me_harder(struct sk_buff *skb, unsigned int family)
dst = xfrm_lookup(dev_net(dst->dev), dst, &fl, skb->sk, 0);
if (IS_ERR(dst))
- return -1;
+ return PTR_ERR(dst);
skb_dst_drop(skb);
skb_dst_set(skb, dst);
@@ -107,7 +108,7 @@ int nf_xfrm_me_harder(struct sk_buff *skb, unsigned int family)
hh_len = skb_dst(skb)->dev->hard_header_len;
if (skb_headroom(skb) < hh_len &&
pskb_expand_head(skb, hh_len - skb_headroom(skb), 0, GFP_ATOMIC))
- return -1;
+ return -ENOMEM;
return 0;
}
EXPORT_SYMBOL(nf_xfrm_me_harder);
--
1.8.1.4
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH 0/3] netfilter: propagate routing and XFRM errors
2013-04-05 16:41 [PATCH 0/3] netfilter: propagate routing and XFRM errors Patrick McHardy
` (2 preceding siblings ...)
2013-04-05 16:41 ` [PATCH 3/3] netfilter: nat: propagate errors from xfrm_me_harder() Patrick McHardy
@ 2013-04-06 12:02 ` Pablo Neira Ayuso
3 siblings, 0 replies; 5+ messages in thread
From: Pablo Neira Ayuso @ 2013-04-06 12:02 UTC (permalink / raw)
To: Patrick McHardy; +Cc: netfilter-devel, netdev
On Fri, Apr 05, 2013 at 06:41:09PM +0200, Patrick McHardy wrote:
> These patches fix a long standing annoyance: netfilter will return
> EPERM for all errors during rerouting or XFRM policy lookups.
>
> These patches change {ip,ip6}_route_me_harder() and nf_xfrm_me_harder()
> to return errno codes and use NF_DROP_ERR() to propagate those back
> to userspace.
Applied, thanks Patrick!
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2013-04-06 12:02 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-04-05 16:41 [PATCH 0/3] netfilter: propagate routing and XFRM errors Patrick McHardy
2013-04-05 16:41 ` [PATCH 1/3] netfilter: ipv4: propagate routing errors from ip_route_me_harder() Patrick McHardy
2013-04-05 16:41 ` [PATCH 2/3] netfilter: ipv6: propagate routing errors from ip6_route_me_harder() Patrick McHardy
2013-04-05 16:41 ` [PATCH 3/3] netfilter: nat: propagate errors from xfrm_me_harder() Patrick McHardy
2013-04-06 12:02 ` [PATCH 0/3] netfilter: propagate routing and XFRM errors Pablo Neira Ayuso
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.