From nobody Thu Sep 19 01:20:52 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) client-ip=8.43.85.245; envelope-from=devel-bounces@lists.libvirt.org; helo=lists.libvirt.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [8.43.85.245]) by mx.zohomail.com with SMTPS id 1715967866021374.34588953762875; Fri, 17 May 2024 10:44:26 -0700 (PDT) Received: by lists.libvirt.org (Postfix, from userid 996) id E51B61C35; Fri, 17 May 2024 13:44:24 -0400 (EDT) Received: from lists.libvirt.org (localhost [IPv6:::1]) by lists.libvirt.org (Postfix) with ESMTP id 1F4BD1D67; Fri, 17 May 2024 13:31:05 -0400 (EDT) Received: by lists.libvirt.org (Postfix, from userid 996) id D97841898; Fri, 17 May 2024 13:30:16 -0400 (EDT) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by lists.libvirt.org (Postfix) with ESMTPS id E949E1927 for ; Fri, 17 May 2024 13:30:11 -0400 (EDT) Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-186-GkyWZ-KRPo-ZHo07uA0NWA-1; Fri, 17 May 2024 13:30:10 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id E786B3813BC9 for ; Fri, 17 May 2024 17:30:09 +0000 (UTC) Received: from vhost3.router.laine.org (unknown [10.22.16.223]) by smtp.corp.redhat.com (Postfix) with ESMTP id D1D3640C6CB7 for ; Fri, 17 May 2024 17:30:09 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=-0.5 required=5.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H4,RCVD_IN_MSPIKE_WL,SPF_HELO_NONE autolearn=unavailable autolearn_force=no version=3.4.4 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1715967011; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=f1DW2S6BeEiVyfdh96RtPnzLGsY5AguiqNJdLCeY8Ao=; b=eE7GaQ9q5pz1aYug9Gu+OmRhEkYb9I5V/4zTUJDyGY5wAKR+y5tiZAoTmHe/sRdZQ748Nr DIMa0Uxk2Pfqf6/i3Q5o4lrRNj1L4hm1MRPzVnO4xFZ7awihX6xhsEM2N7bFVlvhE3jAGV dLFk8HZ28uSYWLkiJvWk53ScXCQNckQ= X-MC-Unique: GkyWZ-KRPo-ZHo07uA0NWA-1 From: Laine Stump To: devel@lists.libvirt.org Subject: [PATCH v5 14/30] util: new functions to support adding individual firewall rollback commands Date: Fri, 17 May 2024 13:29:51 -0400 Message-ID: <20240517173007.8125-15-laine@redhat.com> In-Reply-To: <20240517173007.8125-1-laine@redhat.com> References: <20240517173007.8125-1-laine@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.2 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Message-ID-Hash: SWR6F5WUCBA3AQRXKNL7QDYJFCKIO2EE X-Message-ID-Hash: SWR6F5WUCBA3AQRXKNL7QDYJFCKIO2EE X-MailFrom: laine@redhat.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-config-1; header-match-config-2; header-match-config-3; header-match-devel.lists.libvirt.org-0; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; suspicious-header X-Mailman-Version: 3.2.2 Precedence: list List-Id: Development discussions about the libvirt library & tools Archived-At: List-Archive: List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1715967867215100001 Content-Type: text/plain; charset="utf-8" In the past virFirewall required all rollback commands for a group (those commands necessary to "undo" any rules that had been added in that group in case of a later failure) to be manually added by switching into the virFirewall object into "rollback mode" and then re-calling the inverse of the exact virFirewallAddCmd*() APIs that had been called to add the original rules (ie. for each "iptables --insert" command, for rollback we would need to add a command with all arguments identical except that "--insert" would be replaced by "--delete"). Because nftables can't search for rules to remove by comparing all the arguments (it instead expects *only* a handle that is provided via stdout when the rule was originally added), we won't be able to follow the iptables method and manually construct the command to undo any given nft command by just duplicating all the args of the command (except the action). Instead we will need to be able to automatically create a rollback command at the time the rule-adding command is executed (e.g. an "nft delete rule" command that would include the rule handle returned in stdout by an "nft add rule" command). In order to make this happen, we need to be able to 1) learn whether the user of the virFirewall API desires this behavior (handled by a new transaction flag called VIR_FIREWALL_TRANSACTION_AUTO_ROLLBACK that can be retrieved with the new virFirewallTransactionGetFlags() API), and 2) add a new command to the current group's rollback command list (with the new virFirewallAddRollbackCmd()). We will actually use this capability in an upcoming patch. Signed-off-by: Laine Stump Reviewed-by: Daniel P. Berrang=C3=A9 --- src/libvirt_private.syms | 1 + src/util/virfirewall.c | 55 +++++++++++++++++++++++++++++++++++----- src/util/virfirewall.h | 7 +++++ 3 files changed, 57 insertions(+), 6 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 6cb3003499..893859caba 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2405,6 +2405,7 @@ virFileCacheSetPriv; =20 # util/virfirewall.h virFirewallAddCmdFull; +virFirewallAddRollbackCmd; virFirewallApply; virFirewallBackendTypeFromString; virFirewallBackendTypeToString; diff --git a/src/util/virfirewall.c b/src/util/virfirewall.c index 77de34533d..9def8999d5 100644 --- a/src/util/virfirewall.c +++ b/src/util/virfirewall.c @@ -198,10 +198,12 @@ void virFirewallFree(virFirewall *firewall) fwCmd->args[fwCmd->argsLen++] =3D g_strdup(str); \ } while (0) =20 + static virFirewallCmd * virFirewallAddCmdFullV(virFirewall *firewall, virFirewallLayer layer, bool ignoreErrors, + bool isRollback, virFirewallQueryCallback cb, void *opaque, va_list args) @@ -218,18 +220,16 @@ virFirewallAddCmdFullV(virFirewall *firewall, } group =3D firewall->groups[firewall->currentGroup]; =20 - fwCmd =3D g_new0(virFirewallCmd, 1); - fwCmd->layer =3D layer; - fwCmd->queryCB =3D cb; - fwCmd->queryOpaque =3D opaque; =20 while ((str =3D va_arg(args, char *)) !=3D NULL) ADD_ARG(fwCmd, str); =20 - if (group->addingRollback) { + if (isRollback || group->addingRollback) { fwCmd->ignoreErrors =3D true; /* always ignore errors when rolling= back */ + fwCmd->queryCB =3D NULL; /* rollback commands can't have a callbac= k */ + fwCmd->queryOpaque =3D NULL; VIR_APPEND_ELEMENT_COPY(group->rollback, group->nrollback, fwCmd); } else { /* when not rolling back, ignore errors if this group (transaction) @@ -237,6 +237,8 @@ virFirewallAddCmdFullV(virFirewall *firewall, * if this specific rule was created with ignoreErrors =3D=3D true */ fwCmd->ignoreErrors =3D ignoreErrors || (group->actionFlags & VIR_= FIREWALL_TRANSACTION_IGNORE_ERRORS); + fwCmd->queryCB =3D cb; + fwCmd->queryOpaque =3D opaque; VIR_APPEND_ELEMENT_COPY(group->action, group->naction, fwCmd); } =20 @@ -277,7 +279,33 @@ virFirewallCmd *virFirewallAddCmdFull(virFirewall *fir= ewall, virFirewallCmd *fwCmd; va_list args; va_start(args, opaque); - fwCmd =3D virFirewallAddCmdFullV(firewall, layer, ignoreErrors, cb, op= aque, args); + fwCmd =3D virFirewallAddCmdFullV(firewall, layer, ignoreErrors, false,= cb, opaque, args); + va_end(args); + return fwCmd; +} + + +/** + * virFirewallAddRollbackCmd: + * @firewall: firewall commands to add to + * @layer: the firewall layer to change + * @...: NULL terminated list of strings for the command + * + * Add a command to the current firewall command group "rollback". + * Rollback commands always ignore errors and don't support any + * callbacks. + * + * Returns the new Command + */ +virFirewallCmd * +virFirewallAddRollbackCmd(virFirewall *firewall, + virFirewallLayer layer, + ...) +{ + virFirewallCmd *fwCmd; + va_list args; + va_start(args, layer); + fwCmd =3D virFirewallAddCmdFullV(firewall, layer, true, true, NULL, NU= LL, args); va_end(args); return fwCmd; } @@ -434,6 +462,21 @@ void virFirewallStartTransaction(virFirewall *firewall, firewall->currentGroup =3D firewall->ngroups - 1; } =20 + +/** + * virFirewallTransactionGetFlags: + * @firewall: the firewall to look at + * + * Returns the virFirewallTransactionFlags for the currently active + * group (transaction) in @firewall. + */ +static virFirewallTransactionFlags G_GNUC_UNUSED +virFirewallTransactionGetFlags(virFirewall *firewall) +{ + return firewall->groups[firewall->currentGroup]->actionFlags; +} + + /** * virFirewallBeginRollback: * @firewall: the firewall ruleset diff --git a/src/util/virfirewall.h b/src/util/virfirewall.h index 1ca1cce10a..e6aac365f1 100644 --- a/src/util/virfirewall.h +++ b/src/util/virfirewall.h @@ -73,6 +73,11 @@ virFirewallCmd *virFirewallAddCmdFull(virFirewall *firew= all, ...) G_GNUC_NULL_TERMINATED; =20 +virFirewallCmd *virFirewallAddRollbackCmd(virFirewall *firewall, + virFirewallLayer layer, + ...) + G_GNUC_NULL_TERMINATED; + void virFirewallRemoveCmd(virFirewall *firewall, virFirewallCmd *rule); =20 @@ -105,6 +110,8 @@ typedef enum { /* Ignore all errors when applying rules, so no * rollback block will be required */ VIR_FIREWALL_TRANSACTION_IGNORE_ERRORS =3D (1 << 0), + /* Set to auto-add a rollback rule for each rule that is applied */ + VIR_FIREWALL_TRANSACTION_AUTO_ROLLBACK =3D (1 << 1), } virFirewallTransactionFlags; =20 void virFirewallStartTransaction(virFirewall *firewall, --=20 2.45.0