+++ /dev/null
-Patch from https://bugzilla.redhat.com/show_bug.cgi?id=1157689
-
-Signed-off-by: Gustavo Zacarias <gustavo@zacarias.com.ar>
-
-WARNING !!! WARNING !!! WARNING !!! WARNING !!! WARNING !!! WARNING !!!
-EMBARGOED !!! EMBARGOED !!! EMARGOED !!! EMBARGOED !!! EMBARGOED !!!
-SECURITY !!! SECURITY !!! SECURITY !!! SECURITY !!! SECURITY !!!
-
-CVE-2014-7817:
-
-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 parse_arith(). The patch also hardens parse_backticks() and
-parse_comm() to check for WRDE_NOCMD flag and return an error instead
-of ever running a shell.
-
-We expand the testsuite and add 3 new regression tests of roughtly
-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, 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.
-
-2014-10-27 Carlos O'Donell <carlos@redhat.com>
-
- * wordexp-test.c (__dso_handle): Add prototype.
- (__register_atfork): Likewise.
- (__app_register_atfork): New function.
- (registered_forks): New global.
- (register_fork): New function.
- (test_case): Add 3 new tests for WRDE_CMDSUB.
- (main): Call __app_register_atfork.
- (testit): If WRDE_NOCMD set registered_forks to zero, run test, and
- if fork count is non-zero fail the test.
- * posix/wordexp.c (parse_arith): Return WRDE_NOCMD if WRDE_NOCMD flag
- is set and parsing '`'.
- (parse_comm): Return WRDE_NOCMD if WRDE_NOCMD flag is set.
- (parse_backtick): Return WRDE_NOCMD if WRDE_NOCMD flag is set and
- parsing '`'.
-
-diff --git a/posix/wordexp-test.c b/posix/wordexp-test.c
-index 4957006..5ce2a1b 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 b6b65dd..d6a158f 100644
---- a/posix/wordexp.c
-+++ b/posix/wordexp.c
-@@ -693,6 +693,12 @@ parse_arith (char **word, size_t *word_length, size_t *max_length,
- break;
-
- case '`':
-+ if (flags & WRDE_NOCMD)
-+ {
-+ free (expr);
-+ return WRDE_NOCMD;
-+ }
-+
- (*offset)++;
- error = parse_backtick (&expr, &expr_length, &expr_maxlen,
- words, offset, flags, NULL, NULL, NULL);
-@@ -1144,6 +1150,10 @@ parse_comm (char **word, size_t *word_length, size_t *max_length,
- size_t comm_maxlen;
- char *comm = w_newword (&comm_length, &comm_maxlen);
-
-+ /* Do nothing if command substitution should not succeed. */
-+ if (flags & WRDE_NOCMD)
-+ return WRDE_CMDSUB;
-+
- for (; words[*offset]; ++(*offset))
- {
- switch (words[*offset])
-@@ -2121,6 +2131,9 @@ parse_backtick (char **word, size_t *word_length, size_t *max_length,
- switch (words[*offset])
- {
- case '`':
-+ if (flags & WRDE_NOCMD)
-+ return WRDE_NOCMD;
-+
- /* Go -- give the script to the shell */
- error = exec_comm (comm, word, word_length, max_length, flags,
- pwordexp, ifs, ifs_white);
+++ /dev/null
-Fix CVE-2015-1472 - heap buffer overflow in wscanf
-Backport from upstream:
-https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=5bd80bfe9ca0d955bfbbc002781bc7b01b6bcb06
-See: https://bugzilla.redhat.com/show_bug.cgi?id=1188235
-
-Signed-off-by: Gustavo Zacarias <gustavo@zacarias.com.ar>
-
-diff --git a/stdio-common/tst-sscanf.c b/stdio-common/tst-sscanf.c
-index aece3f2..8a2eb9e 100644
---- a/stdio-common/tst-sscanf.c
-+++ b/stdio-common/tst-sscanf.c
-@@ -233,5 +233,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 cd129a8..0e204e7 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 (__glibc_unlikely (wpsize == wpmax)) \
- { \
- 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); \
---
-1.9.4
-