netfilter: nft_socket: only do sk lookups when indev is available
commit 743b83f15d4069ea57c3e40996bf4a1077e0cdc1 upstream.
Check if the incoming interface is available and NFT_BREAK
in case neither skb->sk nor input device are set.
Because nf_sk_lookup_slow*() assume packet headers are in the
'in' direction, use in postrouting is not going to yield a meaningful
result. Same is true for the forward chain, so restrict the use
to prerouting, input and output.
Use in output work if a socket is already attached to the skb.
Fixes: 554ced0a6e
("netfilter: nf_tables: add support for native socket matching")
Reported-and-tested-by: Topi Miettinen <toiwoton@gmail.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
7346e54dbf
commit
842a9bbbef
|
@ -33,6 +33,32 @@ static void nft_socket_wildcard(const struct nft_pktinfo *pkt,
|
|||
}
|
||||
}
|
||||
|
||||
static struct sock *nft_socket_do_lookup(const struct nft_pktinfo *pkt)
|
||||
{
|
||||
const struct net_device *indev = nft_in(pkt);
|
||||
const struct sk_buff *skb = pkt->skb;
|
||||
struct sock *sk = NULL;
|
||||
|
||||
if (!indev)
|
||||
return NULL;
|
||||
|
||||
switch (nft_pf(pkt)) {
|
||||
case NFPROTO_IPV4:
|
||||
sk = nf_sk_lookup_slow_v4(nft_net(pkt), skb, indev);
|
||||
break;
|
||||
#if IS_ENABLED(CONFIG_NF_TABLES_IPV6)
|
||||
case NFPROTO_IPV6:
|
||||
sk = nf_sk_lookup_slow_v6(nft_net(pkt), skb, indev);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
WARN_ON_ONCE(1);
|
||||
break;
|
||||
}
|
||||
|
||||
return sk;
|
||||
}
|
||||
|
||||
static void nft_socket_eval(const struct nft_expr *expr,
|
||||
struct nft_regs *regs,
|
||||
const struct nft_pktinfo *pkt)
|
||||
|
@ -46,20 +72,7 @@ static void nft_socket_eval(const struct nft_expr *expr,
|
|||
sk = NULL;
|
||||
|
||||
if (!sk)
|
||||
switch(nft_pf(pkt)) {
|
||||
case NFPROTO_IPV4:
|
||||
sk = nf_sk_lookup_slow_v4(nft_net(pkt), skb, nft_in(pkt));
|
||||
break;
|
||||
#if IS_ENABLED(CONFIG_NF_TABLES_IPV6)
|
||||
case NFPROTO_IPV6:
|
||||
sk = nf_sk_lookup_slow_v6(nft_net(pkt), skb, nft_in(pkt));
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
WARN_ON_ONCE(1);
|
||||
regs->verdict.code = NFT_BREAK;
|
||||
return;
|
||||
}
|
||||
sk = nft_socket_do_lookup(pkt);
|
||||
|
||||
if (!sk) {
|
||||
regs->verdict.code = NFT_BREAK;
|
||||
|
@ -150,6 +163,16 @@ static int nft_socket_dump(struct sk_buff *skb,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int nft_socket_validate(const struct nft_ctx *ctx,
|
||||
const struct nft_expr *expr,
|
||||
const struct nft_data **data)
|
||||
{
|
||||
return nft_chain_validate_hooks(ctx->chain,
|
||||
(1 << NF_INET_PRE_ROUTING) |
|
||||
(1 << NF_INET_LOCAL_IN) |
|
||||
(1 << NF_INET_LOCAL_OUT));
|
||||
}
|
||||
|
||||
static struct nft_expr_type nft_socket_type;
|
||||
static const struct nft_expr_ops nft_socket_ops = {
|
||||
.type = &nft_socket_type,
|
||||
|
@ -157,6 +180,7 @@ static const struct nft_expr_ops nft_socket_ops = {
|
|||
.eval = nft_socket_eval,
|
||||
.init = nft_socket_init,
|
||||
.dump = nft_socket_dump,
|
||||
.validate = nft_socket_validate,
|
||||
};
|
||||
|
||||
static struct nft_expr_type nft_socket_type __read_mostly = {
|
||||
|
|
Loading…
Reference in New Issue
Block a user