1
Description: fix denial of service via buffer overflow in getaddrinfo
2
Origin: backport, https://sourceware.org/git/?p=glibc.git;h=f2962a71959fd254a7a223437ca4b63b9e81130c
3
Origin: backport, https://sourceware.org/git/?p=glibc.git;h=34a9094f49241ebb72084c536cf468fd51ebe3ec
4
Bug: http://sourceware.org/bugzilla/show_bug.cgi?id=12671
5
Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=742925
7
Index: eglibc-2.11.1/include/alloca.h
8
===================================================================
9
--- eglibc-2.11.1.orig/include/alloca.h 2014-07-28 11:18:56.773591507 -0400
10
+++ eglibc-2.11.1/include/alloca.h 2014-07-28 11:18:56.765591507 -0400
13
#if defined stackinfo_get_sp && defined stackinfo_sub_sp
14
# define alloca_account(size, avar) \
15
- ({ void *old__ = stackinfo_get_sp (); \
16
- void *m__ = __alloca (size); \
17
- avar += stackinfo_sub_sp (old__); \
18
+ ({ void *old__ = stackinfo_get_sp (); \
19
+ void *m__ = __alloca (size); \
20
+ avar += stackinfo_sub_sp (old__); \
22
+# define extend_alloca_account(buf, len, newlen, avar) \
23
+ ({ void *old__ = stackinfo_get_sp (); \
24
+ void *m__ = extend_alloca (buf, len, newlen); \
25
+ avar += stackinfo_sub_sp (old__); \
28
# define alloca_account(size, avar) \
29
- ({ size_t s__ = (size); \
31
+ ({ size_t s__ = (size); \
34
+# define extend_alloca_account(buf, len, newlen, avar) \
35
+ ({ size_t s__ = (newlen); \
37
+ extend_alloca (buf, len, s__); })
41
Index: eglibc-2.11.1/nis/nss_nis/nis-alias.c
42
===================================================================
43
--- eglibc-2.11.1.orig/nis/nss_nis/nis-alias.c 2014-07-28 11:18:56.773591507 -0400
44
+++ eglibc-2.11.1/nis/nss_nis/nis-alias.c 2014-07-28 11:18:56.765591507 -0400
49
- yperr = yp_first (domain, "mail.aliases", &outkey, &keylen, &result,
50
+ yperr = yp_first (domain, "mail.aliases", &outkey, &keylen, &result,
53
- yperr = yp_next (domain, "mail.aliases", oldkey, oldkeylen, &outkey,
54
+ yperr = yp_next (domain, "mail.aliases", oldkey, oldkeylen, &outkey,
55
&keylen, &result, &len);
57
if (__builtin_expect (yperr != YPERR_SUCCESS, 0))
59
enum nss_status retval = yperr2nss (yperr);
61
if (retval == NSS_STATUS_TRYAGAIN)
69
if (__builtin_expect ((size_t) (len + 1) > buflen, 0))
74
- return NSS_STATUS_TRYAGAIN;
77
+ return NSS_STATUS_TRYAGAIN;
79
char *p = strncpy (buffer, result, len);
86
parse_res = _nss_nis_parse_aliasent (outkey, p, alias, buffer,
88
return NSS_STATUS_UNAVAIL;
91
- size_t namlen = strlen (name);
92
- char name2[namlen + 1];
95
if (__builtin_expect (yp_get_default_domain (&domain), 0))
96
return NSS_STATUS_UNAVAIL;
98
+ size_t namlen = strlen (name);
100
+ int use_alloca = __libc_use_alloca (namlen + 1);
102
+ name2 = __alloca (namlen + 1);
105
+ name2 = malloc (namlen + 1);
109
+ return NSS_STATUS_TRYAGAIN;
113
/* Convert name to lowercase. */
115
for (i = 0; i < namlen; ++i)
118
int yperr = yp_match (domain, "mail.aliases", name2, namlen, &result, &len);
123
if (__builtin_expect (yperr != YPERR_SUCCESS, 0))
125
enum nss_status retval = yperr2nss (yperr);
126
Index: eglibc-2.11.1/nscd/nscd_getserv_r.c
127
===================================================================
128
--- eglibc-2.11.1.orig/nscd/nscd_getserv_r.c 2014-07-28 11:18:56.773591507 -0400
129
+++ eglibc-2.11.1/nscd/nscd_getserv_r.c 2014-07-28 11:18:56.765591507 -0400
131
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
137
#include <not-cancel.h>
142
+ size_t alloca_used = 0;
144
/* If the mapping is available, try to search there instead of
145
communicating with the nscd. */
148
size_t protolen = proto == NULL ? 0 : strlen (proto);
149
size_t keylen = critlen + 1 + protolen + 1;
150
- char *key = alloca (keylen);
151
+ int alloca_key = __libc_use_alloca (keylen);
154
+ key = alloca_account (keylen, alloca_used);
157
+ key = malloc (keylen);
161
memcpy (__mempcpy (__mempcpy (key, crit, critlen),
162
"/", 1), proto ?: "", protolen + 1);
165
const char *s_name = NULL;
166
const char *s_proto = NULL;
167
+ int alloca_aliases_len = 0;
168
const uint32_t *aliases_len = NULL;
169
const char *aliases_list = NULL;
172
if (((uintptr_t) aliases_len & (__alignof__ (*aliases_len) - 1))
175
- uint32_t *tmp = alloca (serv_resp.s_aliases_cnt
176
- * sizeof (uint32_t));
179
+ = __libc_use_alloca (alloca_used
180
+ + (serv_resp.s_aliases_cnt
181
+ * sizeof (uint32_t)));
182
+ if (alloca_aliases_len)
183
+ tmp = __alloca (serv_resp.s_aliases_cnt * sizeof (uint32_t));
186
+ tmp = malloc (serv_resp.s_aliases_cnt * sizeof (uint32_t));
193
aliases_len = memcpy (tmp, aliases_len,
194
serv_resp.s_aliases_cnt
195
* sizeof (uint32_t));
198
if (serv_resp.s_aliases_cnt > 0)
200
- aliases_len = alloca (serv_resp.s_aliases_cnt
201
- * sizeof (uint32_t));
202
+ assert (alloca_aliases_len == 0);
204
+ = __libc_use_alloca (alloca_used
205
+ + (serv_resp.s_aliases_cnt
206
+ * sizeof (uint32_t)));
207
+ if (alloca_aliases_len)
208
+ aliases_len = alloca (serv_resp.s_aliases_cnt
209
+ * sizeof (uint32_t));
212
+ aliases_len = malloc (serv_resp.s_aliases_cnt
213
+ * sizeof (uint32_t));
214
+ if (aliases_len == NULL)
220
vec[n].iov_base = (void *) aliases_len;
221
vec[n].iov_len = serv_resp.s_aliases_cnt * sizeof (uint32_t);
227
+ if (!alloca_aliases_len)
228
+ free ((void *) aliases_len);
234
Index: eglibc-2.11.1/posix/glob.c
235
===================================================================
236
--- eglibc-2.11.1.orig/posix/glob.c 2014-07-28 11:18:56.773591507 -0400
237
+++ eglibc-2.11.1/posix/glob.c 2014-07-28 11:18:56.769591507 -0400
240
static int glob_in_dir (const char *pattern, const char *directory,
241
int flags, int (*errfunc) (const char *, int),
243
+ glob_t *pglob, size_t alloca_used);
244
extern int __glob_pattern_type (const char *pattern, int quote)
247
@@ -256,13 +256,18 @@
250
const char *filename;
251
- const char *dirname;
252
+ char *dirname = NULL;
257
int dirname_modified;
258
+ int malloc_dirname = 0;
262
+ size_t alloca_used = 0;
265
if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0)
267
@@ -311,20 +316,26 @@
272
- char onealt[strlen (pattern) - 1];
274
- char *onealt = (char *) malloc (strlen (pattern) - 1);
275
- if (onealt == NULL)
277
+ size_t pattern_len = strlen (pattern) - 1;
279
+ int alloca_onealt = __libc_use_alloca (alloca_used + pattern_len);
281
+ onealt = alloca_account (pattern_len, alloca_used);
285
- if (!(flags & GLOB_APPEND))
286
+ onealt = (char *) malloc (pattern_len);
287
+ if (onealt == NULL)
289
- pglob->gl_pathc = 0;
290
- pglob->gl_pathv = NULL;
291
+ if (!(flags & GLOB_APPEND))
293
+ pglob->gl_pathc = 0;
294
+ pglob->gl_pathv = NULL;
296
+ return GLOB_NOSPACE;
298
- return GLOB_NOSPACE;
302
/* We know the prefix for all sub-patterns. */
303
alt_start = mempcpy (onealt, pattern, begin - pattern);
307
/* It is an illegal expression. */
312
+ if (__builtin_expect (!alloca_onealt, 0))
315
return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob);
320
rest = next_brace_sub (rest + 1, flags);
323
- /* It is an illegal expression. */
327
- return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob);
329
+ /* It is an illegal expression. */
330
+ goto illegal_brace;
332
/* Please note that we now can be sure the brace expression
335
/* If we got an error, return it. */
336
if (result && result != GLOB_NOMATCH)
341
+ if (__builtin_expect (!alloca_onealt, 0))
344
if (!(flags & GLOB_APPEND))
348
assert (next != NULL);
354
+ if (__builtin_expect (!alloca_onealt, 0))
358
if (pglob->gl_pathc != firstc)
359
/* We found some entries. */
361
case is nothing but a notation for a directory. */
362
if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && pattern[0] == '~')
365
+ dirname = (char *) pattern;
366
dirlen = strlen (pattern);
368
/* Set FILENAME to NULL as a special flag. This is ugly but
374
+ dirname = (char *) "";
377
+ dirname = (char *) ".";
382
&& (flags & GLOB_NOESCAPE) == 0))
384
/* "/pattern" or "\\/pattern". */
386
+ dirname = (char *) "/";
391
from "d:/", since "d:" and "d:/" are not the same.*/
394
- newp = (char *) __alloca (dirlen + 1);
396
+ if (__libc_use_alloca (alloca_used + dirlen + 1))
397
+ newp = alloca_account (dirlen + 1, alloca_used);
401
+ newp = malloc (dirlen + 1);
403
+ return GLOB_NOSPACE;
404
+ malloc_dirname = 1;
406
*((char *) mempcpy (newp, pattern, dirlen)) = '\0';
410
oldcount = pglob->gl_pathc + pglob->gl_offs;
420
&& (dirname[2] == '\0' || dirname[2] == '/')))
422
/* Look up home directory. */
423
- const char *home_dir = getenv ("HOME");
424
+ char *home_dir = getenv ("HOME");
425
+ int malloc_home_dir = 0;
427
if (home_dir == NULL || home_dir[0] == '\0')
430
/* `sysconf' does not support _SC_LOGIN_NAME_MAX. Try
433
- name = (char *) __alloca (buflen);
434
+ name = alloca_account (buflen, alloca_used);
436
success = getlogin_r (name, buflen) == 0;
439
long int pwbuflen = GETPW_R_SIZE_MAX ();
442
+ int malloc_pwtmpbuf = 0;
447
Try a moderate value. */
450
- pwtmpbuf = (char *) __alloca (pwbuflen);
451
+ if (__libc_use_alloca (alloca_used + pwbuflen))
452
+ pwtmpbuf = alloca_account (pwbuflen, alloca_used);
455
+ pwtmpbuf = malloc (pwbuflen);
456
+ if (pwtmpbuf == NULL)
458
+ retval = GLOB_NOSPACE;
461
+ malloc_pwtmpbuf = 1;
464
while (getpwnam_r (name, &pwbuf, pwtmpbuf, pwbuflen, &p)
466
@@ -608,47 +642,116 @@
471
- pwtmpbuf = extend_alloca (pwtmpbuf, pwbuflen,
473
+ if (!malloc_pwtmpbuf
474
+ && __libc_use_alloca (alloca_used
476
+ pwtmpbuf = extend_alloca_account (pwtmpbuf, pwbuflen,
481
+ char *newp = realloc (malloc_pwtmpbuf
486
- pwtmpbuf = (char *) __alloca (pwbuflen);
490
+ if (__builtin_expect (malloc_pwtmpbuf, 0))
492
+ retval = GLOB_NOSPACE;
496
+ pwbuflen = 2 * pwbuflen;
497
+ malloc_pwtmpbuf = 1;
505
- home_dir = p->pw_dir;
507
+ if (!malloc_pwtmpbuf)
508
+ home_dir = p->pw_dir;
511
+ size_t home_dir_len = strlen (p->pw_dir) + 1;
512
+ if (__libc_use_alloca (alloca_used + home_dir_len))
513
+ home_dir = alloca_account (home_dir_len,
517
+ home_dir = malloc (home_dir_len);
518
+ if (home_dir == NULL)
521
+ retval = GLOB_NOSPACE;
524
+ malloc_home_dir = 1;
526
+ memcpy (home_dir, p->pw_dir, home_dir_len);
533
# endif /* ! _LIBC || __OPTION_EGLIBC_GETLOGIN */
534
if (home_dir == NULL || home_dir[0] == '\0')
536
if (flags & GLOB_TILDE_CHECK)
537
- return GLOB_NOMATCH;
539
+ if (__builtin_expect (malloc_home_dir, 0))
541
+ retval = GLOB_NOMATCH;
545
- home_dir = "~"; /* No luck. */
546
+ home_dir = (char *) "~"; /* No luck. */
548
# endif /* WINDOWS32 */
550
/* Now construct the full directory. */
551
if (dirname[1] == '\0')
553
+ if (__builtin_expect (malloc_dirname, 0))
557
dirlen = strlen (dirname);
558
+ malloc_dirname = malloc_home_dir;
563
size_t home_len = strlen (home_dir);
564
- newp = (char *) __alloca (home_len + dirlen);
565
+ int use_alloca = __libc_use_alloca (alloca_used
566
+ + home_len + dirlen);
568
+ newp = alloca_account (home_len + dirlen, alloca_used);
571
+ newp = malloc (home_len + dirlen);
574
+ if (__builtin_expect (malloc_home_dir, 0))
576
+ retval = GLOB_NOSPACE;
581
mempcpy (mempcpy (newp, home_dir, home_len),
582
&dirname[1], dirlen);
584
+ if (__builtin_expect (malloc_dirname, 0))
588
dirlen += home_len - 1;
589
+ malloc_dirname = !use_alloca;
591
dirname_modified = 1;
596
char *end_name = strchr (dirname, '/');
597
- const char *user_name;
599
+ int malloc_user_name = 0;
600
const char *home_dir;
601
char *unescape = NULL;
607
- newp = (char *) __alloca (end_name - dirname);
608
+ if (__libc_use_alloca (alloca_used + (end_name - dirname)))
609
+ newp = alloca_account (end_name - dirname, alloca_used);
612
+ newp = malloc (end_name - dirname);
615
+ retval = GLOB_NOSPACE;
618
+ malloc_user_name = 1;
620
if (unescape != NULL)
622
char *p = mempcpy (newp, dirname + 1,
624
# if defined HAVE_GETPWNAM_R || defined _LIBC
625
long int buflen = GETPW_R_SIZE_MAX ();
627
+ int malloc_pwtmpbuf = 0;
635
- pwtmpbuf = (char *) __alloca (buflen);
636
+ if (__libc_use_alloca (alloca_used + buflen))
637
+ pwtmpbuf = alloca_account (buflen, alloca_used);
640
+ pwtmpbuf = malloc (buflen);
641
+ if (pwtmpbuf == NULL)
644
+ if (__builtin_expect (malloc_user_name, 0))
646
+ retval = GLOB_NOSPACE;
649
+ malloc_pwtmpbuf = 1;
652
while (getpwnam_r (user_name, &pwbuf, pwtmpbuf, buflen, &p) != 0)
654
@@ -731,40 +861,77 @@
659
- pwtmpbuf = extend_alloca (pwtmpbuf, buflen, 2 * buflen);
662
- pwtmpbuf = __alloca (buflen);
664
+ if (!malloc_pwtmpbuf
665
+ && __libc_use_alloca (alloca_used + 2 * buflen))
666
+ pwtmpbuf = extend_alloca_account (pwtmpbuf, buflen,
667
+ 2 * buflen, alloca_used);
670
+ char *newp = realloc (malloc_pwtmpbuf ? pwtmpbuf : NULL,
674
+ if (__builtin_expect (malloc_pwtmpbuf, 0))
679
+ malloc_pwtmpbuf = 1;
684
p = getpwnam (user_name);
687
+ if (__builtin_expect (malloc_user_name, 0))
690
+ /* If we found a home directory use this. */
692
- home_dir = p->pw_dir;
694
+ size_t home_len = strlen (p->pw_dir);
695
+ size_t rest_len = end_name == NULL ? 0 : strlen (end_name);
697
+ if (__builtin_expect (malloc_dirname, 0))
699
+ malloc_dirname = 0;
701
+ if (__libc_use_alloca (alloca_used + home_len + rest_len + 1))
702
+ dirname = alloca_account (home_len + rest_len + 1,
706
+ dirname = malloc (home_len + rest_len + 1);
707
+ if (dirname == NULL)
709
+ if (__builtin_expect (malloc_pwtmpbuf, 0))
711
+ retval = GLOB_NOSPACE;
714
+ malloc_dirname = 1;
716
+ *((char *) mempcpy (mempcpy (dirname, p->pw_dir, home_len),
717
+ end_name, rest_len)) = '\0';
719
+ dirlen = home_len + rest_len;
720
+ dirname_modified = 1;
722
+ if (__builtin_expect (malloc_pwtmpbuf, 0))
728
+ if (__builtin_expect (malloc_pwtmpbuf, 0))
731
+ if (flags & GLOB_TILDE_CHECK)
732
+ /* We have to regard it as an error if we cannot find the
734
+ return GLOB_NOMATCH;
737
- /* If we found a home directory use this. */
738
- if (home_dir != NULL)
741
- size_t home_len = strlen (home_dir);
742
- size_t rest_len = end_name == NULL ? 0 : strlen (end_name);
743
- newp = (char *) __alloca (home_len + rest_len + 1);
744
- *((char *) mempcpy (mempcpy (newp, home_dir, home_len),
745
- end_name, rest_len)) = '\0';
747
- dirlen = home_len + rest_len;
748
- dirname_modified = 1;
751
- if (flags & GLOB_TILDE_CHECK)
752
- /* We have to regard it as an error if we cannot find the
754
- return GLOB_NOMATCH;
756
# endif /* Not Amiga && not WINDOWS32. */
759
status = glob_in_dir (filename, dirs.gl_pathv[i],
760
((flags | GLOB_APPEND)
761
& ~(GLOB_NOCHECK | GLOB_NOMAGIC)),
763
+ errfunc, pglob, alloca_used);
764
if (status == GLOB_NOMATCH)
765
/* No matches in this directory. Try the next. */
769
if (dirname_modified)
770
flags &= ~(GLOB_NOCHECK | GLOB_NOMAGIC);
771
- status = glob_in_dir (filename, dirname, flags, errfunc, pglob);
772
+ status = glob_in_dir (filename, dirname, flags, errfunc, pglob,
776
if (status == GLOB_NOMATCH && flags != orig_flags
777
@@ -1062,7 +1230,11 @@
778
sizeof (char *), collated_compare);
783
+ if (__builtin_expect (malloc_dirname, 0))
788
#if defined _LIBC && !defined glob
789
libc_hidden_def (glob)
790
@@ -1272,7 +1444,7 @@
792
glob_in_dir (const char *pattern, const char *directory, int flags,
793
int (*errfunc) (const char *, int),
795
+ glob_t *pglob, size_t alloca_used)
797
size_t dirlen = strlen (directory);
799
@@ -1287,11 +1459,12 @@
800
struct globnames *names = &init_names;
801
struct globnames *names_alloca = &init_names;
803
- size_t allocasize = sizeof (init_names);
808
+ alloca_used += sizeof (init_names);
810
init_names.next = NULL;
811
init_names.count = INITIAL_COUNT;
813
@@ -1307,20 +1480,36 @@
815
/* Since we use the normal file functions we can also use stat()
816
to verify the file is there. */
818
- struct_stat64 st64;
822
+ struct_stat64 st64;
824
size_t patlen = strlen (pattern);
825
- char *fullname = (char *) __alloca (dirlen + 1 + patlen + 1);
826
+ int alloca_fullname = __libc_use_alloca (alloca_used
827
+ + dirlen + 1 + patlen + 1);
829
+ if (alloca_fullname)
830
+ fullname = alloca_account (dirlen + 1 + patlen + 1, alloca_used);
833
+ fullname = malloc (dirlen + 1 + patlen + 1);
834
+ if (fullname == NULL)
835
+ return GLOB_NOSPACE;
838
mempcpy (mempcpy (mempcpy (fullname, directory, dirlen),
840
pattern, patlen + 1);
841
if ((__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)
842
- ? (*pglob->gl_stat) (fullname, &st)
843
- : __stat64 (fullname, &st64)) == 0)
844
+ ? (*pglob->gl_stat) (fullname, &ust.st)
845
+ : __stat64 (fullname, &ust.st64)) == 0)
846
/* We found this file to be existing. Now tell the rest
847
of the function to copy this name into the result. */
848
flags |= GLOB_NOCHECK;
850
+ if (__builtin_expect (!alloca_fullname, 0))
855
@@ -1408,9 +1597,9 @@
856
size_t size = (sizeof (struct globnames)
857
+ ((count - INITIAL_COUNT)
859
- allocasize += size;
860
- if (__libc_use_alloca (allocasize))
861
- newnames = names_alloca = __alloca (size);
862
+ if (__libc_use_alloca (alloca_used + size))
863
+ newnames = names_alloca
864
+ = alloca_account (size, alloca_used);
865
else if ((newnames = malloc (size))
868
Index: eglibc-2.11.1/sysdeps/posix/getaddrinfo.c
869
===================================================================
870
--- eglibc-2.11.1.orig/sysdeps/posix/getaddrinfo.c 2014-07-28 11:18:56.773591507 -0400
871
+++ eglibc-2.11.1/sysdeps/posix/getaddrinfo.c 2014-07-28 11:18:56.769591507 -0400
873
bool got_ipv6 = false;
874
const char *canon = NULL;
875
const char *orig_name = name;
876
+ size_t alloca_used = 0;
878
if (req->ai_protocol || req->ai_socktype)
883
st = (struct gaih_servtuple *)
884
- __alloca (sizeof (struct gaih_servtuple));
885
+ alloca_account (sizeof (struct gaih_servtuple), alloca_used);
887
if ((rc = gaih_inet_serv (service->name, tp, req, st)))
892
newp = (struct gaih_servtuple *)
893
- __alloca (sizeof (struct gaih_servtuple));
894
+ alloca_account (sizeof (struct gaih_servtuple),
897
if ((rc = gaih_inet_serv (service->name, tp, req, newp)))
901
if (req->ai_socktype || req->ai_protocol)
903
- st = __alloca (sizeof (struct gaih_servtuple));
904
+ st = alloca_account (sizeof (struct gaih_servtuple), alloca_used);
906
st->socktype = tp->socktype;
907
st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY)
910
struct gaih_servtuple *newp;
912
- newp = __alloca (sizeof (struct gaih_servtuple));
913
+ newp = alloca_account (sizeof (struct gaih_servtuple),
916
newp->socktype = tp->socktype;
917
newp->protocol = tp->protocol;
918
@@ -391,10 +394,17 @@
922
+ bool malloc_name = false;
923
+ bool malloc_addrmem = false;
924
+ struct gaih_addrtuple *addrmem = NULL;
925
+ bool malloc_canonbuf = false;
926
+ char *canonbuf = NULL;
927
+ bool malloc_tmpbuf = false;
928
+ char *tmpbuf = NULL;
932
- at = __alloca (sizeof (struct gaih_addrtuple));
934
+ at = alloca_account (sizeof (struct gaih_addrtuple), alloca_used);
935
at->family = AF_UNSPEC;
939
rc = __idna_to_ascii_lz (name, &p, idn_flags);
940
if (rc != IDNA_SUCCESS)
942
+ /* No need to jump to free_and_return here. */
943
if (rc == IDNA_MALLOC_ERROR)
945
if (rc == IDNA_DLOPEN_ERROR)
947
/* In case the output string is the same as the input string
948
no new string has been allocated. */
951
- name = strdupa (p);
954
+ malloc_name = true;
958
@@ -441,23 +449,59 @@
959
at->family = AF_INET6;
962
- return -EAI_ADDRFAMILY;
964
+ result = -EAI_ADDRFAMILY;
965
+ goto free_and_return;
968
if (req->ai_flags & AI_CANONNAME)
971
else if (at->family == AF_UNSPEC)
973
- char *namebuf = (char *) name;
974
char *scope_delim = strchr (name, SCOPE_DELIMITER);
977
- if (__builtin_expect (scope_delim != NULL, 0))
979
- namebuf = alloca (scope_delim - name + 1);
980
- *((char *) __mempcpy (namebuf, name, scope_delim - name)) = '\0';
983
+ bool malloc_namebuf = false;
984
+ char *namebuf = (char *) name;
986
+ if (__builtin_expect (scope_delim != NULL, 0))
989
+ *scope_delim = '\0';
992
+ if (__libc_use_alloca (alloca_used
993
+ + scope_delim - name + 1))
995
+ namebuf = alloca_account (scope_delim - name + 1,
997
+ *((char *) __mempcpy (namebuf, name,
998
+ scope_delim - name)) = '\0';
1002
+ namebuf = strndup (name, scope_delim - name);
1003
+ if (namebuf == NULL)
1005
+ assert (!malloc_name);
1006
+ return -EAI_MEMORY;
1008
+ malloc_namebuf = true;
1013
+ e = inet_pton (AF_INET6, namebuf, at->addr);
1015
- if (inet_pton (AF_INET6, namebuf, at->addr) > 0)
1016
+ if (malloc_namebuf)
1018
+ else if (scope_delim != NULL && malloc_name)
1019
+ /* Undo what we did above. */
1020
+ *scope_delim = SCOPE_DELIMITER;
1024
if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
1025
at->family = AF_INET6;
1026
@@ -468,7 +512,10 @@
1027
at->family = AF_INET;
1030
- return -EAI_ADDRFAMILY;
1032
+ result = -EAI_ADDRFAMILY;
1033
+ goto free_and_return;
1036
if (scope_delim != NULL)
1038
@@ -490,7 +537,10 @@
1039
at->scopeid = (uint32_t) strtoul (scope_delim + 1, &end,
1042
- return GAIH_OKIFUNSPEC | -EAI_NONAME;
1044
+ result = GAIH_OKIFUNSPEC | -EAI_NONAME;
1045
+ goto free_and_return;
1052
int family = req->ai_family;
1053
size_t tmpbuflen = 512;
1054
- char *tmpbuf = alloca (tmpbuflen);
1055
+ assert (tmpbuf == NULL);
1056
+ tmpbuf = alloca_account (tmpbuflen, alloca_used);
1060
@@ -532,7 +583,25 @@
1061
tmpbuflen, &h, &herrno);
1062
if (rc != ERANGE || herrno != NETDB_INTERNAL)
1064
- tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen);
1066
+ if (!malloc_tmpbuf
1067
+ && __libc_use_alloca (alloca_used + 2 * tmpbuflen))
1068
+ tmpbuf = extend_alloca_account (tmpbuf, tmpbuflen,
1073
+ char *newp = realloc (malloc_tmpbuf ? tmpbuf : NULL,
1077
+ result = -EAI_MEMORY;
1078
+ goto free_and_return;
1081
+ malloc_tmpbuf = true;
1082
+ tmpbuflen = 2 * tmpbuflen;
1087
@@ -551,12 +620,36 @@
1091
- /* We found data, now convert it into the list. */
1092
- for (int i = 0; h->h_addr_list[i]; ++i)
1094
+ /* We found data, count the number of addresses. */
1095
+ for (i = 0; h->h_addr_list[i]; ++i)
1097
+ if (i > 0 && *pat != NULL)
1100
+ if (__libc_use_alloca (alloca_used
1101
+ + i * sizeof (struct gaih_addrtuple)))
1102
+ addrmem = alloca_account (i * sizeof (struct gaih_addrtuple),
1106
+ addrmem = malloc (i
1107
+ * sizeof (struct gaih_addrtuple));
1108
+ if (addrmem == NULL)
1110
+ result = -EAI_MEMORY;
1111
+ goto free_and_return;
1113
+ malloc_addrmem = true;
1116
+ /* Now convert it into the list. */
1117
+ struct gaih_addrtuple *addrfree = addrmem;
1118
+ for (i = 0; h->h_addr_list[i]; ++i)
1122
- *pat = __alloca (sizeof (struct gaih_addrtuple));
1123
+ *pat = addrfree++;
1124
(*pat)->scopeid = 0;
1126
(*pat)->next = NULL;
1127
@@ -581,15 +674,16 @@
1128
if (herrno == NETDB_INTERNAL)
1130
__set_h_errno (herrno);
1131
- return -EAI_SYSTEM;
1132
+ result = -EAI_SYSTEM;
1134
- if (herrno == TRY_AGAIN)
1136
- return -EAI_AGAIN;
1138
- /* We made requests but they turned out no data.
1139
- The name is known, though. */
1140
- return GAIH_OKIFUNSPEC | -EAI_NODATA;
1141
+ else if (herrno == TRY_AGAIN)
1142
+ result = -EAI_AGAIN;
1144
+ /* We made requests but they turned out no data.
1145
+ The name is known, though. */
1146
+ result = GAIH_OKIFUNSPEC | -EAI_NODATA;
1148
+ goto free_and_return;
1152
@@ -612,21 +706,56 @@
1153
bool added_canon = (req->ai_flags & AI_CANONNAME) == 0;
1154
char *addrs = air->addrs;
1156
+ if (__libc_use_alloca (alloca_used
1157
+ + air->naddrs * sizeof (struct gaih_addrtuple)))
1158
+ addrmem = alloca_account (air->naddrs
1159
+ * sizeof (struct gaih_addrtuple),
1163
+ addrmem = malloc (air->naddrs
1164
+ * sizeof (struct gaih_addrtuple));
1165
+ if (addrmem == NULL)
1167
+ result = -EAI_MEMORY;
1168
+ goto free_and_return;
1170
+ malloc_addrmem = true;
1173
+ struct gaih_addrtuple *addrfree = addrmem;
1174
for (int i = 0; i < air->naddrs; ++i)
1176
socklen_t size = (air->family[i] == AF_INET
1177
? INADDRSZ : IN6ADDRSZ);
1180
- *pat = __alloca (sizeof (struct gaih_addrtuple));
1181
+ *pat = addrfree++;
1182
(*pat)->scopeid = 0;
1184
uint32_t *pataddr = (*pat)->addr;
1185
(*pat)->next = NULL;
1186
if (added_canon || air->canon == NULL)
1187
(*pat)->name = NULL;
1189
- canon = (*pat)->name = strdupa (air->canon);
1190
+ else if (canonbuf == NULL)
1192
+ size_t canonlen = strlen (air->canon) + 1;
1193
+ if ((req->ai_flags & AI_CANONIDN) != 0
1194
+ && __libc_use_alloca (alloca_used + canonlen))
1195
+ canonbuf = alloca_account (canonlen, alloca_used);
1198
+ canonbuf = malloc (canonlen);
1199
+ if (canonbuf == NULL)
1201
+ result = -EAI_MEMORY;
1202
+ goto free_and_return;
1204
+ malloc_canonbuf = true;
1206
+ canon = (*pat)->name = memcpy (canonbuf, air->canon,
1210
if (air->family[i] == AF_INET
1211
&& req->ai_family == AF_INET6
1212
@@ -656,20 +785,26 @@
1215
if (at->family == AF_UNSPEC)
1216
- return GAIH_OKIFUNSPEC | -EAI_NONAME;
1218
+ result = GAIH_OKIFUNSPEC | -EAI_NONAME;
1219
+ goto free_and_return;
1225
/* The database contains a negative entry. */
1227
+ goto free_and_return;
1228
else if (__nss_not_use_nscd_hosts == 0)
1230
if (herrno == NETDB_INTERNAL && errno == ENOMEM)
1231
- return -EAI_MEMORY;
1232
- if (herrno == TRY_AGAIN)
1233
- return -EAI_AGAIN;
1234
- return -EAI_SYSTEM;
1235
+ result = -EAI_MEMORY;
1236
+ else if (herrno == TRY_AGAIN)
1237
+ result = -EAI_AGAIN;
1239
+ result = -EAI_SYSTEM;
1241
+ goto free_and_return;
1245
@@ -698,7 +833,19 @@
1246
_res.options &= ~RES_USE_INET6;
1248
size_t tmpbuflen = 1024;
1249
- char *tmpbuf = alloca (tmpbuflen);
1250
+ malloc_tmpbuf = !__libc_use_alloca (alloca_used + tmpbuflen);
1251
+ assert (tmpbuf == NULL);
1252
+ if (malloc_tmpbuf)
1253
+ tmpbuf = alloca_account (tmpbuflen, alloca_used);
1256
+ tmpbuf = malloc (tmpbuflen);
1257
+ if (tmpbuf == NULL)
1259
+ result = -EAI_MEMORY;
1260
+ goto free_and_return;
1266
@@ -729,8 +876,25 @@
1267
no_data = herrno == NO_DATA;
1270
- tmpbuf = extend_alloca (tmpbuf,
1271
- tmpbuflen, 2 * tmpbuflen);
1273
+ if (!malloc_tmpbuf
1274
+ && __libc_use_alloca (alloca_used + 2 * tmpbuflen))
1275
+ tmpbuf = extend_alloca_account (tmpbuf, tmpbuflen,
1280
+ char *newp = realloc (malloc_tmpbuf ? tmpbuf : NULL,
1284
+ result = -EAI_MEMORY;
1285
+ goto free_and_return;
1288
+ malloc_tmpbuf = true;
1289
+ tmpbuflen = 2 * tmpbuflen;
1293
no_inet6_data = no_data;
1294
@@ -805,18 +969,40 @@
1297
const size_t max_fqdn_len = 256;
1298
- char *buf = alloca (max_fqdn_len);
1299
+ if ((req->ai_flags & AI_CANONIDN) != 0
1300
+ && __libc_use_alloca (alloca_used
1302
+ canonbuf = alloca_account (max_fqdn_len,
1306
+ canonbuf = malloc (max_fqdn_len);
1307
+ if (canonbuf == NULL)
1309
+ result = -EAI_MEMORY;
1310
+ goto free_and_return;
1312
+ malloc_canonbuf = true;
1316
if (DL_CALL_FCT (cfct, (at->name ?: name,
1317
- buf, max_fqdn_len,
1321
== NSS_STATUS_SUCCESS)
1324
- /* Set to name now to avoid using
1328
+ /* Set to name now to avoid using
1330
+ if (malloc_canonbuf)
1333
+ malloc_canonbuf = false;
1340
@@ -850,22 +1036,27 @@
1342
/* If both requests timed out report this. */
1343
if (no_data == EAI_AGAIN && no_inet6_data == EAI_AGAIN)
1344
- return -EAI_AGAIN;
1345
+ result = -EAI_AGAIN;
1347
+ /* We made requests but they turned out no data. The name
1348
+ is known, though. */
1349
+ result = GAIH_OKIFUNSPEC | -EAI_NODATA;
1351
- /* We made requests but they turned out no data. The name
1352
- is known, though. */
1353
- return GAIH_OKIFUNSPEC | -EAI_NODATA;
1354
+ goto free_and_return;
1359
if (at->family == AF_UNSPEC)
1360
- return GAIH_OKIFUNSPEC | -EAI_NONAME;
1362
+ result = GAIH_OKIFUNSPEC | -EAI_NONAME;
1363
+ goto free_and_return;
1368
struct gaih_addrtuple *atr;
1369
- atr = at = __alloca (sizeof (struct gaih_addrtuple));
1370
+ atr = at = alloca_account (sizeof (struct gaih_addrtuple), alloca_used);
1371
memset (at, '\0', sizeof (struct gaih_addrtuple));
1373
if (req->ai_family == AF_UNSPEC)
1374
@@ -904,30 +1095,56 @@
1375
/* Only the first entry gets the canonical name. */
1376
if (at2 == at && (req->ai_flags & AI_CANONNAME) != 0)
1378
+ char *tmpbuf2 = NULL;
1379
+ bool malloc_tmpbuf2 = false;
1383
struct hostent *h = NULL;
1386
- size_t tmpbuflen = 512;
1387
- char *tmpbuf = NULL;
1388
+ size_t tmpbuf2len = 512;
1392
- tmpbuf = extend_alloca (tmpbuf, tmpbuflen, tmpbuflen * 2);
1393
+ if (__libc_use_alloca (alloca_used + 2 * tmpbuf2len))
1394
+ tmpbuf2 = extend_alloca_account (tmpbuf2, tmpbuf2len,
1399
+ char *newp = realloc (malloc_tmpbuf2 ? tmpbuf2 : NULL,
1403
+ if (malloc_tmpbuf2)
1405
+ result = -EAI_MEMORY;
1406
+ goto free_and_return;
1410
+ tmpbuf2len = 2 * tmpbuf2len;
1411
+ malloc_tmpbuf2 = true;
1414
rc = __gethostbyaddr_r (at2->addr,
1415
((at2->family == AF_INET6)
1416
? sizeof (struct in6_addr)
1417
: sizeof (struct in_addr)),
1418
- at2->family, &th, tmpbuf,
1419
- tmpbuflen, &h, &herrno);
1420
+ at2->family, &th, tmpbuf2,
1421
+ tmpbuf2len, &h, &herrno);
1423
while (rc == ERANGE && herrno == NETDB_INTERNAL);
1425
if (rc != 0 && herrno == NETDB_INTERNAL)
1427
+ if (malloc_tmpbuf2)
1430
__set_h_errno (herrno);
1431
- return -EAI_SYSTEM;
1432
+ result = -EAI_SYSTEM;
1433
+ goto free_and_return;
1437
@@ -954,11 +1171,16 @@
1438
int rc = __idna_to_unicode_lzlz (canon, &out, idn_flags);
1439
if (rc != IDNA_SUCCESS)
1441
+ if (malloc_tmpbuf2)
1444
if (rc == IDNA_MALLOC_ERROR)
1445
- return -EAI_MEMORY;
1446
- if (rc == IDNA_DLOPEN_ERROR)
1447
- return -EAI_SYSTEM;
1448
- return -EAI_IDN_ENCODE;
1449
+ result = -EAI_MEMORY;
1450
+ else if (rc == IDNA_DLOPEN_ERROR)
1451
+ result = -EAI_SYSTEM;
1453
+ result = -EAI_IDN_ENCODE;
1454
+ goto free_and_return;
1456
/* In case the output string is the same as the input
1457
string no new string has been allocated and we
1458
@@ -972,10 +1194,25 @@
1462
- canon = strdup (canon);
1463
- if (canon == NULL)
1464
- return -EAI_MEMORY;
1465
+ if (malloc_canonbuf)
1466
+ /* We already allocated the string using malloc. */
1467
+ malloc_canonbuf = false;
1470
+ canon = strdup (canon);
1471
+ if (canon == NULL)
1473
+ if (malloc_tmpbuf2)
1476
+ result = -EAI_MEMORY;
1477
+ goto free_and_return;
1482
+ if (malloc_tmpbuf2)
1486
family = at2->family;
1487
@@ -1001,7 +1238,8 @@
1490
free ((char *) canon);
1491
- return -EAI_MEMORY;
1492
+ result = -EAI_MEMORY;
1493
+ goto free_and_return;
1496
ai->ai_flags = req->ai_flags;
1497
@@ -1054,7 +1292,18 @@
1505
+ free ((char *) name);
1506
+ if (malloc_addrmem)
1508
+ if (malloc_canonbuf)
1510
+ if (malloc_tmpbuf)