Skip to content

Commit 2195574

Browse files
n132ummakynes
authored andcommitted
netfilter: nfnetlink_osf: fix divide-by-zero in OSF_WSS_MODULO
nf_osf_match_one() computes ctx->window % f->wss.val in the OSF_WSS_MODULO branch with no guard for f->wss.val == 0. A CAP_NET_ADMIN user can add such a fingerprint via nfnetlink; a subsequent matching TCP SYN divides by zero and panics the kernel. Reject the bogus fingerprint in nfnl_osf_add_callback() above the per-option for-loop. f->wss is per-fingerprint, not per-option, so the check must run regardless of f->opt_num (including 0). Also reject wss.wc >= OSF_WSS_MAX; nf_osf_match_one() already treats that as "should not happen". Crash: Oops: divide error: 0000 [#1] SMP KASAN NOPTI RIP: 0010:nf_osf_match_one (net/netfilter/nfnetlink_osf.c:98) Call Trace: <IRQ> nf_osf_match (net/netfilter/nfnetlink_osf.c:220) xt_osf_match_packet (net/netfilter/xt_osf.c:32) ipt_do_table (net/ipv4/netfilter/ip_tables.c:348) nf_hook_slow (net/netfilter/core.c:622) ip_local_deliver (net/ipv4/ip_input.c:265) ip_rcv (include/linux/skbuff.h:1162) __netif_receive_skb_one_core (net/core/dev.c:6181) process_backlog (net/core/dev.c:6642) __napi_poll (net/core/dev.c:7710) net_rx_action (net/core/dev.c:7945) handle_softirqs (kernel/softirq.c:622) Fixes: 11eeef4 ("netfilter: passive OS fingerprint xtables match") Reported-by: Weiming Shi <bestswngs@gmail.com> Suggested-by: Florian Westphal <fw@strlen.de> Suggested-by: Pablo Neira Ayuso <pablo@netfilter.org> Signed-off-by: Xiang Mei <xmei5@asu.edu> Reviewed-by: Fernando Fernandez Mancera <fmancera@suse.de> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
1 parent b336fdb commit 2195574

1 file changed

Lines changed: 4 additions & 0 deletions

File tree

net/netfilter/nfnetlink_osf.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,10 @@ static int nfnl_osf_add_callback(struct sk_buff *skb,
320320
if (f->opt_num > ARRAY_SIZE(f->opt))
321321
return -EINVAL;
322322

323+
if (f->wss.wc >= OSF_WSS_MAX ||
324+
(f->wss.wc == OSF_WSS_MODULO && f->wss.val == 0))
325+
return -EINVAL;
326+
323327
for (i = 0; i < f->opt_num; i++) {
324328
if (!f->opt[i].length || f->opt[i].length > MAX_IPOPTLEN)
325329
return -EINVAL;

0 commit comments

Comments
 (0)