Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 28 Nov 2013 10:28:28 +0000 (UTC)
From:      "Alexander V. Chernikov" <melifaro@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r258708 - in head: sbin/ipfw sys/netpfil/ipfw
Message-ID:  <201311281028.rASASSoE086573@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: melifaro
Date: Thu Nov 28 10:28:28 2013
New Revision: 258708
URL: http://svnweb.freebsd.org/changeset/base/258708

Log:
  Check ipfw table numbers in both user and kernel space before rule addition.
  
  Found by:	Saychik Pavel <umka@localka.net>
  MFC after:	2 weeks
  Sponsored by:	Yandex LLC

Modified:
  head/sbin/ipfw/ipfw2.c
  head/sbin/ipfw/ipfw2.h
  head/sys/netpfil/ipfw/ip_fw_sockopt.c

Modified: head/sbin/ipfw/ipfw2.c
==============================================================================
--- head/sbin/ipfw/ipfw2.c	Thu Nov 28 10:04:53 2013	(r258707)
+++ head/sbin/ipfw/ipfw2.c	Thu Nov 28 10:28:28 2013	(r258708)
@@ -60,6 +60,8 @@ int resvd_set_number = RESVD_SET;
 
 int ipfw_socket = -1;
 
+uint32_t ipfw_tables_max = 0; /* Number of tables supported by kernel */
+
 #ifndef s6_addr32
 #define s6_addr32 __u6_addr.__u6_addr32
 #endif
@@ -2203,6 +2205,7 @@ fill_ip(ipfw_insn_ip *cmd, char *av, int
 {
 	int len = 0;
 	uint32_t *d = ((ipfw_insn_u32 *)cmd)->d;
+	uint32_t tables_max;
 
 	cmd->o.len &= ~F_LEN_MASK;	/* zero len */
 
@@ -2221,6 +2224,10 @@ fill_ip(ipfw_insn_ip *cmd, char *av, int
 			*p++ = '\0';
 		cmd->o.opcode = O_IP_DST_LOOKUP;
 		cmd->o.arg1 = strtoul(av + 6, NULL, 0);
+		tables_max = ipfw_get_tables_max();
+		if (cmd->o.arg1 > tables_max)
+			errx(EX_USAGE, "The table number exceeds the maximum "
+			    "allowed value (%u)", tables_max - 1);
 		if (p) {
 			cmd->o.len |= F_INSN_SIZE(ipfw_insn_u32);
 			d[0] = strtoul(p, NULL, 0);
@@ -4119,6 +4126,33 @@ static void table_list(uint16_t num, int
 static void table_fill_xentry(char *arg, ipfw_table_xentry *xent);
 
 /*
+ * Retrieve maximum number of tables supported by ipfw(4) module.
+ */
+uint32_t
+ipfw_get_tables_max()
+{
+	size_t len;
+	uint32_t tables_max;
+
+	if (ipfw_tables_max != 0)
+		return (ipfw_tables_max);
+
+	len = sizeof(tables_max);
+	if (sysctlbyname("net.inet.ip.fw.tables_max", &tables_max, &len,
+	    NULL, 0) == -1) {
+		if (co.test_only)
+			tables_max = 128; /* Old conservative default */
+		else
+			errx(1, "Can't determine maximum number of ipfw tables."
+			    " Perhaps you forgot to load ipfw module?");
+	}
+
+	ipfw_tables_max = tables_max;
+
+	return (ipfw_tables_max);
+}
+
+/*
  * This one handles all table-related commands
  * 	ipfw table N add addr[/masklen] [value]
  * 	ipfw table N delete addr[/masklen]
@@ -4131,19 +4165,10 @@ ipfw_table_handler(int ac, char *av[])
 	ipfw_table_xentry xent;
 	int do_add;
 	int is_all;
-	size_t len;
 	uint32_t a;
 	uint32_t tables_max;
 
-	len = sizeof(tables_max);
-	if (sysctlbyname("net.inet.ip.fw.tables_max", &tables_max, &len,
-	    NULL, 0) == -1) {
-		if (co.test_only)
-			tables_max = 128; /* Old conservative default */
-		else
-			errx(1, "Can't determine maximum number of ipfw tables."
-			    " Perhaps you forgot to load ipfw module?");
-	}
+	tables_max = ipfw_get_tables_max();
 
 	memset(&xent, 0, sizeof(xent));
 

Modified: head/sbin/ipfw/ipfw2.h
==============================================================================
--- head/sbin/ipfw/ipfw2.h	Thu Nov 28 10:04:53 2013	(r258707)
+++ head/sbin/ipfw/ipfw2.h	Thu Nov 28 10:28:28 2013	(r258708)
@@ -228,6 +228,8 @@ char const *match_value(struct _s_x *p, 
 
 int do_cmd(int optname, void *optval, uintptr_t optlen);
 
+uint32_t ipfw_get_tables_max(void);
+
 struct in6_addr;
 void n2mask(struct in6_addr *mask, int n);
 int contigmask(uint8_t *p, int len);

Modified: head/sys/netpfil/ipfw/ip_fw_sockopt.c
==============================================================================
--- head/sys/netpfil/ipfw/ip_fw_sockopt.c	Thu Nov 28 10:04:53 2013	(r258707)
+++ head/sys/netpfil/ipfw/ip_fw_sockopt.c	Thu Nov 28 10:28:28 2013	(r258708)
@@ -653,7 +653,7 @@ check_ipfw_struct(struct ip_fw *rule, in
 
 		case O_IP_SRC_LOOKUP:
 		case O_IP_DST_LOOKUP:
-			if (cmd->arg1 >= IPFW_TABLES_MAX) {
+			if (cmd->arg1 >= V_fw_tables_max) {
 				printf("ipfw: invalid table number %d\n",
 				    cmd->arg1);
 				return (EINVAL);



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