From nobody Wed Apr 8 10:02:55 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id CD0B3C25B08 for ; Sat, 20 Aug 2022 17:36:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1346612AbiHTRgQ (ORCPT ); Sat, 20 Aug 2022 13:36:16 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44726 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231989AbiHTRgN (ORCPT ); Sat, 20 Aug 2022 13:36:13 -0400 Received: from Chamillionaire.breakpoint.cc (Chamillionaire.breakpoint.cc [IPv6:2a0a:51c0:0:12e:520::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A8F6752812; Sat, 20 Aug 2022 10:36:12 -0700 (PDT) Received: from fw by Chamillionaire.breakpoint.cc with local (Exim 4.92) (envelope-from ) id 1oPSOB-0007Ea-1e; Sat, 20 Aug 2022 19:36:03 +0200 From: Florian Westphal To: Cc: syzkaller@googlegroups.com, george.kennedy@oracle.com, vegard.nossum@oracle.com, john.p.donnelly@oracle.com, bridge@lists.linux-foundation.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Florian Westphal , Harshit Mogalapalli Subject: [PATCH nf] netfilter: ebtables: reject blobs that don't provide all entry points Date: Sat, 20 Aug 2022 19:35:55 +0200 Message-Id: <20220820173555.131326-1-fw@strlen.de> X-Mailer: git-send-email 2.37.2 In-Reply-To: <20220820070331.48817-1-harshit.m.mogalapalli@oracle.com> References: <20220820070331.48817-1-harshit.m.mogalapalli@oracle.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" For some reason ebtables reject blobs that provide entry points that are not supported by the table. What it should instead reject is the opposite, i.e. rulesets that DO NOT provide an entry point that is supported by the table. t->valid_hooks is the bitmask of hooks (input, forward ...) that will see packets. So, providing an entry point that is not support is harmless (never called/used), but the reverse is NOT, this will cause crash because the ebtables traverser doesn't expect a NULL blob for a location its receiving packets for. Instead of fixing all the individual checks, do what iptables is doing and reject all blobs that doesn't provide the expected hooks. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Reported-by: Harshit Mogalapalli Signed-off-by: Florian Westphal --- Harshit, can you check if this also silences your reproducer? Thanks! include/linux/netfilter_bridge/ebtables.h | 4 ---- net/bridge/netfilter/ebtable_broute.c | 8 -------- net/bridge/netfilter/ebtable_filter.c | 8 -------- net/bridge/netfilter/ebtable_nat.c | 8 -------- net/bridge/netfilter/ebtables.c | 8 +------- 5 files changed, 1 insertion(+), 35 deletions(-) diff --git a/include/linux/netfilter_bridge/ebtables.h b/include/linux/netf= ilter_bridge/ebtables.h index a13296d6c7ce..fd533552a062 100644 --- a/include/linux/netfilter_bridge/ebtables.h +++ b/include/linux/netfilter_bridge/ebtables.h @@ -94,10 +94,6 @@ struct ebt_table { struct ebt_replace_kernel *table; unsigned int valid_hooks; rwlock_t lock; - /* e.g. could be the table explicitly only allows certain - * matches, targets, ... 0 =3D=3D let it in */ - int (*check)(const struct ebt_table_info *info, - unsigned int valid_hooks); /* the data used by the kernel */ struct ebt_table_info *private; struct nf_hook_ops *ops; diff --git a/net/bridge/netfilter/ebtable_broute.c b/net/bridge/netfilter/e= btable_broute.c index 1a11064f9990..8f19253024b0 100644 --- a/net/bridge/netfilter/ebtable_broute.c +++ b/net/bridge/netfilter/ebtable_broute.c @@ -36,18 +36,10 @@ static struct ebt_replace_kernel initial_table =3D { .entries =3D (char *)&initial_chain, }; =20 -static int check(const struct ebt_table_info *info, unsigned int valid_hoo= ks) -{ - if (valid_hooks & ~(1 << NF_BR_BROUTING)) - return -EINVAL; - return 0; -} - static const struct ebt_table broute_table =3D { .name =3D "broute", .table =3D &initial_table, .valid_hooks =3D 1 << NF_BR_BROUTING, - .check =3D check, .me =3D THIS_MODULE, }; =20 diff --git a/net/bridge/netfilter/ebtable_filter.c b/net/bridge/netfilter/e= btable_filter.c index cb949436bc0e..278f324e6752 100644 --- a/net/bridge/netfilter/ebtable_filter.c +++ b/net/bridge/netfilter/ebtable_filter.c @@ -43,18 +43,10 @@ static struct ebt_replace_kernel initial_table =3D { .entries =3D (char *)initial_chains, }; =20 -static int check(const struct ebt_table_info *info, unsigned int valid_hoo= ks) -{ - if (valid_hooks & ~FILTER_VALID_HOOKS) - return -EINVAL; - return 0; -} - static const struct ebt_table frame_filter =3D { .name =3D "filter", .table =3D &initial_table, .valid_hooks =3D FILTER_VALID_HOOKS, - .check =3D check, .me =3D THIS_MODULE, }; =20 diff --git a/net/bridge/netfilter/ebtable_nat.c b/net/bridge/netfilter/ebta= ble_nat.c index 5ee0531ae506..9066f7f376d5 100644 --- a/net/bridge/netfilter/ebtable_nat.c +++ b/net/bridge/netfilter/ebtable_nat.c @@ -43,18 +43,10 @@ static struct ebt_replace_kernel initial_table =3D { .entries =3D (char *)initial_chains, }; =20 -static int check(const struct ebt_table_info *info, unsigned int valid_hoo= ks) -{ - if (valid_hooks & ~NAT_VALID_HOOKS) - return -EINVAL; - return 0; -} - static const struct ebt_table frame_nat =3D { .name =3D "nat", .table =3D &initial_table, .valid_hooks =3D NAT_VALID_HOOKS, - .check =3D check, .me =3D THIS_MODULE, }; =20 diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtable= s.c index f2dbefb61ce8..9a0ae59cdc50 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -1040,8 +1040,7 @@ static int do_replace_finish(struct net *net, struct = ebt_replace *repl, goto free_iterate; } =20 - /* the table doesn't like it */ - if (t->check && (ret =3D t->check(newinfo, repl->valid_hooks))) + if (repl->valid_hooks !=3D t->valid_hooks) goto free_unlock; =20 if (repl->num_counters && repl->num_counters !=3D t->private->nentries) { @@ -1231,11 +1230,6 @@ int ebt_register_table(struct net *net, const struct= ebt_table *input_table, if (ret !=3D 0) goto free_chainstack; =20 - if (table->check && table->check(newinfo, table->valid_hooks)) { - ret =3D -EINVAL; - goto free_chainstack; - } - table->private =3D newinfo; rwlock_init(&table->lock); mutex_lock(&ebt_mutex); --=20 2.37.2