glibc: updated to 2.21

This commit is contained in:
Fredrik Rinnestam 2015-06-20 22:42:25 +02:00
parent 2bbb4cc395
commit df59473fce
10 changed files with 97 additions and 1377 deletions

View File

@ -5,56 +5,55 @@ drwxr-xr-x root/root etc/
-rw-r--r-- root/root etc/ld.so.conf
drwxr-xr-x root/root etc/ld.so.conf.d/
lrwxrwxrwx root/root etc/localtime -> ../usr/share/zoneinfo/UTC
-rw-r--r-- root/root etc/nscd.conf
-rw-r--r-- root/root etc/nsswitch.conf
-rw-r--r-- root/root etc/resolv.conf
-rw-r--r-- root/root etc/rpc
drwxr-xr-x root/root lib/
-rwxr-xr-x root/root lib/ld-2.19.so
lrwxrwxrwx root/root lib/ld-linux-x86-64.so.2 -> ld-2.19.so
-rwxr-xr-x root/root lib/libBrokenLocale-2.19.so
lrwxrwxrwx root/root lib/libBrokenLocale.so.1 -> libBrokenLocale-2.19.so
-rwxr-xr-x root/root lib/ld-2.21.so
lrwxrwxrwx root/root lib/ld-linux-x86-64.so.2 -> ld-2.21.so
-rwxr-xr-x root/root lib/libBrokenLocale-2.21.so
lrwxrwxrwx root/root lib/libBrokenLocale.so.1 -> libBrokenLocale-2.21.so
-rwxr-xr-x root/root lib/libSegFault.so
-rwxr-xr-x root/root lib/libanl-2.19.so
lrwxrwxrwx root/root lib/libanl.so.1 -> libanl-2.19.so
-rwxr-xr-x root/root lib/libc-2.19.so
lrwxrwxrwx root/root lib/libc.so.6 -> libc-2.19.so
-rwxr-xr-x root/root lib/libcidn-2.19.so
lrwxrwxrwx root/root lib/libcidn.so.1 -> libcidn-2.19.so
-rwxr-xr-x root/root lib/libcrypt-2.19.so
lrwxrwxrwx root/root lib/libcrypt.so.1 -> libcrypt-2.19.so
-rwxr-xr-x root/root lib/libdl-2.19.so
lrwxrwxrwx root/root lib/libdl.so.2 -> libdl-2.19.so
-rwxr-xr-x root/root lib/libm-2.19.so
lrwxrwxrwx root/root lib/libm.so.6 -> libm-2.19.so
-rwxr-xr-x root/root lib/libanl-2.21.so
lrwxrwxrwx root/root lib/libanl.so.1 -> libanl-2.21.so
-rwxr-xr-x root/root lib/libc-2.21.so
lrwxrwxrwx root/root lib/libc.so.6 -> libc-2.21.so
-rwxr-xr-x root/root lib/libcidn-2.21.so
lrwxrwxrwx root/root lib/libcidn.so.1 -> libcidn-2.21.so
-rwxr-xr-x root/root lib/libcrypt-2.21.so
lrwxrwxrwx root/root lib/libcrypt.so.1 -> libcrypt-2.21.so
-rwxr-xr-x root/root lib/libdl-2.21.so
lrwxrwxrwx root/root lib/libdl.so.2 -> libdl-2.21.so
-rwxr-xr-x root/root lib/libm-2.21.so
lrwxrwxrwx root/root lib/libm.so.6 -> libm-2.21.so
-rwxr-xr-x root/root lib/libmemusage.so
-rwxr-xr-x root/root lib/libnsl-2.19.so
lrwxrwxrwx root/root lib/libnsl.so.1 -> libnsl-2.19.so
-rwxr-xr-x root/root lib/libnss_compat-2.19.so
lrwxrwxrwx root/root lib/libnss_compat.so.2 -> libnss_compat-2.19.so
-rwxr-xr-x root/root lib/libnss_db-2.19.so
lrwxrwxrwx root/root lib/libnss_db.so.2 -> libnss_db-2.19.so
-rwxr-xr-x root/root lib/libnss_dns-2.19.so
lrwxrwxrwx root/root lib/libnss_dns.so.2 -> libnss_dns-2.19.so
-rwxr-xr-x root/root lib/libnss_files-2.19.so
lrwxrwxrwx root/root lib/libnss_files.so.2 -> libnss_files-2.19.so
-rwxr-xr-x root/root lib/libnss_hesiod-2.19.so
lrwxrwxrwx root/root lib/libnss_hesiod.so.2 -> libnss_hesiod-2.19.so
-rwxr-xr-x root/root lib/libnss_nis-2.19.so
lrwxrwxrwx root/root lib/libnss_nis.so.2 -> libnss_nis-2.19.so
-rwxr-xr-x root/root lib/libnss_nisplus-2.19.so
lrwxrwxrwx root/root lib/libnss_nisplus.so.2 -> libnss_nisplus-2.19.so
-rwxr-xr-x root/root lib/libnsl-2.21.so
lrwxrwxrwx root/root lib/libnsl.so.1 -> libnsl-2.21.so
-rwxr-xr-x root/root lib/libnss_compat-2.21.so
lrwxrwxrwx root/root lib/libnss_compat.so.2 -> libnss_compat-2.21.so
-rwxr-xr-x root/root lib/libnss_db-2.21.so
lrwxrwxrwx root/root lib/libnss_db.so.2 -> libnss_db-2.21.so
-rwxr-xr-x root/root lib/libnss_dns-2.21.so
lrwxrwxrwx root/root lib/libnss_dns.so.2 -> libnss_dns-2.21.so
-rwxr-xr-x root/root lib/libnss_files-2.21.so
lrwxrwxrwx root/root lib/libnss_files.so.2 -> libnss_files-2.21.so
-rwxr-xr-x root/root lib/libnss_hesiod-2.21.so
lrwxrwxrwx root/root lib/libnss_hesiod.so.2 -> libnss_hesiod-2.21.so
-rwxr-xr-x root/root lib/libnss_nis-2.21.so
lrwxrwxrwx root/root lib/libnss_nis.so.2 -> libnss_nis-2.21.so
-rwxr-xr-x root/root lib/libnss_nisplus-2.21.so
lrwxrwxrwx root/root lib/libnss_nisplus.so.2 -> libnss_nisplus-2.21.so
-rwxr-xr-x root/root lib/libpcprofile.so
-rwxr-xr-x root/root lib/libpthread-2.19.so
lrwxrwxrwx root/root lib/libpthread.so.0 -> libpthread-2.19.so
-rwxr-xr-x root/root lib/libresolv-2.19.so
lrwxrwxrwx root/root lib/libresolv.so.2 -> libresolv-2.19.so
-rwxr-xr-x root/root lib/librt-2.19.so
lrwxrwxrwx root/root lib/librt.so.1 -> librt-2.19.so
-rwxr-xr-x root/root lib/libpthread-2.21.so
lrwxrwxrwx root/root lib/libpthread.so.0 -> libpthread-2.21.so
-rwxr-xr-x root/root lib/libresolv-2.21.so
lrwxrwxrwx root/root lib/libresolv.so.2 -> libresolv-2.21.so
-rwxr-xr-x root/root lib/librt-2.21.so
lrwxrwxrwx root/root lib/librt.so.1 -> librt-2.21.so
-rwxr-xr-x root/root lib/libthread_db-1.0.so
lrwxrwxrwx root/root lib/libthread_db.so.1 -> libthread_db-1.0.so
-rwxr-xr-x root/root lib/libutil-2.19.so
lrwxrwxrwx root/root lib/libutil.so.1 -> libutil-2.19.so
-rwxr-xr-x root/root lib/libutil-2.21.so
lrwxrwxrwx root/root lib/libutil.so.1 -> libutil-2.21.so
drwxr-xr-x root/root sbin/
-rwxr-xr-x root/root sbin/ldconfig
-rwxr-xr-x root/root sbin/sln
@ -359,6 +358,7 @@ drwxr-xr-x root/root usr/include/drm/
-rw-r--r-- root/root usr/include/glob.h
-rw-r--r-- root/root usr/include/gnu-versions.h
drwxr-xr-x root/root usr/include/gnu/
-rw-r--r-- root/root usr/include/gnu/lib-names-64.h
-rw-r--r-- root/root usr/include/gnu/lib-names.h
-rw-r--r-- root/root usr/include/gnu/libc-version.h
-rw-r--r-- root/root usr/include/gnu/stubs-64.h
@ -1850,6 +1850,7 @@ drwxr-xr-x root/root usr/share/i18n/locales/
-rw-r--r-- root/root usr/share/i18n/locales/ber_DZ
-rw-r--r-- root/root usr/share/i18n/locales/ber_MA
-rw-r--r-- root/root usr/share/i18n/locales/bg_BG
-rw-r--r-- root/root usr/share/i18n/locales/bh_IN
-rw-r--r-- root/root usr/share/i18n/locales/bho_IN
-rw-r--r-- root/root usr/share/i18n/locales/bn_BD
-rw-r--r-- root/root usr/share/i18n/locales/bn_IN
@ -1865,6 +1866,7 @@ drwxr-xr-x root/root usr/share/i18n/locales/
-rw-r--r-- root/root usr/share/i18n/locales/ca_ES@euro
-rw-r--r-- root/root usr/share/i18n/locales/ca_FR
-rw-r--r-- root/root usr/share/i18n/locales/ca_IT
-rw-r--r-- root/root usr/share/i18n/locales/ce_RU
-rw-r--r-- root/root usr/share/i18n/locales/cmn_TW
-rw-r--r-- root/root usr/share/i18n/locales/crh_UA
-rw-r--r-- root/root usr/share/i18n/locales/cs_CZ
@ -2050,6 +2052,7 @@ drwxr-xr-x root/root usr/share/i18n/locales/
-rw-r--r-- root/root usr/share/i18n/locales/pt_PT
-rw-r--r-- root/root usr/share/i18n/locales/pt_PT@euro
-rw-r--r-- root/root usr/share/i18n/locales/quz_PE
-rw-r--r-- root/root usr/share/i18n/locales/raj_IN
-rw-r--r-- root/root usr/share/i18n/locales/ro_RO
-rw-r--r-- root/root usr/share/i18n/locales/ru_RU
-rw-r--r-- root/root usr/share/i18n/locales/ru_UA
@ -2111,6 +2114,7 @@ drwxr-xr-x root/root usr/share/i18n/locales/
-rw-r--r-- root/root usr/share/i18n/locales/ts_ZA
-rw-r--r-- root/root usr/share/i18n/locales/tt_RU
-rw-r--r-- root/root usr/share/i18n/locales/tt_RU@iqtelif
-rw-r--r-- root/root usr/share/i18n/locales/tu_IN
-rw-r--r-- root/root usr/share/i18n/locales/ug_CN
-rw-r--r-- root/root usr/share/i18n/locales/uk_UA
-rw-r--r-- root/root usr/share/i18n/locales/unm_US
@ -2137,6 +2141,3 @@ drwxr-xr-x root/root usr/share/i18n/locales/
drwxr-xr-x root/root var/
drwxr-xr-x root/root var/db/
-rw-r--r-- root/root var/db/Makefile
drwxr-xr-x root/root var/db/nscd/
drwxr-xr-x root/root var/run/
drwxr-xr-x root/root var/run/nscd/

View File

@ -1,13 +1,7 @@
c241d3240d0d98af4f1b948cd940dbd8 CVE-2012-3406-Stack-overflow-in-vfprintf-BZ-16617.patch
1d06c7a6084db7710bec7215143c5799 CVE-2014-0475.patch
59f56ab2c3b3334074c07dec6c217301 CVE-2014-7817-wordexp-fails-to-honour-WRDE_NOCMD.patch
27ae57547600f9c6a9a897aa6f4e5555 CVE-2014-9402-Avoid-infinite-loop-in-nss_dns-getnetbyname.patch
b2a77e95e8694f37415f86e8bc0a1fe5 CVE-2015-1472-wscanf-allocates-too-little-memory.patch
a568134a222776d8fc23059dfb25d835 glibc-2.19-multilib-dirs.patch
e26b8cc666b162f999404b03970f14e4 glibc-2.19.tar.xz
aaad345ff18993dafe3e44ac947f7157 glibc-2.20-multilib-dirs.patch
9cb398828e8f84f57d1f7d5588cf40cd glibc-2.21.tar.xz
96156bec8e05de67384dc93e72bdc313 host.conf
fbbc215a9b15ba4846f326cc88108057 hosts
922519df77d72faea626ddc3854d6bad iconv-gconv_trans.c.patch
2297992bd1eb0d62211effafd84b6454 kernel-headers-3.12.tar.bz2
f7fefce570a3c776e26e778c5e401490 ld.so.conf
75931315bf9bc9be15a5e25e4ddd5f0d nsswitch.conf

View File

@ -1,274 +0,0 @@
From 6143805bb45e716829d86851e9372f55a136064b Mon Sep 17 00:00:00 2001
From: Jeff Law <law@redhat.com>
Date: Mon, 15 Dec 2014 10:09:32 +0100
Subject: [PATCH 35/37] CVE-2012-3406: Stack overflow in vfprintf [BZ #16617]
A larger number of format specifiers coudld cause a stack overflow,
potentially allowing to bypass _FORTIFY_SOURCE format string
protection.
Conflicts:
ChangeLog
NEWS
---
ChangeLog | 13 +++++++++
NEWS | 57 ++++++++++++++++++++++++++++++++++++++++
stdio-common/Makefile | 2 +-
stdio-common/bug23-2.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++
stdio-common/bug23-3.c | 50 +++++++++++++++++++++++++++++++++++
stdio-common/bug23-4.c | 31 ++++++++++++++++++++++
stdio-common/vfprintf.c | 40 ++++++++++++++++++++++++++--
7 files changed, 260 insertions(+), 3 deletions(-)
create mode 100644 stdio-common/bug23-2.c
create mode 100644 stdio-common/bug23-3.c
create mode 100644 stdio-common/bug23-4.c
diff --git a/stdio-common/bug23-2.c b/stdio-common/bug23-2.c
new file mode 100644
index 0000000..9e0cfe6
--- /dev/null
+++ b/stdio-common/bug23-2.c
@@ -0,0 +1,70 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+static const char expected[] = "\
+\n\
+a\n\
+abbcd55\
+\n\
+a\n\
+abbcd55\
+\n\
+a\n\
+abbcd55\
+\n\
+a\n\
+abbcd55\
+\n\
+a\n\
+abbcd55\
+\n\
+a\n\
+abbcd55\
+\n\
+a\n\
+abbcd55\
+\n\
+a\n\
+abbcd55\
+\n\
+a\n\
+abbcd55\
+\n\
+a\n\
+abbcd55\
+\n\
+a\n\
+abbcd55\
+\n\
+a\n\
+abbcd55\
+\n\
+a\n\
+abbcd55%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
+
+static int
+do_test (void)
+{
+ char *buf = malloc (strlen (expected) + 1);
+ snprintf (buf, strlen (expected) + 1,
+ "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
+ "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
+ "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
+ "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
+ "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
+ "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
+ "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
+ "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
+ "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
+ "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
+ "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
+ "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
+ "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
+ "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n",
+ "a", "b", "c", "d", 5);
+ return strcmp (buf, expected) != 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/stdio-common/bug23-3.c b/stdio-common/bug23-3.c
new file mode 100644
index 0000000..57c8cef
--- /dev/null
+++ b/stdio-common/bug23-3.c
@@ -0,0 +1,50 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+int
+do_test (void)
+{
+ size_t instances = 16384;
+#define X0 "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
+ const char *item = "\na\nabbcd55";
+#define X3 X0 X0 X0 X0 X0 X0 X0 X0
+#define X6 X3 X3 X3 X3 X3 X3 X3 X3
+#define X9 X6 X6 X6 X6 X6 X6 X6 X6
+#define X12 X9 X9 X9 X9 X9 X9 X9 X9
+#define X14 X12 X12 X12 X12
+#define TRAILER "%%%%%%%%%%%%%%%%%%%%%%%%%%"
+#define TRAILER2 TRAILER TRAILER
+ size_t length = instances * strlen (item) + strlen (TRAILER) + 1;
+
+ char *buf = malloc (length + 1);
+ snprintf (buf, length + 1,
+ X14 TRAILER2 "\n",
+ "a", "b", "c", "d", 5);
+
+ const char *p = buf;
+ size_t i;
+ for (i = 0; i < instances; ++i)
+ {
+ const char *expected;
+ for (expected = item; *expected; ++expected)
+ {
+ if (*p != *expected)
+ {
+ printf ("mismatch at offset %zu (%zu): expected %d, got %d\n",
+ (size_t) (p - buf), i, *expected & 0xFF, *p & 0xFF);
+ return 1;
+ }
+ ++p;
+ }
+ }
+ if (strcmp (p, TRAILER "\n") != 0)
+ {
+ printf ("mismatch at trailer: [%s]\n", p);
+ return 1;
+ }
+ free (buf);
+ return 0;
+}
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/stdio-common/bug23-4.c b/stdio-common/bug23-4.c
new file mode 100644
index 0000000..a478564
--- /dev/null
+++ b/stdio-common/bug23-4.c
@@ -0,0 +1,31 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/resource.h>
+
+#define LIMIT 1000000
+
+int
+main (void)
+{
+ struct rlimit lim;
+ getrlimit (RLIMIT_STACK, &lim);
+ lim.rlim_cur = 1048576;
+ setrlimit (RLIMIT_STACK, &lim);
+ char *fmtstr = malloc (4 * LIMIT + 1);
+ if (fmtstr == NULL)
+ abort ();
+ char *output = malloc (LIMIT + 1);
+ if (output == NULL)
+ abort ();
+ for (size_t i = 0; i < LIMIT; i++)
+ memcpy (fmtstr + 4 * i, "%1$d", 4);
+ fmtstr[4 * LIMIT] = '\0';
+ int ret = snprintf (output, LIMIT + 1, fmtstr, 0);
+ if (ret != LIMIT)
+ abort ();
+ for (size_t i = 0; i < LIMIT; i++)
+ if (output[i] != '0')
+ abort ();
+ return 0;
+}
diff --git a/stdio-common/vfprintf.c b/stdio-common/vfprintf.c
index f7e5f61..f423be6 100644
--- a/stdio-common/vfprintf.c
+++ b/stdio-common/vfprintf.c
@@ -263,6 +263,12 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
/* For the argument descriptions, which may be allocated on the heap. */
void *args_malloced = NULL;
+ /* For positional argument handling. */
+ struct printf_spec *specs;
+
+ /* Track if we malloced the SPECS array and thus must free it. */
+ bool specs_malloced = false;
+
/* This table maps a character into a number representing a
class. In each step there is a destination label for each
class. */
@@ -1678,8 +1684,8 @@ do_positional:
size_t nspecs = 0;
/* A more or less arbitrary start value. */
size_t nspecs_size = 32 * sizeof (struct printf_spec);
- struct printf_spec *specs = alloca (nspecs_size);
+ specs = alloca (nspecs_size);
/* The number of arguments the format string requests. This will
determine the size of the array needed to store the argument
attributes. */
@@ -1720,11 +1726,39 @@ do_positional:
if (nspecs * sizeof (*specs) >= nspecs_size)
{
/* Extend the array of format specifiers. */
+ if (nspecs_size * 2 < nspecs_size)
+ {
+ __set_errno (ENOMEM);
+ done = -1;
+ goto all_done;
+ }
struct printf_spec *old = specs;
- specs = extend_alloca (specs, nspecs_size, 2 * nspecs_size);
+ if (__libc_use_alloca (2 * nspecs_size))
+ specs = extend_alloca (specs, nspecs_size, 2 * nspecs_size);
+ else
+ {
+ nspecs_size *= 2;
+ specs = malloc (nspecs_size);
+ if (specs == NULL)
+ {
+ __set_errno (ENOMEM);
+ specs = old;
+ done = -1;
+ goto all_done;
+ }
+ }
/* Copy the old array's elements to the new space. */
memmove (specs, old, nspecs * sizeof (*specs));
+
+ /* If we had previously malloc'd space for SPECS, then
+ release it after the copy is complete. */
+ if (specs_malloced)
+ free (old);
+
+ /* Now set SPECS_MALLOCED if needed. */
+ if (!__libc_use_alloca (nspecs_size))
+ specs_malloced = true;
}
/* Parse the format specifier. */
@@ -2045,6 +2079,8 @@ do_positional:
}
all_done:
+ if (specs_malloced)
+ free (specs);
if (__glibc_unlikely (args_malloced != NULL))
free (args_malloced);
if (__glibc_unlikely (workstart != NULL))
--
2.2.1

View File

@ -1,673 +0,0 @@
From 176fc6c7ddec8d93468f9b790d39dcab6d41b1a6 Mon Sep 17 00:00:00 2001
From: Florian Weimer <fweimer@redhat.com>
Date: Mon, 12 May 2014 15:24:12 +0200
Subject: [PATCH] _nl_find_locale: Improve handling of crafted locale names [BZ #17137]
Prevent directory traversal in locale-related environment variables
(CVE-2014-0475).
(cherry picked from commit 4e8f95a0df7c2300b830ec12c0ae1e161bc8a8a3)
Conflicts:
NEWS
localedata/Makefile
---
ChangeLog | 9 ++
NEWS | 11 ++-
locale/findlocale.c | 74 +++++++++++++---
localedata/ChangeLog | 6 ++
localedata/Makefile | 2 +-
localedata/tst-setlocale3.c | 203 +++++++++++++++++++++++++++++++++++++++++++
6 files changed, 290 insertions(+), 15 deletions(-)
create mode 100644 localedata/tst-setlocale3.c
diff --git a/locale/findlocale.c b/locale/findlocale.c
index 0c42b99..faeee61 100644
--- a/locale/findlocale.c
+++ b/locale/findlocale.c
@@ -17,6 +17,7 @@
<http://www.gnu.org/licenses/>. */
#include <assert.h>
+#include <errno.h>
#include <locale.h>
#include <stdlib.h>
#include <string.h>
@@ -57,6 +58,45 @@ struct loaded_l10nfile *_nl_locale_file_list[__LC_LAST];
const char _nl_default_locale_path[] attribute_hidden = LOCALEDIR;
+/* Checks if the name is actually present, that is, not NULL and not
+ empty. */
+static inline int
+name_present (const char *name)
+{
+ return name != NULL && name[0] != '\0';
+}
+
+/* Checks that the locale name neither extremely long, nor contains a
+ ".." path component (to prevent directory traversal). */
+static inline int
+valid_locale_name (const char *name)
+{
+ /* Not set. */
+ size_t namelen = strlen (name);
+ /* Name too long. The limit is arbitrary and prevents stack overflow
+ issues later. */
+ if (__glibc_unlikely (namelen > 255))
+ return 0;
+ /* Directory traversal attempt. */
+ static const char slashdot[4] = {'/', '.', '.', '/'};
+ if (__glibc_unlikely (memmem (name, namelen,
+ slashdot, sizeof (slashdot)) != NULL))
+ return 0;
+ if (namelen == 2 && __glibc_unlikely (name[0] == '.' && name [1] == '.'))
+ return 0;
+ if (namelen >= 3
+ && __glibc_unlikely (((name[0] == '.'
+ && name[1] == '.'
+ && name[2] == '/')
+ || (name[namelen - 3] == '/'
+ && name[namelen - 2] == '.'
+ && name[namelen - 1] == '.'))))
+ return 0;
+ /* If there is a slash in the name, it must start with one. */
+ if (__glibc_unlikely (memchr (name, '/', namelen) != NULL) && name[0] != '/')
+ return 0;
+ return 1;
+}
struct __locale_data *
internal_function
@@ -65,7 +105,7 @@ _nl_find_locale (const char *locale_path, size_t locale_path_len,
{
int mask;
/* Name of the locale for this category. */
- char *loc_name;
+ char *loc_name = (char *) *name;
const char *language;
const char *modifier;
const char *territory;
@@ -73,31 +113,39 @@ _nl_find_locale (const char *locale_path, size_t locale_path_len,
const char *normalized_codeset;
struct loaded_l10nfile *locale_file;
- if ((*name)[0] == '\0')
+ if (loc_name[0] == '\0')
{
/* The user decides which locale to use by setting environment
variables. */
- *name = getenv ("LC_ALL");
- if (*name == NULL || (*name)[0] == '\0')
- *name = getenv (_nl_category_names.str
+ loc_name = getenv ("LC_ALL");
+ if (!name_present (loc_name))
+ loc_name = getenv (_nl_category_names.str
+ _nl_category_name_idxs[category]);
- if (*name == NULL || (*name)[0] == '\0')
- *name = getenv ("LANG");
+ if (!name_present (loc_name))
+ loc_name = getenv ("LANG");
+ if (!name_present (loc_name))
+ loc_name = (char *) _nl_C_name;
}
- if (*name == NULL || (*name)[0] == '\0'
- || (__builtin_expect (__libc_enable_secure, 0)
- && strchr (*name, '/') != NULL))
- *name = (char *) _nl_C_name;
+ /* We used to fall back to the C locale if the name contains a slash
+ character '/', but we now check for directory traversal in
+ valid_locale_name, so this is no longer necessary. */
- if (__builtin_expect (strcmp (*name, _nl_C_name), 1) == 0
- || __builtin_expect (strcmp (*name, _nl_POSIX_name), 1) == 0)
+ if (__builtin_expect (strcmp (loc_name, _nl_C_name), 1) == 0
+ || __builtin_expect (strcmp (loc_name, _nl_POSIX_name), 1) == 0)
{
/* We need not load anything. The needed data is contained in
the library itself. */
*name = (char *) _nl_C_name;
return _nl_C[category];
}
+ else if (!valid_locale_name (loc_name))
+ {
+ __set_errno (EINVAL);
+ return NULL;
+ }
+
+ *name = loc_name;
/* We really have to load some data. First we try the archive,
but only if there was no LOCPATH environment variable specified. */
diff --git a/localedata/Makefile b/localedata/Makefile
index 7d157bf..9daa470 100644
--- a/localedata/Makefile
+++ b/localedata/Makefile
@@ -77,7 +77,7 @@ locale_test_suite := tst_iswalnum tst_iswalpha tst_iswcntrl \
tests = $(locale_test_suite) tst-digits tst-setlocale bug-iconv-trans \
tst-leaks tst-mbswcs6 tst-xlocale1 tst-xlocale2 bug-usesetlocale \
- tst-strfmon1 tst-sscanf bug-setlocale1 tst-setlocale2
+ tst-strfmon1 tst-sscanf bug-setlocale1 tst-setlocale2 tst-setlocale3
tests-static = bug-setlocale1-static
tests += $(tests-static)
ifeq (yes,$(build-shared))
diff --git a/localedata/tst-setlocale3.c b/localedata/tst-setlocale3.c
new file mode 100644
index 0000000..e3b21a9
--- /dev/null
+++ b/localedata/tst-setlocale3.c
@@ -0,0 +1,203 @@
+/* Regression test for setlocale invalid environment variable handling.
+ Copyright (C) 2014 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 <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* The result of setlocale may be overwritten by subsequent calls, so
+ this wrapper makes a copy. */
+static char *
+setlocale_copy (int category, const char *locale)
+{
+ const char *result = setlocale (category, locale);
+ if (result == NULL)
+ return NULL;
+ return strdup (result);
+}
+
+static char *de_locale;
+
+static void
+setlocale_fail (const char *envstring)
+{
+ setenv ("LC_CTYPE", envstring, 1);
+ if (setlocale (LC_CTYPE, "") != NULL)
+ {
+ printf ("unexpected setlocale success for \"%s\" locale\n", envstring);
+ exit (1);
+ }
+ const char *newloc = setlocale (LC_CTYPE, NULL);
+ if (strcmp (newloc, de_locale) != 0)
+ {
+ printf ("failed setlocale call \"%s\" changed locale to \"%s\"\n",
+ envstring, newloc);
+ exit (1);
+ }
+}
+
+static void
+setlocale_success (const char *envstring)
+{
+ setenv ("LC_CTYPE", envstring, 1);
+ char *newloc = setlocale_copy (LC_CTYPE, "");
+ if (newloc == NULL)
+ {
+ printf ("setlocale for \"%s\": %m\n", envstring);
+ exit (1);
+ }
+ if (strcmp (newloc, de_locale) == 0)
+ {
+ printf ("setlocale with LC_CTYPE=\"%s\" left locale at \"%s\"\n",
+ envstring, de_locale);
+ exit (1);
+ }
+ if (setlocale (LC_CTYPE, de_locale) == NULL)
+ {
+ printf ("restoring locale \"%s\" with LC_CTYPE=\"%s\": %m\n",
+ de_locale, envstring);
+ exit (1);
+ }
+ char *newloc2 = setlocale_copy (LC_CTYPE, newloc);
+ if (newloc2 == NULL)
+ {
+ printf ("restoring locale \"%s\" following \"%s\": %m\n",
+ newloc, envstring);
+ exit (1);
+ }
+ if (strcmp (newloc, newloc2) != 0)
+ {
+ printf ("representation of locale \"%s\" changed from \"%s\" to \"%s\"",
+ envstring, newloc, newloc2);
+ exit (1);
+ }
+ free (newloc);
+ free (newloc2);
+
+ if (setlocale (LC_CTYPE, de_locale) == NULL)
+ {
+ printf ("restoring locale \"%s\" with LC_CTYPE=\"%s\": %m\n",
+ de_locale, envstring);
+ exit (1);
+ }
+}
+
+/* Checks that a known-good locale still works if LC_ALL contains a
+ value which should be ignored. */
+static void
+setlocale_ignore (const char *to_ignore)
+{
+ const char *fr_locale = "fr_FR.UTF-8";
+ setenv ("LC_CTYPE", fr_locale, 1);
+ char *expected_locale = setlocale_copy (LC_CTYPE, "");
+ if (expected_locale == NULL)
+ {
+ printf ("setlocale with LC_CTYPE=\"%s\" failed: %m\n", fr_locale);
+ exit (1);
+ }
+ if (setlocale (LC_CTYPE, de_locale) == NULL)
+ {
+ printf ("failed to restore locale: %m\n");
+ exit (1);
+ }
+ unsetenv ("LC_CTYPE");
+
+ setenv ("LC_ALL", to_ignore, 1);
+ setenv ("LC_CTYPE", fr_locale, 1);
+ const char *actual_locale = setlocale (LC_CTYPE, "");
+ if (actual_locale == NULL)
+ {
+ printf ("setlocale with LC_ALL, LC_CTYPE=\"%s\" failed: %m\n",
+ fr_locale);
+ exit (1);
+ }
+ if (strcmp (actual_locale, expected_locale) != 0)
+ {
+ printf ("setlocale under LC_ALL failed: got \"%s\", expected \"%s\"\n",
+ actual_locale, expected_locale);
+ exit (1);
+ }
+ unsetenv ("LC_CTYPE");
+ setlocale_success (fr_locale);
+ unsetenv ("LC_ALL");
+ free (expected_locale);
+}
+
+static int
+do_test (void)
+{
+ /* The glibc test harness sets this environment variable
+ uncondionally. */
+ unsetenv ("LC_ALL");
+
+ de_locale = setlocale_copy (LC_CTYPE, "de_DE.UTF-8");
+ if (de_locale == NULL)
+ {
+ printf ("setlocale (LC_CTYPE, \"de_DE.UTF-8\"): %m\n");
+ return 1;
+ }
+ setlocale_success ("C");
+ setlocale_success ("en_US.UTF-8");
+ setlocale_success ("/en_US.UTF-8");
+ setlocale_success ("//en_US.UTF-8");
+ setlocale_ignore ("");
+
+ setlocale_fail ("does-not-exist");
+ setlocale_fail ("/");
+ setlocale_fail ("/../localedata/en_US.UTF-8");
+ setlocale_fail ("en_US.UTF-8/");
+ setlocale_fail ("en_US.UTF-8/..");
+ setlocale_fail ("en_US.UTF-8/../en_US.UTF-8");
+ setlocale_fail ("../localedata/en_US.UTF-8");
+ {
+ size_t large_length = 1024;
+ char *large_name = malloc (large_length + 1);
+ if (large_name == NULL)
+ {
+ puts ("malloc failure");
+ return 1;
+ }
+ memset (large_name, '/', large_length);
+ const char *suffix = "en_US.UTF-8";
+ strcpy (large_name + large_length - strlen (suffix), suffix);
+ setlocale_fail (large_name);
+ free (large_name);
+ }
+ {
+ size_t huge_length = 64 * 1024 * 1024;
+ char *huge_name = malloc (huge_length + 1);
+ if (huge_name == NULL)
+ {
+ puts ("malloc failure");
+ return 1;
+ }
+ memset (huge_name, 'X', huge_length);
+ huge_name[huge_length] = '\0';
+ /* Construct a composite locale specification. */
+ const char *prefix = "LC_CTYPE=de_DE.UTF-8;LC_TIME=";
+ memcpy (huge_name, prefix, strlen (prefix));
+ setlocale_fail (huge_name);
+ free (huge_name);
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
---
From d07eb371352d67ee4ef931b6956d1e0f28b599dc Mon Sep 17 00:00:00 2001
From: Florian Weimer <fweimer@redhat.com>
Date: Wed, 28 May 2014 14:05:03 +0200
Subject: [PATCH] manual: Update the locale documentation
(cherry picked from commit 585367266923156ac6fb789939a923641ba5aaf4)
Conflicts:
manual/locale.texi
---
ChangeLog | 13 +++++
manual/locale.texi | 146 ++++++++++++++++++++++++++++++++++++++++-----------
2 files changed, 127 insertions(+), 32 deletions(-)
diff --git a/manual/locale.texi b/manual/locale.texi
index 8bfd653..ee1c3a1 100644
--- a/manual/locale.texi
+++ b/manual/locale.texi
@@ -29,6 +29,7 @@ will follow the conventions preferred by the user.
* Setting the Locale:: How a program specifies the locale
with library functions.
* Standard Locales:: Locale names available on all systems.
+* Locale Names:: Format of system-specific locale names.
* Locale Information:: How to access the information for the locale.
* Formatting Numbers:: A dedicated function to format numbers.
* Yes-or-No Questions:: Check a Response against the locale.
@@ -99,14 +100,16 @@ locale named @samp{espana-castellano} to use the standard conventions of
most of Spain.
The set of locales supported depends on the operating system you are
-using, and so do their names. We can't make any promises about what
-locales will exist, except for one standard locale called @samp{C} or
-@samp{POSIX}. Later we will describe how to construct locales.
-@comment (@pxref{Building Locale Files}).
+using, and so do their names, except that the standard locale called
+@samp{C} or @samp{POSIX} always exist. @xref{Locale Names}.
+
+In order to force the system to always use the default locale, the
+user can set the @code{LC_ALL} environment variable to @samp{C}.
@cindex combining locales
-A user also has the option of specifying different locales for different
-purposes---in effect, choosing a mixture of multiple locales.
+A user also has the option of specifying different locales for
+different purposes---in effect, choosing a mixture of multiple
+locales. @xref{Locale Categories}.
For example, the user might specify the locale @samp{espana-castellano}
for most purposes, but specify the locale @samp{usa-english} for
@@ -120,7 +123,7 @@ which locales apply. However, the user can choose to use each locale
for a particular subset of those purposes.
@node Locale Categories, Setting the Locale, Choosing Locale, Locales
-@section Categories of Activities that Locales Affect
+@section Locale Categories
@cindex categories for locales
@cindex locale categories
@@ -128,7 +131,11 @@ The purposes that locales serve are grouped into @dfn{categories}, so
that a user or a program can choose the locale for each category
independently. Here is a table of categories; each name is both an
environment variable that a user can set, and a macro name that you can
-use as an argument to @code{setlocale}.
+use as the first argument to @code{setlocale}.
+
+The contents of the environment variable (or the string in the second
+argument to @code{setlocale}) has to be a valid locale name.
+@xref{Locale Names}.
@vtable @code
@comment locale.h
@@ -172,7 +179,7 @@ for affirmative and negative responses.
@comment locale.h
@comment ISO
@item LC_ALL
-This is not an environment variable; it is only a macro that you can use
+This is not a category; it is only a macro that you can use
with @code{setlocale} to set a single locale for all purposes. Setting
this environment variable overwrites all selections by the other
@code{LC_*} variables or @code{LANG}.
@@ -355,13 +362,7 @@ The symbols in this section are defined in the header file @file{locale.h}.
@c strndup @ascuheap @acsmem
@c strcasecmp_l ok (C locale)
The function @code{setlocale} sets the current locale for category
-@var{category} to @var{locale}. A list of all the locales the system
-provides can be created by running
-
-@pindex locale
-@smallexample
- locale -a
-@end smallexample
+@var{category} to @var{locale}.
If @var{category} is @code{LC_ALL}, this specifies the locale for all
purposes. The other possible values of @var{category} specify an
@@ -386,10 +387,9 @@ is passed in as @var{locale} parameter.
When you read the current locale for category @code{LC_ALL}, the value
encodes the entire combination of selected locales for all categories.
-In this case, the value is not just a single locale name. In fact, we
-don't make any promises about what it looks like. But if you specify
-the same ``locale name'' with @code{LC_ALL} in a subsequent call to
-@code{setlocale}, it restores the same combination of locale selections.
+If you specify the same ``locale name'' with @code{LC_ALL} in a
+subsequent call to @code{setlocale}, it restores the same combination
+of locale selections.
To be sure you can use the returned string encoding the currently selected
locale at a later time, you must make a copy of the string. It is not
@@ -405,20 +405,15 @@ for @var{category}.
If a nonempty string is given for @var{locale}, then the locale of that
name is used if possible.
+The effective locale name (either the second argument to
+@code{setlocale}, or if the argument is an empty string, the name
+obtained from the process environment) must be valid locale name.
+@xref{Locale Names}.
+
If you specify an invalid locale name, @code{setlocale} returns a null
pointer and leaves the current locale unchanged.
@end deftypefun
-The path used for finding locale data can be set using the
-@code{LOCPATH} environment variable. The default path for finding
-locale data is system specific. It is computed from the value given
-as the prefix while configuring the C library. This value normally is
-@file{/usr} or @file{/}. For the former the complete path is:
-
-@smallexample
-/usr/lib/locale
-@end smallexample
-
Here is an example showing how you might use @code{setlocale} to
temporarily switch to a new locale.
@@ -458,7 +453,7 @@ locale categories, and future versions of the library will do so. For
portability, assume that any symbol beginning with @samp{LC_} might be
defined in @file{locale.h}.
-@node Standard Locales, Locale Information, Setting the Locale, Locales
+@node Standard Locales, Locale Names, Setting the Locale, Locales
@section Standard Locales
The only locale names you can count on finding on all operating systems
@@ -492,7 +487,94 @@ with the environment, rather than trying to specify some non-standard
locale explicitly by name. Remember, different machines might have
different sets of locales installed.
-@node Locale Information, Formatting Numbers, Standard Locales, Locales
+@node Locale Names, Locale Information, Standard Locales, Locales
+@section Locale Names
+
+The following command prints a list of locales supported by the
+system:
+
+@pindex locale
+@smallexample
+ locale -a
+@end smallexample
+
+@strong{Portability Note:} With the notable exception of the standard
+locale names @samp{C} and @samp{POSIX}, locale names are
+system-specific.
+
+Most locale names follow XPG syntax and consist of up to four parts:
+
+@smallexample
+@var{language}[_@var{territory}[.@var{codeset}]][@@@var{modifier}]
+@end smallexample
+
+Beside the first part, all of them are allowed to be missing. If the
+full specified locale is not found, less specific ones are looked for.
+The various parts will be stripped off, in the following order:
+
+@enumerate
+@item
+codeset
+@item
+normalized codeset
+@item
+territory
+@item
+modifier
+@end enumerate
+
+For example, the locale name @samp{de_AT.iso885915@@euro} denotes a
+German-language locale for use in Austria, using the ISO-8859-15
+(Latin-9) character set, and with the Euro as the currency symbol.
+
+In addition to locale names which follow XPG syntax, systems may
+provide aliases such as @samp{german}. Both categories of names must
+not contain the slash character @samp{/}.
+
+If the locale name starts with a slash @samp{/}, it is treated as a
+path relative to the configured locale directories; see @code{LOCPATH}
+below. The specified path must not contain a component @samp{..}, or
+the name is invalid, and @code{setlocale} will fail.
+
+@strong{Portability Note:} POSIX suggests that if a locale name starts
+with a slash @samp{/}, it is resolved as an absolute path. However,
+@theglibc{} treats it as a relative path under the directories listed
+in @code{LOCPATH} (or the default locale directory if @code{LOCPATH}
+is unset).
+
+Locale names which are longer than an implementation-defined limit are
+invalid and cause @code{setlocale} to fail.
+
+As a special case, locale names used with @code{LC_ALL} can combine
+several locales, reflecting different locale settings for different
+categories. For example, you might want to use a U.S. locale with ISO
+A4 paper format, so you set @code{LANG} to @samp{en_US.UTF-8}, and
+@code{LC_PAPER} to @samp{de_DE.UTF-8}. In this case, the
+@code{LC_ALL}-style combined locale name is
+
+@smallexample
+LC_CTYPE=en_US.UTF-8;LC_TIME=en_US.UTF-8;LC_PAPER=de_DE.UTF-8;@dots{}
+@end smallexample
+
+followed by other category settings not shown here.
+
+@vindex LOCPATH
+The path used for finding locale data can be set using the
+@code{LOCPATH} environment variable. This variable lists the
+directories in which to search for locale definitions, separated by a
+colon @samp{:}.
+
+The default path for finding locale data is system specific. A typical
+value for the @code{LOCPATH} default is:
+
+@smallexample
+/usr/share/locale
+@end smallexample
+
+The value of @code{LOCPATH} is ignored by privileged programs for
+security reasons, and only the default directory is used.
+
+@node Locale Information, Formatting Numbers, Locale Names, Locales
@section Accessing Locale Information
There are several ways to access locale information. The simplest
--
From b76db403426d4978ca2e60998c6dc62668a3f998 Mon Sep 17 00:00:00 2001
From: Florian Weimer <fweimer@redhat.com>
Date: Wed, 28 May 2014 14:41:52 +0200
Subject: [PATCH] setlocale: Use the heap for the copy of the locale argument
This avoids alloca calls with potentially large arguments.
(cherry picked from commit d183645616b0533b3acee28f1a95570bffbdf50f)
---
ChangeLog | 5 +++++
locale/setlocale.c | 14 ++++++++++++--
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/locale/setlocale.c b/locale/setlocale.c
index b70fa6c..a4c5983 100644
--- a/locale/setlocale.c
+++ b/locale/setlocale.c
@@ -272,6 +272,8 @@ setlocale (int category, const char *locale)
of entries of the form `CATEGORY=VALUE'. */
const char *newnames[__LC_LAST];
struct __locale_data *newdata[__LC_LAST];
+ /* Copy of the locale argument, for in-place splitting. */
+ char *locale_copy = NULL;
/* Set all name pointers to the argument name. */
for (category = 0; category < __LC_LAST; ++category)
@@ -281,7 +283,13 @@ setlocale (int category, const char *locale)
if (__builtin_expect (strchr (locale, ';') != NULL, 0))
{
/* This is a composite name. Make a copy and split it up. */
- char *np = strdupa (locale);
+ locale_copy = strdup (locale);
+ if (__glibc_unlikely (locale_copy == NULL))
+ {
+ __libc_rwlock_unlock (__libc_setlocale_lock);
+ return NULL;
+ }
+ char *np = locale_copy;
char *cp;
int cnt;
@@ -299,6 +307,7 @@ setlocale (int category, const char *locale)
{
error_return:
__libc_rwlock_unlock (__libc_setlocale_lock);
+ free (locale_copy);
/* Bogus category name. */
ERROR_RETURN;
@@ -391,8 +400,9 @@ setlocale (int category, const char *locale)
/* Critical section left. */
__libc_rwlock_unlock (__libc_setlocale_lock);
- /* Free the resources (the locale path variable). */
+ /* Free the resources. */
free (locale_path);
+ free (locale_copy);
return composite;
}
--
1.7.1

View File

@ -1,174 +0,0 @@
From b9b6e3f01655942891bf4c66a2c5e8246cdad7e1 Mon Sep 17 00:00:00 2001
From: Carlos O'Donell <carlos@redhat.com>
Date: Wed, 19 Nov 2014 11:44:12 -0500
Subject: [PATCH 1/2] CVE-2014-7817: wordexp fails to honour WRDE_NOCMD.
The function wordexp() fails to properly handle the WRDE_NOCMD
flag when processing arithmetic inputs in the form of "$((... ``))"
where "..." can be anything valid. The backticks in the arithmetic
epxression are evaluated by in a shell even if WRDE_NOCMD forbade
command substitution. This allows an attacker to attempt to pass
dangerous commands via constructs of the above form, and bypass
the WRDE_NOCMD flag. This patch fixes this by checking for WRDE_NOCMD
in exec_comm(), the only place that can execute a shell. All other
checks for WRDE_NOCMD are superfluous and removed.
We expand the testsuite and add 3 new regression tests of roughly
the same form but with a couple of nested levels.
On top of the 3 new tests we add fork validation to the WRDE_NOCMD
testing. If any forks are detected during the execution of a wordexp()
call with WRDE_NOCMD, the test is marked as failed. This is slightly
heuristic since vfork might be used in the future, but it provides a
higher level of assurance that no shells were executed as part of
command substitution with WRDE_NOCMD in effect. In addition it doesn't
require libpthread or libdl, instead we use the public implementation
namespace function __register_atfork (already part of the public ABI
for libpthread).
Tested on x86_64 with no regressions.
Conflicts:
ChangeLog
NEWS
---
ChangeLog | 266 +++++++++++++++++++++++++++++++++++++++++++++++++++
NEWS | 10 ++
posix/wordexp-test.c | 44 +++++++++
posix/wordexp.c | 16 +---
4 files changed, 324 insertions(+), 12 deletions(-)
diff --git a/posix/wordexp-test.c b/posix/wordexp-test.c
index 4957006..bdd65e4 100644
--- a/posix/wordexp-test.c
+++ b/posix/wordexp-test.c
@@ -27,6 +27,25 @@
#define IFS " \n\t"
+extern void *__dso_handle __attribute__ ((__weak__, __visibility__ ("hidden")));
+extern int __register_atfork (void (*) (void), void (*) (void), void (*) (void), void *);
+
+static int __app_register_atfork (void (*prepare) (void), void (*parent) (void), void (*child) (void))
+{
+ return __register_atfork (prepare, parent, child,
+ &__dso_handle == NULL ? NULL : __dso_handle);
+}
+
+/* Number of forks seen. */
+static int registered_forks;
+
+/* For each fork increment the fork count. */
+static void
+register_fork (void)
+{
+ registered_forks++;
+}
+
struct test_case_struct
{
int retval;
@@ -206,6 +225,12 @@ struct test_case_struct
{ WRDE_SYNTAX, NULL, "$((2+))", 0, 0, { NULL, }, IFS },
{ WRDE_SYNTAX, NULL, "`", 0, 0, { NULL, }, IFS },
{ WRDE_SYNTAX, NULL, "$((010+4+))", 0, 0, { NULL }, IFS },
+ /* Test for CVE-2014-7817. We test 3 combinations of command
+ substitution inside an arithmetic expression to make sure that
+ no commands are executed and error is returned. */
+ { WRDE_CMDSUB, NULL, "$((`echo 1`))", WRDE_NOCMD, 0, { NULL, }, IFS },
+ { WRDE_CMDSUB, NULL, "$((1+`echo 1`))", WRDE_NOCMD, 0, { NULL, }, IFS },
+ { WRDE_CMDSUB, NULL, "$((1+$((`echo 1`))))", WRDE_NOCMD, 0, { NULL, }, IFS },
{ -1, NULL, NULL, 0, 0, { NULL, }, IFS },
};
@@ -258,6 +283,15 @@ main (int argc, char *argv[])
return -1;
}
+ /* If we are not allowed to do command substitution, we install
+ fork handlers to verify that no forks happened. No forks should
+ happen at all if command substitution is disabled. */
+ if (__app_register_atfork (register_fork, NULL, NULL) != 0)
+ {
+ printf ("Failed to register fork handler.\n");
+ return -1;
+ }
+
for (test = 0; test_case[test].retval != -1; test++)
if (testit (&test_case[test]))
++fail;
@@ -367,6 +401,9 @@ testit (struct test_case_struct *tc)
printf ("Test %d (%s): ", ++tests, tc->words);
+ if (tc->flags & WRDE_NOCMD)
+ registered_forks = 0;
+
if (tc->flags & WRDE_APPEND)
{
/* initial wordexp() call, to be appended to */
@@ -378,6 +415,13 @@ testit (struct test_case_struct *tc)
}
retval = wordexp (tc->words, &we, tc->flags);
+ if ((tc->flags & WRDE_NOCMD)
+ && (registered_forks > 0))
+ {
+ printf ("FAILED fork called for WRDE_NOCMD\n");
+ return 1;
+ }
+
if (tc->flags & WRDE_DOOFFS)
start_offs = sav_we.we_offs;
diff --git a/posix/wordexp.c b/posix/wordexp.c
index 366ec18..36a1367 100644
--- a/posix/wordexp.c
+++ b/posix/wordexp.c
@@ -893,6 +893,10 @@ exec_comm (char *comm, char **word, size_t *word_length, size_t *max_length,
pid_t pid;
int noexec = 0;
+ /* Do nothing if command substitution should not succeed. */
+ if (flags & WRDE_NOCMD)
+ return WRDE_CMDSUB;
+
/* Don't fork() unless necessary */
if (!comm || !*comm)
return 0;
@@ -2082,9 +2086,6 @@ parse_dollars (char **word, size_t *word_length, size_t *max_length,
}
}
- if (flags & WRDE_NOCMD)
- return WRDE_CMDSUB;
-
(*offset) += 2;
return parse_comm (word, word_length, max_length, words, offset, flags,
quoted? NULL : pwordexp, ifs, ifs_white);
@@ -2196,9 +2197,6 @@ parse_dquote (char **word, size_t *word_length, size_t *max_length,
break;
case '`':
- if (flags & WRDE_NOCMD)
- return WRDE_CMDSUB;
-
++(*offset);
error = parse_backtick (word, word_length, max_length, words,
offset, flags, NULL, NULL, NULL);
@@ -2357,12 +2355,6 @@ wordexp (const char *words, wordexp_t *pwordexp, int flags)
break;
case '`':
- if (flags & WRDE_NOCMD)
- {
- error = WRDE_CMDSUB;
- goto do_error;
- }
-
++words_offset;
error = parse_backtick (&word, &word_length, &max_length, words,
&words_offset, flags, pwordexp, ifs,
--
2.2.1

View File

@ -1,32 +0,0 @@
From c9e9c2e4b1bdd880e11ad1d0756da87634456b95 Mon Sep 17 00:00:00 2001
From: Florian Weimer <fweimer@redhat.com>
Date: Mon, 15 Dec 2014 17:41:13 +0100
Subject: [PATCH] Avoid infinite loop in nss_dns getnetbyname [BZ #17630]
Conflicts:
ChangeLog
NEWS
---
ChangeLog | 14 ++++++++++++++
NEWS | 8 ++++++++
resolv/nss_dns/dns-network.c | 4 ++--
3 files changed, 24 insertions(+), 2 deletions(-)
diff --git a/resolv/nss_dns/dns-network.c b/resolv/nss_dns/dns-network.c
index 13ad38c..1993ec1 100644
--- a/resolv/nss_dns/dns-network.c
+++ b/resolv/nss_dns/dns-network.c
@@ -398,8 +398,8 @@ getanswer_r (const querybuf *answer, int anslen, struct netent *result,
case BYNAME:
{
- char **ap = result->n_aliases++;
- while (*ap != NULL)
+ char **ap;
+ for (ap = result->n_aliases; *ap != NULL; ++ap)
{
/* Check each alias name for being of the forms:
4.3.2.1.in-addr.arpa = net 1.2.3.4
--
2.2.1

View File

@ -1,105 +0,0 @@
From 18d9cd1d9d95503074db705686d0236c99db5d00 Mon Sep 17 00:00:00 2001
From: Paul Pluzhnikov <ppluzhnikov@google.com>
Date: Fri, 6 Feb 2015 00:30:42 -0500
Subject: [PATCH 2/2] CVE-2015-1472: wscanf allocates too little memory
BZ #16618
Under certain conditions wscanf can allocate too little memory for the
to-be-scanned arguments and overflow the allocated buffer. The
implementation now correctly computes the required buffer size when
using malloc.
A regression test was added to tst-sscanf.
Conflicts:
ChangeLog
NEWS
---
ChangeLog | 133 ++++++++++++++++++++++++++++++++++++++++++++++
NEWS | 44 +++++++++++++++
stdio-common/tst-sscanf.c | 33 ++++++++++++
stdio-common/vfscanf.c | 12 ++---
4 files changed, 216 insertions(+), 6 deletions(-)
diff --git a/stdio-common/tst-sscanf.c b/stdio-common/tst-sscanf.c
index 1214c7d..c62bee6 100644
--- a/stdio-common/tst-sscanf.c
+++ b/stdio-common/tst-sscanf.c
@@ -232,5 +232,38 @@ main (void)
}
}
+ /* BZ #16618
+ The test will segfault during SSCANF if the buffer overflow
+ is not fixed. The size of `s` is such that it forces the use
+ of malloc internally and this triggers the incorrect computation.
+ Thus the value for SIZE is arbitrariy high enough that malloc
+ is used. */
+ {
+#define SIZE 131072
+ CHAR *s = malloc ((SIZE + 1) * sizeof (*s));
+ if (s == NULL)
+ abort ();
+ for (size_t i = 0; i < SIZE; i++)
+ s[i] = L('0');
+ s[SIZE] = L('\0');
+ int i = 42;
+ /* Scan multi-digit zero into `i`. */
+ if (SSCANF (s, L("%d"), &i) != 1)
+ {
+ printf ("FAIL: bug16618: SSCANF did not read one input item.\n");
+ result = 1;
+ }
+ if (i != 0)
+ {
+ printf ("FAIL: bug16618: Value of `i` was not zero as expected.\n");
+ result = 1;
+ }
+ free (s);
+ if (result != 1)
+ printf ("PASS: bug16618: Did not crash.\n");
+#undef SIZE
+ }
+
+
return result;
}
diff --git a/stdio-common/vfscanf.c b/stdio-common/vfscanf.c
index 2e1e91a..d7a18e3 100644
--- a/stdio-common/vfscanf.c
+++ b/stdio-common/vfscanf.c
@@ -272,9 +272,10 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
if (__builtin_expect (wpsize == wpmax, 0)) \
{ \
CHAR_T *old = wp; \
- size_t newsize = (UCHAR_MAX + 1 > 2 * wpmax \
- ? UCHAR_MAX + 1 : 2 * wpmax); \
- if (use_malloc || !__libc_use_alloca (newsize)) \
+ bool fits = __glibc_likely (wpmax <= SIZE_MAX / sizeof (CHAR_T) / 2); \
+ size_t wpneed = MAX (UCHAR_MAX + 1, 2 * wpmax); \
+ size_t newsize = fits ? wpneed * sizeof (CHAR_T) : SIZE_MAX; \
+ if (!__libc_use_alloca (newsize)) \
{ \
wp = realloc (use_malloc ? wp : NULL, newsize); \
if (wp == NULL) \
@@ -286,14 +287,13 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
} \
if (! use_malloc) \
MEMCPY (wp, old, wpsize); \
- wpmax = newsize; \
+ wpmax = wpneed; \
use_malloc = true; \
} \
else \
{ \
size_t s = wpmax * sizeof (CHAR_T); \
- wp = (CHAR_T *) extend_alloca (wp, s, \
- newsize * sizeof (CHAR_T)); \
+ wp = (CHAR_T *) extend_alloca (wp, s, newsize); \
wpmax = s / sizeof (CHAR_T); \
if (old != NULL) \
MEMCPY (wp, old, wpsize); \
--
2.2.1

View File

@ -3,16 +3,11 @@
# Maintainer: CRUX System Team, core-ports at crux dot nu
name=glibc
version=2.19
release=5
version=2.21
release=1
source=(http://ftp.gnu.org/gnu/glibc/glibc-$version.tar.xz \
http://crux.nu/files/distfiles/kernel-headers-3.12.tar.bz2 \
$name-$version-multilib-dirs.patch \
CVE-2014-0475.patch iconv-gconv_trans.c.patch \
CVE-2012-3406-Stack-overflow-in-vfprintf-BZ-16617.patch \
CVE-2014-7817-wordexp-fails-to-honour-WRDE_NOCMD.patch \
CVE-2014-9402-Avoid-infinite-loop-in-nss_dns-getnetbyname.patch \
CVE-2015-1472-wscanf-allocates-too-little-memory.patch \
$name-2.20-multilib-dirs.patch \
hosts resolv.conf nsswitch.conf host.conf ld.so.conf)
build() {
@ -21,37 +16,28 @@ build() {
cp -r $SRC/kernel-headers-3.12/include $PKG/usr
chown root:root $PKG/usr
patch -p1 -d $SRC/$name-$version -i $SRC/$name-$version-multilib-dirs.patch
patch -p1 -d $SRC/$name-$version -i $SRC/CVE-2014-0475.patch
patch -p1 -d $SRC/$name-$version -i $SRC/iconv-gconv_trans.c.patch
patch -p1 -d $SRC/$name-$version -i $SRC/CVE-2012-3406-Stack-overflow-in-vfprintf-BZ-16617.patch
patch -p1 -d $SRC/$name-$version -i $SRC/CVE-2014-7817-wordexp-fails-to-honour-WRDE_NOCMD.patch
patch -p1 -d $SRC/$name-$version -i $SRC/CVE-2014-9402-Avoid-infinite-loop-in-nss_dns-getnetbyname.patch
patch -p1 -d $SRC/$name-$version -i $SRC/CVE-2015-1472-wscanf-allocates-too-little-memory.patch
patch -p1 -d $SRC/$name-$version -i $SRC/$name-2.20-multilib-dirs.patch
mkdir $SRC/build
cd $SRC/build
../$name-$version/configure --prefix=/usr \
--libexecdir=/usr/lib \
--with-headers=$PKG/usr/include \
--enable-kernel=3.10 \
--enable-kernel=3.12 \
--enable-add-ons \
--disable-profile \
--without-gd \
--enable-obsolete-rpc \
--enable-multi-arch \
--enable-static-nss
--enable-obsolete-rpc --enable-multi-arch
make
#make check
make install_root=$PKG install
install -m 0644 $SRC/$name-$version/nscd/nscd.conf $PKG/etc
install -d $PKG/var/{db,run}/nscd
install -m 0644 $SRC/{hosts,resolv.conf,nsswitch.conf,host.conf,ld.so.conf} $PKG/etc
cp $SRC/{hosts,resolv.conf,nsswitch.conf,host.conf,ld.so.conf} $PKG/etc
ln -sf ../usr/share/zoneinfo/UTC $PKG/etc/localtime
mkdir -p $PKG/etc/ld.so.conf.d $PKG/usr/lib/locale
touch $PKG/etc/ld.so.cache
rm -rf $PKG/usr/{share/{info,locale},bin/tzselect,sbin/z{dump,ic}}
rm -rf $PKG/usr/share/{info,locale} \
$PKG/usr/bin/tzselect \
$PKG/usr/sbin/z{dump,ic}
}

View File

@ -1,43 +0,0 @@
diff -rupN glibc-2.18.orig/sysdeps/gnu/configure glibc-2.18/sysdeps/gnu/configure
--- glibc-2.18.orig/sysdeps/gnu/configure 2013-08-13 09:25:25.678263957 +0200
+++ glibc-2.18/sysdeps/gnu/configure 2013-08-13 09:34:04.270306644 +0200
@@ -14,14 +14,14 @@ case "$prefix" in
test -n "$libc_cv_slibdir" || \
case $machine in
sparc/sparc64 | x86_64* | powerpc/powerpc64 | s390/s390-64)
- libc_cv_slibdir=/lib64
+ libc_cv_slibdir=/lib
case $machine in
s390/s390-64)
libc_cv_rtlddir=/lib
;;
esac
if test "$libdir" = '${exec_prefix}/lib'; then
- libdir='${exec_prefix}/lib64';
+ libdir='${exec_prefix}/lib';
# Locale data can be shared between 32bit and 64bit libraries
libc_cv_localedir='${exec_prefix}/lib/locale'
fi
diff -rupN glibc-2.18.orig/sysdeps/unix/sysv/linux/x86_64/ldconfig.h glibc-2.18/sysdeps/unix/sysv/linux/x86_64/ldconfig.h
--- glibc-2.18.orig/sysdeps/unix/sysv/linux/x86_64/ldconfig.h 2013-08-13 09:25:25.611261622 +0200
+++ glibc-2.18/sysdeps/unix/sysv/linux/x86_64/ldconfig.h 2013-08-13 09:27:16.032107337 +0200
@@ -18,9 +18,9 @@
#include <sysdeps/generic/ldconfig.h>
#define SYSDEP_KNOWN_INTERPRETER_NAMES \
- { "/lib/ld-linux.so.2", FLAG_ELF_LIBC6 }, \
+ { "/lib32/ld-linux.so.2", FLAG_ELF_LIBC6 }, \
{ "/libx32/ld-linux-x32.so.2", FLAG_ELF_LIBC6 }, \
- { "/lib64/ld-linux-x86-64.so.2", FLAG_ELF_LIBC6 },
+ { "/lib/ld-linux-x86-64.so.2", FLAG_ELF_LIBC6 },
#define SYSDEP_KNOWN_LIBRARY_NAMES \
{ "libc.so.6", FLAG_ELF_LIBC6 }, \
{ "libm.so.6", FLAG_ELF_LIBC6 },
diff -rupN glibc-2.18.orig/sysdeps/unix/sysv/linux/x86_64/ldd-rewrite.sed glibc-2.18/sysdeps/unix/sysv/linux/x86_64/ldd-rewrite.sed
--- glibc-2.18.orig/sysdeps/unix/sysv/linux/x86_64/ldd-rewrite.sed 2013-08-13 09:25:25.611261622 +0200
+++ glibc-2.18/sysdeps/unix/sysv/linux/x86_64/ldd-rewrite.sed 2013-08-13 09:32:04.476137395 +0200
@@ -1,3 +1,3 @@
/LD_TRACE_LOADED_OBJECTS=1/a\
add_env="$add_env LD_LIBRARY_VERSION=\\$verify_out"
-s_^\(RTLDLIST=\)\(.*lib\)\(\|64\|x32\)\(/[^/]*\)\(-x86-64\|-x32\)\(\.so\.[0-9.]*\)[ ]*$_\1"\2\4\6 \264\4-x86-64\6 \2x32\4-x32\6"_
+s_^\(RTLDLIST=\)\(.*lib\)\(\|64\|x32\)\(/[^/]*\)\(-x86-64\|-x32\)\(\.so\.[0-9.]*\)[ ]*$_\1"\232\4\6 \2\4-x86-64\6 \2x32\4-x32\6"_

View File

@ -0,0 +1,40 @@
diff -rupN glibc-2.20-orig/sysdeps/unix/sysv/linux/x86_64/64/configure glibc-2.20/sysdeps/unix/sysv/linux/x86_64/64/configure
--- glibc-2.20-orig/sysdeps/unix/sysv/linux/x86_64/64/configure 2014-09-07 22:22:21.455309835 +0200
+++ glibc-2.20/sysdeps/unix/sysv/linux/x86_64/64/configure 2014-09-07 22:39:12.718456952 +0200
@@ -4,10 +4,10 @@
test -n "$libc_cv_slibdir" ||
case "$prefix" in
/usr | /usr/)
- libc_cv_slibdir=/lib64
- libc_cv_rtlddir=/lib64
+ libc_cv_slibdir=/lib
+ libc_cv_rtlddir=/lib
if test "$libdir" = '${exec_prefix}/lib'; then
- libdir='${exec_prefix}/lib64';
+ libdir='${exec_prefix}/lib';
# Locale data can be shared between 32-bit and 64-bit libraries.
libc_cv_localedir='${exec_prefix}/lib/locale'
fi
diff -rupN glibc-2.20-orig/sysdeps/unix/sysv/linux/x86_64/ldconfig.h glibc-2.20/sysdeps/unix/sysv/linux/x86_64/ldconfig.h
--- glibc-2.20-orig/sysdeps/unix/sysv/linux/x86_64/ldconfig.h 2014-09-07 22:22:21.456309870 +0200
+++ glibc-2.20/sysdeps/unix/sysv/linux/x86_64/ldconfig.h 2014-09-07 22:38:43.949456973 +0200
@@ -18,9 +18,9 @@
#include <sysdeps/generic/ldconfig.h>
#define SYSDEP_KNOWN_INTERPRETER_NAMES \
- { "/lib/ld-linux.so.2", FLAG_ELF_LIBC6 }, \
+ { "/lib32/ld-linux.so.2", FLAG_ELF_LIBC6 }, \
{ "/libx32/ld-linux-x32.so.2", FLAG_ELF_LIBC6 }, \
- { "/lib64/ld-linux-x86-64.so.2", FLAG_ELF_LIBC6 },
+ { "/lib/ld-linux-x86-64.so.2", FLAG_ELF_LIBC6 },
#define SYSDEP_KNOWN_LIBRARY_NAMES \
{ "libc.so.6", FLAG_ELF_LIBC6 }, \
{ "libm.so.6", FLAG_ELF_LIBC6 },
diff -rupN glibc-2.20-orig/sysdeps/unix/sysv/linux/x86_64/ldd-rewrite.sed glibc-2.20/sysdeps/unix/sysv/linux/x86_64/ldd-rewrite.sed
--- glibc-2.20-orig/sysdeps/unix/sysv/linux/x86_64/ldd-rewrite.sed 2014-09-07 22:22:21.456309870 +0200
+++ glibc-2.20/sysdeps/unix/sysv/linux/x86_64/ldd-rewrite.sed 2014-09-07 22:38:43.949456973 +0200
@@ -1,3 +1,3 @@
/LD_TRACE_LOADED_OBJECTS=1/a\
add_env="$add_env LD_LIBRARY_VERSION=\\$verify_out"
-s_^\(RTLDLIST=\)\(.*lib\)\(\|64\|x32\)\(/[^/]*\)\(-x86-64\|-x32\)\(\.so\.[0-9.]*\)[ ]*$_\1"\2\4\6 \264\4-x86-64\6 \2x32\4-x32\6"_
+s_^\(RTLDLIST=\)\(.*lib\)\(\|64\|x32\)\(/[^/]*\)\(-x86-64\|-x32\)\(\.so\.[0-9.]*\)[ ]*$_\1"\232\4\6 \2\4-x86-64\6 \2x32\4-x32\6"_