From patchwork Wed Mar 7 09:10:40 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Serhey Popovych X-Patchwork-Id: 882482 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="K8rbk58Y"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3zx7Cw6WFHz9sfK for ; Wed, 7 Mar 2018 20:10:52 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751130AbeCGJKw (ORCPT ); Wed, 7 Mar 2018 04:10:52 -0500 Received: from mail-lf0-f68.google.com ([209.85.215.68]:38865 "EHLO mail-lf0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751036AbeCGJKv (ORCPT ); Wed, 7 Mar 2018 04:10:51 -0500 Received: by mail-lf0-f68.google.com with SMTP id i80-v6so2142633lfg.5 for ; Wed, 07 Mar 2018 01:10:50 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=9W8YrDed7Wi9msIt0RA56U5Zl3YoL4PbWFGekO4pfQM=; b=K8rbk58YcMhtbI1UyonqK6Xekf7qGVGEMMfKSc5IsCavJrwR6bh2IuqvkXPXlZqQXy TLMz3KHWpfhw/DvRrgi/1e7IuitfSGA368p2QSI3M7mhbW7CYhVRTch+Alfb/CUKR5mp GefU7oZFjvigr8kj38Y0NW4MQKt7PVkjfAqwPwreXyc8u0qvQ6TVa8qrkNsesOVWz1qC fjz/lyLOZxB4q5Ln5TEKapHkAP5M35Ypg0v/YIh2SJynjJyQNwVpIJ3Sg6hqnsT+r9hn hRVDdgz5fHEkfdydrq7u0N5mOi7JLytkrYhQHp5HoMuOqltK7bJYc66IJE/P1uOFPRzU zqFw== 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:in-reply-to :references; bh=9W8YrDed7Wi9msIt0RA56U5Zl3YoL4PbWFGekO4pfQM=; b=RcuWOcVUkWFPV8mRvgcNwWIOLhSZvfhIsunaOEoozJlwlI80gixRCIS1WT75cSckUi B7aCUwk+tKraej5CKZCcr6UkDlSLDdmM8UBFkXkffPswF9thOWBvP5xTpcD5U2orRRnF ma0t6jpiPydCq1bDcg0vDxHNxuOGhxuFL8k1qfu+yAvzUgD4wdcMqOXlx6v997bC5MEm MaEnpLIFrnVvDrar0FiAwfXXMy6xnyP/hDS4AU5RgO39G7UOtnxnXFMWFf4xvlCNjssZ zn3aXF2d5Gozh/5+HGSF4op4SH6OWL9Yr2DuHcFEdF68r78YQsiA1iNeN2ie1gPHzpwe bEJw== X-Gm-Message-State: AElRT7Erx/8mHZ0Gil/C9rGviN1rFCW/fye5EIcF+1X6nS9I36pApDdx c3+Q3rW2Hy4+UTVxu52RJJfbkQ== X-Google-Smtp-Source: AG47ELuhjBdIUBKbChL9/84MOQdUNAHN5m1DW2HWA83hSvBVACi5YRs9jsNP6oGyWbtZEsf3JW0v6g== X-Received: by 10.46.73.73 with SMTP id b9mr1835393ljd.129.1520413849185; Wed, 07 Mar 2018 01:10:49 -0800 (PST) Received: from tuxracer.localdomain ([2a01:6d80::195:20:96:53]) by smtp.gmail.com with ESMTPSA id j7sm3643490lfh.46.2018.03.07.01.10.48 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 07 Mar 2018 01:10:48 -0800 (PST) From: Serhey Popovych To: netfilter-devel@vger.kernel.org Cc: willem.j.debruijn@gmail.com Subject: [PATCH iptables 1/4] xtables: Do not register matches/targets with incompatible revision Date: Wed, 7 Mar 2018 11:10:40 +0200 Message-Id: <1520413843-24456-2-git-send-email-serhe.popovych@gmail.com> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1520413843-24456-1-git-send-email-serhe.popovych@gmail.com> References: <1520413843-24456-1-git-send-email-serhe.popovych@gmail.com> Sender: netfilter-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org If kernel tells revision isn't found/supported at the moment we should keep entity in pending list, not register or bail to do so later. Kernel might still load module for entity we asking it for and this could be slow on some embedded devices. Catch double registration attempts by checking me->next being non-NULL in xtables_register_match() and xtables_register_target(). Signed-off-by: Serhey Popovych --- libxtables/xtables.c | 66 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 42 insertions(+), 24 deletions(-) diff --git a/libxtables/xtables.c b/libxtables/xtables.c index 57a1102..5aaa238 100644 --- a/libxtables/xtables.c +++ b/libxtables/xtables.c @@ -198,8 +198,8 @@ struct xtables_match *xtables_matches; struct xtables_target *xtables_targets; /* Fully register a match/target which was previously partially registered. */ -static void xtables_fully_register_pending_match(struct xtables_match *me); -static void xtables_fully_register_pending_target(struct xtables_target *me); +static bool xtables_fully_register_pending_match(struct xtables_match *me); +static bool xtables_fully_register_pending_target(struct xtables_target *me); void xtables_init(void) { @@ -638,11 +638,11 @@ xtables_find_match(const char *name, enum xtables_tryload tryload, if (extension_cmp(name, (*dptr)->name, (*dptr)->family)) { ptr = *dptr; *dptr = (*dptr)->next; - ptr->next = NULL; - xtables_fully_register_pending_match(ptr); - } else { - dptr = &((*dptr)->next); + if (xtables_fully_register_pending_match(ptr)) + continue; + *dptr = ptr; } + dptr = &((*dptr)->next); } for (ptr = xtables_matches; ptr; ptr = ptr->next) { @@ -728,11 +728,11 @@ xtables_find_target(const char *name, enum xtables_tryload tryload) if (extension_cmp(name, (*dptr)->name, (*dptr)->family)) { ptr = *dptr; *dptr = (*dptr)->next; - ptr->next = NULL; - xtables_fully_register_pending_target(ptr); - } else { - dptr = &((*dptr)->next); + if (xtables_fully_register_pending_target(ptr)) + continue; + *dptr = ptr; } + dptr = &((*dptr)->next); } for (ptr = xtables_targets; ptr; ptr = ptr->next) { @@ -846,6 +846,12 @@ static void xtables_check_options(const char *name, const struct option *opt) void xtables_register_match(struct xtables_match *me) { + if (me->next) { + fprintf(stderr, "%s: match \"%s\" already registered\n", + xt_params->program_name, me->name); + exit(1); + } + if (me->version == NULL) { fprintf(stderr, "%s: match %s<%u> is missing a version\n", xt_params->program_name, me->name, me->revision); @@ -947,12 +953,17 @@ static int xtables_target_prefer(const struct xtables_target *a, b->revision, b->family); } -static void xtables_fully_register_pending_match(struct xtables_match *me) +static bool xtables_fully_register_pending_match(struct xtables_match *me) { struct xtables_match **i, *old; const char *rn; int compare; + /* See if new match can be used. */ + rn = (me->real_name != NULL) ? me->real_name : me->name; + if (!compatible_match_revision(rn, me->revision)) + return false; + old = xtables_find_match(me->name, XTF_DURING_LOAD, NULL); if (old) { compare = xtables_match_prefer(old, me); @@ -967,12 +978,7 @@ static void xtables_fully_register_pending_match(struct xtables_match *me) rn = (old->real_name != NULL) ? old->real_name : old->name; if (compare > 0 && compatible_match_revision(rn, old->revision)) - return; - - /* See if new match can be used. */ - rn = (me->real_name != NULL) ? me->real_name : me->name; - if (!compatible_match_revision(rn, me->revision)) - return; + return true; /* Delete old one. */ for (i = &xtables_matches; *i!=old; i = &(*i)->next); @@ -993,6 +999,8 @@ static void xtables_fully_register_pending_match(struct xtables_match *me) me->m = NULL; me->mflags = 0; + + return true; } void xtables_register_matches(struct xtables_match *match, unsigned int n) @@ -1004,6 +1012,12 @@ void xtables_register_matches(struct xtables_match *match, unsigned int n) void xtables_register_target(struct xtables_target *me) { + if (me->next) { + fprintf(stderr, "%s: target \"%s\" already registered\n", + xt_params->program_name, me->name); + exit(1); + } + if (me->version == NULL) { fprintf(stderr, "%s: target %s<%u> is missing a version\n", xt_params->program_name, me->name, me->revision); @@ -1044,12 +1058,19 @@ void xtables_register_target(struct xtables_target *me) xtables_pending_targets = me; } -static void xtables_fully_register_pending_target(struct xtables_target *me) +static bool xtables_fully_register_pending_target(struct xtables_target *me) { struct xtables_target *old; const char *rn; int compare; + if (strcmp(me->name, "standard") != 0) { + /* See if new target can be used. */ + rn = (me->real_name != NULL) ? me->real_name : me->name; + if (!compatible_target_revision(rn, me->revision)) + return false; + } + old = xtables_find_target(me->name, XTF_DURING_LOAD); if (old) { struct xtables_target **i; @@ -1066,12 +1087,7 @@ static void xtables_fully_register_pending_target(struct xtables_target *me) rn = (old->real_name != NULL) ? old->real_name : old->name; if (compare > 0 && compatible_target_revision(rn, old->revision)) - return; - - /* See if new target can be used. */ - rn = (me->real_name != NULL) ? me->real_name : me->name; - if (!compatible_target_revision(rn, me->revision)) - return; + return true; /* Delete old one. */ for (i = &xtables_targets; *i!=old; i = &(*i)->next); @@ -1090,6 +1106,8 @@ static void xtables_fully_register_pending_target(struct xtables_target *me) xtables_targets = me; me->t = NULL; me->tflags = 0; + + return true; } void xtables_register_targets(struct xtables_target *target, unsigned int n)