From patchwork Wed Sep 28 13:55:24 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Phil Sutter X-Patchwork-Id: 1683904 X-Patchwork-Delegate: fw@strlen.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=2620:137:e000::1:20; helo=out1.vger.email; envelope-from=netfilter-devel-owner@vger.kernel.org; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=nwl.cc header.i=@nwl.cc header.a=rsa-sha256 header.s=mail2022 header.b=qWL6lsb1; dkim-atps=neutral Received: from out1.vger.email (out1.vger.email [IPv6:2620:137:e000::1:20]) by legolas.ozlabs.org (Postfix) with ESMTP id 4Mcygd5C0Mz1yqJ for ; Wed, 28 Sep 2022 23:55:41 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233713AbiI1Nzi (ORCPT ); Wed, 28 Sep 2022 09:55:38 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60294 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231703AbiI1Nzh (ORCPT ); Wed, 28 Sep 2022 09:55:37 -0400 Received: from orbyte.nwl.cc (orbyte.nwl.cc [IPv6:2001:41d0:e:133a::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D837932067 for ; Wed, 28 Sep 2022 06:55:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=nwl.cc; s=mail2022; h=Content-Transfer-Encoding:MIME-Version:Message-Id:Date:Subject: Cc:To:From:Sender:Reply-To:Content-Type:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: In-Reply-To:References:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=2LB4R909MwnmCHOS1L+GuEUTlcx25NDQD7ZTyOk/AXM=; b=qWL6lsb19+ZSIX8n1jH+/WVqMR /C/GV7hQL/At+nWTW/WI4XCSKCtaQ+2+dY2EBDbi9Lg9IS/4SNmNt/qbae4xTKKAjZpkuwXj8Ue2J i/1I5S0qg4QMMhCFU6v2JIe/bdzNmTgZR7Aed3EtEB4kORnrsGlbcv1+e/H0U1WXoxXcXYIJbYeP8 Q92U2aNoDYd3C3hM5vHKf4p88UjCP+0OVH3YvQOgKjWxO3s/5NNE1zTW1VjM6m1tLE4MXrXSvxHVS pMWynpqEa5OcumfbsNyyP2ptKuIc3txbWq5XD2PSI7bJ0+3EDZGSSWE+14SUZcSfrLWIqszSnYWnz +OUGbHKg==; Received: from localhost ([::1] helo=xic) by orbyte.nwl.cc with esmtp (Exim 4.94.2) (envelope-from ) id 1odXXB-0000HF-0A; Wed, 28 Sep 2022 15:55:33 +0200 From: Phil Sutter To: Florian Westphal Cc: netfilter-devel@vger.kernel.org Subject: [iptables PATCH] ebtables: Fix among match Date: Wed, 28 Sep 2022 15:55:24 +0200 Message-Id: <20220928135524.22822-1-phil@nwl.cc> X-Mailer: git-send-email 2.34.1 MIME-Version: 1.0 X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org Fixed commit broke among match in two ways: 1) The two lookup sizes are 12 and 6, not 12 and 4 - among supports either ether+IP or ether only, not IP only. 2) Adding two to sreg_count to get the second register is too simple: It works only for four byte regs, not the 16 byte ones. The first register is always a 16 byte one, though. Fixing (1) is trivial, fix (2) by introduction of nft_get_next_reg() doing the right thing. For consistency, use it for among match creation, too. Fixes: f315af1cf8871 ("nft: track each register individually") Signed-off-by: Phil Sutter --- iptables/nft-bridge.c | 4 ++-- iptables/nft-shared.c | 16 ++++++++++++++++ iptables/nft-shared.h | 5 +++++ iptables/nft.c | 6 ++---- 4 files changed, 25 insertions(+), 6 deletions(-) diff --git a/iptables/nft-bridge.c b/iptables/nft-bridge.c index 659c5b58ba633..596dfdf8991f1 100644 --- a/iptables/nft-bridge.c +++ b/iptables/nft-bridge.c @@ -349,7 +349,7 @@ static int lookup_analyze_payloads(struct nft_xt_ctx *ctx, return -1; } - sreg_count += 2; + sreg_count = nft_get_next_reg(sreg_count, ETH_ALEN); reg = nft_xt_ctx_get_sreg(ctx, sreg_count); if (!reg) { @@ -375,7 +375,7 @@ static int lookup_analyze_payloads(struct nft_xt_ctx *ctx, return -1; } break; - case 4: /* ipv4addr */ + case 6: /* ether */ val = lookup_check_ether_payload(reg->payload.base, reg->payload.offset, reg->payload.len); diff --git a/iptables/nft-shared.c b/iptables/nft-shared.c index f8de2b715dd61..909fe6483205c 100644 --- a/iptables/nft-shared.c +++ b/iptables/nft-shared.c @@ -10,6 +10,7 @@ * This code has been sponsored by Sophos Astaro */ +#include #include #include #include @@ -1603,3 +1604,18 @@ int nft_parse_hl(struct nft_xt_ctx *ctx, return 0; } + +enum nft_registers nft_get_next_reg(enum nft_registers reg, size_t size) +{ + /* convert size to NETLINK_ALIGN-sized chunks */ + size = (size + NETLINK_ALIGN - 1) / NETLINK_ALIGN; + + /* map 16byte reg to 4byte one */ + if (reg < __NFT_REG_MAX) + reg = NFT_REG32_00 + (reg - 1) * NFT_REG_SIZE / NFT_REG32_SIZE; + + reg += size; + assert(reg <= NFT_REG32_15); + + return reg; +} diff --git a/iptables/nft-shared.h b/iptables/nft-shared.h index 8fcedcdd78fbe..c07d3270a407e 100644 --- a/iptables/nft-shared.h +++ b/iptables/nft-shared.h @@ -276,4 +276,9 @@ int nft_parse_hl(struct nft_xt_ctx *ctx, struct nftnl_expr *e, struct iptables_c #define min(x, y) ((x) < (y) ? (x) : (y)) #define max(x, y) ((x) > (y) ? (x) : (y)) +/* simplified nftables:include/netlink.h, netlink_padded_len() */ +#define NETLINK_ALIGN 4 + +enum nft_registers nft_get_next_reg(enum nft_registers reg, size_t size); + #endif diff --git a/iptables/nft.c b/iptables/nft.c index 2165733ff74e9..09cb19c987322 100644 --- a/iptables/nft.c +++ b/iptables/nft.c @@ -1133,9 +1133,6 @@ gen_lookup(uint32_t sreg, const char *set_name, uint32_t set_id, uint32_t flags) return e; } -/* simplified nftables:include/netlink.h, netlink_padded_len() */ -#define NETLINK_ALIGN 4 - /* from nftables:include/datatype.h, TYPE_BITS */ #define CONCAT_TYPE_BITS 6 @@ -1208,8 +1205,9 @@ static int __add_nft_among(struct nft_handle *h, const char *table, nftnl_rule_add_expr(r, e); if (ip) { + reg = nft_get_next_reg(reg, ETH_ALEN); e = __gen_payload(NFT_PAYLOAD_NETWORK_HEADER, ip_addr_off[dst], - sizeof(struct in_addr), NFT_REG32_02); + sizeof(struct in_addr), reg); if (!e) return -ENOMEM; nftnl_rule_add_expr(r, e);