From 901d7989466218970e7e8364ab73dd5cd10c6e08 Mon Sep 17 00:00:00 2001 From: Siddhesh Poyarekar Date: Tue, 25 Jun 2013 19:51:23 +0530 Subject: [PATCH] backport multiple fixes from 2.18 - Preserve errno across _PC_CHOWN_RESTRICTED call on XFS (#977870). - Remove PIPE_BUF Linux-specific code (#977872). - Fix FPE in memusagestat when malloc utilization is zero (#977874). - Accept leading and trailing spaces in getdate input string (#977875). --- glibc-rh977870.patch | 67 +++++++++++ glibc-rh977872.patch | 268 +++++++++++++++++++++++++++++++++++++++++++ glibc-rh977874.patch | 148 ++++++++++++++++++++++++ glibc-rh977875.patch | 96 ++++++++++++++++ glibc.spec | 16 ++- 5 files changed, 594 insertions(+), 1 deletion(-) create mode 100644 glibc-rh977870.patch create mode 100644 glibc-rh977872.patch create mode 100644 glibc-rh977874.patch create mode 100644 glibc-rh977875.patch diff --git a/glibc-rh977870.patch b/glibc-rh977870.patch new file mode 100644 index 0000000..5f441db --- /dev/null +++ b/glibc-rh977870.patch @@ -0,0 +1,67 @@ +commit d755bba40f880c01ced8740a26fecc85534454b9 +Author: Siddhesh Poyarekar +Date: Wed Apr 3 10:56:45 2013 +0530 + + Preserve errno across _PC_CHOWN_RESTRICTED call on XFS + + Fix BZ #15305. + + On kernel versions earlier than 2.6.29, the Linux kernel exported a + sysctl called restrict_chown for xfs, which could be used to allow + chown to users other than the owner. 2.6.29 removed this support, + causing the open_not_cancel_2 to fail and thus modify errno. The fix + is to save and restore errno so that the caller sees it as unmodified. + + Additionally, since the code to check the sysctl is not useful on + newer kernels, we add an ifdef so that in future the code block gets + rmeoved completely. + +diff --git a/sysdeps/unix/sysv/linux/kernel-features.h b/sysdeps/unix/sysv/linux/kernel-features.h +index 8fdff7e..ccd4c59 100644 +--- a/sysdeps/unix/sysv/linux/kernel-features.h ++++ b/sysdeps/unix/sysv/linux/kernel-features.h +@@ -221,3 +221,9 @@ + #if defined __x86_64__ && __LINUX_KERNEL_VERSION >= 0x030100 + # define __ASSUME_GETCPU_SYSCALL 1 + #endif ++ ++/* 2.6.29 removed the XFS restricted_chown sysctl, so it is pointless looking ++ for it in newer kernels. */ ++#if __LINUX_KERNEL_VERSION >= 0x02061d ++# define __ASSUME_XFS_RESTRICTED_CHOWN 1 ++#endif +diff --git a/sysdeps/unix/sysv/linux/pathconf.c b/sysdeps/unix/sysv/linux/pathconf.c +index de91a45..723d234 100644 +--- a/sysdeps/unix/sysv/linux/pathconf.c ++++ b/sysdeps/unix/sysv/linux/pathconf.c +@@ -289,11 +289,16 @@ __statfs_chown_restricted (int result, const struct statfs *fsbuf) + return -1; + } + ++#if __ASSUME_XFS_RESTRICTED_CHOWN ++ return 1; ++#else + int fd; ++ int save_errno; + long int retval = 1; + switch (fsbuf->f_type) + { + case XFS_SUPER_MAGIC: ++ save_errno = errno; + /* Read the value from /proc/sys/fs/xfs/restrict_chown. If we cannot + read it default to assume the restriction is in place. */ + fd = open_not_cancel_2 ("/proc/sys/fs/xfs/restrict_chown", O_RDONLY); +@@ -306,6 +311,7 @@ __statfs_chown_restricted (int result, const struct statfs *fsbuf) + + close_not_cancel_no_status (fd); + } ++ __set_errno (save_errno); + break; + + default: +@@ -313,4 +319,5 @@ __statfs_chown_restricted (int result, const struct statfs *fsbuf) + } + + return retval; ++#endif + } diff --git a/glibc-rh977872.patch b/glibc-rh977872.patch new file mode 100644 index 0000000..f1c50ff --- /dev/null +++ b/glibc-rh977872.patch @@ -0,0 +1,268 @@ +commit adbb8027be47b3295367019b2f45863ea3d6c727 +Author: Siddhesh Poyarekar +Date: Thu Mar 7 12:15:08 2013 +0530 + + Remove PIPE_BUF Linux-specific code + + Fixes BZ #12723 + + The variable pipe buffer size does nothing to the value of PIPE_BUF, + since the number of bytes that are atomically written is still + PIPE_BUF on Linux. + +diff --git a/posix/Makefile b/posix/Makefile +index 2cacd21..658c47e 100644 +--- a/posix/Makefile ++++ b/posix/Makefile +@@ -86,7 +86,8 @@ tests := tstgetopt testfnm runtests runptests \ + tst-rfc3484-3 \ + tst-getaddrinfo3 tst-fnmatch2 tst-cpucount tst-cpuset \ + bug-getopt1 bug-getopt2 bug-getopt3 bug-getopt4 \ +- bug-getopt5 tst-getopt_long1 bug-regex34 ++ bug-getopt5 tst-getopt_long1 bug-regex34 \ ++ tst-pathconf + xtests := bug-ga2 + ifeq (yes,$(build-shared)) + test-srcs := globtest +diff --git a/posix/tst-pathconf.c b/posix/tst-pathconf.c +new file mode 100644 +index 0000000..7627a24 +--- /dev/null ++++ b/posix/tst-pathconf.c +@@ -0,0 +1,176 @@ ++/* Test that values of pathconf and fpathconf are consistent for a file. ++ Copyright (C) 2013 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++ ++static void prepare (void); ++#define PREPARE(argc, argv) prepare () ++ ++static int do_test (void); ++#define TEST_FUNCTION do_test () ++ ++#include "../test-skeleton.c" ++ ++static int dir_fd; ++static char *dirbuf; ++ ++static void ++prepare (void) ++{ ++ size_t test_dir_len = strlen (test_dir); ++ static const char dir_name[] = "/tst-pathconf.XXXXXX"; ++ ++ size_t dirbuflen = test_dir_len + sizeof (dir_name); ++ dirbuf = malloc (dirbuflen); ++ if (dirbuf == NULL) ++ { ++ puts ("Out of memory"); ++ exit (1); ++ } ++ ++ snprintf (dirbuf, dirbuflen, "%s%s", test_dir, dir_name); ++ if (mkdtemp (dirbuf) == NULL) ++ { ++ printf ("Cannot create temporary directory: %s\n", strerror (errno)); ++ exit (1); ++ } ++ ++ add_temp_file (dirbuf); ++ ++ dir_fd = open (dirbuf, O_RDONLY); ++ if (dir_fd == -1) ++ { ++ printf ("Cannot open directory: %s\n", strerror (errno)); ++ exit (1); ++ } ++} ++ ++ ++static int ++do_test (void) ++{ ++ int ret = 0; ++ static const char *fifo_name = "some-fifo"; ++ ++ size_t filenamelen = strlen (dirbuf) + strlen (fifo_name) + 2; ++ char *filename = malloc (filenamelen); ++ ++ snprintf (filename, filenamelen, "%s/%s", dirbuf, fifo_name); ++ ++ /* Create a fifo in the directory. */ ++ int e = mkfifo (filename, 0777); ++ if (e == -1) ++ { ++ printf ("fifo creation failed (%s)\n", strerror (errno)); ++ ret = 1; ++ goto out_nofifo; ++ } ++ ++ long dir_pathconf = pathconf (dirbuf, _PC_PIPE_BUF); ++ ++ if (dir_pathconf < 0) ++ { ++ printf ("pathconf on directory failed: %s\n", strerror (errno)); ++ ret = 1; ++ goto out_nofifo; ++ } ++ ++ long fifo_pathconf = pathconf (filename, _PC_PIPE_BUF); ++ ++ if (fifo_pathconf < 0) ++ { ++ printf ("pathconf on file failed: %s\n", strerror (errno)); ++ ret = 1; ++ goto out_nofifo; ++ } ++ ++ int fifo = open (filename, O_RDONLY | O_NONBLOCK); ++ ++ if (fifo < 0) ++ { ++ printf ("fifo open failed (%s)\n", strerror (errno)); ++ ret = 1; ++ goto out_nofifo; ++ } ++ ++ long dir_fpathconf = fpathconf (dir_fd, _PC_PIPE_BUF); ++ ++ if (dir_fpathconf < 0) ++ { ++ printf ("fpathconf on directory failed: %s\n", strerror (errno)); ++ ret = 1; ++ goto out; ++ } ++ ++ long fifo_fpathconf = fpathconf (fifo, _PC_PIPE_BUF); ++ ++ if (fifo_fpathconf < 0) ++ { ++ printf ("fpathconf on file failed: %s\n", strerror (errno)); ++ ret = 1; ++ goto out; ++ } ++ ++ if (fifo_pathconf != fifo_fpathconf) ++ { ++ printf ("fifo pathconf (%ld) != fifo fpathconf (%ld)\n", fifo_pathconf, ++ fifo_fpathconf); ++ ret = 1; ++ goto out; ++ } ++ ++ if (dir_pathconf != fifo_pathconf) ++ { ++ printf ("directory pathconf (%ld) != fifo pathconf (%ld)\n", ++ dir_pathconf, fifo_pathconf); ++ ret = 1; ++ goto out; ++ } ++ ++ if (dir_fpathconf != fifo_fpathconf) ++ { ++ printf ("directory fpathconf (%ld) != fifo fpathconf (%ld)\n", ++ dir_fpathconf, fifo_fpathconf); ++ ret = 1; ++ goto out; ++ } ++ ++out: ++ close (fifo); ++out_nofifo: ++ close (dir_fd); ++ ++ if (unlink (filename) != 0) ++ { ++ printf ("Could not remove fifo (%s)\n", strerror (errno)); ++ ret = 1; ++ } ++ ++ if (rmdir (dirbuf) != 0) ++ { ++ printf ("Could not remove directory (%s)\n", strerror (errno)); ++ ret = 1; ++ } ++ ++ return ret; ++} +diff --git a/sysdeps/unix/sysv/linux/fpathconf.c b/sysdeps/unix/sysv/linux/fpathconf.c +index c971644..e8c4dc9 100644 +--- a/sysdeps/unix/sysv/linux/fpathconf.c ++++ b/sysdeps/unix/sysv/linux/fpathconf.c +@@ -33,7 +33,6 @@ __fpathconf (fd, name) + int name; + { + struct statfs fsbuf; +- int r; + + switch (name) + { +@@ -49,12 +48,6 @@ __fpathconf (fd, name) + case _PC_CHOWN_RESTRICTED: + return __statfs_chown_restricted (__fstatfs (fd, &fsbuf), &fsbuf); + +- case _PC_PIPE_BUF: +- r = __fcntl (fd, F_GETPIPE_SZ); +- if (r > 0) +- return r; +- /* FALLTHROUGH */ +- + default: + return posix_fpathconf (fd, name); + } +diff --git a/sysdeps/unix/sysv/linux/pathconf.c b/sysdeps/unix/sysv/linux/pathconf.c +index edc691e..de91a45 100644 +--- a/sysdeps/unix/sysv/linux/pathconf.c ++++ b/sysdeps/unix/sysv/linux/pathconf.c +@@ -39,8 +39,6 @@ long int + __pathconf (const char *file, int name) + { + struct statfs fsbuf; +- int fd; +- int flags; + + switch (name) + { +@@ -56,21 +54,6 @@ __pathconf (const char *file, int name) + case _PC_CHOWN_RESTRICTED: + return __statfs_chown_restricted (__statfs (file, &fsbuf), &fsbuf); + +- case _PC_PIPE_BUF: +- flags = O_RDONLY|O_NONBLOCK|O_NOCTTY; +-#ifdef O_CLOEXEC +- flags |= O_CLOEXEC; +-#endif +- fd = open_not_cancel_2 (file, flags); +- if (fd >= 0) +- { +- long int r = __fcntl (fd, F_GETPIPE_SZ); +- close_not_cancel_no_status (fd); +- if (r > 0) +- return r; +- } +- /* FALLTHROUGH */ +- + default: + return posix_pathconf (file, name); + } diff --git a/glibc-rh977874.patch b/glibc-rh977874.patch new file mode 100644 index 0000000..1624d9d --- /dev/null +++ b/glibc-rh977874.patch @@ -0,0 +1,148 @@ +commit 7da6d9ed266105e0ebefd01a4b6bf08bf56257c3 +Author: Siddhesh Poyarekar +Date: Tue Feb 26 14:24:40 2013 +0530 + + Fix FPE in memusagestat when malloc utilization is zero + + [BZ #15160] + + Draw graphs for heap and stack only if MAXSIZE_HEAP and MAXSIZE_STACK + are non-zero. + +diff --git a/malloc/memusagestat.c b/malloc/memusagestat.c +index f561e0d..7bbd009 100644 +--- a/malloc/memusagestat.c ++++ b/malloc/memusagestat.c +@@ -319,17 +319,26 @@ main (int argc, char *argv[]) + + for (line = 1; line <= 3; ++line) + { +- cnt = ((ysize - 40) * (maxsize_heap / 4 * line / heap_scale)) / +- (maxsize_heap / heap_scale); +- gdImageDashedLine (im_out, 40, ysize - 20 - cnt, xsize - 40, +- ysize - 20 - cnt, red); +- snprintf (buf, sizeof (buf), heap_format, maxsize_heap / 4 * line / +- heap_scale); +- gdImageString (im_out, gdFontSmall, 39 - strlen (buf) * 6, +- ysize - 26 - cnt, (unsigned char *) buf, red); +- +- cnt2 = ((ysize - 40) * (maxsize_stack / 4 * line / stack_scale)) / +- (maxsize_stack / stack_scale); ++ if (maxsize_heap > 0) ++ { ++ cnt = (((ysize - 40) * (maxsize_heap / 4 * line / heap_scale)) ++ / (maxsize_heap / heap_scale)); ++ gdImageDashedLine (im_out, 40, ysize - 20 - cnt, xsize - 40, ++ ysize - 20 - cnt, red); ++ snprintf (buf, sizeof (buf), heap_format, ++ maxsize_heap / 4 * line / heap_scale); ++ gdImageString (im_out, gdFontSmall, 39 - strlen (buf) * 6, ++ ysize - 26 - cnt, (unsigned char *) buf, red); ++ } ++ else ++ cnt = 0; ++ ++ if (maxsize_stack > 0) ++ cnt2 = (((ysize - 40) * (maxsize_stack / 4 * line / stack_scale)) ++ / (maxsize_stack / stack_scale)); ++ else ++ cnt2 = 0; ++ + if (cnt != cnt2) + gdImageDashedLine (im_out, 40, ysize - 20 - cnt2, xsize - 40, + ysize - 20 - cnt2, green); +@@ -372,7 +381,7 @@ main (int argc, char *argv[]) + ysize - 14, yellow); + previously = now; + +- if (also_total) ++ if (also_total && maxsize_heap > 0) + { + size_t new3; + +@@ -386,21 +395,27 @@ main (int argc, char *argv[]) + last_total = new3; + } + +- // assert (entry.heap <= maxsize_heap); +- new[0] = (ysize - 20) - ((((unsigned long long int) (ysize - 40)) +- * entry.heap) / maxsize_heap); +- gdImageLine (im_out, 40 + ((xsize - 80) * (cnt - 1)) / total, +- last_heap, 40 + ((xsize - 80) * cnt) / total, new[0], +- red); +- last_heap = new[0]; +- +- // assert (entry.stack <= maxsize_stack); +- new[1] = (ysize - 20) - ((((unsigned long long int) (ysize - 40)) +- * entry.stack) / maxsize_stack); +- gdImageLine (im_out, 40 + ((xsize - 80) * (cnt - 1)) / total, +- last_stack, 40 + ((xsize - 80) * cnt) / total, new[1], +- green); +- last_stack = new[1]; ++ if (maxsize_heap > 0) ++ { ++ new[0] = ((ysize - 20) ++ - ((((unsigned long long int) (ysize - 40)) ++ * entry.heap) / maxsize_heap)); ++ gdImageLine (im_out, 40 + ((xsize - 80) * (cnt - 1)) / total, ++ last_heap, 40 + ((xsize - 80) * cnt) / total, ++ new[0], red); ++ last_heap = new[0]; ++ } ++ ++ if (maxsize_stack > 0) ++ { ++ new[1] = ((ysize - 20) ++ - ((((unsigned long long int) (ysize - 40)) ++ * entry.stack) / maxsize_stack)); ++ gdImageLine (im_out, 40 + ((xsize - 80) * (cnt - 1)) / total, ++ last_stack, 40 + ((xsize - 80) * cnt) / total, ++ new[1], green); ++ last_stack = new[1]; ++ } + } + + cnt = 0; +@@ -448,7 +463,7 @@ main (int argc, char *argv[]) + next_tick += MAX (1, total / 20); + } + +- if (also_total) ++ if (also_total && maxsize_heap > 0) + { + size_t new3; + +@@ -459,16 +474,24 @@ main (int argc, char *argv[]) + last_total = new3; + } + +- new[0] = (ysize - 20) - ((((unsigned long long int) (ysize - 40)) +- * entry.heap) / maxsize_heap); +- gdImageLine (im_out, last_xpos, last_heap, xpos, new[0], red); +- last_heap = new[0]; ++ if (maxsize_heap > 0) ++ { ++ new[0] = ((ysize - 20) ++ - ((((unsigned long long int) (ysize - 40)) ++ * entry.heap) / maxsize_heap)); ++ gdImageLine (im_out, last_xpos, last_heap, xpos, new[0], red); ++ last_heap = new[0]; ++ } + +- // assert (entry.stack <= maxsize_stack); +- new[1] = (ysize - 20) - ((((unsigned long long int) (ysize - 40)) +- * entry.stack) / maxsize_stack); +- gdImageLine (im_out, last_xpos, last_stack, xpos, new[1], green); +- last_stack = new[1]; ++ if (maxsize_stack > 0) ++ { ++ new[1] = ((ysize - 20) ++ - ((((unsigned long long int) (ysize - 40)) ++ * entry.stack) / maxsize_stack)); ++ gdImageLine (im_out, last_xpos, last_stack, xpos, new[1], ++ green); ++ last_stack = new[1]; ++ } + + last_xpos = xpos; + } diff --git a/glibc-rh977875.patch b/glibc-rh977875.patch new file mode 100644 index 0000000..9cbcb3d --- /dev/null +++ b/glibc-rh977875.patch @@ -0,0 +1,96 @@ +commit abe7f530bf5c741fe6f0658da7be59d8db168f7f +Author: Siddhesh Poyarekar +Date: Wed Apr 10 11:31:46 2013 +0530 + + Accept leading and trailing spaces in getdate input string + + Fixes #15346. + + The POSIX description of getdate allows for extra spaces in the + getdate input string. __getdate_r uses strptime internally, which + works fine with extra spaces between format strings (and hence within + an input string) but not with leading and trailing spaces. So we trim + off the leading and trailing spaces before we pass it on to strptime. + +diff --git a/time/getdate.c b/time/getdate.c +index 637dd18..eadebc3 100644 +--- a/time/getdate.c ++++ b/time/getdate.c +@@ -25,6 +25,8 @@ + #include + #include + #include ++#include ++#include + + #define TM_YEAR_BASE 1900 + +@@ -135,6 +137,44 @@ __getdate_r (const char *string, struct tm *tp) + /* No threads reading this stream. */ + __fsetlocking (fp, FSETLOCKING_BYCALLER); + ++ /* Skip leading whitespace. */ ++ while (isspace (*string)) ++ string++; ++ ++ size_t inlen, oldlen; ++ ++ oldlen = inlen = strlen (string); ++ ++ /* Skip trailing whitespace. */ ++ while (inlen > 0 && isspace (string[inlen - 1])) ++ inlen--; ++ ++ char *instr = NULL; ++ ++ if (inlen < oldlen) ++ { ++ bool using_malloc = false; ++ ++ if (__libc_use_alloca (inlen + 1)) ++ instr = alloca (inlen + 1); ++ else ++ { ++ instr = malloc (inlen + 1); ++ if (instr == NULL) ++ { ++ fclose (fp); ++ return 6; ++ } ++ using_malloc = true; ++ } ++ memcpy (instr, string, inlen); ++ instr[inlen] = '\0'; ++ string = instr; ++ ++ if (!using_malloc) ++ instr = NULL; ++ } ++ + line = NULL; + len = 0; + do +@@ -159,6 +199,8 @@ __getdate_r (const char *string, struct tm *tp) + } + while (!feof_unlocked (fp)); + ++ free (instr); ++ + /* Free the buffer. */ + free (line); + +diff --git a/time/tst-getdate.c b/time/tst-getdate.c +index 7604e83..dc8ecf4 100644 +--- a/time/tst-getdate.c ++++ b/time/tst-getdate.c +@@ -31,6 +31,10 @@ static const struct + } tests [] = + { + {"21:01:10 1999-1-31", "Universal", 0, {10, 1, 21, 31, 0, 99, 0, 0, 0}}, ++ {"21:01:10 1999-1-31", "Universal", 0, {10, 1, 21, 31, 0, 99, 0, 0, 0}}, ++ {" 21:01:10 1999-1-31", "Universal", 0, {10, 1, 21, 31, 0, 99, 0, 0, 0}}, ++ {"21:01:10 1999-1-31 ", "Universal", 0, {10, 1, 21, 31, 0, 99, 0, 0, 0}}, ++ {" 21:01:10 1999-1-31 ", "Universal", 0, {10, 1, 21, 31, 0, 99, 0, 0, 0}}, + {"21:01:10 1999-2-28", "Universal", 0, {10, 1, 21, 28, 1, 99, 0, 0, 0}}, + {"16:30:46 2000-2-29", "Universal", 0, {46, 30,16, 29, 1, 100, 0, 0, 0}}, + {"01-08-2000 05:06:07", "Europe/Berlin", 0, {7, 6, 5, 1, 7, 100, 0, 0, 0}} diff --git a/glibc.spec b/glibc.spec index cb6a92c..d3566c5 100644 --- a/glibc.spec +++ b/glibc.spec @@ -27,7 +27,7 @@ Summary: The GNU libc libraries Name: glibc Version: %{glibcversion} -Release: 9%{?dist} +Release: 10%{?dist} # GPLv2+ is used in a bunch of programs, LGPLv2+ is used for libraries. # Things that are linked directly into dynamically linked programs # and shared libraries (e.g. crt files, lib*_nonshared.a) have an additional @@ -116,6 +116,10 @@ Patch0038: %{name}-rh959034.patch # Patch1000: %{name}-rh905877.patch Patch1001: %{name}-rh958652.patch +Patch1002: %{name}-rh977870.patch +Patch1003: %{name}-rh977872.patch +Patch1004: %{name}-rh977874.patch +Patch1005: %{name}-rh977875.patch # # Patches submitted, but not yet approved upstream. @@ -415,6 +419,10 @@ package or when debugging this package. %patch0038 -p1 %patch2039 -p1 %patch1001 -p1 +%patch1002 -p1 +%patch1003 -p1 +%patch1004 -p1 +%patch1005 -p1 # On powerpc32, hp timing is only available in power4/power6 # libs, not in base, so pre-power4 dynamic linker is incompatible @@ -1210,6 +1218,12 @@ rm -f *.filelist* %endif %changelog +* Tue Jun 25 2013 Siddhesh Poyarekar - 2.17-10 + - Preserve errno across _PC_CHOWN_RESTRICTED call on XFS (#977870). + - Remove PIPE_BUF Linux-specific code (#977872). + - Fix FPE in memusagestat when malloc utilization is zero (#977874). + - Accept leading and trailing spaces in getdate input string (#977875). + * Thu Jun 20 2013 Siddhesh Poyarekar - 2.17-9 - Set EAI_SYSTEM only when h_errno is NETDB_INTERNAL (#958652).