Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Leap:15.1
glibc
getaddrinfo-parse-ipv4-address.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File getaddrinfo-parse-ipv4-address.patch of Package glibc
2019-02-04 Florian Weimer <fweimer@redhat.com> [BZ #20018] nscd: Do not rely on new GLIBC_PRIVATE ABI after CVE-2016-10739 fix. * nscd/nscd-inet_addr.c: New file. Build resolv/inet_addr.c for nscd, without public symbols. * nscd/Makefile (nscd-modules): Add it. * nscd/gai.c: Include <arpa/inet.h> and change visibility of __inet_aton_exact. 2019-01-21 Florian Weimer <fweimer@redhat.com> [BZ #20018] CVE-2016-10739 resolv: Reject trailing characters in host names * include/arpa/inet.h (__inet_aton_exact): Declare. (inet_aton): Remove hidden prototype. No longer used internally. * nscd/gai.c (__inet_aton): Do not define. * nscd/gethstbynm3_r.c (__inet_aton): Likewise. * nss/digits_dots.c (__inet_aton): Likewise. (__nss_hostname_digits_dots_context): Call __inet_aton_exact. * resolv/Versions (GLIBC_PRIVATE): Export __inet_aton_exact from libc. * resolv/inet_addr.c (inet_aton_end): Remame from __inet_aton. Make static. Add endp parameter. (__inet_aton_exact): New function. (__inet_aton_ignore_trailing): New function, aliased to inet_aton. (__inet_addr): Call inet_aton_end. * resolv/res_init.c (res_vinit_1): Truncate nameserver for IPv4, not just IPv6. Call __inet_aton_exact. * sysdeps/posix/getaddrinfo.c (gaih_inet): Call __inet_aton_exact. 2019-01-18 Florian Weimer <fweimer@redhat.com> [BZ #24112] resolv: Do not send queries for non-host-names in nss_dns. * resolv/nss_dns/dns-host.c (check_name): New function. (_nss_dns_gethostbyname2_r): Use it. (_nss_dns_gethostbyname_r): Likewise. (_nss_dns_gethostbyname4_r): Likewise. Index: glibc-2.26/include/arpa/inet.h =================================================================== --- glibc-2.26.orig/include/arpa/inet.h +++ glibc-2.26/include/arpa/inet.h @@ -1,10 +1,10 @@ #include <inet/arpa/inet.h> #ifndef _ISOMAC -extern int __inet_aton (const char *__cp, struct in_addr *__inp); -libc_hidden_proto (__inet_aton) +/* Variant of inet_aton which rejects trailing garbage. */ +extern int __inet_aton_exact (const char *__cp, struct in_addr *__inp); +libc_hidden_proto (__inet_aton_exact) -libc_hidden_proto (inet_aton) libc_hidden_proto (inet_ntop) libc_hidden_proto (inet_pton) extern __typeof (inet_pton) __inet_pton; Index: glibc-2.26/nscd/Makefile =================================================================== --- glibc-2.26.orig/nscd/Makefile +++ glibc-2.26/nscd/Makefile @@ -36,7 +36,7 @@ nscd-modules := nscd connections pwdcach getsrvbynm_r getsrvbypt_r servicescache \ dbg_log nscd_conf nscd_stat cache mem nscd_setup_thread \ xmalloc xstrdup aicache initgrcache gai res_hconf \ - netgroupcache nscd_hash + netgroupcache nscd_hash nscd-inet_addr ifeq ($(build-nscd)$(have-thread-library),yesyes) Index: glibc-2.26/nscd/gai.c =================================================================== --- glibc-2.26.orig/nscd/gai.c +++ glibc-2.26/nscd/gai.c @@ -19,7 +19,6 @@ /* This file uses the getaddrinfo code but it compiles it without NSCD support. We just need a few symbol renames. */ -#define __inet_aton inet_aton #define __ioctl ioctl #define __getsockname getsockname #define __socket socket @@ -32,6 +31,12 @@ /* nscd uses 1MB or 2MB thread stacks. */ #define __libc_use_alloca(size) (size <= __MAX_ALLOCA_CUTOFF) +/* We do not want to export __inet_aton_exact. Get the prototype and + change its visibility to hidden. */ +#include <arpa/inet.h> +__typeof__ (__inet_aton_exact) __inet_aton_exact + __attribute__ ((visibility ("hidden"))); + /* We are nscd, so we don't want to be talking to ourselves. */ #undef USE_NSCD Index: glibc-2.26/nscd/gethstbynm3_r.c =================================================================== --- glibc-2.26.orig/nscd/gethstbynm3_r.c +++ glibc-2.26/nscd/gethstbynm3_r.c @@ -38,8 +38,6 @@ #define HAVE_LOOKUP_BUFFER 1 #define HAVE_AF 1 -#define __inet_aton inet_aton - /* We are nscd, so we don't want to be talking to ourselves. */ #undef USE_NSCD Index: glibc-2.26/nscd/nscd-inet_addr.c =================================================================== --- /dev/null +++ glibc-2.26/nscd/nscd-inet_addr.c @@ -0,0 +1,32 @@ +/* Legacy IPv4 text-to-address functions. Version for nscd. + Copyright (C) 2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <arpa/inet.h> + +/* We do not want to export __inet_aton_exact. Get the prototype and + change the visibility to hidden. */ +#include <arpa/inet.h> +__typeof__ (__inet_aton_exact) __inet_aton_exact + __attribute__ ((visibility ("hidden"))); + +/* Do not provide definitions of the public symbols exported from + libc. */ +#undef weak_alias +#define weak_alias(from, to) + +#include <resolv/inet_addr.c> Index: glibc-2.26/nss/digits_dots.c =================================================================== --- glibc-2.26.orig/nss/digits_dots.c +++ glibc-2.26/nss/digits_dots.c @@ -29,7 +29,6 @@ #include "nsswitch.h" #ifdef USE_NSCD -# define inet_aton __inet_aton # include <nscd/nscd_proto.h> #endif @@ -160,7 +159,7 @@ __nss_hostname_digits_dots_context (stru 255.255.255.255? The test below will succeed spuriously... ??? */ if (af == AF_INET) - ok = __inet_aton (name, (struct in_addr *) host_addr); + ok = __inet_aton_exact (name, (struct in_addr *) host_addr); else { assert (af == AF_INET6); Index: glibc-2.26/resolv/Versions =================================================================== --- glibc-2.26.orig/resolv/Versions +++ glibc-2.26/resolv/Versions @@ -27,6 +27,7 @@ libc { __h_errno; __resp; __res_iclose; + __inet_aton_exact; __inet_pton_length; __resolv_context_get; __resolv_context_get_preinit; Index: glibc-2.26/resolv/inet_addr.c =================================================================== --- glibc-2.26.orig/resolv/inet_addr.c +++ glibc-2.26/resolv/inet_addr.c @@ -79,28 +79,15 @@ #include <errno.h> /* - * Ascii internet address interpretation routine. - * The value returned is in network order. - */ -in_addr_t -__inet_addr(const char *cp) { - struct in_addr val; - - if (__inet_aton(cp, &val)) - return (val.s_addr); - return (INADDR_NONE); -} -weak_alias (__inet_addr, inet_addr) - -/* * Check whether "cp" is a valid ascii representation * of an Internet address and convert to a binary address. * Returns 1 if the address is valid, 0 if not. * This replaces inet_addr, the return value from which * cannot distinguish between failure and a local broadcast address. + * Write a pointer to the first non-converted character to *endp. */ -int -__inet_aton(const char *cp, struct in_addr *addr) +static int +inet_aton_end(const char *cp, struct in_addr *addr, const char **endp) { static const in_addr_t max[4] = { 0xffffffff, 0xffffff, 0xffff, 0xff }; in_addr_t val; @@ -170,6 +157,7 @@ __inet_aton(const char *cp, struct in_ad if (addr != NULL) addr->s_addr = res.word | htonl (val); + *endp = cp; __set_errno (saved_errno); return (1); @@ -178,6 +166,41 @@ ret_0: __set_errno (saved_errno); return (0); } -weak_alias (__inet_aton, inet_aton) -libc_hidden_def (__inet_aton) -libc_hidden_weak (inet_aton) + +int +__inet_aton_exact (const char *cp, struct in_addr *addr) +{ + struct in_addr val; + const char *endp; + /* Check that inet_aton_end parsed the entire string. */ + if (inet_aton_end (cp, &val, &endp) != 0 && *endp == 0) + { + *addr = val; + return 1; + } + else + return 0; +} +libc_hidden_def (__inet_aton_exact) + +/* inet_aton ignores trailing garbage. */ +int +__inet_aton_ignore_trailing (const char *cp, struct in_addr *addr) +{ + const char *endp; + return inet_aton_end (cp, addr, &endp); +} +weak_alias (__inet_aton_ignore_trailing, inet_aton) + +/* ASCII IPv4 Internet address interpretation routine. The value + returned is in network order. */ +in_addr_t +__inet_addr (const char *cp) +{ + struct in_addr val; + const char *endp; + if (inet_aton_end (cp, &val, &endp)) + return val.s_addr; + return INADDR_NONE; +} +weak_alias (__inet_addr, inet_addr) Index: glibc-2.26/resolv/nss_dns/dns-host.c =================================================================== --- glibc-2.26.orig/resolv/nss_dns/dns-host.c +++ glibc-2.26/resolv/nss_dns/dns-host.c @@ -273,11 +273,26 @@ gethostbyname3_context (struct resolv_co return status; } +/* Verify that the name looks like a host name. There is no point in + sending a query which will not produce a usable name in the + response. */ +static enum nss_status +check_name (const char *name, int *h_errnop) +{ + if (res_hnok (name)) + return NSS_STATUS_SUCCESS; + *h_errnop = HOST_NOT_FOUND; + return NSS_STATUS_NOTFOUND; +} + enum nss_status _nss_dns_gethostbyname2_r (const char *name, int af, struct hostent *result, char *buffer, size_t buflen, int *errnop, int *h_errnop) { + enum nss_status status = check_name (name, h_errnop); + if (status != NSS_STATUS_SUCCESS) + return status; return _nss_dns_gethostbyname3_r (name, af, result, buffer, buflen, errnop, h_errnop, NULL, NULL); } @@ -288,6 +303,9 @@ _nss_dns_gethostbyname_r (const char *na char *buffer, size_t buflen, int *errnop, int *h_errnop) { + enum nss_status status = check_name (name, h_errnop); + if (status != NSS_STATUS_SUCCESS) + return status; struct resolv_context *ctx = __resolv_context_get (); if (ctx == NULL) { @@ -295,7 +313,7 @@ _nss_dns_gethostbyname_r (const char *na *h_errnop = NETDB_INTERNAL; return NSS_STATUS_UNAVAIL; } - enum nss_status status = NSS_STATUS_NOTFOUND; + status = NSS_STATUS_NOTFOUND; if (res_use_inet6 ()) status = gethostbyname3_context (ctx, name, AF_INET6, result, buffer, buflen, errnop, h_errnop, NULL, NULL); @@ -312,6 +330,9 @@ _nss_dns_gethostbyname4_r (const char *n char *buffer, size_t buflen, int *errnop, int *herrnop, int32_t *ttlp) { + enum nss_status status = check_name (name, herrnop); + if (status != NSS_STATUS_SUCCESS) + return status; struct resolv_context *ctx = __resolv_context_get (); if (ctx == NULL) { @@ -346,7 +367,6 @@ _nss_dns_gethostbyname4_r (const char *n int ans2p_malloced = 0; int olderr = errno; - enum nss_status status; int n = __res_context_search (ctx, name, C_IN, T_QUERY_A_AND_AAAA, host_buffer.buf->buf, 2048, &host_buffer.ptr, &ans2p, &nans2p, &resplen2, &ans2p_malloced); Index: glibc-2.26/resolv/res_init.c =================================================================== --- glibc-2.26.orig/resolv/res_init.c +++ glibc-2.26/resolv/res_init.c @@ -399,8 +399,16 @@ res_vinit_1 (FILE *fp, struct resolv_con cp = parser->buffer + sizeof ("nameserver") - 1; while (*cp == ' ' || *cp == '\t') cp++; + + /* Ignore trailing contents on the name server line. */ + { + char *el; + if ((el = strpbrk (cp, " \t\n")) != NULL) + *el = '\0'; + } + struct sockaddr *sa; - if ((*cp != '\0') && (*cp != '\n') && __inet_aton (cp, &a)) + if ((*cp != '\0') && (*cp != '\n') && __inet_aton_exact (cp, &a)) { sa = allocate_address_v4 (a, NAMESERVER_PORT); if (sa == NULL) @@ -410,9 +418,6 @@ res_vinit_1 (FILE *fp, struct resolv_con { struct in6_addr a6; char *el; - - if ((el = strpbrk (cp, " \t\n")) != NULL) - *el = '\0'; if ((el = strchr (cp, SCOPE_DELIMITER)) != NULL) *el = '\0'; if ((*cp != '\0') && (__inet_pton (AF_INET6, cp, &a6) > 0)) @@ -472,7 +477,7 @@ res_vinit_1 (FILE *fp, struct resolv_con char separator = *cp; *cp = 0; struct resolv_sortlist_entry e; - if (__inet_aton (net, &a)) + if (__inet_aton_exact (net, &a)) { e.addr = a; if (is_sort_mask (separator)) @@ -484,7 +489,7 @@ res_vinit_1 (FILE *fp, struct resolv_con cp++; separator = *cp; *cp = 0; - if (__inet_aton (net, &a)) + if (__inet_aton_exact (net, &a)) e.mask = a.s_addr; else e.mask = net_mask (e.addr); Index: glibc-2.26/resolv/tst-aton.c =================================================================== --- glibc-2.26.orig/resolv/tst-aton.c +++ glibc-2.26/resolv/tst-aton.c @@ -16,6 +16,7 @@ static struct tests { "-1", 0, 0 }, { "256", 1, 0x00000100 }, { "256.", 0, 0 }, + { "255a", 0, 0 }, { "256a", 0, 0 }, { "0x100", 1, 0x00000100 }, { "0200.0x123456", 1, 0x80123456 }, @@ -40,7 +41,12 @@ static struct tests { "1.2.256.4", 0, 0 }, { "1.2.3.0x100", 0, 0 }, { "323543357756889", 0, 0 }, - { "10.1.2.3.4", 0, 0}, + { "10.1.2.3.4", 0, 0 }, + { "192.0.2.1", 1, 0xc0000201 }, + { "192.0.2.2\nX", 1, 0xc0000202 }, + { "192.0.2.3 Y", 1, 0xc0000203 }, + { "192.0.2.3Z", 0, 0 }, + { "192.000.002.010", 1, 0xc0000208 }, }; Index: glibc-2.26/sysdeps/posix/getaddrinfo.c =================================================================== --- glibc-2.26.orig/sysdeps/posix/getaddrinfo.c +++ glibc-2.26/sysdeps/posix/getaddrinfo.c @@ -508,7 +508,7 @@ gaih_inet (const char *name, const struc } #endif - if (__inet_aton (name, (struct in_addr *) at->addr) != 0) + if (__inet_aton_exact (name, (struct in_addr *) at->addr) != 0) { if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET) at->family = AF_INET;
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor