Date: Sun, 8 Apr 2018 15:52:32 +0000 (UTC) From: Brooks Davis <brooks@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org Subject: svn commit: r332281 - stable/11/sys/net Message-ID: <201804081552.w38FqWMj077072@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
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 */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201804081552.w38FqWMj077072>