Page MenuHomeFreeBSD

D51458.diff
No OneTemporary

D51458.diff

diff --git a/sys/netpfil/ipfw/ip_fw_private.h b/sys/netpfil/ipfw/ip_fw_private.h
--- a/sys/netpfil/ipfw/ip_fw_private.h
+++ b/sys/netpfil/ipfw/ip_fw_private.h
@@ -489,6 +489,7 @@
struct rule_check_info {
uint16_t flags; /* rule-specific check flags */
+#define IPFW_RCIFLAG_HAS_STATE 0x0001
uint16_t object_opcodes; /* num of opcodes referencing objects */
uint16_t urule_numoff; /* offset of rulenum in bytes */
uint8_t version; /* rule version */
diff --git a/sys/netpfil/ipfw/ip_fw_sockopt.c b/sys/netpfil/ipfw/ip_fw_sockopt.c
--- a/sys/netpfil/ipfw/ip_fw_sockopt.c
+++ b/sys/netpfil/ipfw/ip_fw_sockopt.c
@@ -1311,6 +1311,9 @@
return (check_ipfw_rule_body(rule->cmd, rule->cmd_len, ci));
}
+#define CHECK_TARG(a, c) \
+ ((a) == IP_FW_TARG && ((c)->flags & IPFW_RCIFLAG_HAS_STATE))
+
enum ipfw_opcheck_result
ipfw_check_opcode(ipfw_insn **pcmd, int *plen, struct rule_check_info *ci)
{
@@ -1326,6 +1329,7 @@
if (cmdlen != F_INSN_SIZE(ipfw_insn_kidx))
return (BAD_SIZE);
ci->object_opcodes++;
+ ci->flags |= IPFW_RCIFLAG_HAS_STATE;
break;
case O_PROTO:
case O_IP_SRC_ME:
@@ -1410,6 +1414,8 @@
cmd->arg1 & 0x7FFF);
return (FAILED);
}
+ if (CHECK_TARG(cmd->arg1, ci))
+ goto bad_targ;
return (CHECK_ACTION);
case O_UID:
@@ -1518,11 +1524,16 @@
case O_QUEUE:
if (cmdlen != F_INSN_SIZE(ipfw_insn))
return (BAD_SIZE);
+ if (CHECK_TARG(cmd->arg1, ci))
+ goto bad_targ;
return (CHECK_ACTION);
case O_FORWARD_IP:
if (cmdlen != F_INSN_SIZE(ipfw_insn_sa))
return (BAD_SIZE);
+ if (insntoc(cmd, sa)->sa.sin_addr.s_addr == INADDR_ANY &&
+ (ci->flags & IPFW_RCIFLAG_HAS_STATE))
+ goto bad_targ;
return (CHECK_ACTION);
#ifdef INET6
case O_FORWARD_IP6:
@@ -1537,6 +1548,8 @@
return (FAILED);
if (cmdlen != F_INSN_SIZE(ipfw_insn))
return (BAD_SIZE);
+ if (CHECK_TARG(cmd->arg1, ci))
+ goto bad_targ;
return (CHECK_ACTION);
case O_NETGRAPH:
case O_NGTEE:
@@ -1544,12 +1557,16 @@
return (FAILED);
if (cmdlen != F_INSN_SIZE(ipfw_insn))
return (BAD_SIZE);
+ if (CHECK_TARG(cmd->arg1, ci))
+ goto bad_targ;
return (CHECK_ACTION);
case O_NAT:
if (!IPFW_NAT_LOADED)
return (FAILED);
if (cmdlen != F_INSN_SIZE(ipfw_insn_nat))
return (BAD_SIZE);
+ if (CHECK_TARG(cmd->arg1, ci))
+ goto bad_targ;
return (CHECK_ACTION);
case O_SKIPTO:
@@ -1557,6 +1574,11 @@
case O_SETMARK:
if (cmdlen != F_INSN_SIZE(ipfw_insn_u32))
return (BAD_SIZE);
+ /* O_CALLRETURN + F_NOT means 'return' opcode. */
+ if (cmd->opcode != O_CALLRETURN || (cmd->len & F_NOT) == 0) {
+ if (CHECK_TARG(insntoc(cmd, u32)->d[0], ci))
+ goto bad_targ;
+ }
return (CHECK_ACTION);
case O_CHECK_STATE:
@@ -1577,6 +1599,8 @@
case O_REASS:
if (cmdlen != F_INSN_SIZE(ipfw_insn))
return (BAD_SIZE);
+ if (cmd->opcode == O_SETDSCP && CHECK_TARG(cmd->arg1, ci))
+ goto bad_targ;
return (CHECK_ACTION);
#ifdef INET6
case O_IP6_SRC:
@@ -1627,6 +1651,13 @@
}
}
return (SUCCESS);
+bad_targ:
+ /*
+ * For dynamic states we can not correctly initialize tablearg value,
+ * because we don't go through rule's opcodes except rule action.
+ */
+ printf("ipfw: tablearg is not allowed with dynamic states\n");
+ return (FAILED);
}
static __noinline int

File Metadata

Mime Type
text/plain
Expires
Mon, Mar 9, 4:26 AM (18 h, 53 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29420936
Default Alt Text
D51458.diff (3 KB)

Event Timeline