changeset 11220:41c5df5d6f31

6871708 LIFNAMSIZ not accounting for logical numbers are pathway for ip panics
author Girish Moodalbail <Girish.Moodalbail@Sun.COM>
date Tue, 01 Dec 2009 11:45:15 -0500
parents b9e0489718e9
children b211d0a04b63
files usr/src/cmd/cmd-inet/usr.sbin/ifconfig/ifconfig.c usr/src/uts/common/inet/ip/ip.c usr/src/uts/common/inet/ip/ip_if.c usr/src/uts/common/inet/ip/ip_ndp.c usr/src/uts/common/inet/ip/tnet.c
diffstat 5 files changed, 61 insertions(+), 37 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/cmd/cmd-inet/usr.sbin/ifconfig/ifconfig.c	Tue Dec 01 07:21:46 2009 -0800
+++ b/usr/src/cmd/cmd-inet/usr.sbin/ifconfig/ifconfig.c	Tue Dec 01 11:45:15 2009 -0500
@@ -4284,6 +4284,13 @@
 	case EEXIST:
 		(void) fprintf(stderr, "%s: already exists\n", str);
 		break;
+	case ENAMETOOLONG:
+		(void) fprintf(stderr, "%s: interface name too long\n", str);
+		break;
+	case ERANGE:
+		(void) fprintf(stderr, "%s: logical interface id is outside "
+		    "allowed range\n", str);
+		break;
 	default:
 		errno = error;
 		perror(str);
--- a/usr/src/uts/common/inet/ip/ip.c	Tue Dec 01 07:21:46 2009 -0800
+++ b/usr/src/uts/common/inet/ip/ip.c	Tue Dec 01 11:45:15 2009 -0500
@@ -665,8 +665,6 @@
 /* RFC 1122 Conformance */
 #define	IP_FORWARD_DEFAULT	IP_FORWARD_NEVER
 
-#define	ILL_MAX_NAMELEN			LIFNAMSIZ
-
 static int	ip_open(queue_t *q, dev_t *devp, int flag, int sflag,
 		    cred_t *credp, boolean_t isv6);
 static mblk_t	*ip_xmit_attach_llhdr(mblk_t *, nce_t *);
--- a/usr/src/uts/common/inet/ip/ip_if.c	Tue Dec 01 07:21:46 2009 -0800
+++ b/usr/src/uts/common/inet/ip/ip_if.c	Tue Dec 01 11:45:15 2009 -0500
@@ -144,7 +144,7 @@
 static void	ipsq_delete(ipsq_t *);
 
 static ipif_t	*ipif_allocate(ill_t *ill, int id, uint_t ire_type,
-    boolean_t initialize, boolean_t insert);
+    boolean_t initialize, boolean_t insert, int *errorp);
 static ire_t	**ipif_create_bcast_ires(ipif_t *ipif, ire_t **irep);
 static void	ipif_delete_bcast_ires(ipif_t *ipif);
 static int	ipif_add_ires_v4(ipif_t *, boolean_t);
@@ -3392,7 +3392,7 @@
 	 * the device name.
 	 */
 	frag_ptr = (uchar_t *)mi_zalloc(ILL_FRAG_HASH_TBL_SIZE +
-	    2 * LIFNAMSIZ + 5 + strlen(ipv6_forward_suffix));
+	    2 * LIFNAMSIZ + strlen(ipv6_forward_suffix));
 	if (frag_ptr == NULL) {
 		freemsg(info_mp);
 		return (ENOMEM);
@@ -3751,7 +3751,7 @@
 	if (!ipsq_init(ill, B_FALSE))
 		goto done;
 
-	ipif = ipif_allocate(ill, 0L, IRE_LOOPBACK, B_TRUE, B_TRUE);
+	ipif = ipif_allocate(ill, 0L, IRE_LOOPBACK, B_TRUE, B_TRUE, NULL);
 	if (ipif == NULL)
 		goto done;
 
@@ -4215,7 +4215,7 @@
 		 * the wakeup.
 		 */
 		(void) ipif_allocate(ill, 0, IRE_LOCAL,
-		    dlia->dl_provider_style != DL_STYLE2, B_TRUE);
+		    dlia->dl_provider_style != DL_STYLE2, B_TRUE, NULL);
 		mutex_enter(&ill->ill_lock);
 		ASSERT(ill->ill_dlpi_style_set == 0);
 		ill->ill_dlpi_style_set = 1;
@@ -9191,8 +9191,7 @@
 	 * instead.
 	 */
 	if ((ipif = ipif_allocate(ill, found_sep ? id : -1, IRE_LOCAL,
-	    B_TRUE, B_TRUE)) == NULL) {
-		err = ENOBUFS;
+	    B_TRUE, B_TRUE, &err)) == NULL) {
 		goto done;
 	}
 
@@ -11518,6 +11517,22 @@
 }
 
 /*
+ * checks if:
+ *	- <ill_name>:<ipif_id> is at most LIFNAMSIZ - 1 and
+ *	- logical interface is within the allowed range
+ */
+static int
+is_lifname_valid(ill_t *ill, unsigned int ipif_id)
+{
+	if (snprintf(NULL, 0, "%s:%d", ill->ill_name, ipif_id) >= LIFNAMSIZ)
+		return (ENAMETOOLONG);
+
+	if (ipif_id >= ill->ill_ipst->ips_ip_addrs_per_if)
+		return (ERANGE);
+	return (0);
+}
+
+/*
  * Insert the ipif, so that the list of ipifs on the ill will be sorted
  * with respect to ipif_id. Note that an ipif with an ipif_id of -1 will
  * be inserted into the first space available in the list. The value of
@@ -11529,7 +11544,7 @@
 	ill_t *ill;
 	ipif_t *tipif;
 	ipif_t **tipifp;
-	int id;
+	int id, err;
 	ip_stack_t	*ipst;
 
 	ASSERT(ipif->ipif_ill->ill_net_type == IRE_LOOPBACK ||
@@ -11558,15 +11573,14 @@
 			id++;
 			tipifp = &(tipif->ipif_next);
 		}
-		/* limit number of logical interfaces */
-		if (id >= ipst->ips_ip_addrs_per_if) {
+		if ((err = is_lifname_valid(ill, id)) != 0) {
 			mutex_exit(&ill->ill_lock);
 			if (acquire_g_lock)
 				rw_exit(&ipst->ips_ill_g_lock);
-			return (-1);
+			return (err);
 		}
 		ipif->ipif_id = id; /* assign new id */
-	} else if (id < ipst->ips_ip_addrs_per_if) {
+	} else if ((err = is_lifname_valid(ill, id)) == 0) {
 		/* we have a real id; insert ipif in the right place */
 		while ((tipif = *tipifp) != NULL) {
 			ASSERT(tipif->ipif_id != id);
@@ -11578,7 +11592,7 @@
 		mutex_exit(&ill->ill_lock);
 		if (acquire_g_lock)
 			rw_exit(&ipst->ips_ill_g_lock);
-		return (-1);
+		return (err);
 	}
 
 	ASSERT(tipifp != &(ill->ill_ipif) || id == 0);
@@ -11628,8 +11642,9 @@
  */
 static ipif_t *
 ipif_allocate(ill_t *ill, int id, uint_t ire_type, boolean_t initialize,
-    boolean_t insert)
-{
+    boolean_t insert, int *errorp)
+{
+	int err;
 	ipif_t	*ipif;
 	ip_stack_t *ipst = ill->ill_ipst;
 
@@ -11637,8 +11652,14 @@
 	    ill->ill_name, id, (void *)ill));
 	ASSERT(ire_type == IRE_LOOPBACK || IAM_WRITER_ILL(ill));
 
-	if ((ipif = (ipif_t *)mi_alloc(sizeof (ipif_t), BPRI_MED)) == NULL)
+	if (errorp != NULL)
+		*errorp = 0;
+
+	if ((ipif = mi_alloc(sizeof (ipif_t), BPRI_MED)) == NULL) {
+		if (errorp != NULL)
+			*errorp = ENOMEM;
 		return (NULL);
+	}
 	*ipif = ipif_zero;	/* start clean */
 
 	ipif->ipif_ill = ill;
@@ -11652,8 +11673,10 @@
 	ipif->ipif_refcnt = 0;
 
 	if (insert) {
-		if (ipif_insert(ipif, ire_type != IRE_LOOPBACK) != 0) {
+		if ((err = ipif_insert(ipif, ire_type != IRE_LOOPBACK)) != 0) {
 			mi_free(ipif);
+			if (errorp != NULL)
+				*errorp = err;
 			return (NULL);
 		}
 		/* -1 id should have been replaced by real id */
@@ -11678,6 +11701,8 @@
 				rw_exit(&ipst->ips_ill_g_lock);
 			}
 			mi_free(ipif);
+			if (errorp != NULL)
+				*errorp = ENOMEM;
 			return (NULL);
 		}
 	}
@@ -13377,7 +13402,7 @@
 		ire_type = IRE_LOOPBACK;
 	else
 		ire_type = IRE_LOCAL;
-	ipif = ipif_allocate(ill, id, ire_type, B_TRUE, B_TRUE);
+	ipif = ipif_allocate(ill, id, ire_type, B_TRUE, B_TRUE, NULL);
 	if (ipif != NULL)
 		ipif_refhold_locked(ipif);
 	mutex_exit(&ill->ill_lock);
@@ -13838,14 +13863,14 @@
 		 * to starting the move (and grabbing locks).
 		 */
 		if (ipif->ipif_id == 0) {
-			moveipif = ipif_allocate(ill, 0, IRE_LOCAL, B_TRUE,
-			    B_FALSE);
-			stubipif = ipif_allocate(ill, 0, IRE_LOCAL, B_TRUE,
-			    B_FALSE);
-			if (moveipif == NULL || stubipif == NULL) {
+			if ((moveipif = ipif_allocate(ill, 0, IRE_LOCAL, B_TRUE,
+			    B_FALSE, &err)) == NULL) {
+				return (err);
+			}
+			if ((stubipif = ipif_allocate(ill, 0, IRE_LOCAL, B_TRUE,
+			    B_FALSE, &err)) == NULL) {
 				mi_free(moveipif);
-				mi_free(stubipif);
-				return (ENOMEM);
+				return (err);
 			}
 		}
 
@@ -13875,7 +13900,7 @@
 			ipif = ipmp_ill->ill_ipif;
 		} else {
 			ipif->ipif_id = -1;
-			if (ipif_insert(ipif, B_FALSE) != 0) {
+			if ((err = ipif_insert(ipif, B_FALSE)) != 0) {
 				/*
 				 * No more available ipif_id's -- put it back
 				 * on the original ill and fail the operation.
@@ -13891,7 +13916,7 @@
 					VERIFY(ipif_insert(ipif, B_FALSE) == 0);
 				}
 				rw_exit(&ipst->ips_ill_g_lock);
-				return (ENOMEM);
+				return (err);
 			}
 		}
 		rw_exit(&ipst->ips_ill_g_lock);
--- a/usr/src/uts/common/inet/ip/ip_ndp.c	Tue Dec 01 07:21:46 2009 -0800
+++ b/usr/src/uts/common/inet/ip/ip_ndp.c	Tue Dec 01 11:45:15 2009 -0500
@@ -2468,7 +2468,7 @@
 			}
 			if (ipif != NULL) {
 				if (ipif->ipif_was_dup) {
-					char ibuf[LIFNAMSIZ + 10];
+					char ibuf[LIFNAMSIZ];
 					char sbuf[INET6_ADDRSTRLEN];
 
 					ipif->ipif_was_dup = B_FALSE;
--- a/usr/src/uts/common/inet/ip/tnet.c	Tue Dec 01 07:21:46 2009 -0800
+++ b/usr/src/uts/common/inet/ip/tnet.c	Tue Dec 01 11:45:15 2009 -0500
@@ -2050,8 +2050,7 @@
 	zone_t *zone;
 	ts_label_t *plabel;
 	const bslabel_t *label;
-	char ifbuf[LIFNAMSIZ + 10];
-	const char *ifname;
+	char ifname[LIFNAMSIZ];
 	boolean_t retval;
 	tsol_rhent_t rhent;
 	netstack_t *ns = ipif->ipif_ill->ill_ipst->ips_netstack;
@@ -2107,12 +2106,7 @@
 		return (B_TRUE);
 	}
 
-	ifname = ipif->ipif_ill->ill_name;
-	if (ipif->ipif_id != 0) {
-		(void) snprintf(ifbuf, sizeof (ifbuf), "%s:%u", ifname,
-		    ipif->ipif_id);
-		ifname = ifbuf;
-	}
+	ipif_get_name(ipif, ifname, sizeof (ifname));
 	(void) inet_ntop(af, addr, addrbuf, sizeof (addrbuf));
 
 	if (tp == NULL) {