kern/189089: Panic when removing an IP address from an interface, if the same address exists on another interface

Alan Somers asomers at freebsd.org
Mon Apr 28 22:50:00 UTC 2014


>Number:         189089
>Category:       kern
>Synopsis:       Panic when removing an IP address from an interface, if the same address exists on another interface
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Mon Apr 28 22:50:00 UTC 2014
>Closed-Date:
>Last-Modified:
>Originator:     Alan Somers
>Release:        11.0 CURRENT
>Organization:
Spectra Logic
>Environment:
FreeBSD b 11.0-CURRENT FreeBSD 11.0-CURRENT #9 r264904M: Fri Apr 25 14:46:45 PDT 2014     neel at b:/usr/obj/neel/usr/freebsd/head2/sys/GENERIC  amd64
>Description:
If you assign the same IP address to multiple interfaces simultaneously, then remove it from one of them, the system will panic with this message:

panic: rtalloc1_fib: bad fibnum

The panic was introduced by revision 264887, which changed the fibnum parameter in the call to rtalloc1_fib() in ifa_switch_loopback_route() from RT_DEFAULT_FIB to RT_ALL_FIBS.  Prior to 264887 the call would always succeed, but it could corrupt the network stack if the route in question was not located in the default fib.  That wasn't a big deal though, since prior to 264887 it was very difficult create that route in a nondefault fib.


>How-To-Repeat:
# # Set net.fibs=1 and net.add_addr_allfibs=1
# ifconfig tap0 create
# ifconfig tap1 create
# ifconfig tap0 192.0.0.2/24 up
# ifconfig tap1 192.0.0.2/32 up
# netstat -rn -f inet
Routing tables

Internet:
Destination        Gateway            Flags    Netif Expire
default            10.1.0.1           UGS       em0
10.1.0.0/20        link#1             U         em0
10.1.3.220         link#1             UHS       lo0
127.0.0.1          link#2             UH        lo0
192.0.0.0/24       link#3             U        tap0
192.0.0.2          link#3             UHS       lo0
192.0.0.2/32       link#4             U        tap1
# ifconfig tap1 -alias 192.0.0.2 # This line will panic!

>Fix:
The solution is to use the interface fib instead of either the default fib or ALL_FIBS.  This will give equivalent behavior as the pre-264887 status quo for the majority of users.

Patch attached with submission follows:

Index: sys/netinet/in.c
===================================================================
--- sys/netinet/in.c	(revision 265061)
+++ sys/netinet/in.c	(working copy)
@@ -696,11 +696,9 @@
 {
 	struct in_ifaddr *ia;
 	struct in_addr prefix, mask, p, m;
-	int error = 0, fibnum;
+	int error = 0;
 	struct sockaddr_in prefix0, mask0;
 
-	fibnum = rt_add_addr_allfibs ? RT_ALL_FIBS : target->ia_ifp->if_fib;
-
 	/*
 	 * Remove the loopback route to the interface address.
 	 */
@@ -712,6 +710,8 @@
 		eia = in_localip_more(target);
 
 		if (eia != NULL) {
+			int fibnum = target->ia_ifp->if_fib;
+
 			error = ifa_switch_loopback_route((struct ifaddr *)eia,
 			    (struct sockaddr *)&target->ia_addr, fibnum);
 			ifa_free(&eia->ia_ifa);
@@ -736,6 +736,10 @@
 	}
 
 	if ((target->ia_flags & IFA_ROUTE) == 0) {
+		int fibnum;
+		
+		fibnum = rt_add_addr_allfibs ? RT_ALL_FIBS :
+			target->ia_ifp->if_fib;
 		rt_addrmsg(RTM_DELETE, &target->ia_ifa, fibnum);
 		return (0);
 	}
Index: tests/sys/netinet/fibs_test.sh
===================================================================
--- tests/sys/netinet/fibs_test.sh	(revision 265061)
+++ tests/sys/netinet/fibs_test.sh	(working copy)
@@ -213,6 +213,45 @@
 }
 
 
+# Regression test for a panic introduced in change 264887
+# Create two tap interfaces and assign them both the same IP address but with
+# different netmasks, and both on the default FIB.  Then remove one's IP
+# address.  Hopefully the machine won't panic.
+atf_test_case same_ip_multiple_ifaces_fib0 cleanup
+same_ip_multiple_ifaces_fib0_head()
+{
+	atf_set "descr" "Can remove an IP alias from an interface when the same IP is also assigned to another interface."
+	atf_set "require.user" "root"
+	atf_set "require.config" "fibs"
+}
+same_ip_multiple_ifaces_fib0_body()
+{
+	ADDR="192.0.2.2"
+	MASK0="24"
+	MASK1="32"
+
+	# Unlike most of the tests in this file, this is applicable regardless
+	# of net.add_addr_allfibs
+
+	# Setup the interfaces, then remove one alias.  It should not panic.
+	setup_tap 0 ${ADDR} ${MASK0}
+	TAP0=${TAP}
+	setup_tap 0 ${ADDR} ${MASK1}
+	TAP1=${TAP}
+	ifconfig ${TAP1} -alias ${ADDR}
+
+	# Do it again, in the opposite order.  It should not panic.
+	setup_tap 0 ${ADDR} ${MASK0}
+	TAP0=${TAP}
+	setup_tap 0 ${ADDR} ${MASK1}
+	TAP1=${TAP}
+	ifconfig ${TAP0} -alias ${ADDR}
+}
+same_ip_multiple_ifaces_fib0_cleanup()
+{
+	cleanup_tap
+}
+
 # Regression test for kern/187550
 atf_test_case subnet_route_with_multiple_fibs_on_same_subnet cleanup
 subnet_route_with_multiple_fibs_on_same_subnet_head()
@@ -309,6 +348,7 @@
 	atf_add_test_case arpresolve_checks_interface_fib
 	atf_add_test_case loopback_and_network_routes_on_nondefault_fib
 	atf_add_test_case default_route_with_multiple_fibs_on_same_subnet
+	atf_add_test_case same_ip_multiple_ifaces_fib0
 	atf_add_test_case subnet_route_with_multiple_fibs_on_same_subnet
 	atf_add_test_case udp_dontroute
 }


>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list