Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 15 Jul 2002 12:51:58 +0200
From:      Thomas Moestl <tmoestl@gmx.net>
To:        Mike Barcroft <mike@FreeBSD.org>
Cc:        Luigi Rizzo <luigi@freebsd.org>, current@freebsd.org
Subject:   Re: different packing of structs in kernel vs. userland ?
Message-ID:  <20020715105158.GA314@crow.dom2ip.de>
In-Reply-To: <20020714230821.C64412@espresso.q9media.com>
References:  <20020714011810.A72236@iguana.icir.org> <20020714203642.GD314@crow.dom2ip.de> <20020714230821.C64412@espresso.q9media.com>

next in thread | previous in thread | raw e-mail | index | archive | help
On Sun, 2002/07/14 at 23:08:21 -0400, Mike Barcroft wrote:
> Thomas Moestl <tmoestl@gmx.net> writes:
> > (Disclaimer: my solution below is untested, so it may all be bogus)
> 
> As request, here are the test results.
> 
> Most rules work, except my final one:
> %%%
> bowie# ipfw add allow all from any to any
> ipfw: getsockopt(IP_FW_ADD): Invalid argument
> %%%

Oh, right, that's related: the kernel checks for a minimum size of the
passed data on two occasions, first in sooptcopyin(), and then again
in check_ipfw_struct().
It the size to be at least sizeof(struct ip_fw), however for
structures containing just one action (like the one for the command
above) this is again too much in the 64-bit case because of the
padding. Can you please try the attached patch (against the CVS
version)?

	- thomas

-- 
Thomas Moestl <tmoestl@gmx.net>	http://www.tu-bs.de/~y0015675/
              <tmm@FreeBSD.org>	http://people.FreeBSD.org/~tmm/
PGP fingerprint: 1C97 A604 2BD0 E492 51D0  9C0F 1FE6 4F1D 419C 776C

Index: ip_fw.h
===================================================================
RCS file: /home/ncvs/src/sys/netinet/ip_fw.h,v
retrieving revision 1.71
diff -u -r1.71 ip_fw.h
--- ip_fw.h	8 Jul 2002 22:39:19 -0000	1.71
+++ ip_fw.h	15 Jul 2002 10:48:19 -0000
@@ -294,8 +294,9 @@
 #define ACTION_PTR(rule)				\
 	(ipfw_insn *)( (u_int32_t *)((rule)->cmd) + ((rule)->act_ofs) )
 
-#define RULESIZE(rule)  (sizeof(struct ip_fw) + \
-	((struct ip_fw *)(rule))->cmd_len * 4 - 4)
+#define	RULESIZE_FROMLEN(len)	(offsetof(struct ip_fw, cmd) + (len) * 4)
+#define	RULESIZE(rule)	RULESIZE_FROMLEN(((struct ip_fw *)(rule))->cmd_len)
+#define	RULESIZE_MIN	RULESIZE_FROMLEN(1)
 
 /*
  * This structure is used as a flow mask and a flow id for various
Index: ip_fw2.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/ip_fw2.c,v
retrieving revision 1.4
diff -u -r1.4 ip_fw2.c
--- ip_fw2.c	8 Jul 2002 22:46:01 -0000	1.4
+++ ip_fw2.c	15 Jul 2002 10:38:09 -0000
@@ -2142,7 +2142,7 @@
 	int have_action=0;
 	ipfw_insn *cmd;
 
-	if (size < sizeof(*rule)) {
+	if (size < RULESIZE_MIN) {
 		printf("ipfw: rule too short\n");
 		return (EINVAL);
 	}
@@ -2428,7 +2428,7 @@
 	case IP_FW_ADD:
 		rule = (struct ip_fw *)rule_buf; /* XXX do a malloc */
 		error = sooptcopyin(sopt, rule, sizeof(rule_buf),
-			sizeof(struct ip_fw) );
+			RULESIZE_MIN);
 		size = sopt->sopt_valsize;
 		if (error || (error = check_ipfw_struct(rule, size)))
 			break;

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message




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