From patchwork Tue May 15 12:24:01 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Taehee Yoo X-Patchwork-Id: 913602 X-Patchwork-Delegate: pablo@netfilter.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netfilter-devel-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="gsskXkM1"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 40lcF5266zz9s1B for ; Tue, 15 May 2018 22:24:09 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753299AbeEOMYI (ORCPT ); Tue, 15 May 2018 08:24:08 -0400 Received: from mail-pl0-f67.google.com ([209.85.160.67]:33955 "EHLO mail-pl0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752421AbeEOMYI (ORCPT ); Tue, 15 May 2018 08:24:08 -0400 Received: by mail-pl0-f67.google.com with SMTP id ay10-v6so9337524plb.1 for ; Tue, 15 May 2018 05:24:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=R2S6H7jcdL2kfoIKsPJl/xTPugeKaviRroKKyyrLRJU=; b=gsskXkM1nAnjgT8knEN4kaJbYenKXrLzw73Ht1XOcDNu1Pr77AmdIDUq/vaKDkJbkM 8Py9eccOLbuna27GuNQI9s6yu9mSKOVJ0tM5kuVBOzZ+USYClZvZCzPhljywQkvGCY8i pS/jiwBP+C0hdg3TREo84ulfIQa0UlSC7hoWJ0Md34cXT31eugf2GuzxRUD/t1UyMITO RiE2iEFaZcJToBWDbPAJae5pPCZok1KD6uqY42QJY9KDmf8UY9qXbKskO7mR9QZjFM4L BCHdKKgFQNgQr9pqxDDbc+2iqn+yLfLwZLrr8PCjQxL5FQx7kht0qD7EjYlKwZpFUJlq ix9g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=R2S6H7jcdL2kfoIKsPJl/xTPugeKaviRroKKyyrLRJU=; b=hrz1MuWXR2C8z/OaCwgz6UjlkcmWLtRYFU3JWNUCA9x16Aq/X/02AgZHSUExO0nrXm /Rozq6oqfQAyXB0WRcA8Xsz70ngbbJ2VONMNr3GCTDq2EFGMN8oxlYkhv7ol/DANyCeV RbLaHdK0seB1X6wPFgb/GjB+lHVAKmnG/v+YlL4IJPmn3fk9Lj1ae9ORqTbJJe0wa2nm 6CYxjWrQ81gp18SLnBA0x1YlsQk5JfMKOPzdq8Ja6VtJ7/ChuXT7WnW5kUXnlGEn4zEL 068Z4kEtkenAOATPkte2OmLvu6LOf8ZZcuoP29aDExpPnFlXLMRUVBKWQjRD65WFMnjR ltpw== X-Gm-Message-State: ALKqPwf9kKLlo4PDwK2pk65pgyz4KceqymaBPHkzk86PCH2fOzIwkZoe BiOLqoWHNO5BUXUDopzoyWtSDA== X-Google-Smtp-Source: AB8JxZo1GPpJU8BxI2BONGXlMNjDaz0Dow3nW7+8pWieCXLN+B4/RQau/8h9NEpZrqVpU93T/XaiNw== X-Received: by 2002:a17:902:7883:: with SMTP id q3-v6mr14324892pll.71.1526387047761; Tue, 15 May 2018 05:24:07 -0700 (PDT) Received: from ap-To-be-filled-by-O-E-M.8.8.8.8 ([125.130.197.10]) by smtp.gmail.com with ESMTPSA id x88-v6sm35073410pfj.126.2018.05.15.05.24.06 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 15 May 2018 05:24:07 -0700 (PDT) From: Taehee Yoo To: pablo@netfilter.org, netfilter-devel@vger.kernel.org Cc: ap420073@gmail.com Subject: [PATCH nf 4/5] netfilter: nf_tables: use chain info to validate type and hook. Date: Tue, 15 May 2018 21:24:01 +0900 Message-Id: <20180515122401.29480-1-ap420073@gmail.com> X-Mailer: git-send-email 2.9.3 Sender: netfilter-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org After this patch, the nft_chain_validate_dependency and nft_chain_validate_hooks use chain information array. so that these functions can validate both basechain and non-basechain. Now expr->ops->validate should be called in the nf_tables_validate because that uses chain information that is allocated in the nf_tables_validate. But exceptionally, the nf_tables_check_loops can call that if ops is "immediate". Now, nft_compat.c uses common validate routine instead of the nft_compat_chain_validate_dependency. Signed-off-by: Taehee Yoo --- net/netfilter/nf_tables_api.c | 51 +++++++++++------------------- net/netfilter/nft_compat.c | 73 ++++++++++++++----------------------------- 2 files changed, 42 insertions(+), 82 deletions(-) diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 36d8fba..d902ef9 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -1899,26 +1899,13 @@ static int nf_tables_newexpr(const struct nft_ctx *ctx, expr->ops = ops; if (ops->init) { err = ops->init(ctx, expr, (const struct nlattr **)info->tb); - if (err < 0) - goto err1; - } - - if (ops->validate) { - const struct nft_data *data = NULL; - - err = ops->validate(ctx, expr, &data); - if (err < 0) - goto err2; + if (err < 0) { + expr->ops = NULL; + return err; + } } return 0; - -err2: - if (ops->destroy) - ops->destroy(ctx, expr); -err1: - expr->ops = NULL; - return err; } static void nf_tables_expr_destroy(const struct nft_ctx *ctx, @@ -6397,13 +6384,12 @@ static const struct nfnetlink_subsystem nf_tables_subsys = { int nft_chain_validate_dependency(const struct nft_ctx *ctx, enum nft_chain_types type) { - const struct nft_base_chain *basechain; + struct net *net = ctx->net; + struct nft_chain *chain = ctx->chain; + struct nft_chain_info *cinfo = nft_get_chain_info(net, chain); - if (nft_is_base_chain(ctx->chain)) { - basechain = nft_base_chain(ctx->chain); - if (basechain->type->type != type) - return -EOPNOTSUPP; - } + if (cinfo->type && cinfo->type != type) + return -EOPNOTSUPP; return 0; } EXPORT_SYMBOL_GPL(nft_chain_validate_dependency); @@ -6411,17 +6397,14 @@ EXPORT_SYMBOL_GPL(nft_chain_validate_dependency); int nft_chain_validate_hooks(const struct nft_ctx *ctx, unsigned int hook_flags) { - struct nft_base_chain *basechain; - - if (nft_is_base_chain(ctx->chain)) { - basechain = nft_base_chain(ctx->chain); - - if ((1 << basechain->ops.hooknum) & hook_flags) - return 0; + struct net *net = ctx->net; + struct nft_chain *chain = ctx->chain; + struct nft_chain_info *cinfo = nft_get_chain_info(net, chain); + if (!hook_flags) + return 0; + if (cinfo->hooknum & ~hook_flags) return -EOPNOTSUPP; - } - return 0; } EXPORT_SYMBOL_GPL(nft_chain_validate_hooks); @@ -6479,12 +6462,14 @@ static int nf_tables_check_loops(const struct nft_ctx *ctx, if (!expr->ops->validate) continue; + if (strcmp(expr->ops->type->name, "immediate")) + continue; err = expr->ops->validate(ctx, expr, &data); if (err < 0) return err; - if (data == NULL) + if (!data) continue; switch (data->verdict.code) { diff --git a/net/netfilter/nft_compat.c b/net/netfilter/nft_compat.c index 1d99a1ef..c7aad9c 100644 --- a/net/netfilter/nft_compat.c +++ b/net/netfilter/nft_compat.c @@ -54,23 +54,6 @@ static bool nft_xt_put(struct nft_xt *xt) return false; } -static int nft_compat_chain_validate_dependency(const char *tablename, - const struct nft_chain *chain) -{ - const struct nft_base_chain *basechain; - - if (!tablename || - !nft_is_base_chain(chain)) - return 0; - - basechain = nft_base_chain(chain); - if (strcmp(tablename, "nat") == 0 && - basechain->type->type != NFT_CHAIN_T_NAT) - return -EINVAL; - - return 0; -} - union nft_entry { struct ipt_entry e4; struct ip6t_entry e6; @@ -311,24 +294,20 @@ static int nft_target_validate(const struct nft_ctx *ctx, const struct nft_data **data) { struct xt_target *target = expr->ops->data; - unsigned int hook_mask = 0; - int ret; - - if (nft_is_base_chain(ctx->chain)) { - const struct nft_base_chain *basechain = - nft_base_chain(ctx->chain); - const struct nf_hook_ops *ops = &basechain->ops; + enum nft_chain_types type; + int err; - hook_mask = 1 << ops->hooknum; - if (target->hooks && !(hook_mask & target->hooks)) - return -EINVAL; + if (!target->table) + return 0; + if (!strcmp(target->table, "nat")) + type = NFT_CHAIN_T_NAT; + else + type = NFT_CHAIN_T_DEFAULT; - ret = nft_compat_chain_validate_dependency(target->table, - ctx->chain); - if (ret < 0) - return ret; - } - return 0; + err = nft_chain_validate_dependency(ctx, type); + if (err < 0) + return err; + return nft_chain_validate_hooks(ctx, target->hooks); } static void __nft_match_eval(const struct nft_expr *expr, @@ -558,24 +537,20 @@ static int nft_match_validate(const struct nft_ctx *ctx, const struct nft_data **data) { struct xt_match *match = expr->ops->data; - unsigned int hook_mask = 0; - int ret; - - if (nft_is_base_chain(ctx->chain)) { - const struct nft_base_chain *basechain = - nft_base_chain(ctx->chain); - const struct nf_hook_ops *ops = &basechain->ops; + enum nft_chain_types type; + int err; - hook_mask = 1 << ops->hooknum; - if (match->hooks && !(hook_mask & match->hooks)) - return -EINVAL; + if (!match->table) + return 0; + if (!strcmp(match->table, "nat")) + type = NFT_CHAIN_T_NAT; + else + type = NFT_CHAIN_T_DEFAULT; - ret = nft_compat_chain_validate_dependency(match->table, - ctx->chain); - if (ret < 0) - return ret; - } - return 0; + err = nft_chain_validate_dependency(ctx, type); + if (err < 0) + return err; + return nft_chain_validate_hooks(ctx, match->hooks); } static int