Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 15 Dec 2002 11:40:10 -0800 (PST)
From:      Matthew Dillon <dillon@apollo.backplane.com>
To:        "M. Warner Losh" <imp@bsdimp.com>
Cc:        sam@errno.com, mux@FreeBSD.ORG, obrien@FreeBSD.ORG, current@FreeBSD.ORG
Subject:   Re: ipfw userland breaks again.
Message-ID:  <200212151940.gBFJeA1l086827@apollo.backplane.com>
References:  <200212151826.gBFIQMpo081407@apollo.backplane.com> <20021215.115657.90648628.imp@bsdimp.com> <200212151908.gBFJ811I081774@apollo.backplane.com> <20021215.121446.79106618.imp@bsdimp.com>

next in thread | previous in thread | raw e-mail | index | archive | help
:I've answered this in other email, but you need to expand the check at
:the top of ipfw_ctl to include this new message as one of the ones
:that is disallowed at high security levels.
:
:Warner

    Here's a new patch.  But there isn't much of a point if we do not
    also disallow ipfw DELETE and FLUSH.  And the pipe config commands
    as well as anything else that changes the firewall state.  Firewalls
    are there to protect the systems behind them.  I think deleting the
    rule that, say, prevents spoofing is as bad as adding a rule that
    allows everything through :-(

					-Matt
					Matthew Dillon 
					<dillon@backplane.com>


Index: sbin/ipfw/ipfw.8
===================================================================
RCS file: /home/ncvs/src/sbin/ipfw/ipfw.8,v
retrieving revision 1.116
diff -u -r1.116 ipfw.8
--- sbin/ipfw/ipfw.8	26 Nov 2002 19:51:40 -0000	1.116
+++ sbin/ipfw/ipfw.8	14 Dec 2002 22:17:17 -0000
@@ -21,6 +21,9 @@
 .Cm flush
 .Nm
 .Op Fl q
+.Cm unbreak
+.Nm
+.Op Fl q
 .Brq Cm delete | zero | resetlog
 .Op Cm set
 .Op Ar number ...
@@ -179,6 +182,16 @@
 and
 .Cm resetlog
 commands.
+.Pp
+When upgrading your kernel and userland you may wind up in a situation
+where
+.Nm
+is unable to add rules due to a kernel/userland mismatch.  If you depend
+on NFS as your install source this can result in a no-win situation.
+You can use the
+.Cm unbreak
+command to flush and install a simple pass-through rule that will allow
+you to get your network up and running so you can resolve the problem.
 .Pp
 Also, each rule belongs to one of 32 different
 .Em sets
Index: sbin/ipfw/ipfw2.c
===================================================================
RCS file: /home/ncvs/src/sbin/ipfw/ipfw2.c,v
retrieving revision 1.18
diff -u -r1.18 ipfw2.c
--- sbin/ipfw/ipfw2.c	26 Nov 2002 22:53:14 -0000	1.18
+++ sbin/ipfw/ipfw2.c	14 Dec 2002 22:08:11 -0000
@@ -3307,6 +3307,30 @@
 		printf("Flushed all %s.\n", do_pipe ? "pipes" : "rules");
 }
 
+static void
+unbreak()
+{
+	if (!do_force && !do_quiet) { /* need to ask user */
+		int c;
+
+		printf("Are you sure? [yn] ");
+		fflush(stdout);
+		do {
+			c = toupper(getc(stdin));
+			while (c != '\n' && getc(stdin) != '\n')
+				if (feof(stdin))
+					return; /* and do not flush */
+		} while (c != 'Y' && c != 'N');
+		printf("\n");
+		if (c == 'N')	/* user said no */
+			return;
+	}
+	if (setsockopt(s, IPPROTO_IP, IP_FW_UNBREAK, NULL, 0) < 0)
+		err(EX_UNAVAILABLE, "setsockopt(IP_FW_UNBREAK)");
+	if (!do_quiet)
+		printf("Flushed all rules and installed a pass-through.\n");
+}
+
 static int
 ipfw_main(int ac, char **av)
 {
@@ -3398,6 +3422,8 @@
 		delete(ac, av);
 	else if (!strncmp(*av, "flush", strlen(*av)))
 		flush();
+	else if (!strncmp(*av, "unbreak", strlen(*av)))
+		unbreak();
 	else if (!strncmp(*av, "zero", strlen(*av)))
 		zero(ac, av);
 	else if (!strncmp(*av, "resetlog", strlen(*av)))
Index: sys/netinet/in.h
===================================================================
RCS file: /home/ncvs/src/sys/netinet/in.h,v
retrieving revision 1.73
diff -u -r1.73 in.h
--- sys/netinet/in.h	29 Oct 2002 16:46:13 -0000	1.73
+++ sys/netinet/in.h	14 Dec 2002 21:32:07 -0000
@@ -393,6 +393,7 @@
 #define	IP_FW_ZERO    		53   /* clear single/all firewall counter(s) */
 #define	IP_FW_GET     		54   /* get entire firewall rule chain */
 #define	IP_FW_RESETLOG		55   /* reset logging counters */
+#define	IP_FW_UNBREAK		56   /* flush and install a pass-thru rule */
 
 #define	IP_DUMMYNET_CONFIGURE	60   /* add/configure a dummynet pipe */
 #define	IP_DUMMYNET_DEL		61   /* delete a dummynet pipe from chain */
Index: sys/netinet/ip_fw2.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/ip_fw2.c,v
retrieving revision 1.20
diff -u -r1.20 ip_fw2.c
--- sys/netinet/ip_fw2.c	15 Dec 2002 09:44:02 -0000	1.20
+++ sys/netinet/ip_fw2.c	15 Dec 2002 19:36:54 -0000
@@ -2457,7 +2457,7 @@
 	 * Disallow modifications in really-really secure mode, but still allow
 	 * the logging counters to be reset.
 	 */
-	if (sopt->sopt_name == IP_FW_ADD ||
+	if (sopt->sopt_name == IP_FW_ADD || sopt->sopt_name == IP_FW_UNBREAK ||
 	    (sopt->sopt_dir == SOPT_SET && sopt->sopt_name != IP_FW_RESETLOG)) {
 #if __FreeBSD_version >= 500034
 		error = securelevel_ge(sopt->sopt_td->td_ucred, 3);
@@ -2535,6 +2535,7 @@
 		break;
 
 	case IP_FW_FLUSH:
+	case IP_FW_UNBREAK:
 		/*
 		 * Normally we cannot release the lock on each iteration.
 		 * We could do it here only because we start from the head all
@@ -2551,6 +2552,22 @@
 		s = splimp();
 		free_chain(&layer3_chain, 0 /* keep default rule */);
 		splx(s);
+
+		/*
+		 * If unbreaking the rulechain, which a sysad may have to do
+		 * if IP_FW_ADD fails due to a userland/kernelland mismatch,
+		 * install a pass-through rule.
+		 */
+		if (sopt->sopt_name == IP_FW_UNBREAK) {
+			rule = (struct ip_fw *)rule_buf; /* XXX do a malloc */
+			bzero(rule, sizeof(*rule));
+			rule->rulenum = 2;
+			rule->cmd_len = 1;
+			rule->set = 1;
+			rule->cmd[0].len = 1;
+			rule->cmd[0].opcode = O_ACCEPT;
+			error = add_rule(&layer3_chain, rule);
+		}
 		break;
 
 	case IP_FW_ADD:
Index: sys/netinet/raw_ip.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/raw_ip.c,v
retrieving revision 1.107
diff -u -r1.107 raw_ip.c
--- sys/netinet/raw_ip.c	20 Nov 2002 19:00:54 -0000	1.107
+++ sys/netinet/raw_ip.c	14 Dec 2002 21:33:58 -0000
@@ -399,6 +399,7 @@
 		case IP_FW_ADD:
 		case IP_FW_DEL:
 		case IP_FW_FLUSH:
+		case IP_FW_UNBREAK:
 		case IP_FW_ZERO:
 		case IP_FW_RESETLOG:
 			if (IPFW_LOADED)

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?200212151940.gBFJeA1l086827>