Print this page
8429 getallifaddrs dereferences invalid pointer causing SIGSEGV
Reviewed by: Sebastian Wiedenroth <sw@core.io>
Reviewed by: Yuri Pankov <yuripv@gmx.com>
Reviewed by: Toomas Soome <tsoome@me.com>


   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.

  24  */
  25 
  26 #include <netdb.h>
  27 #include <nss_dbdefs.h>
  28 #include <netinet/in.h>
  29 #include <sys/socket.h>
  30 #include <string.h>
  31 #include <stdio.h>
  32 #include <sys/sockio.h>
  33 #include <sys/types.h>
  34 #include <stdlib.h>
  35 #include <net/if.h>
  36 #include <ifaddrs.h>
  37 #include <libsocket_priv.h>
  38 
  39 /*
  40  * Create a linked list of `struct ifaddrs' structures, one for each
  41  * address that is UP. If successful, store the list in *ifap and
  42  * return 0.  On errors, return -1 and set `errno'.
  43  *


  85 /*
  86  * Returns all addresses configured on the system. If flags contain
  87  * LIFC_ENABLED, only the addresses that are UP are returned.
  88  * Address list that is returned by this function must be freed
  89  * using freeifaddrs().
  90  */
  91 int
  92 getallifaddrs(sa_family_t af, struct ifaddrs **ifap, int64_t flags)
  93 {
  94         struct lifreq *buf = NULL;
  95         struct lifreq *lifrp;
  96         struct lifreq lifrl;
  97         int ret;
  98         int s, n, numifs;
  99         struct ifaddrs *curr, *prev;
 100         sa_family_t lifr_af;
 101         int sock4;
 102         int sock6;
 103         int err;
 104 








 105         if ((sock4 = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
 106                 return (-1);
 107         if ((sock6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
 108                 err = errno;
 109                 close(sock4);
 110                 errno = err;
 111                 return (-1);
 112         }
 113 
 114 retry:
 115         /* Get all interfaces from SIOCGLIFCONF */
 116         ret = getallifs(sock4, af, &buf, &numifs, (flags & ~LIFC_ENABLED));
 117         if (ret != 0)
 118                 goto fail;
 119 
 120         /*
 121          * Loop through the interfaces obtained from SIOCGLIFCOMF
 122          * and retrieve the addresses, netmask and flags.
 123          */
 124         prev = NULL;
 125         lifrp = buf;
 126         *ifap = NULL;
 127         for (n = 0; n < numifs; n++, lifrp++) {
 128 
 129                 /* Prepare for the ioctl call */
 130                 (void) strncpy(lifrl.lifr_name, lifrp->lifr_name,
 131                     sizeof (lifrl.lifr_name));
 132                 lifr_af = lifrp->lifr_addr.ss_family;
 133                 if (af != AF_UNSPEC && lifr_af != af)
 134                         continue;
 135 
 136                 s = (lifr_af == AF_INET ? sock4 : sock6);
 137 
 138                 if (ioctl(s, SIOCGLIFFLAGS, (caddr_t)&lifrl) < 0)
 139                         goto fail;
 140                 if ((flags & LIFC_ENABLED) && !(lifrl.lifr_flags & IFF_UP))
 141                         continue;
 142 
 143                 /*
 144                  * Allocate the current list node. Each node contains data
 145                  * for one ifaddrs structure.
 146                  */




   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright 2017 RackTop Systems.
  25  */
  26 
  27 #include <netdb.h>
  28 #include <nss_dbdefs.h>
  29 #include <netinet/in.h>
  30 #include <sys/socket.h>
  31 #include <string.h>
  32 #include <stdio.h>
  33 #include <sys/sockio.h>
  34 #include <sys/types.h>
  35 #include <stdlib.h>
  36 #include <net/if.h>
  37 #include <ifaddrs.h>
  38 #include <libsocket_priv.h>
  39 
  40 /*
  41  * Create a linked list of `struct ifaddrs' structures, one for each
  42  * address that is UP. If successful, store the list in *ifap and
  43  * return 0.  On errors, return -1 and set `errno'.
  44  *


  86 /*
  87  * Returns all addresses configured on the system. If flags contain
  88  * LIFC_ENABLED, only the addresses that are UP are returned.
  89  * Address list that is returned by this function must be freed
  90  * using freeifaddrs().
  91  */
  92 int
  93 getallifaddrs(sa_family_t af, struct ifaddrs **ifap, int64_t flags)
  94 {
  95         struct lifreq *buf = NULL;
  96         struct lifreq *lifrp;
  97         struct lifreq lifrl;
  98         int ret;
  99         int s, n, numifs;
 100         struct ifaddrs *curr, *prev;
 101         sa_family_t lifr_af;
 102         int sock4;
 103         int sock6;
 104         int err;
 105 
 106         /*
 107          * Initialize ifap to NULL so we can safely call freeifaddrs
 108          * on it in case of error.
 109          */
 110         if (ifap == NULL)
 111                 return (EINVAL);
 112         *ifap = NULL;
 113 
 114         if ((sock4 = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
 115                 return (-1);
 116         if ((sock6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
 117                 err = errno;
 118                 close(sock4);
 119                 errno = err;
 120                 return (-1);
 121         }
 122 
 123 retry:
 124         /* Get all interfaces from SIOCGLIFCONF */
 125         ret = getallifs(sock4, af, &buf, &numifs, (flags & ~LIFC_ENABLED));
 126         if (ret != 0)
 127                 goto fail;
 128 
 129         /*
 130          * Loop through the interfaces obtained from SIOCGLIFCOMF
 131          * and retrieve the addresses, netmask and flags.
 132          */
 133         prev = NULL;
 134         lifrp = buf;

 135         for (n = 0; n < numifs; n++, lifrp++) {
 136 
 137                 /* Prepare for the ioctl call */
 138                 (void) strncpy(lifrl.lifr_name, lifrp->lifr_name,
 139                     sizeof (lifrl.lifr_name));
 140                 lifr_af = lifrp->lifr_addr.ss_family;
 141                 if (af != AF_UNSPEC && lifr_af != af)
 142                         continue;
 143 
 144                 s = (lifr_af == AF_INET ? sock4 : sock6);
 145 
 146                 if (ioctl(s, SIOCGLIFFLAGS, (caddr_t)&lifrl) < 0)
 147                         goto fail;
 148                 if ((flags & LIFC_ENABLED) && !(lifrl.lifr_flags & IFF_UP))
 149                         continue;
 150 
 151                 /*
 152                  * Allocate the current list node. Each node contains data
 153                  * for one ifaddrs structure.
 154                  */