if_tap: Disallow change network device type
authorAaron LI <aly@aaronly.me>
Tue, 17 Jul 2018 06:29:44 +0000 (14:29 +0800)
committerAaron LI <aly@aaronly.me>
Tue, 17 Jul 2018 06:57:32 +0000 (14:57 +0800)
Disallow ioctl(2) to change the network device type of tap(4).
Otherwise, page faults and panics can happen when access uninitialized
fields in the "struct ifnet" which are specific to the network device
type.

Obtained-from: FreeBSD (revision 326362)

share/man/man4/tap.4
sys/net/tap/if_tap.c
sys/net/tap/if_tap.h

index 2445a39..f98ba13 100644 (file)
@@ -1,7 +1,7 @@
 .\" $FreeBSD: src/share/man/man4/tap.4,v 1.1.2.7 2002/04/16 23:59:28 trhodes Exp $
 .\" Based on PR#2411
 .\"
-.Dd July 13, 2018
+.Dd July 17, 2018
 .Dt TAP 4
 .Os
 .Sh NAME
@@ -167,7 +167,14 @@ The argument should be a pointer to an
 .Va int ;
 this stores the internal debugging variable's value into it.
 .It Dv TAPSIFINFO
-Set network interface information (line speed, MTU and type).
+Set network interface information (line speed and MTU).
+The type must be the same as returned by
+.Dv TAPGIFINFO
+or set to
+.Dv IFT_ETHER ,
+otherwise the
+.Xr ioctl 2
+call will fail.
 The argument should be a pointer to a
 .Va struct tapinfo .
 .It Dv TAPGIFINFO
index 9a6ffb7..083d083 100644 (file)
@@ -754,8 +754,9 @@ tapioctl(struct dev_ioctl_args *ap)
        switch (ap->a_cmd) {
        case TAPSIFINFO:
                tapp = (struct tapinfo *)data;
+               if (ifp->if_type != tapp->type)
+                       return (EPROTOTYPE);
                ifp->if_mtu = tapp->mtu;
-               ifp->if_type = tapp->type;
                ifp->if_baudrate = tapp->baudrate;
                break;
 
index 8285377..e4146c3 100644 (file)
 #define        TAPMRU          16384
 
 struct tapinfo {
-       int     baudrate;       /* linespeed                 */
+       int     baudrate;       /* linespeed */
        short   mtu;            /* maximum transmission unit */
-       u_char  type;           /* ethernet, tokenring, etc. */
-       u_char  dummy;          /* place holder              */
+       u_char  type;           /* IFT_ETHER only */
+       u_char  dummy;          /* place holder */
 };
 
 struct ifreq;