Hi,

Although ifconfig(8) checks it already, contiguous inet netmask
should be enforced by the kernel.  Currently the routing table does
not support non-contiguous netmask, but we should error out early
during interface ioctl(2).

ok?

bluhm

Index: netinet/in.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/in.c,v
retrieving revision 1.166
diff -u -p -r1.166 in.c
--- netinet/in.c        8 Nov 2019 07:16:29 -0000       1.166
+++ netinet/in.c        18 Nov 2019 22:50:38 -0000
@@ -330,8 +330,16 @@ in_ioctl(u_long cmd, caddr_t data, struc
                        error = EINVAL;
                        break;
                }
+               /* do not check inet family or strict len */
+               sin = satosin(&ifr->ifr_addr);
+               if (ntohl(sin->sin_addr.s_addr) &
+                   (~ntohl(sin->sin_addr.s_addr) >> 1)) {
+                       /* non-contiguous netmask */
+                       error = EINVAL;
+                       break;
+               }
                ia->ia_netmask = ia->ia_sockmask.sin_addr.s_addr =
-                   satosin(&ifr->ifr_addr)->sin_addr.s_addr;
+                   sin->sin_addr.s_addr;
                break;
        }
 err:
@@ -404,6 +412,7 @@ in_ioctl_change_ifaddr(u_long cmd, caddr
        struct in_ifaddr *ia = NULL;
        struct in_aliasreq *ifra = (struct in_aliasreq *)data;
        struct sockaddr_in *sin = NULL, *dstsin = NULL, *broadsin = NULL;
+       struct sockaddr_in *masksin = NULL;
        int error = 0;
        int newifaddr;

@@ -440,6 +449,14 @@ in_ioctl_change_ifaddr(u_long cmd, caddr
                                error = EINVAL;
                                break;
                        }
+                       /* do not check inet family or strict len */
+                       masksin = &ifra->ifra_mask;
+                       if (ntohl(masksin->sin_addr.s_addr) &
+                           (~ntohl(masksin->sin_addr.s_addr) >> 1)) {
+                               /* non-contiguous netmask */
+                               error = EINVAL;
+                               break;
+                       }
                }
                if ((ifp->if_flags & IFF_POINTOPOINT) &&
                    ifra->ifra_dstaddr.sin_family == AF_INET) {
@@ -480,10 +497,10 @@ in_ioctl_change_ifaddr(u_long cmd, caddr
                    sin->sin_addr.s_addr != ia->ia_addr.sin_addr.s_addr) {
                        needinit = 1;
                }
-               if (ifra->ifra_mask.sin_len) {
+               if (masksin != NULL) {
                        in_ifscrub(ifp, ia);
                        ia->ia_netmask = ia->ia_sockmask.sin_addr.s_addr =
-                           ifra->ifra_mask.sin_addr.s_addr;
+                           masksin->sin_addr.s_addr;
                        needinit = 1;
                }
                if (dstsin != NULL) {

Reply via email to