Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 19 Jul 2019 15:17:54 +0000 (UTC)
From:      "Andrey V. Elsukov" <ae@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org
Subject:   svn commit: r350137 - stable/12/sys/netpfil/ipfw
Message-ID:  <201907191517.x6JFHsR3057929@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ae
Date: Fri Jul 19 15:17:54 2019
New Revision: 350137
URL: https://svnweb.freebsd.org/changeset/base/350137

Log:
  MFC r349940:
    Correctly truncate the rule in case when it has several action opcodes.
  
    It is possible, that opcode at the ACTION_PTR() location is not real
    action, but action modificator like "log", "tag" etc. In this case we
    need to check for each opcode in the loop to find O_EXTERNAL_ACTION.
  
    Obtained from:	Yandex LLC
    Sponsored by:	Yandex LLC
  
  MFC r349941:
    Do not modify cmd pointer if it is already last opcode in the rule.

Modified:
  stable/12/sys/netpfil/ipfw/ip_fw_eaction.c
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/sys/netpfil/ipfw/ip_fw_eaction.c
==============================================================================
--- stable/12/sys/netpfil/ipfw/ip_fw_eaction.c	Fri Jul 19 15:12:20 2019	(r350136)
+++ stable/12/sys/netpfil/ipfw/ip_fw_eaction.c	Fri Jul 19 15:17:54 2019	(r350137)
@@ -377,35 +377,51 @@ ipfw_reset_eaction(struct ip_fw_chain *ch, struct ip_f
     uint16_t eaction_id, uint16_t default_id, uint16_t instance_id)
 {
 	ipfw_insn *cmd, *icmd;
+	int l, cmdlen;
 
 	IPFW_UH_WLOCK_ASSERT(ch);
 	IPFW_WLOCK_ASSERT(ch);
 
 	cmd = ACTION_PTR(rule);
+	l = rule->cmd_len - rule->act_ofs;
+	while (l > 0) {
+		cmdlen = F_LEN(cmd);
+		l -= cmdlen;
+		if (cmd->opcode == O_EXTERNAL_ACTION || l <= 0)
+			break;
+		cmd += cmdlen;
+	}
+	/*
+	 * Return if there is not O_EXTERNAL_ACTION or its id is
+	 * different.
+	 */
 	if (cmd->opcode != O_EXTERNAL_ACTION ||
 	    cmd->arg1 != eaction_id)
 		return (0);
-
-	if (instance_id != 0 && rule->act_ofs < rule->cmd_len - 1) {
+	/*
+	 * If instance_id is specified, we need to truncate the
+	 * rule length. Check if there is O_EXTERNAL_INSTANCE opcode.
+	 */
+	if (instance_id != 0 && l > 0) {
+		MPASS(cmdlen == 1);
 		icmd = cmd + 1;
 		if (icmd->opcode != O_EXTERNAL_INSTANCE ||
 		    icmd->arg1 != instance_id)
 			return (0);
-		/* FALLTHROUGH */
+		/*
+		 * Since named_object related to this instance will be
+		 * destroyed, truncate the chain of opcodes to remove
+		 * the rest of cmd chain just after O_EXTERNAL_ACTION
+		 * opcode.
+		 */
+		EACTION_DEBUG("truncate rule %d: len %u -> %u",
+		    rule->rulenum, rule->cmd_len, rule->cmd_len - l);
+		rule->cmd_len -= l;
+		MPASS(((uint32_t *)icmd -
+		    (uint32_t *)rule->cmd) == rule->cmd_len);
 	}
 
 	cmd->arg1 = default_id; /* Set to default id */
-	/*
-	 * Since named_object related to this instance will be
-	 * also destroyed, truncate the chain of opcodes to
-	 * remove the rest of cmd chain just after O_EXTERNAL_ACTION
-	 * opcode.
-	 */
-	if (rule->act_ofs < rule->cmd_len - 1) {
-		EACTION_DEBUG("truncate rule %d: len %u -> %u",
-		    rule->rulenum, rule->cmd_len, rule->act_ofs + 1);
-		rule->cmd_len = rule->act_ofs + 1;
-	}
 	/*
 	 * Return 1 when reset successfully happened.
 	 */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201907191517.x6JFHsR3057929>