Date: Tue, 23 May 2017 12:36:18 +0000 From: bugzilla-noreply@freebsd.org To: freebsd-bugs@FreeBSD.org Subject: [Bug 219472] Out of bounds access in vlan Message-ID: <bug-219472-8@https.bugs.freebsd.org/bugzilla/>
next in thread | raw e-mail | index | archive | help
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=219472 Bug ID: 219472 Summary: Out of bounds access in vlan Product: Base System Version: CURRENT Hardware: Any OS: Any Status: New Severity: Affects Only Me Priority: --- Component: kern Assignee: freebsd-bugs@FreeBSD.org Reporter: ecturt@gmail.com This whole struct (`ifv_mib`) is user controllable through the `IFDATA_LINKSPECIFIC` sysctl command: https://github.com/freebsd/freebsd/blob/release/11.0.1/sys/net/if_mib.c#L117 case IFDATA_LINKSPECIFIC: error = SYSCTL_OUT(req, ifp->if_linkmib, ifp->if_linkmiblen); if (error || !req->newptr) goto out; error = SYSCTL_IN(req, ifp->if_linkmib, ifp->if_linkmiblen); if (error) goto out; break; In the case of `struct ifvlan`, the contained `if_linkmib` is a `struct ifv_linkmib` containing a `uint16_t` called `ifvm_vid`: https://github.com/freebsd/freebsd/blob/release/11.0.1/sys/net/if_vlan.c#L108 struct ifvlan { struct ifvlantrunk *ifv_trunk; struct ifnet *ifv_ifp; #define TRUNK(ifv) ((ifv)->ifv_trunk) #define PARENT(ifv) ((ifv)->ifv_trunk->parent) void *ifv_cookie; int ifv_pflags; /* special flags we have set on parent */ struct ifv_linkmib { int ifvm_encaplen; /* encapsulation length */ int ifvm_mtufudge; /* MTU fudged by this much */ int ifvm_mintu; /* min transmission unit */ uint16_t ifvm_proto; /* encapsulation ethertype */ uint16_t ifvm_tag; /* tag to apply on packets leaving if */ uint16_t ifvm_vid; /* VLAN ID */ uint8_t ifvm_pcp; /* Priority Code Point (PCP). */ } ifv_mib; SLIST_HEAD(, vlan_mc_entry) vlan_mc_listhead; #ifndef VLAN_ARRAY LIST_ENTRY(ifvlan) ifv_list; #endif }; #define ifv_proto ifv_mib.ifvm_proto #define ifv_tag ifv_mib.ifvm_tag #define ifv_vid ifv_mib.ifvm_vid #define ifv_pcp ifv_mib.ifvm_pcp #define ifv_encaplen ifv_mib.ifvm_encaplen #define ifv_mtufudge ifv_mib.ifvm_mtufudge #define ifv_mintu ifv_mib.ifvm_mintu Thus, it follows that `ifv->ifv_vid` is a completely user controlled `uint16_t`, through the `IFDATA_LINKSPECIFIC` `sysctl` name. This value is used as an index to perform reads and writes on the `vlans` array of size `0x1000` in multiple places. https://github.com/freebsd/freebsd/blob/release/11.0.1/sys/net/if_vlan.c#L427 static __inline int vlan_inshash(struct ifvlantrunk *trunk, struct ifvlan *ifv) { if (trunk->vlans[ifv->ifv_vid] != NULL) return EEXIST; trunk->vlans[ifv->ifv_vid] = ifv; trunk->refcnt++; return (0); } static __inline int vlan_remhash(struct ifvlantrunk *trunk, struct ifvlan *ifv) { trunk->vlans[ifv->ifv_vid] = NULL; trunk->refcnt--; return (0); } ... However, this is a static array of size `VLAN_ARRAY_SIZE` (`0x1000`) elements: https://github.com/freebsd/freebsd/blob/release/11.0.1/sys/net/ethernet.h#L86 #define EVL_VLID_MASK 0x0FFF https://github.com/freebsd/freebsd/blob/release/11.0.1/sys/net/if_vlan.c#L89 struct ifvlantrunk { struct ifnet *parent; /* parent interface of this trunk */ struct rmlock lock; #ifdef VLAN_ARRAY #define VLAN_ARRAY_SIZE (EVL_VLID_MASK + 1) struct ifvlan *vlans[VLAN_ARRAY_SIZE]; /* static table */ #else struct ifvlanhead *hash; /* dynamic hash-list table */ uint16_t hmask; uint16_t hwidth; #endif int refcnt; }; So, out of bounds access is possible if `ifv_vid` is set to a value greater than `0xfff`. -- You are receiving this mail because: You are the assignee for the bug.
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?bug-219472-8>
