Commit ec34c015 authored by David S. Miller's avatar David S. Miller

Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf

Pablo Neira Ayuso says:

====================
Netfilter fixes for net

The following patchset contains Netfilter fixes for net:

1) Fix endianness issue in flowtable TCP flags dissector,
   from Arnd Bergmann.

2) Extend flowtable test script with dnat rules, from Florian Westphal.

3) Reject padding in ebtables user entries and validate computed user
   offset, reported by syzbot, from Florian Westphal.

4) Fix endianness in nft_tproxy, from Phil Sutter.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents a5bcd72e 8cb4ec44
...@@ -1867,7 +1867,7 @@ static int ebt_buf_count(struct ebt_entries_buf_state *state, unsigned int sz) ...@@ -1867,7 +1867,7 @@ static int ebt_buf_count(struct ebt_entries_buf_state *state, unsigned int sz)
} }
static int ebt_buf_add(struct ebt_entries_buf_state *state, static int ebt_buf_add(struct ebt_entries_buf_state *state,
void *data, unsigned int sz) const void *data, unsigned int sz)
{ {
if (state->buf_kern_start == NULL) if (state->buf_kern_start == NULL)
goto count_only; goto count_only;
...@@ -1901,7 +1901,7 @@ enum compat_mwt { ...@@ -1901,7 +1901,7 @@ enum compat_mwt {
EBT_COMPAT_TARGET, EBT_COMPAT_TARGET,
}; };
static int compat_mtw_from_user(struct compat_ebt_entry_mwt *mwt, static int compat_mtw_from_user(const struct compat_ebt_entry_mwt *mwt,
enum compat_mwt compat_mwt, enum compat_mwt compat_mwt,
struct ebt_entries_buf_state *state, struct ebt_entries_buf_state *state,
const unsigned char *base) const unsigned char *base)
...@@ -1979,22 +1979,23 @@ static int compat_mtw_from_user(struct compat_ebt_entry_mwt *mwt, ...@@ -1979,22 +1979,23 @@ static int compat_mtw_from_user(struct compat_ebt_entry_mwt *mwt,
/* return size of all matches, watchers or target, including necessary /* return size of all matches, watchers or target, including necessary
* alignment and padding. * alignment and padding.
*/ */
static int ebt_size_mwt(struct compat_ebt_entry_mwt *match32, static int ebt_size_mwt(const struct compat_ebt_entry_mwt *match32,
unsigned int size_left, enum compat_mwt type, unsigned int size_left, enum compat_mwt type,
struct ebt_entries_buf_state *state, const void *base) struct ebt_entries_buf_state *state, const void *base)
{ {
const char *buf = (const char *)match32;
int growth = 0; int growth = 0;
char *buf;
if (size_left == 0) if (size_left == 0)
return 0; return 0;
buf = (char *) match32; do {
while (size_left >= sizeof(*match32)) {
struct ebt_entry_match *match_kern; struct ebt_entry_match *match_kern;
int ret; int ret;
if (size_left < sizeof(*match32))
return -EINVAL;
match_kern = (struct ebt_entry_match *) state->buf_kern_start; match_kern = (struct ebt_entry_match *) state->buf_kern_start;
if (match_kern) { if (match_kern) {
char *tmp; char *tmp;
...@@ -2031,22 +2032,18 @@ static int ebt_size_mwt(struct compat_ebt_entry_mwt *match32, ...@@ -2031,22 +2032,18 @@ static int ebt_size_mwt(struct compat_ebt_entry_mwt *match32,
if (match_kern) if (match_kern)
match_kern->match_size = ret; match_kern->match_size = ret;
/* rule should have no remaining data after target */
if (type == EBT_COMPAT_TARGET && size_left)
return -EINVAL;
match32 = (struct compat_ebt_entry_mwt *) buf; match32 = (struct compat_ebt_entry_mwt *) buf;
} } while (size_left);
return growth; return growth;
} }
/* called for all ebt_entry structures. */ /* called for all ebt_entry structures. */
static int size_entry_mwt(struct ebt_entry *entry, const unsigned char *base, static int size_entry_mwt(const struct ebt_entry *entry, const unsigned char *base,
unsigned int *total, unsigned int *total,
struct ebt_entries_buf_state *state) struct ebt_entries_buf_state *state)
{ {
unsigned int i, j, startoff, new_offset = 0; unsigned int i, j, startoff, next_expected_off, new_offset = 0;
/* stores match/watchers/targets & offset of next struct ebt_entry: */ /* stores match/watchers/targets & offset of next struct ebt_entry: */
unsigned int offsets[4]; unsigned int offsets[4];
unsigned int *offsets_update = NULL; unsigned int *offsets_update = NULL;
...@@ -2132,11 +2129,13 @@ static int size_entry_mwt(struct ebt_entry *entry, const unsigned char *base, ...@@ -2132,11 +2129,13 @@ static int size_entry_mwt(struct ebt_entry *entry, const unsigned char *base,
return ret; return ret;
} }
startoff = state->buf_user_offset - startoff; next_expected_off = state->buf_user_offset - startoff;
if (next_expected_off != entry->next_offset)
return -EINVAL;
if (WARN_ON(*total < startoff)) if (*total < entry->next_offset)
return -EINVAL; return -EINVAL;
*total -= startoff; *total -= entry->next_offset;
return 0; return 0;
} }
......
...@@ -88,7 +88,7 @@ static int nf_flow_rule_match(struct nf_flow_match *match, ...@@ -88,7 +88,7 @@ static int nf_flow_rule_match(struct nf_flow_match *match,
switch (tuple->l4proto) { switch (tuple->l4proto) {
case IPPROTO_TCP: case IPPROTO_TCP:
key->tcp.flags = 0; key->tcp.flags = 0;
mask->tcp.flags = TCP_FLAG_RST | TCP_FLAG_FIN; mask->tcp.flags = cpu_to_be16(be32_to_cpu(TCP_FLAG_RST | TCP_FLAG_FIN) >> 16);
match->dissector.used_keys |= BIT(FLOW_DISSECTOR_KEY_TCP); match->dissector.used_keys |= BIT(FLOW_DISSECTOR_KEY_TCP);
break; break;
case IPPROTO_UDP: case IPPROTO_UDP:
......
...@@ -50,7 +50,7 @@ static void nft_tproxy_eval_v4(const struct nft_expr *expr, ...@@ -50,7 +50,7 @@ static void nft_tproxy_eval_v4(const struct nft_expr *expr,
taddr = nf_tproxy_laddr4(skb, taddr, iph->daddr); taddr = nf_tproxy_laddr4(skb, taddr, iph->daddr);
if (priv->sreg_port) if (priv->sreg_port)
tport = regs->data[priv->sreg_port]; tport = nft_reg_load16(&regs->data[priv->sreg_port]);
if (!tport) if (!tport)
tport = hp->dest; tport = hp->dest;
...@@ -117,7 +117,7 @@ static void nft_tproxy_eval_v6(const struct nft_expr *expr, ...@@ -117,7 +117,7 @@ static void nft_tproxy_eval_v6(const struct nft_expr *expr,
taddr = *nf_tproxy_laddr6(skb, &taddr, &iph->daddr); taddr = *nf_tproxy_laddr6(skb, &taddr, &iph->daddr);
if (priv->sreg_port) if (priv->sreg_port)
tport = regs->data[priv->sreg_port]; tport = nft_reg_load16(&regs->data[priv->sreg_port]);
if (!tport) if (!tport)
tport = hp->dest; tport = hp->dest;
......
...@@ -226,17 +226,19 @@ check_transfer() ...@@ -226,17 +226,19 @@ check_transfer()
return 0 return 0
} }
test_tcp_forwarding() test_tcp_forwarding_ip()
{ {
local nsa=$1 local nsa=$1
local nsb=$2 local nsb=$2
local dstip=$3
local dstport=$4
local lret=0 local lret=0
ip netns exec $nsb nc -w 5 -l -p 12345 < "$ns2in" > "$ns2out" & ip netns exec $nsb nc -w 5 -l -p 12345 < "$ns2in" > "$ns2out" &
lpid=$! lpid=$!
sleep 1 sleep 1
ip netns exec $nsa nc -w 4 10.0.2.99 12345 < "$ns1in" > "$ns1out" & ip netns exec $nsa nc -w 4 "$dstip" "$dstport" < "$ns1in" > "$ns1out" &
cpid=$! cpid=$!
sleep 3 sleep 3
...@@ -258,6 +260,28 @@ test_tcp_forwarding() ...@@ -258,6 +260,28 @@ test_tcp_forwarding()
return $lret return $lret
} }
test_tcp_forwarding()
{
test_tcp_forwarding_ip "$1" "$2" 10.0.2.99 12345
return $?
}
test_tcp_forwarding_nat()
{
local lret
test_tcp_forwarding_ip "$1" "$2" 10.0.2.99 12345
lret=$?
if [ $lret -eq 0 ] ; then
test_tcp_forwarding_ip "$1" "$2" 10.6.6.6 1666
lret=$?
fi
return $lret
}
make_file "$ns1in" "ns1" make_file "$ns1in" "ns1"
make_file "$ns2in" "ns2" make_file "$ns2in" "ns2"
...@@ -283,14 +307,19 @@ ip -net ns2 route add 192.168.10.1 via 10.0.2.1 ...@@ -283,14 +307,19 @@ ip -net ns2 route add 192.168.10.1 via 10.0.2.1
# Same, but with NAT enabled. # Same, but with NAT enabled.
ip netns exec nsr1 nft -f - <<EOF ip netns exec nsr1 nft -f - <<EOF
table ip nat { table ip nat {
chain prerouting {
type nat hook prerouting priority 0; policy accept;
meta iif "veth0" ip daddr 10.6.6.6 tcp dport 1666 counter dnat ip to 10.0.2.99:12345
}
chain postrouting { chain postrouting {
type nat hook postrouting priority 0; policy accept; type nat hook postrouting priority 0; policy accept;
meta oifname "veth1" masquerade meta oifname "veth1" counter masquerade
} }
} }
EOF EOF
test_tcp_forwarding ns1 ns2 test_tcp_forwarding_nat ns1 ns2
if [ $? -eq 0 ] ;then if [ $? -eq 0 ] ;then
echo "PASS: flow offloaded for ns1/ns2 with NAT" echo "PASS: flow offloaded for ns1/ns2 with NAT"
...@@ -313,7 +342,7 @@ fi ...@@ -313,7 +342,7 @@ fi
ip netns exec ns1 sysctl net.ipv4.ip_no_pmtu_disc=0 > /dev/null ip netns exec ns1 sysctl net.ipv4.ip_no_pmtu_disc=0 > /dev/null
ip netns exec ns2 sysctl net.ipv4.ip_no_pmtu_disc=0 > /dev/null ip netns exec ns2 sysctl net.ipv4.ip_no_pmtu_disc=0 > /dev/null
test_tcp_forwarding ns1 ns2 test_tcp_forwarding_nat ns1 ns2
if [ $? -eq 0 ] ;then if [ $? -eq 0 ] ;then
echo "PASS: flow offloaded for ns1/ns2 with NAT and pmtu discovery" echo "PASS: flow offloaded for ns1/ns2 with NAT and pmtu discovery"
else else
......
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