In the Linux kernel, the following vulnerability has been resolved:
net: dsa: fix netdev_priv() dereference before check on non-DSA netdevice events
After the blamed commit, we started doing this dereference for every NETDEVCHANGEUPPER and NETDEVPRECHANGEUPPER event in the system.
static inline struct dsaport *dsausertoport(const struct netdevice *dev) { struct dsauserpriv *p = netdevpriv(dev);
return p->dp;
}
Which is obviously bogus, because not all netdevices have a netdevpriv() of type struct dsauserpriv. But struct dsauserpriv is fairly small, and p->dp means dereferencing 8 bytes starting with offset 16. Most drivers allocate that much private memory anyway, making our access not fault, and we discard the bogus data quickly afterwards, so this wasn't caught.
But the dummy interface is somewhat special in that it calls allocnetdev() with a priv size of 0. So every netdevpriv() dereference is invalid, and we get this when we emit a NETDEV_PRECHANGEUPPER event with a VLAN as its new upper:
$ ip link add dummy1 type dummy $ ip link add link dummy1 name dummy1.100 type vlan id 100 [ 43.309174] ================================================================== [ 43.316456] BUG: KASAN: slab-out-of-bounds in dsauserprechangeupper+0x30/0xe8 [ 43.323835] Read of size 8 at addr ffff3f86481d2990 by task ip/374 [ 43.330058] [ 43.342436] Call trace: [ 43.366542] dsauserprechangeupper+0x30/0xe8 [ 43.371024] dsausernetdeviceevent+0xb38/0xee8 [ 43.375768] notifiercallchain+0xa4/0x210 [ 43.379985] rawnotifiercallchain+0x24/0x38 [ 43.384464] _netdevupperdevlink+0x3ec/0x5d8 [ 43.389120] netdevupperdevlink+0x70/0xa8 [ 43.393424] registervlandev+0x1bc/0x310 [ 43.397554] vlannewlink+0x210/0x248 [ 43.401247] rtnlnewlink+0x9fc/0xe30 [ 43.404942] rtnetlinkrcv_msg+0x378/0x580
Avoid the kernel oops by dereferencing after the type check, as customary.