diff --git a/SOURCES/glibc-rh1170118-CVE-2014-7817.patch b/SOURCES/glibc-rh1170118-CVE-2014-7817.patch
new file mode 100644
index 0000000..1accbf3
--- /dev/null
+++ b/SOURCES/glibc-rh1170118-CVE-2014-7817.patch
@@ -0,0 +1,163 @@
+#
+# commit a39208bd7fb76c1b01c127b4c61f9bfd915bfe7c
+# Author: Carlos O'Donell <carlos@redhat.com>
+# Date:   Wed Nov 19 11:44:12 2014 -0500
+# 
+#     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.
+# 
+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 b6b65dd..26f3a26 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,
diff --git a/SOURCES/glibc-rh1170187.patch b/SOURCES/glibc-rh1170187.patch
new file mode 100644
index 0000000..4ea2762
--- /dev/null
+++ b/SOURCES/glibc-rh1170187.patch
@@ -0,0 +1,202 @@
+commit e276f4f310a89a925dd59e583f7a1bef2114d9a7
+Author: Siddhesh Poyarekar <siddhesh@redhat.com>
+Date:   Tue Nov 25 21:15:16 2014 +0530
+
+    ftell: seek to end only when there are unflushed bytes (BZ #17647)
+    
+    Currently we seek to end of file if there are unflushed writes or the
+    stream is in write mode, to get the current offset for writing in
+    append mode, which is the end of file.  The latter case (i.e. stream
+    is in write mode, but no unflushed writes) is unnecessary since it
+    will only happen when the stream has just been flushed, in which case
+    the recorded offset ought to be reliable.
+    
+    Removing that case lets ftell give the correct offset when it follows
+    an ftruncate.  The latter truncates the file, but does not change the
+    file position, due to which it is permissible to call ftell without an
+    intervening fseek call.
+    
+    Tested on x86_64 to verify that the added test case fails without the
+    patch and succeeds with it, and that there are no additional
+    regressions due to it.
+    
+    	[BZ #17647]
+    	* libio/fileops.c (do_ftell): Seek only when there are
+    	unflushed writes.
+    	* libio/wfileops.c (do_ftell_wide): Likewise.
+    	* libio/tst-ftell-active-handler.c (do_ftruncate_test): New
+    	test case.
+    	(do_one_test): Call it.
+
+diff --git a/libio/fileops.c b/libio/fileops.c
+index e0d7b76..1fc5719 100644
+--- a/libio/fileops.c
++++ b/libio/fileops.c
+@@ -943,15 +943,14 @@ do_ftell (_IO_FILE *fp)
+      yet.  */
+   if (fp->_IO_buf_base != NULL)
+     {
+-      bool was_writing = (fp->_IO_write_ptr > fp->_IO_write_base
+-			  || _IO_in_put_mode (fp));
++      bool unflushed_writes = (fp->_IO_write_ptr > fp->_IO_write_base);
+ 
+       bool append_mode = (fp->_flags & _IO_IS_APPENDING) == _IO_IS_APPENDING;
+ 
+       /* When we have unflushed writes in append mode, seek to the end of the
+ 	 file and record that offset.  This is the only time we change the file
+ 	 stream state and it is safe since the file handle is active.  */
+-      if (was_writing && append_mode)
++      if (unflushed_writes && append_mode)
+ 	{
+ 	  result = _IO_SYSSEEK (fp, 0, _IO_seek_end);
+ 	  if (result == _IO_pos_BAD)
+@@ -961,7 +960,7 @@ do_ftell (_IO_FILE *fp)
+ 	}
+ 
+       /* Adjust for unflushed data.  */
+-      if (!was_writing)
++      if (!unflushed_writes)
+ 	offset -= fp->_IO_read_end - fp->_IO_read_ptr;
+       /* We don't trust _IO_read_end to represent the current file offset when
+ 	 writing in append mode because the value would have to be shifted to
+diff --git a/libio/tst-ftell-active-handler.c b/libio/tst-ftell-active-handler.c
+index e9dc7b3..9f23c55 100644
+--- a/libio/tst-ftell-active-handler.c
++++ b/libio/tst-ftell-active-handler.c
+@@ -88,6 +88,95 @@ static size_t file_len;
+ typedef int (*fputs_func_t) (const void *data, FILE *fp);
+ fputs_func_t fputs_func;
+ 
++/* This test verifies that the offset reported by ftell is correct after the
++   file is truncated using ftruncate.  ftruncate does not change the file
++   offset on truncation and hence, SEEK_CUR should continue to point to the
++   old offset and not be changed to the new offset.  */
++static int
++do_ftruncate_test (const char *filename)
++{
++  FILE *fp = NULL;
++  int fd;
++  int ret = 0;
++  struct test
++    {
++      const char *mode;
++      int fd_mode;
++    } test_modes[] = {
++	  {"r+", O_RDWR},
++	  {"w", O_WRONLY},
++	  {"w+", O_RDWR},
++	  {"a", O_WRONLY},
++	  {"a+", O_RDWR}
++    };
++
++  for (int j = 0; j < 2; j++)
++    {
++      for (int i = 0; i < sizeof (test_modes) / sizeof (struct test); i++)
++	{
++	  int fileret;
++	  printf ("\tftruncate: %s (file, \"%s\"): ",
++		  j == 0 ? "fopen" : "fdopen",
++		  test_modes[i].mode);
++
++	  if (j == 0)
++	    fileret = get_handles_fopen (filename, fd, fp, test_modes[i].mode);
++	  else
++	    fileret = get_handles_fdopen (filename, fd, fp,
++					  test_modes[i].fd_mode,
++					  test_modes[i].mode);
++
++	  if (fileret != 0)
++	    return fileret;
++
++	  /* Write some data.  */
++	  size_t written = fputs_func (data, fp);
++
++	  if (written == EOF)
++	    {
++	      printf ("fputs[1] failed to write data\n");
++	      ret |= 1;
++	    }
++
++	  /* Record the offset.  */
++	  long offset = ftell (fp);
++
++	  /* Flush data to allow switching active handles.  */
++	  if (fflush (fp))
++	    {
++	      printf ("Flush failed: %m\n");
++	      ret |= 1;
++	    }
++
++	  /* Now truncate the file.  */
++	  if (ftruncate (fd, 0) != 0)
++	    {
++	      printf ("Failed to truncate file: %m\n");
++	      ret |= 1;
++	    }
++
++	  /* ftruncate does not change the offset, so there is no need to call
++	     anything to be able to switch active handles.  */
++	  long new_offset = ftell (fp);
++
++	  /* The offset should remain unchanged since ftruncate does not update
++	     it.  */
++	  if (offset != new_offset)
++	    {
++	      printf ("Incorrect offset.  Expected %zu, but got %ld\n",
++		      offset, new_offset);
++
++	      ret |= 1;
++	    }
++	  else
++	    printf ("offset = %ld\n", offset);
++
++	  fclose (fp);
++	}
++    }
++
++  return ret;
++}
+ /* Test that ftell output after a rewind is correct.  */
+ static int
+ do_rewind_test (const char *filename)
+@@ -481,6 +570,7 @@ do_one_test (const char *filename)
+   ret |= do_write_test (filename);
+   ret |= do_append_test (filename);
+   ret |= do_rewind_test (filename);
++  ret |= do_ftruncate_test (filename);
+ 
+   return ret;
+ }
+diff --git a/libio/wfileops.c b/libio/wfileops.c
+index 6a088b1..71281c1 100644
+--- a/libio/wfileops.c
++++ b/libio/wfileops.c
+@@ -626,16 +626,15 @@ do_ftell_wide (_IO_FILE *fp)
+       const wchar_t *wide_read_base;
+       const wchar_t *wide_read_ptr;
+       const wchar_t *wide_read_end;
+-      bool was_writing = ((fp->_wide_data->_IO_write_ptr
+-			   > fp->_wide_data->_IO_write_base)
+-			  || _IO_in_put_mode (fp));
++      bool unflushed_writes = (fp->_wide_data->_IO_write_ptr
++			       > fp->_wide_data->_IO_write_base);
+ 
+       bool append_mode = (fp->_flags & _IO_IS_APPENDING) == _IO_IS_APPENDING;
+ 
+       /* When we have unflushed writes in append mode, seek to the end of the
+ 	 file and record that offset.  This is the only time we change the file
+ 	 stream state and it is safe since the file handle is active.  */
+-      if (was_writing && append_mode)
++      if (unflushed_writes && append_mode)
+ 	{
+ 	  result = _IO_SYSSEEK (fp, 0, _IO_seek_end);
+ 	  if (result == _IO_pos_BAD)
+@@ -674,7 +673,7 @@ do_ftell_wide (_IO_FILE *fp)
+       struct _IO_codecvt *cv = fp->_codecvt;
+       int clen = (*cv->__codecvt_do_encoding) (cv);
+ 
+-      if (!was_writing)
++      if (!unflushed_writes)
+ 	{
+ 	  if (clen > 0)
+ 	    {
diff --git a/SPECS/glibc.spec b/SPECS/glibc.spec
index 763be2e..d337dc4 100644
--- a/SPECS/glibc.spec
+++ b/SPECS/glibc.spec
@@ -1,6 +1,6 @@
 %define glibcsrcdir glibc-2.17-c758a686
 %define glibcversion 2.17
-%define glibcrelease 55%{?dist}.1
+%define glibcrelease 55%{?dist}.3
 ##############################################################################
 # If run_glibc_tests is zero then tests are not run for the build.
 # You must always set run_glibc_tests to one for production builds.
@@ -320,6 +320,9 @@ Patch1063: %{name}-rh1074410.patch
 Patch1509: %{name}-rh1133811-2.patch
 Patch1510: %{name}-rh1133811-3.patch
 
+# Upstream CVE-2014-7817.
+Patch1511: %{name}-rh1170118-CVE-2014-7817.patch
+
 ##############################################################################
 #
 # Patches submitted, but not yet approved upstream.
@@ -359,6 +362,8 @@ Patch2052: %{name}-rh1048123.patch
 # Upstream BZ 16680
 Patch2053: %{name}-rh1074410-2.patch
 
+Patch2065: %{name}-rh1170187.patch
+
 ##############################################################################
 # End of glibc patches.
 ##############################################################################
@@ -756,6 +761,8 @@ package or when debugging this package.
 %patch0061 -p1
 %patch1509 -p1
 %patch1510 -p1
+%patch2065 -p1
+%patch1511 -p1
 
 ##############################################################################
 # %%prep - Additional prep required...
@@ -1811,6 +1818,12 @@ rm -f *.filelist*
 %endif
 
 %changelog
+* Fri Dec  5 2014 Carlos O'Donell <carlos@redhat.com> - 2.17-55.3
+- Fix wordexp() to honour WRDE_NOCMD (CVE-2014-7817, #1170118)
+
+* Thu Dec  4 2014 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.17-55.2
+- ftell: seek to end only when there are unflushed bytes (#1170187).
+
 * Tue Aug 26 2014 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.17-55.1
 - Remove gconv transliteration loadable modules support (CVE-2014-5119,
   #1133811).