diff options
author | Jun-ichiro itojun Hagino <itojun@cvs.openbsd.org> | 2000-10-07 04:05:38 +0000 |
---|---|---|
committer | Jun-ichiro itojun Hagino <itojun@cvs.openbsd.org> | 2000-10-07 04:05:38 +0000 |
commit | b0440a9dfc86020196fd9d1844b50ca6f7e74f41 (patch) | |
tree | cb73d292db4941a98208b122fc6a114ba6811a25 /sys/net/if_gif.c | |
parent | dbd9a5c25db05515d85dda7a4d5a087bd4bf97aa (diff) |
on SIOC*IFPHY*, validate args more correctly.
Diffstat (limited to 'sys/net/if_gif.c')
-rw-r--r-- | sys/net/if_gif.c | 55 |
1 files changed, 37 insertions, 18 deletions
diff --git a/sys/net/if_gif.c b/sys/net/if_gif.c index 95970926ff3..b4455d74cae 100644 --- a/sys/net/if_gif.c +++ b/sys/net/if_gif.c @@ -1,9 +1,10 @@ -/* $OpenBSD: if_gif.c,v 1.7 2000/01/17 06:29:27 itojun Exp $ */ +/* $OpenBSD: if_gif.c,v 1.8 2000/10/07 04:05:37 itojun Exp $ */ +/* $KAME: if_gif.c,v 1.32 2000/10/07 03:20:55 itojun Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. * All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -15,7 +16,7 @@ * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -233,13 +234,19 @@ gif_ioctl(ifp, cmd, data) #ifdef INET6 case SIOCSIFPHYADDR_IN6: #endif /* INET6 */ - switch (ifr->ifr_addr.sa_family) { + switch (cmd) { #ifdef INET - case AF_INET: + case SIOCSIFPHYADDR: src = (struct sockaddr *) &(((struct in_aliasreq *)data)->ifra_addr); dst = (struct sockaddr *) &(((struct in_aliasreq *)data)->ifra_dstaddr); + if (src->sa_len != sizeof(struct sockaddr_in) || + dst->sa_len != sizeof(struct sockaddr_in)) + return EINVAL; + if (src->sa_family != AF_INET || + dst->sa_family != AF_INET) + return EAFNOSUPPORT; /* only one gif can have dst = INADDR_ANY */ #define satosaddr(sa) (((struct sockaddr_in *)(sa))->sin_addr.s_addr) @@ -262,11 +269,17 @@ gif_ioctl(ifp, cmd, data) break; #endif /* INET */ #ifdef INET6 - case AF_INET6: + case SIOCSIFPHYADDR_IN6: src = (struct sockaddr *) &(((struct in6_aliasreq *)data)->ifra_addr); dst = (struct sockaddr *) &(((struct in6_aliasreq *)data)->ifra_dstaddr); + if (src->sa_len != sizeof(struct sockaddr_in6) || + dst->sa_len != sizeof(struct sockaddr_in6)) + return EINVAL; + if (src->sa_family != AF_INET6 || + dst->sa_family != AF_INET6) + return EAFNOSUPPORT; /* only one gif can have dst = in6addr_any */ #define satoin6(sa) (&((struct sockaddr_in6 *)(sa))->sin6_addr) @@ -312,6 +325,7 @@ gif_ioctl(ifp, cmd, data) ifp->if_flags |= IFF_UP; if_up(ifp); /* send up RTM_IFINFO */ + error = 0; break; case SIOCGIFPSRCADDR: @@ -323,25 +337,27 @@ gif_ioctl(ifp, cmd, data) goto bad; } src = sc->gif_psrc; - switch (sc->gif_psrc->sa_family) { + switch (cmd) { #ifdef INET - case AF_INET: + case SIOCGIFPSRCADDR: dst = &ifr->ifr_addr; - size = sizeof(struct sockaddr_in); + size = sizeof(ifr->ifr_addr); break; #endif /* INET */ #ifdef INET6 - case AF_INET6: + case SIOCGIFPSRCADDR_IN6: dst = (struct sockaddr *) &(((struct in6_ifreq *)data)->ifr_addr); - size = sizeof(struct sockaddr_in6); + size = sizeof(((struct in6_ifreq *)data)->ifr_addr); break; #endif /* INET6 */ default: error = EADDRNOTAVAIL; goto bad; } - bcopy((caddr_t)src, (caddr_t)dst, size); + if (src->sa_len > size) + return EINVAL; + bcopy((caddr_t)src, (caddr_t)dst, src->sa_len); break; case SIOCGIFPDSTADDR: @@ -353,28 +369,31 @@ gif_ioctl(ifp, cmd, data) goto bad; } src = sc->gif_pdst; - switch (sc->gif_pdst->sa_family) { + switch (cmd) { #ifdef INET - case AF_INET: + case SIOCGIFPDSTADDR: dst = &ifr->ifr_addr; - size = sizeof(struct sockaddr_in); + size = sizeof(ifr->ifr_addr); break; #endif /* INET */ #ifdef INET6 - case AF_INET6: + case SIOCGIFPDSTADDR_IN6: dst = (struct sockaddr *) &(((struct in6_ifreq *)data)->ifr_addr); - size = sizeof(struct sockaddr_in6); + size = sizeof(((struct in6_ifreq *)data)->ifr_addr); break; #endif /* INET6 */ default: error = EADDRNOTAVAIL; goto bad; } - bcopy((caddr_t)src, (caddr_t)dst, size); + if (src->sa_len > size) + return EINVAL; + bcopy((caddr_t)src, (caddr_t)dst, src->sa_len); break; case SIOCSIFFLAGS: + /* if_ioctl() takes care of it */ break; default: |