netfilter: nf_tables: fix crash when nf_trace is enabled
do not access info->pkt when info->trace is not 1.
nft_traceinfo is not initialized, except when tracing is enabled.
The 'nft_trace_enabled' static key cannot be used for this, we must
always check info->trace first.
Pass nft_pktinfo directly to avoid this.
Fixes: e34b9ed96c
("netfilter: nf_tables: avoid skb access on nf_stolen")
Reported-by: Hangbin Liu <liuhangbin@gmail.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Родитель
2e64fe4624
Коммит
399a14ec79
|
@ -34,25 +34,23 @@ static noinline void __nft_trace_packet(struct nft_traceinfo *info,
|
|||
nft_trace_notify(info);
|
||||
}
|
||||
|
||||
static inline void nft_trace_packet(struct nft_traceinfo *info,
|
||||
static inline void nft_trace_packet(const struct nft_pktinfo *pkt,
|
||||
struct nft_traceinfo *info,
|
||||
const struct nft_chain *chain,
|
||||
const struct nft_rule_dp *rule,
|
||||
enum nft_trace_types type)
|
||||
{
|
||||
if (static_branch_unlikely(&nft_trace_enabled)) {
|
||||
const struct nft_pktinfo *pkt = info->pkt;
|
||||
|
||||
info->nf_trace = pkt->skb->nf_trace;
|
||||
info->rule = rule;
|
||||
__nft_trace_packet(info, chain, type);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void nft_trace_copy_nftrace(struct nft_traceinfo *info)
|
||||
static inline void nft_trace_copy_nftrace(const struct nft_pktinfo *pkt,
|
||||
struct nft_traceinfo *info)
|
||||
{
|
||||
if (static_branch_unlikely(&nft_trace_enabled)) {
|
||||
const struct nft_pktinfo *pkt = info->pkt;
|
||||
|
||||
if (info->trace)
|
||||
info->nf_trace = pkt->skb->nf_trace;
|
||||
}
|
||||
|
@ -96,7 +94,6 @@ static noinline void __nft_trace_verdict(struct nft_traceinfo *info,
|
|||
const struct nft_chain *chain,
|
||||
const struct nft_regs *regs)
|
||||
{
|
||||
const struct nft_pktinfo *pkt = info->pkt;
|
||||
enum nft_trace_types type;
|
||||
|
||||
switch (regs->verdict.code) {
|
||||
|
@ -110,7 +107,9 @@ static noinline void __nft_trace_verdict(struct nft_traceinfo *info,
|
|||
break;
|
||||
default:
|
||||
type = NFT_TRACETYPE_RULE;
|
||||
info->nf_trace = pkt->skb->nf_trace;
|
||||
|
||||
if (info->trace)
|
||||
info->nf_trace = info->pkt->skb->nf_trace;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -271,10 +270,10 @@ next_rule:
|
|||
switch (regs.verdict.code) {
|
||||
case NFT_BREAK:
|
||||
regs.verdict.code = NFT_CONTINUE;
|
||||
nft_trace_copy_nftrace(&info);
|
||||
nft_trace_copy_nftrace(pkt, &info);
|
||||
continue;
|
||||
case NFT_CONTINUE:
|
||||
nft_trace_packet(&info, chain, rule,
|
||||
nft_trace_packet(pkt, &info, chain, rule,
|
||||
NFT_TRACETYPE_RULE);
|
||||
continue;
|
||||
}
|
||||
|
@ -318,7 +317,7 @@ next_rule:
|
|||
goto next_rule;
|
||||
}
|
||||
|
||||
nft_trace_packet(&info, basechain, NULL, NFT_TRACETYPE_POLICY);
|
||||
nft_trace_packet(pkt, &info, basechain, NULL, NFT_TRACETYPE_POLICY);
|
||||
|
||||
if (static_branch_unlikely(&nft_counters_enabled))
|
||||
nft_update_chain_stats(basechain, pkt);
|
||||
|
|
Загрузка…
Ссылка в новой задаче