svn commit: r332281 - stable/11/sys/net
Brooks Davis
brooks at FreeBSD.org
Sun Apr 8 15:52:33 UTC 2018
Author: brooks
Date: Sun Apr 8 15:52:32 2018
New Revision: 332281
URL: https://svnweb.freebsd.org/changeset/base/332281
Log:
MFC r331641, r331644, r332158
r331641:
Fix access to ifru_buffer on freebsd32.
Make all kernel accesses to ifru_buffer go via access functions
which take the process ABI into account and use an appropriate union
to access members in the correct place in struct ifreq.
Reviewed by: kib
Obtained from: CheriBSD
Sponsored by: DARPA, AFRL
Differential Revision: https://reviews.freebsd.org/D14846
r331644:
Fix a whitespace bug missed in refactoring prior to r331641.
MFC with: r331641
r332158:
Remove the thread argument from ifr_buffer_*() accessors.
They are always used in a context where curthread is the correct thread.
This makes them more similar to the ifr_data_get_ptr() accessor.
Modified:
stable/11/sys/net/if.c
stable/11/sys/net/if.h
Directory Properties:
stable/11/ (props changed)
Modified: stable/11/sys/net/if.c
==============================================================================
--- stable/11/sys/net/if.c Sun Apr 8 15:35:57 2018 (r332280)
+++ stable/11/sys/net/if.c Sun Apr 8 15:52:32 2018 (r332281)
@@ -55,6 +55,7 @@
#include <sys/sockio.h>
#include <sys/syslog.h>
#include <sys/sysctl.h>
+#include <sys/sysent.h>
#include <sys/taskqueue.h>
#include <sys/domain.h>
#include <sys/jail.h>
@@ -97,8 +98,50 @@
#ifdef COMPAT_FREEBSD32
#include <sys/mount.h>
#include <compat/freebsd32/freebsd32.h>
+
+struct ifreq_buffer32 {
+ uint32_t length; /* (size_t) */
+ uint32_t buffer; /* (void *) */
+};
+
+/*
+ * Interface request structure used for socket
+ * ioctl's. All interface ioctl's must have parameter
+ * definitions which begin with ifr_name. The
+ * remainder may be interface specific.
+ */
+struct ifreq32 {
+ char ifr_name[IFNAMSIZ]; /* if name, e.g. "en0" */
+ union {
+ struct sockaddr ifru_addr;
+ struct sockaddr ifru_dstaddr;
+ struct sockaddr ifru_broadaddr;
+ struct ifreq_buffer32 ifru_buffer;
+ short ifru_flags[2];
+ short ifru_index;
+ int ifru_jid;
+ int ifru_metric;
+ int ifru_mtu;
+ int ifru_phys;
+ int ifru_media;
+ uint32_t ifru_data;
+ int ifru_cap[2];
+ u_int ifru_fib;
+ u_char ifru_vlan_pcp;
+ } ifr_ifru;
+};
+CTASSERT(sizeof(struct ifreq) == sizeof(struct ifreq32));
+CTASSERT(__offsetof(struct ifreq, ifr_ifru) ==
+ __offsetof(struct ifreq32, ifr_ifru));
#endif
+union ifreq_union {
+ struct ifreq ifr;
+#ifdef COMPAT_FREEBSD32
+ struct ifreq32 ifr32;
+#endif
+};
+
SYSCTL_NODE(_net, PF_LINK, link, CTLFLAG_RW, 0, "Link layers");
SYSCTL_NODE(_net_link, 0, generic, CTLFLAG_RW, 0, "Generic link-management");
@@ -2302,6 +2345,61 @@ ifunit(const char *name)
return (ifp);
}
+static void *
+ifr_buffer_get_buffer(void *data)
+{
+ union ifreq_union *ifrup;
+
+ ifrup = data;
+#ifdef COMPAT_FREEBSD32
+ if (SV_CURPROC_FLAG(SV_ILP32))
+ return ((void *)(uintptr_t)
+ ifrup->ifr32.ifr_ifru.ifru_buffer.buffer);
+#endif
+ return (ifrup->ifr.ifr_ifru.ifru_buffer.buffer);
+}
+
+static void
+ifr_buffer_set_buffer_null(void *data)
+{
+ union ifreq_union *ifrup;
+
+ ifrup = data;
+#ifdef COMPAT_FREEBSD32
+ if (SV_CURPROC_FLAG(SV_ILP32))
+ ifrup->ifr32.ifr_ifru.ifru_buffer.buffer = 0;
+ else
+#endif
+ ifrup->ifr.ifr_ifru.ifru_buffer.buffer = NULL;
+}
+
+static size_t
+ifr_buffer_get_length(void *data)
+{
+ union ifreq_union *ifrup;
+
+ ifrup = data;
+#ifdef COMPAT_FREEBSD32
+ if (SV_CURPROC_FLAG(SV_ILP32))
+ return (ifrup->ifr32.ifr_ifru.ifru_buffer.length);
+#endif
+ return (ifrup->ifr.ifr_ifru.ifru_buffer.length);
+}
+
+static void
+ifr_buffer_set_length(void *data, size_t len)
+{
+ union ifreq_union *ifrup;
+
+ ifrup = data;
+#ifdef COMPAT_FREEBSD32
+ if (SV_CURPROC_FLAG(SV_ILP32))
+ ifrup->ifr32.ifr_ifru.ifru_buffer.length = len;
+ else
+#endif
+ ifrup->ifr.ifr_ifru.ifru_buffer.length = len;
+}
+
/*
* Hardware specific interface ioctls.
*/
@@ -2362,12 +2460,12 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data,
else {
/* space for terminating nul */
descrlen = strlen(ifp->if_description) + 1;
- if (ifr->ifr_buffer.length < descrlen)
- ifr->ifr_buffer.buffer = NULL;
+ if (ifr_buffer_get_length(ifr) < descrlen)
+ ifr_buffer_set_buffer_null(ifr);
else
error = copyout(ifp->if_description,
- ifr->ifr_buffer.buffer, descrlen);
- ifr->ifr_buffer.length = descrlen;
+ ifr_buffer_get_buffer(ifr), descrlen);
+ ifr_buffer_set_length(ifr, descrlen);
}
sx_sunlock(&ifdescr_sx);
break;
@@ -2383,15 +2481,15 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data,
* length parameter is supposed to count the
* terminating nul in.
*/
- if (ifr->ifr_buffer.length > ifdescr_maxlen)
+ if (ifr_buffer_get_length(ifr) > ifdescr_maxlen)
return (ENAMETOOLONG);
- else if (ifr->ifr_buffer.length == 0)
+ else if (ifr_buffer_get_length(ifr) == 0)
descrbuf = NULL;
else {
- descrbuf = malloc(ifr->ifr_buffer.length, M_IFDESCR,
- M_WAITOK | M_ZERO);
- error = copyin(ifr->ifr_buffer.buffer, descrbuf,
- ifr->ifr_buffer.length - 1);
+ descrbuf = malloc(ifr_buffer_get_length(ifr),
+ M_IFDESCR, M_WAITOK | M_ZERO);
+ error = copyin(ifr_buffer_get_buffer(ifr), descrbuf,
+ ifr_buffer_get_length(ifr) - 1);
if (error) {
free(descrbuf, M_IFDESCR);
break;
Modified: stable/11/sys/net/if.h
==============================================================================
--- stable/11/sys/net/if.h Sun Apr 8 15:35:57 2018 (r332280)
+++ stable/11/sys/net/if.h Sun Apr 8 15:52:32 2018 (r332281)
@@ -398,7 +398,9 @@ struct ifreq {
#define ifr_addr ifr_ifru.ifru_addr /* address */
#define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-to-p link */
#define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */
+#ifndef _KERNEL
#define ifr_buffer ifr_ifru.ifru_buffer /* user supplied buffer with its length */
+#endif
#define ifr_flags ifr_ifru.ifru_flags[0] /* flags (low 16 bits) */
#define ifr_flagshigh ifr_ifru.ifru_flags[1] /* flags (high 16 bits) */
#define ifr_jid ifr_ifru.ifru_jid /* jail/vnet */
More information about the svn-src-all
mailing list