svn commit: r332997 - head/sys/net

Brooks Davis brooks at FreeBSD.org
Wed Apr 25 15:30:43 UTC 2018


Author: brooks
Date: Wed Apr 25 15:30:42 2018
New Revision: 332997
URL: https://svnweb.freebsd.org/changeset/base/332997

Log:
  Translate 32-bit ifmedia requests into native ones.
  
  We use transformation rather than accessors as virtually ever driver
  implements SIOCGIFMEDIA and all would have to be touched.
  
  Keep the code readable by always performing copies and (possiably no-op)
  transforms.
  
  Reviewed by:	jhb, kib
  Obtained from:	CheriBSD
  MFC after:	1 week
  Sponsored by:	DARPA, AFRL
  Differential Revision:	https://reviews.freebsd.org/D14996

Modified:
  head/sys/net/if.c

Modified: head/sys/net/if.c
==============================================================================
--- head/sys/net/if.c	Wed Apr 25 15:28:46 2018	(r332996)
+++ head/sys/net/if.c	Wed Apr 25 15:30:42 2018	(r332997)
@@ -150,11 +150,24 @@ struct ifgroupreq32 {
 		uint32_t	ifgru_groups;
 	} ifgr_ifgru;
 };
+
+struct ifmediareq32 {
+	char		ifm_name[IFNAMSIZ];
+	int		ifm_current;
+	int		ifm_mask;
+	int		ifm_status;
+	int		ifm_active;
+	int		ifm_count;
+	uint32_t	ifm_ulist;	/* (int *) */
+};
+#define	SIOCGIFMEDIA32	_IOC_NEWTYPE(SIOCGIFMEDIA, struct ifmediareq32)
+#define	SIOCGIFXMEDIA32	_IOC_NEWTYPE(SIOCGIFXMEDIA, struct ifmediareq32)
+
 #define	_CASE_IOC_IFGROUPREQ_32(cmd)				\
     case _IOC_NEWTYPE((cmd), struct ifgroupreq32):
-#else
+#else /* !COMPAT_FREEBSD32 */
 #define _CASE_IOC_IFGROUPREQ_32(cmd)
-#endif /* COMPAT_FREEBSD32 */
+#endif /* !COMPAT_FREEBSD32 */
 
 #define CASE_IOC_IFGROUPREQ(cmd)	\
     _CASE_IOC_IFGROUPREQ_32(cmd)	\
@@ -2891,12 +2904,48 @@ struct ifconf32 {
 #define	SIOCGIFCONF32	_IOWR('i', 36, struct ifconf32)
 #endif
 
+#ifdef COMPAT_FREEBSD32
+static void
+ifmr_init(struct ifmediareq *ifmr, caddr_t data)
+{
+	struct ifmediareq32 *ifmr32;
+
+	ifmr32 = (struct ifmediareq32 *)data;
+	memcpy(ifmr->ifm_name, ifmr32->ifm_name,
+	    sizeof(ifmr->ifm_name));
+	ifmr->ifm_current = ifmr32->ifm_current;
+	ifmr->ifm_mask = ifmr32->ifm_mask;
+	ifmr->ifm_status = ifmr32->ifm_status;
+	ifmr->ifm_active = ifmr32->ifm_active;
+	ifmr->ifm_count = ifmr32->ifm_count;
+	ifmr->ifm_ulist = (int *)(uintptr_t)ifmr32->ifm_ulist;
+}
+
+static void
+ifmr_update(const struct ifmediareq *ifmr, caddr_t data)
+{
+	struct ifmediareq32 *ifmr32;
+
+	ifmr32 = (struct ifmediareq32 *)data;
+	ifmr32->ifm_current = ifmr->ifm_current;
+	ifmr32->ifm_mask = ifmr->ifm_mask;
+	ifmr32->ifm_status = ifmr->ifm_status;
+	ifmr32->ifm_active = ifmr->ifm_active;
+	ifmr32->ifm_count = ifmr->ifm_count;
+}
+#endif
+
 /*
  * Interface ioctls.
  */
 int
 ifioctl(struct socket *so, u_long cmd, caddr_t data, struct thread *td)
 {
+#ifdef COMPAT_FREEBSD32
+	caddr_t saved_data;
+	struct ifmediareq ifmr;
+#endif
+	struct ifmediareq *ifmrp;
 	struct ifnet *ifp;
 	struct ifreq *ifr;
 	int error;
@@ -2941,17 +2990,29 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, s
 		}
 #endif
 	}
-	ifr = (struct ifreq *)data;
 
+	ifmrp = NULL;
+#ifdef COMPAT_FREEBSD32
 	switch (cmd) {
+	case SIOCGIFMEDIA32:
+	case SIOCGIFXMEDIA32:
+		ifmrp = &ifmr;
+		ifmr_init(ifmrp, data);
+		cmd = _IOC_NEWTYPE(cmd, struct ifmediareq);
+		saved_data = data;
+		data = (caddr_t)ifmrp;
+	}
+#endif
+
+	ifr = (struct ifreq *)data;
+	switch (cmd) {
 #ifdef VIMAGE
 	case SIOCSIFRVNET:
 		error = priv_check(td, PRIV_NET_SETIFVNET);
 		if (error == 0)
 			error = if_vmove_reclaim(td, ifr->ifr_name,
 			    ifr->ifr_jid);
-		CURVNET_RESTORE();
-		return (error);
+		goto out_noref;
 #endif
 	case SIOCIFCREATE:
 	case SIOCIFCREATE2:
@@ -2960,23 +3021,21 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, s
 			error = if_clone_create(ifr->ifr_name,
 			    sizeof(ifr->ifr_name), cmd == SIOCIFCREATE2 ?
 			    ifr_data_get_ptr(ifr) : NULL);
-		CURVNET_RESTORE();
-		return (error);
+		goto out_noref;
 	case SIOCIFDESTROY:
 		error = priv_check(td, PRIV_NET_IFDESTROY);
 		if (error == 0)
 			error = if_clone_destroy(ifr->ifr_name);
-		CURVNET_RESTORE();
-		return (error);
+		goto out_noref;
 
 	case SIOCIFGCLONERS:
 		error = if_clone_list((struct if_clonereq *)data);
-		CURVNET_RESTORE();
-		return (error);
+		goto out_noref;
+
 	CASE_IOC_IFGROUPREQ(SIOCGIFGMEMB):
 		error = if_getgroupmembers((struct ifgroupreq *)data);
-		CURVNET_RESTORE();
-		return (error);
+		goto out_noref;
+
 #if defined(INET) || defined(INET6)
 	case SIOCSVH:
 	case SIOCGVH:
@@ -2984,29 +3043,24 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, s
 			error = EPROTONOSUPPORT;
 		else
 			error = (*carp_ioctl_p)(ifr, cmd, td);
-		CURVNET_RESTORE();
-		return (error);
+		goto out_noref;
 #endif
 	}
 
 	ifp = ifunit_ref(ifr->ifr_name);
 	if (ifp == NULL) {
-		CURVNET_RESTORE();
-		return (ENXIO);
+		error = ENXIO;
+		goto out_noref;
 	}
 
 	error = ifhwioctl(cmd, ifp, data, td);
-	if (error != ENOIOCTL) {
-		if_rele(ifp);
-		CURVNET_RESTORE();
-		return (error);
-	}
+	if (error != ENOIOCTL)
+		goto out_ref;
 
 	oif_flags = ifp->if_flags;
 	if (so->so_proto == NULL) {
-		if_rele(ifp);
-		CURVNET_RESTORE();
-		return (EOPNOTSUPP);
+		error = EOPNOTSUPP;
+		goto out_ref;
 	}
 
 	/*
@@ -3031,7 +3085,19 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, s
 			in6_if_up(ifp);
 #endif
 	}
+
+out_ref:
 	if_rele(ifp);
+out_noref:
+#ifdef COMPAT_FREEBSD32
+	if (ifmrp != NULL) {
+		KASSERT((cmd == SIOCGIFMEDIA || cmd == SIOCGIFXMEDIA),
+		    ("ifmrp non-NULL, but cmd is not an ifmedia req 0x%lx",
+		     cmd));
+		data = saved_data;
+		ifmr_update(ifmrp, data);
+	}
+#endif
 	CURVNET_RESTORE();
 	return (error);
 }


More information about the svn-src-all mailing list