This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "IPFire 2.x development tree".
The branch, next has been updated via 802b916d10aa314ae878ec633e7c3bbd2adaba7e (commit) via 1ffbca6e4f3fdb0fbde2e725ba066877cb7f909e (commit) via 5a9039f1322e6354d48f13a92b84c68201a37a4e (commit) via bb330e25e98f445493f63631c461bec1d7eb211b (commit) via a439a239bc8008659bb40951f5ca15249fb19d97 (commit) via 7f4c06e7a4a32467ca9ceab1499edfb1517aa3b2 (commit) via 2f221a50e3d4434da3787714b94973b35c13416f (commit) via 44ec3a759a43f1d41ac70edc0cc998b9bb4cf8f0 (commit) via d3228e2c6c65503d6493e5aaa36e56df4f4d1f00 (commit) via d3fbc392a7fb7f683f7f015653631d551f91dc2f (commit) via 1b8c3e236214b57638c58ae03bb0f586a2f09140 (commit) via 23c6a8d710f577b503b5fd14d4067f40eaf508ff (commit) from 879458d41f95578cd35e0f8e9f9e5078aa8dccbb (commit)
Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below.
- Log ----------------------------------------------------------------- commit 802b916d10aa314ae878ec633e7c3bbd2adaba7e Merge: 879458d 1ffbca6 Author: Arne Fitzenreiter arne_f@ipfire.org Date: Wed Feb 17 19:45:08 2016 +0100
Merge remote-tracking branch 'origin/master' into next
Signed-off-by: Arne Fitzenreiter arne_f@ipfire.org
Conflicts: make.sh
-----------------------------------------------------------------------
Summary of changes: config/rootfiles/core/99/exclude | 1 + config/rootfiles/oldcore/{97 => 98}/exclude | 0 .../oldcore/{94 => 98}/filelists/armv5tel/glibc | 0 .../rootfiles/oldcore/{88 => 98}/filelists/files | 0 .../oldcore/{94 => 98}/filelists/i586/glibc | 0 config/rootfiles/oldcore/98/filelists/x86_64/glibc | 1 + config/rootfiles/oldcore/{97 => 98}/meta | 0 config/rootfiles/oldcore/98/update.sh | 83 + lfs/glibc | 212 ++- make.sh | 4 +- .../glibc-test-installation.pl-libgcc_s.patch | 69 +- src/patches/glibc/glibc-rh1023306.patch | 64 + src/patches/glibc/glibc-rh1025933.patch | 287 +++ src/patches/glibc/glibc-rh1028285.patch | 149 ++ src/patches/glibc/glibc-rh1039988.patch | 141 ++ src/patches/glibc/glibc-rh1043557.patch | 145 ++ src/patches/glibc/glibc-rh1053178.patch | 214 +++ src/patches/glibc/glibc-rh1054846.patch | 57 + src/patches/glibc/glibc-rh1066724.patch | 620 +++++++ src/patches/glibc/glibc-rh1074342.patch | 26 + src/patches/glibc/glibc-rh1074353.patch | 398 ++++ src/patches/glibc/glibc-rh1082379.patch | 63 + src/patches/glibc/glibc-rh1085273.patch | 31 + src/patches/glibc/glibc-rh1085289.patch | 60 + src/patches/glibc/glibc-rh1085312.patch | 34 + src/patches/glibc/glibc-rh1087833.patch | 65 + src/patches/glibc/glibc-rh1088301.patch | 142 ++ src/patches/glibc/glibc-rh1091915.patch | 40 + src/patches/glibc/glibc-rh1099025-2.patch | 159 ++ src/patches/glibc/glibc-rh1099025.patch | 47 + src/patches/glibc/glibc-rh1116050-1.patch | 57 + src/patches/glibc/glibc-rh1116050.patch | 407 ++++ src/patches/glibc/glibc-rh1124204.patch | 47 + src/patches/glibc/glibc-rh1125307.patch | 19 + ...c-rh1133809-1.patch => glibc-rh1133810-1.patch} | 0 ...c-rh1133809-2.patch => glibc-rh1133810-2.patch} | 0 src/patches/glibc/glibc-rh1138769.patch | 45 + ...glibc-rh1207995.patch => glibc-rh1144019.patch} | 0 src/patches/glibc/glibc-rh1144132.patch | 58 + src/patches/glibc/glibc-rh1159167.patch | 15 + ...glibc-rh1170121.patch => glibc-rh1171296.patch} | 0 ...glibc-rh1139571.patch => glibc-rh1172044.patch} | 0 src/patches/glibc/glibc-rh1176907.patch | 22 + ...glibc-rh1183533.patch => glibc-rh1183534.patch} | 13 + src/patches/glibc/glibc-rh1195453-avx512.patch | 481 +++++ src/patches/glibc/glibc-rh1207236.patch | 12 + ...glibc-rh1209375.patch => glibc-rh1209376.patch} | 0 src/patches/glibc/glibc-rh1256812-2.patch | 15 + src/patches/glibc/glibc-rh1256812-3.patch | 138 ++ src/patches/glibc/glibc-rh1256812-4.patch | 45 + src/patches/glibc/glibc-rh1256812.patch | 56 + src/patches/glibc/glibc-rh1256890.patch | 12 + src/patches/glibc/glibc-rh1256891.patch | 26 + src/patches/glibc/glibc-rh1291270.patch | 41 + src/patches/glibc/glibc-rh1296031-0.patch | 465 +++++ src/patches/glibc/glibc-rh1296031.patch | 544 ++++++ src/patches/glibc/glibc-rh1299319-0.patch | 61 + src/patches/glibc/glibc-rh1299319-1.patch | 19 + src/patches/glibc/glibc-rh552960.patch | 1213 ++++++++++++ src/patches/glibc/glibc-rh629823-2.patch | 95 + src/patches/glibc/glibc-rh629823.patch | 1954 ++++++++++++++++++++ src/patches/glibc/glibc-rh663641-2.patch | 279 +++ src/patches/glibc/glibc-rh663641-3.patch | 31 + src/patches/glibc/glibc-rh663641.patch | 191 ++ src/patches/glibc/glibc-rh788959-2.patch | 245 +-- ...ibc-rh989558-2.patch => glibc-rh834386-2.patch} | 0 .../{glibc-rh989558.patch => glibc-rh834386.patch} | 0 src/patches/glibc/glibc-rh845218.patch | 218 +++ src/patches/glibc/glibc-rh848748.patch | 70 + src/patches/glibc/glibc-rh851470.patch | 52 + src/patches/glibc/glibc-rh859965.patch | 854 +++++++++ src/patches/glibc/glibc-rh862094.patch | 68 + src/patches/glibc/glibc-rh863384.patch | 14 + src/patches/glibc/glibc-rh867679.patch | 139 ++ src/patches/glibc/glibc-rh868808.patch | 99 + src/patches/glibc/glibc-rh905941.patch | 146 ++ .../{glibc-rh970992.patch => glibc-rh919562.patch} | 0 src/patches/glibc/glibc-rh929302.patch | 98 + src/patches/glibc/glibc-rh970776.patch | 279 +++ src/patches/glibc/glibc-rh978098.patch | 124 ++ src/patches/glibc/glibc-rh981942.patch | 22 + src/patches/glibc/glibc-rh988931.patch | 33 + 82 files changed, 11667 insertions(+), 267 deletions(-) copy config/rootfiles/oldcore/{97 => 98}/exclude (100%) copy config/rootfiles/oldcore/{94 => 98}/filelists/armv5tel/glibc (100%) copy config/rootfiles/oldcore/{88 => 98}/filelists/files (100%) copy config/rootfiles/oldcore/{94 => 98}/filelists/i586/glibc (100%) create mode 120000 config/rootfiles/oldcore/98/filelists/x86_64/glibc copy config/rootfiles/oldcore/{97 => 98}/meta (100%) create mode 100644 config/rootfiles/oldcore/98/update.sh create mode 100644 src/patches/glibc/glibc-rh1023306.patch create mode 100644 src/patches/glibc/glibc-rh1025933.patch create mode 100644 src/patches/glibc/glibc-rh1028285.patch create mode 100644 src/patches/glibc/glibc-rh1039988.patch create mode 100644 src/patches/glibc/glibc-rh1043557.patch create mode 100644 src/patches/glibc/glibc-rh1053178.patch create mode 100644 src/patches/glibc/glibc-rh1054846.patch create mode 100644 src/patches/glibc/glibc-rh1066724.patch create mode 100644 src/patches/glibc/glibc-rh1074342.patch create mode 100644 src/patches/glibc/glibc-rh1074353.patch create mode 100644 src/patches/glibc/glibc-rh1082379.patch create mode 100644 src/patches/glibc/glibc-rh1085273.patch create mode 100644 src/patches/glibc/glibc-rh1085289.patch create mode 100644 src/patches/glibc/glibc-rh1085312.patch create mode 100644 src/patches/glibc/glibc-rh1087833.patch create mode 100644 src/patches/glibc/glibc-rh1088301.patch create mode 100644 src/patches/glibc/glibc-rh1091915.patch create mode 100644 src/patches/glibc/glibc-rh1099025-2.patch create mode 100644 src/patches/glibc/glibc-rh1099025.patch create mode 100644 src/patches/glibc/glibc-rh1116050-1.patch create mode 100644 src/patches/glibc/glibc-rh1116050.patch create mode 100644 src/patches/glibc/glibc-rh1124204.patch create mode 100644 src/patches/glibc/glibc-rh1125307.patch rename src/patches/glibc/{glibc-rh1133809-1.patch => glibc-rh1133810-1.patch} (100%) rename src/patches/glibc/{glibc-rh1133809-2.patch => glibc-rh1133810-2.patch} (100%) create mode 100644 src/patches/glibc/glibc-rh1138769.patch rename src/patches/glibc/{glibc-rh1207995.patch => glibc-rh1144019.patch} (100%) create mode 100644 src/patches/glibc/glibc-rh1144132.patch create mode 100644 src/patches/glibc/glibc-rh1159167.patch rename src/patches/glibc/{glibc-rh1170121.patch => glibc-rh1171296.patch} (100%) rename src/patches/glibc/{glibc-rh1139571.patch => glibc-rh1172044.patch} (100%) create mode 100644 src/patches/glibc/glibc-rh1176907.patch rename src/patches/glibc/{glibc-rh1183533.patch => glibc-rh1183534.patch} (94%) create mode 100644 src/patches/glibc/glibc-rh1195453-avx512.patch create mode 100644 src/patches/glibc/glibc-rh1207236.patch rename src/patches/glibc/{glibc-rh1209375.patch => glibc-rh1209376.patch} (100%) create mode 100644 src/patches/glibc/glibc-rh1256812-2.patch create mode 100644 src/patches/glibc/glibc-rh1256812-3.patch create mode 100644 src/patches/glibc/glibc-rh1256812-4.patch create mode 100644 src/patches/glibc/glibc-rh1256812.patch create mode 100644 src/patches/glibc/glibc-rh1256890.patch create mode 100644 src/patches/glibc/glibc-rh1256891.patch create mode 100644 src/patches/glibc/glibc-rh1291270.patch create mode 100644 src/patches/glibc/glibc-rh1296031-0.patch create mode 100644 src/patches/glibc/glibc-rh1296031.patch create mode 100644 src/patches/glibc/glibc-rh1299319-0.patch create mode 100644 src/patches/glibc/glibc-rh1299319-1.patch create mode 100644 src/patches/glibc/glibc-rh552960.patch create mode 100644 src/patches/glibc/glibc-rh629823-2.patch create mode 100644 src/patches/glibc/glibc-rh629823.patch create mode 100644 src/patches/glibc/glibc-rh663641-2.patch create mode 100644 src/patches/glibc/glibc-rh663641-3.patch create mode 100644 src/patches/glibc/glibc-rh663641.patch rename src/patches/glibc/{glibc-rh989558-2.patch => glibc-rh834386-2.patch} (100%) rename src/patches/glibc/{glibc-rh989558.patch => glibc-rh834386.patch} (100%) create mode 100644 src/patches/glibc/glibc-rh845218.patch create mode 100644 src/patches/glibc/glibc-rh848748.patch create mode 100644 src/patches/glibc/glibc-rh851470.patch create mode 100644 src/patches/glibc/glibc-rh859965.patch create mode 100644 src/patches/glibc/glibc-rh862094.patch create mode 100644 src/patches/glibc/glibc-rh863384.patch create mode 100644 src/patches/glibc/glibc-rh867679.patch create mode 100644 src/patches/glibc/glibc-rh868808.patch create mode 100644 src/patches/glibc/glibc-rh905941.patch rename src/patches/glibc/{glibc-rh970992.patch => glibc-rh919562.patch} (100%) create mode 100644 src/patches/glibc/glibc-rh929302.patch create mode 100644 src/patches/glibc/glibc-rh970776.patch create mode 100644 src/patches/glibc/glibc-rh978098.patch create mode 100644 src/patches/glibc/glibc-rh981942.patch create mode 100644 src/patches/glibc/glibc-rh988931.patch
Difference in files: diff --git a/config/rootfiles/core/99/exclude b/config/rootfiles/core/99/exclude index d87f175..8e446ce 100644 --- a/config/rootfiles/core/99/exclude +++ b/config/rootfiles/core/99/exclude @@ -1,6 +1,7 @@ boot/config.txt etc/alternatives etc/collectd.custom +etc/default/grub etc/ipsec.conf etc/ipsec.secrets etc/ipsec.user.conf diff --git a/config/rootfiles/oldcore/98/exclude b/config/rootfiles/oldcore/98/exclude new file mode 100644 index 0000000..d87f175 --- /dev/null +++ b/config/rootfiles/oldcore/98/exclude @@ -0,0 +1,25 @@ +boot/config.txt +etc/alternatives +etc/collectd.custom +etc/ipsec.conf +etc/ipsec.secrets +etc/ipsec.user.conf +etc/ipsec.user.secrets +etc/localtime +etc/shadow +etc/snort/snort.conf +etc/ssh/ssh_config +etc/ssh/sshd_config +etc/ssl/openssl.cnf +etc/sudoers +etc/sysconfig/firewall.local +etc/sysconfig/rc.local +etc/udev/rules.d/30-persistent-network.rules +srv/web/ipfire/html/proxy.pac +var/ipfire/dma +var/ipfire/time +var/ipfire/ovpn +var/lib/alternatives +var/log/cache +var/state/dhcp/dhcpd.leases +var/updatecache diff --git a/config/rootfiles/oldcore/98/filelists/armv5tel/glibc b/config/rootfiles/oldcore/98/filelists/armv5tel/glibc new file mode 120000 index 0000000..4c70d72 --- /dev/null +++ b/config/rootfiles/oldcore/98/filelists/armv5tel/glibc @@ -0,0 +1 @@ +../../../../common/armv5tel/glibc \ No newline at end of file diff --git a/config/rootfiles/oldcore/98/filelists/files b/config/rootfiles/oldcore/98/filelists/files new file mode 100644 index 0000000..409e5fe --- /dev/null +++ b/config/rootfiles/oldcore/98/filelists/files @@ -0,0 +1,2 @@ +etc/system-release +etc/issue diff --git a/config/rootfiles/oldcore/98/filelists/i586/glibc b/config/rootfiles/oldcore/98/filelists/i586/glibc new file mode 120000 index 0000000..943021f --- /dev/null +++ b/config/rootfiles/oldcore/98/filelists/i586/glibc @@ -0,0 +1 @@ +../../../../common/i586/glibc \ No newline at end of file diff --git a/config/rootfiles/oldcore/98/filelists/x86_64/glibc b/config/rootfiles/oldcore/98/filelists/x86_64/glibc new file mode 120000 index 0000000..1119099 --- /dev/null +++ b/config/rootfiles/oldcore/98/filelists/x86_64/glibc @@ -0,0 +1 @@ +../../../../common/x86_64/glibc \ No newline at end of file diff --git a/config/rootfiles/oldcore/98/meta b/config/rootfiles/oldcore/98/meta new file mode 100644 index 0000000..d547fa8 --- /dev/null +++ b/config/rootfiles/oldcore/98/meta @@ -0,0 +1 @@ +DEPS="" diff --git a/config/rootfiles/oldcore/98/update.sh b/config/rootfiles/oldcore/98/update.sh new file mode 100644 index 0000000..ec9c1aa --- /dev/null +++ b/config/rootfiles/oldcore/98/update.sh @@ -0,0 +1,83 @@ +#!/bin/bash +############################################################################ +# # +# This file is part of the IPFire Firewall. # +# # +# IPFire is free software; you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation; either version 3 of the License, or # +# (at your option) any later version. # +# # +# IPFire 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 General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with IPFire; if not, write to the Free Software # +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # +# # +# Copyright (C) 2016 IPFire-Team info@ipfire.org. # +# # +############################################################################ +# +. /opt/pakfire/lib/functions.sh +/usr/local/bin/backupctrl exclude >/dev/null 2>&1 + +# Remove old core updates from pakfire cache to save space... +core=98 +for (( i=1; i<=$core; i++ )) +do + rm -f /var/cache/pakfire/core-upgrade-*-$i.ipfire +done + +# Stop services + +# Extract files +extract_files + +# Bugfixes for core96 updater bugs... +if [ -e /boot/grub/grub.conf ]; then + # legacy grub config on xen or citrix conflicts with grub2 config + rm /boot/grub/grub.cfg +fi + +if [ -e /boot/grub/grub.cfg ]; then + # test if serial console is enabled + grep "^7:2345" /etc/inittab > /dev/null + if [ "${?}" == "0" ]; then + # Fix grub config for serial console + sed -i /etc/default/grub \ + -e "s|"panic=10"|"panic=10 console=ttyS0,115200n8"|g" + sed -i /etc/default/grub \ + -e "s|^GRUB_TERMINAL=.*||g" + sed -i /etc/default/grub \ + -e "s|^GRUB_SERIAL_COMMAND=.*||g" + echo "GRUB_TERMINAL="serial"" >> /etc/default/grub + echo "GRUB_SERIAL_COMMAND="serial --unit=0 --speed=115200"" >> /etc/default/grub + fi +fi + + +# Update Language cache +# /usr/local/bin/update-lang-cache + +# restart init after glibc update +telinit u + +# Start services + +# This update need a reboot... +touch /var/run/need_reboot + +# Finish +/etc/init.d/fireinfo start +sendprofile +# Update grub config to display new core version +if [ -e /boot/grub/grub.cfg ]; then + grub-mkconfig -o /boot/grub/grub.cfg +fi +sync + +# Don't report the exitcode last command +exit 0 diff --git a/lfs/glibc b/lfs/glibc index 56a3533..c0af6fc 100644 --- a/lfs/glibc +++ b/lfs/glibc @@ -1,7 +1,7 @@ ############################################################################### # # # IPFire.org - A linux based firewall # -# Copyright (C) 2007-2011 IPFire Team info@ipfire.org # +# Copyright (C) 2007-2016 IPFire Team info@ipfire.org # # # # This program is free software: you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # @@ -141,156 +141,222 @@ endif cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-getlogin-r.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-localedata.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-recvmmsg.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh580498.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh582738.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh587360.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh582738.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh593396.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh593686.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh601686.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh607010.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh607461.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh615090.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh615701.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh621959.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh623187.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh625893.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh607010.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh630801.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh631011.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh641128.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh642584.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh643822.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh645672.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh580498.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh615090.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh623187.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh646954.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh647448.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh615701.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh652661.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh656014.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh656530.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh657572.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh656014.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh661982.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh667974.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh601686.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh676076.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh676591.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh667974.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh625893.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh681054.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh688720.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh688980.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh689471.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh692177.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh692838.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh694386.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh695595.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh695963.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh696472.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh697421.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh699724.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh700507.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh703480.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh703481.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh705465.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh711927.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh703481.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh694386.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh676591.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh711987.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh712248.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh695595.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh695963.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh713134.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh714823.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh718057.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh726517.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh730379.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh688980.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh712248.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh731042.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh730379.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh700507.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh699724.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh736346.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh737778.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh738665.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh738763.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh739184.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh711927.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh688720.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh726517.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh752122.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh739971.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh740506.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh740506-2.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh749188.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh750531.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh751750.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh752122.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh740506.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh757888.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh766513.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh767146.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh767693.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh767693-2.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh750531.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh749188.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh767746.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh767693.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh740506-2.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh696472.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh771342.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh657572.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh767693-2.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh782585.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh784402.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh697421.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh785984.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh767146.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh766513.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh789209.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh788959.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh788959-2.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh789189.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh789209.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh789238.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh789238-2.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh794817.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh794817-2.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh795498.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh797094-1.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh797094-2.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh804686.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh789238-2.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh795498.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh794817-2.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh804689.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh806404.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh809602.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh808337.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh788959-2.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh808545.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh809602.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh809726.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh833717.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh823909.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh826149.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh827362.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh830127.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh841787.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh809726.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh806404.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh832516.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh830127.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh832694.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh833717.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh837695.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh837918.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh841787.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh843673.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh846342.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh847932.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh848082.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh837918.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh849203.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh849651.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh827362.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh837695.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh804686.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh848082.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh846342.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh852445.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh861167.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh863453.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh864322.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh929388.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh970992.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh989558.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh989558-2.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh919562.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh886968.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh905575.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh905874.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh916986.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh928318.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh947882.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh952422.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh966775.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh834386.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh834386-2.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh862094.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh851470.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh868808.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh552960.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh663641.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh663641-2.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh848748.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh952422.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh663641-3.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh916986.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh970776.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh966778.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh863384.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh629823.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh629823-2.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh947882.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh905874.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh929302.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh928318.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh905575.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh988931.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh970090.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh995972.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1008310.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1019916.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1022022.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1027101.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1027261.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1043557.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1039988.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh995972.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh981942.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1032628.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1027101.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1025933.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh845218.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1044628.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1085273.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1074342.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1085289.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1082379.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1074353.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1019916.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1028285.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1099025.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1087833.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1027261.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh905941.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1054846.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1111460.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1133809-1.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1133809-2.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1139571.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1099025-2.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1133810-1.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1133810-2.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1138769.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1171296.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1172044.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1154563.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1170121.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1183533.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1207995.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1209375.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1125307.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1176907.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1183534.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1159167.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1023306.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1085312.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1091915.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh859965.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1124204.patch +ifneq "$(MACHINE_TYPE)" "arm" + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh978098.patch +endif + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1144019.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1053178.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1144132.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1116050.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1116050-1.patch +ifneq "$(MACHINE_TYPE)" "arm" + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh867679.patch +endif + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1088301.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1195453-avx512.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1066724.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1209376.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1207236.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1217186.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1256812.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1256812-2.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1256812-3.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1256812-4.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1256890.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1256891.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1291270.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1296031.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1296031-0.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1299319-0.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1299319-1.patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc-resolv-stack_chk_fail.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc-remove-ctors-dtors-output-sections.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc-test-installation.pl-nss_test1.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc-test-installation.pl-libgcc_s.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc-2.12-accept-make-versions-4.0-and-greater.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-mq_open.patch diff --git a/make.sh b/make.sh index 0effba5..189f7d9 100755 --- a/make.sh +++ b/make.sh @@ -25,8 +25,8 @@ NAME="IPFire" # Software name SNAME="ipfire" # Short name VERSION="2.17" # Version number -CORE="98" # Core Level (Filename) -PAKFIRE_CORE="97" # Core Level (PAKFIRE) +CORE="99" # Core Level (Filename) +PAKFIRE_CORE="98" # Core Level (PAKFIRE) GIT_BRANCH=`git rev-parse --abbrev-ref HEAD` # Git Branch SLOGAN="www.ipfire.org" # Software slogan CONFIG_ROOT=/var/ipfire # Configuration rootdir diff --git a/src/patches/glibc-test-installation.pl-libgcc_s.patch b/src/patches/glibc-test-installation.pl-libgcc_s.patch index a63d5d8..2221353 100644 --- a/src/patches/glibc-test-installation.pl-libgcc_s.patch +++ b/src/patches/glibc-test-installation.pl-libgcc_s.patch @@ -1,13 +1,8 @@ -From 6e236b92765cdafb46d19e4907471699accc8269 Mon Sep 17 00:00:00 2001 -From: Siddhesh Poyarekar siddhesh@redhat.com -Date: Thu, 26 Apr 2012 09:18:48 +0530 -Subject: [PATCH] move libgcc_s soname definition to shlib-versions - -diff --git a/nptl/sysdeps/pthread/unwind-forcedunwind.c b/nptl/sysdeps/pthread/unwind-forcedunwind.c -index adce6e7..60dfbe6 100644 ---- a/nptl/sysdeps/pthread/unwind-forcedunwind.c -+++ b/nptl/sysdeps/pthread/unwind-forcedunwind.c -@@ -21,7 +21,7 @@ +diff -Naur glibc-2.12-2-gc4ccff1.org/nptl/sysdeps/pthread/unwind-forcedunwind.c glibc-2.12-2-gc4ccff1/nptl/sysdeps/pthread/unwind-forcedunwind.c +index db56428..495f4b7 100644 +--- glibc-2.12-2-gc4ccff1.org/nptl/sysdeps/pthread/unwind-forcedunwind.c ++++ glibc-2.12-2-gc4ccff1/nptl/sysdeps/pthread/unwind-forcedunwind.c +@@ -22,7 +22,7 @@ #include <unwind.h> #include <pthreadP.h> #include <sysdep.h> @@ -16,12 +11,11 @@ index adce6e7..60dfbe6 100644
static void *libgcc_s_handle; static void (*libgcc_s_resume) (struct _Unwind_Exception *exc); -diff --git a/scripts/test-installation.pl b/scripts/test-installation.pl -index c4f3d6d..1b22086 100755 ---- a/scripts/test-installation.pl -+++ b/scripts/test-installation.pl - -@@ -105,9 +105,10 @@ while (<SOVERSIONS>) { +diff -Naur glibc-2.12-2-gc4ccff1.org/scripts/test-installation.pl glibc-2.12-2-gc4ccff1/scripts/test-installation.pl +index 25a919b..3f409ab 100755 +--- glibc-2.12-2-gc4ccff1.org/scripts/test-installation.pl ++++ glibc-2.12-2-gc4ccff1/scripts/test-installation.pl +@@ -106,9 +106,10 @@ while (<SOVERSIONS>) { # - libnss1_* from glibc-compat add-on # - libthread_db since it contains unresolved references # - it's just a test NSS module @@ -33,11 +27,11 @@ index c4f3d6d..1b22086 100755 $link_libs .= " -l$name"; $versions{$name} = $version; } -diff --git a/shlib-versions b/shlib-versions -index c530a44..840e08f 100644 ---- a/shlib-versions -+++ b/shlib-versions -@@ -124,3 +124,7 @@ sparc64.*-.*-.* libBrokenLocale=1 GLIBC_2.2 +diff -Naur glibc-2.12-2-gc4ccff1.org/shlib-versions glibc-2.12-2-gc4ccff1/shlib-versions +index d3e8407..ac98e49 100644 +--- glibc-2.12-2-gc4ccff1.org/shlib-versions ++++ glibc-2.12-2-gc4ccff1/shlib-versions +@@ -138,3 +138,7 @@ sparc64.*-.*-.* libBrokenLocale=1 GLIBC_2.2
# The asynchronous name lookup library. .*-.*-.* libanl=1 @@ -45,10 +39,10 @@ index c530a44..840e08f 100644 +# This defines the libgcc soname version this glibc is to load for +# asynchronous cancellation to work correctly. +.*-.*-.* libgcc_s=1 -diff --git a/sysdeps/generic/framestate.c b/sysdeps/generic/framestate.c -index 3638bbe..3bad5b5 100644 ---- a/sysdeps/generic/framestate.c -+++ b/sysdeps/generic/framestate.c +diff -Naur glibc-2.12-2-gc4ccff1.org/sysdeps/generic/framestate.c glibc-2.12-2-gc4ccff1/sysdeps/generic/framestate.c +index 80375bb..edc3539 100644 +--- glibc-2.12-2-gc4ccff1.org/sysdeps/generic/framestate.c ++++ glibc-2.12-2-gc4ccff1/sysdeps/generic/framestate.c @@ -1,5 +1,5 @@ /* __frame_state_for unwinder helper function wrapper. - Copyright (C) 2001, 2003 Free Software Foundation, Inc. @@ -56,7 +50,7 @@ index 3638bbe..3bad5b5 100644 This file is part of the GNU C Library. Contributed by Jakub Jelinek jakub@redhat.com, 2001.
-@@ -23,7 +23,7 @@ +@@ -24,7 +24,7 @@ #define __frame_state_for fallback_frame_state_for #include <unwind-dw2.c> #undef __frame_state_for @@ -65,33 +59,30 @@ index 3638bbe..3bad5b5 100644
typedef struct frame_state * (*framesf)(void *pc, struct frame_state *); struct frame_state *__frame_state_for (void *pc, -diff --git a/sysdeps/generic/libgcc_s.h b/sysdeps/generic/libgcc_s.h +diff -Naur glibc-2.12-2-gc4ccff1.org/sysdeps/generic/libgcc_s.h glibc-2.12-2-gc4ccff1.org/sysdeps/generic/libgcc_s.h deleted file mode 100644 index e74a103..0000000 ---- a/sysdeps/generic/libgcc_s.h +--- glibc-2.12-2-gc4ccff1.org/sysdeps/generic/libgcc_s.h +++ /dev/null @@ -1,2 +0,0 @@ -/* Name of libgcc_s library provided by gcc. */ -#define LIBGCC_S_SO "libgcc_s.so.1" -diff --git a/sysdeps/gnu/unwind-resume.c b/sysdeps/gnu/unwind-resume.c -index 1d3e33f..6afaebd 100644 ---- a/sysdeps/gnu/unwind-resume.c -+++ b/sysdeps/gnu/unwind-resume.c +diff -Naur glibc-2.12-2-gc4ccff1.org/sysdeps/gnu/unwind-resume.c glibc-2.12-2-gc4ccff1/sysdeps/gnu/unwind-resume.c +index f8ff0c4..dab4370 100644 +--- glibc-2.12-2-gc4ccff1.org/sysdeps/gnu/unwind-resume.c ++++ glibc-2.12-2-gc4ccff1/sysdeps/gnu/unwind-resume.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2003 Free Software Foundation, Inc. +/* Copyright (C) 2003-2012 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Jakub Jelinek jakub@redhat.com.
-@@ -19,7 +19,7 @@ - #include <dlfcn.h> - #include <stdio.h> +@@ -22,7 +22,7 @@ #include <unwind.h> + #include <pthreadP.h> + #include <sysdep.h> -#include <libgcc_s.h> +#include <gnu/lib-names.h>
+ static void *libgcc_s_handle; static void (*libgcc_s_resume) (struct _Unwind_Exception *exc); - static _Unwind_Reason_Code (*libgcc_s_personality) --- -1.7.3.4 - diff --git a/src/patches/glibc/glibc-rh1023306.patch b/src/patches/glibc/glibc-rh1023306.patch new file mode 100644 index 0000000..738052d --- /dev/null +++ b/src/patches/glibc/glibc-rh1023306.patch @@ -0,0 +1,64 @@ +diff -pruN glibc-2.17-c758a686/nptl/Makefile glibc-2.17-c758a686.new/nptl/Makefile +--- glibc-2.17-c758a686/nptl/Makefile 2013-07-31 11:51:24.882747234 +0530 ++++ glibc-2.17-c758a686.new/nptl/Makefile 2013-07-31 11:58:55.964731526 +0530 +@@ -276,10 +276,7 @@ gen-as-const-headers = pthread-errnos.sy + LDFLAGS-tst-cond24 = -lrt + LDFLAGS-tst-cond25 = -lrt + +-# The size is 1MB + 4KB. The extra 4KB has been added to prevent allocatestack +-# from resizing the input size to avoid the 64K aliasing conflict on Intel +-# processors. +-DEFAULT_STACKSIZE=1052672 ++DEFAULT_STACKSIZE=1048576 + CFLAGS-tst-default-attr.c = -DDEFAULT_STACKSIZE=$(DEFAULT_STACKSIZE) + tst-default-attr-ENV = GLIBC_PTHREAD_STACKSIZE=$(DEFAULT_STACKSIZE) + +diff -pruN glibc-2.17-c758a686/nptl/tst-default-attr.c glibc-2.17-c758a686.new/nptl/tst-default-attr.c +--- glibc-2.17-c758a686/nptl/tst-default-attr.c 2013-07-31 11:51:24.885747234 +0530 ++++ glibc-2.17-c758a686.new/nptl/tst-default-attr.c 2013-07-31 12:18:10.016691337 +0530 +@@ -38,6 +38,7 @@ + + /* DEFAULT_STACKSIZE macro is defined in the Makefile. */ + static size_t stacksize = DEFAULT_STACKSIZE; ++long int pagesize; + + static int + verify_stacksize_result (pthread_attr_t *attr) +@@ -46,12 +47,20 @@ verify_stacksize_result (pthread_attr_t + + RETURN_IF_FAIL (pthread_attr_getstacksize, attr, &stack); + +- if (stacksize != stack) ++ /* pthread_create perturbs the stack size by a page if it aligns to 64K to ++ avoid the 64K aliasing conflict. We cannot simply add 4K to the size in ++ the Makefile because it breaks the test on powerpc since the page size ++ there is 64K, resulting in a resize in __pthread_initialize_minimal. ++ Hence, our check is to ensure that the stack size is not more than a page ++ more than the requested size. */ ++ if (stack < stacksize || stack > stacksize + pagesize) + { + printf ("failed to set default stacksize (%zu, %zu)\n", stacksize, stack); + return 1; + } + ++ printf ("Requested %zu and got %zu\n", stacksize, stack); ++ + return 0; + } + +@@ -101,6 +110,15 @@ run_threads (void) + static int + do_test (void) + { ++ pthread_attr_t attr; ++ ++ pagesize = sysconf (_SC_PAGESIZE); ++ if (pagesize < 0) ++ { ++ printf ("sysconf failed: %s\n", strerror (errno)); ++ return 1; ++ } ++ + RETURN_IF_FAIL (run_threads); + return 0; + } diff --git a/src/patches/glibc/glibc-rh1025933.patch b/src/patches/glibc/glibc-rh1025933.patch new file mode 100644 index 0000000..9dc98b9 --- /dev/null +++ b/src/patches/glibc/glibc-rh1025933.patch @@ -0,0 +1,287 @@ +commit 0699f766b10c86912b75f35bef697106b70c1cf6 +Author: Carlos O'Donell carlos@redhat.com +Date: Thu Apr 10 18:31:53 2014 -0400 + + nscd: Make SELinux checks dynamic. + + The SELinux team has indicated to me that glibc's SELinux checks + in nscd are not being carried out as they would expect the API + to be used today. They would like to move away from static header + defines for class and permissions and instead use dynamic checks + at runtime that provide an answer which is dependent on the runtime + status of SELinux i.e. more dynamic. + + The following patch is a minimal change that moves us forward in + this direction. + + It does the following: + + * Stop checking for SELinux headers that define NSCD__SHMEMHOST. + Check only for the presence or absence of the library. + + * Don't encode the specific SELinux permission constants into a + table at build time, and instead use the symbolic name for the + permission as expected. + + * Lookup the "What do we do if we don't know this permission?" + policy and use that if we find SELinux's policy is older than + the glibc policy e.g. we make a request for a permission that + SELinux doesn't know about. + + * Lastly, translate the class and permission and then make + the permission check. This is done every time we lookup + a permission, and this is the expected way to use the API. + SELinux will optimize this for us, and we expect the network + latencies to hide these extra library calls. + + Tested on x86, x86-64, and via Fedora Rawhide since November 2013. + + See: + https://sourceware.org/ml/libc-alpha/2014-04/msg00179.html + +diff --git a/configure b/configure +index abefcdb..8b0b222 100755 +--- a/configure ++++ b/configure +@@ -7774,64 +7774,10 @@ else + have_selinux=no + fi + +- # See if we have the SELinux header with the NSCD permissions in it. +- if test x$have_selinux = xyes ; then +- { $as_echo "$as_me:$LINENO: checking for NSCD Flask permissions in selinux/av_permissions.h" >&5 +-$as_echo_n "checking for NSCD Flask permissions in selinux/av_permissions.h... " >&6; } +- cat >conftest.$ac_ext <<_ACEOF +-/* confdefs.h. */ +-_ACEOF +-cat confdefs.h >>conftest.$ac_ext +-cat >>conftest.$ac_ext <<_ACEOF +-/* end confdefs.h. */ +-#include <selinux/av_permissions.h> +-int +-main () +-{ +-#ifdef NSCD__SHMEMHOST +- return 0; +- #else +- #error NSCD__SHMEMHOST not defined +- #endif +- ; +- return 0; +-} +-_ACEOF +-rm -f conftest.$ac_objext +-if { (ac_try="$ac_compile" +-case "(($ac_try" in +- *"* | *`* | *\*) ac_try_echo=$ac_try;; +- *) ac_try_echo=$ac_try;; +-esac +-eval ac_try_echo=""$as_me:$LINENO: $ac_try_echo"" +-$as_echo "$ac_try_echo") >&5 +- (eval "$ac_compile") 2>conftest.er1 +- ac_status=$? +- grep -v '^ *+' conftest.er1 >conftest.err +- rm -f conftest.er1 +- cat conftest.err >&5 +- $as_echo "$as_me:$LINENO: $? = $ac_status" >&5 +- (exit $ac_status); } && { +- test -z "$ac_c_werror_flag" || +- test ! -s conftest.err +- } && test -s conftest.$ac_objext; then +- have_selinux=yes +-else +- $as_echo "$as_me: failed program was:" >&5 +-sed 's/^/| /' conftest.$ac_ext >&5 +- +- have_selinux=no +-fi +- +-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +- { $as_echo "$as_me:$LINENO: result: $have_selinux" >&5 +-$as_echo "$have_selinux" >&6; } +- fi +- + if test x$with_selinux = xyes ; then + if test x$have_selinux = xno ; then +- { { $as_echo "$as_me:$LINENO: error: SELinux explicitly required, but sufficiently recent SELinux library not found" >&5 +-$as_echo "$as_me: error: SELinux explicitly required, but sufficiently recent SELinux library not found" >&2;} ++ { { $as_echo "$as_me:$LINENO: error: SELinux explicitly required, but SELinux library not found" >&5 ++$as_echo "$as_me: error: SELinux explicitly required, but SELinux library not found" >&2;} + { (exit 1); exit 1; }; } + fi + fi +diff --git a/configure.in b/configure.in +index 6291872..97a9591 100644 +--- a/configure.in ++++ b/configure.in +@@ -1945,22 +1945,9 @@ else + # See if we have the SELinux library + AC_CHECK_LIB(selinux, is_selinux_enabled, + have_selinux=yes, have_selinux=no) +- # See if we have the SELinux header with the NSCD permissions in it. +- if test x$have_selinux = xyes ; then +- AC_MSG_CHECKING([for NSCD Flask permissions in selinux/av_permissions.h]) +- AC_TRY_COMPILE([#include <selinux/av_permissions.h>], +- [#ifdef NSCD__SHMEMHOST +- return 0; +- #else +- #error NSCD__SHMEMHOST not defined +- #endif], +- have_selinux=yes, have_selinux=no) +- AC_MSG_RESULT($have_selinux) +- fi +- + if test x$with_selinux = xyes ; then + if test x$have_selinux = xno ; then +- AC_MSG_ERROR([SELinux explicitly required, but sufficiently recent SELinux library not found]) ++ AC_MSG_ERROR([SELinux explicitly required, but SELinux library not found]) + fi + fi + fi +diff --git a/nscd/selinux.c b/nscd/selinux.c +index 46b0ea9..9a8a5a8 100644 +--- a/nscd/selinux.c ++++ b/nscd/selinux.c +@@ -28,7 +28,6 @@ + #include <syslog.h> + #include <unistd.h> + #include <sys/prctl.h> +-#include <selinux/av_permissions.h> + #include <selinux/avc.h> + #include <selinux/flask.h> + #include <selinux/selinux.h> +@@ -44,35 +43,31 @@ + /* Global variable to tell if the kernel has SELinux support. */ + int selinux_enabled; + +-/* Define mappings of access vector permissions to request types. */ +-static const access_vector_t perms[LASTREQ] = ++/* Define mappings of request type to AVC permission name. */ ++static const char *perms[LASTREQ] = + { +- [GETPWBYNAME] = NSCD__GETPWD, +- [GETPWBYUID] = NSCD__GETPWD, +- [GETGRBYNAME] = NSCD__GETGRP, +- [GETGRBYGID] = NSCD__GETGRP, +- [GETHOSTBYNAME] = NSCD__GETHOST, +- [GETHOSTBYNAMEv6] = NSCD__GETHOST, +- [GETHOSTBYADDR] = NSCD__GETHOST, +- [GETHOSTBYADDRv6] = NSCD__GETHOST, +- [GETSTAT] = NSCD__GETSTAT, +- [SHUTDOWN] = NSCD__ADMIN, +- [INVALIDATE] = NSCD__ADMIN, +- [GETFDPW] = NSCD__SHMEMPWD, +- [GETFDGR] = NSCD__SHMEMGRP, +- [GETFDHST] = NSCD__SHMEMHOST, +- [GETAI] = NSCD__GETHOST, +- [INITGROUPS] = NSCD__GETGRP, +-#ifdef NSCD__GETSERV +- [GETSERVBYNAME] = NSCD__GETSERV, +- [GETSERVBYPORT] = NSCD__GETSERV, +- [GETFDSERV] = NSCD__SHMEMSERV, +-#endif +-#ifdef NSCD__GETNETGRP +- [GETNETGRENT] = NSCD__GETNETGRP, +- [INNETGR] = NSCD__GETNETGRP, +- [GETFDNETGR] = NSCD__SHMEMNETGRP, +-#endif ++ [GETPWBYNAME] = "getpwd", ++ [GETPWBYUID] = "getpwd", ++ [GETGRBYNAME] = "getgrp", ++ [GETGRBYGID] = "getgrp", ++ [GETHOSTBYNAME] = "gethost", ++ [GETHOSTBYNAMEv6] = "gethost", ++ [GETHOSTBYADDR] = "gethost", ++ [GETHOSTBYADDRv6] = "gethost", ++ [SHUTDOWN] = "admin", ++ [GETSTAT] = "getstat", ++ [INVALIDATE] = "admin", ++ [GETFDPW] = "shmempwd", ++ [GETFDGR] = "shmemgrp", ++ [GETFDHST] = "shmemhost", ++ [GETAI] = "gethost", ++ [INITGROUPS] = "getgrp", ++ [GETSERVBYNAME] = "getserv", ++ [GETSERVBYPORT] = "getserv", ++ [GETFDSERV] = "shmemserv", ++ [GETNETGRENT] = "getnetgrp", ++ [INNETGR] = "getnetgrp", ++ [GETFDNETGR] = "shmemnetgrp", + }; + + /* Store an entry ref to speed AVC decisions. */ +@@ -344,7 +339,16 @@ nscd_avc_init (void) + + + /* Check the permission from the caller (via getpeercon) to nscd. +- Returns 0 if access is allowed, 1 if denied, and -1 on error. */ ++ Returns 0 if access is allowed, 1 if denied, and -1 on error. ++ ++ The SELinux policy, enablement, and permission bits are all dynamic and the ++ caching done by glibc is not entirely correct. This nscd support should be ++ rewritten to use selinux_check_permission. A rewrite is risky though and ++ requires some refactoring. Currently we use symbolic mappings instead of ++ compile time constants (which SELinux upstream says are going away), and we ++ use security_deny_unknown to determine what to do if selinux-policy* doesn't ++ have a definition for the the permission or object class we are looking ++ up. */ + int + nscd_request_avc_has_perm (int fd, request_type req) + { +@@ -354,6 +358,33 @@ nscd_request_avc_has_perm (int fd, request_type req) + security_id_t ssid = NULL; + security_id_t tsid = NULL; + int rc = -1; ++ security_class_t sc_nscd; ++ access_vector_t perm; ++ int avc_deny_unknown; ++ ++ /* Check if SELinux denys or allows unknown object classes ++ and permissions. It is 0 if they are allowed, 1 if they ++ are not allowed and -1 on error. */ ++ if ((avc_deny_unknown = security_deny_unknown ()) == -1) ++ dbg_log (_("Error querying policy for undefined object classes " ++ "or permissions.")); ++ ++ /* Get the security class for nscd. If this fails we will likely be ++ unable to do anything unless avc_deny_unknown is 0. */ ++ sc_nscd = string_to_security_class ("nscd"); ++ if (perm == 0 && avc_deny_unknown == 1) ++ dbg_log (_("Error getting security class for nscd.")); ++ ++ /* Convert permission to AVC bits. */ ++ perm = string_to_av_perm (sc_nscd, perms[req]); ++ if (perm == 0 && avc_deny_unknown == 1) ++ dbg_log (_("Error translating permission name " ++ ""%s" to access vector bit."), perms[req]); ++ ++ /* If the nscd security class was not found or perms were not ++ found and AVC does not deny unknown values then allow it. */ ++ if ((sc_nscd == 0 || perm == 0) && avc_deny_unknown == 0) ++ return 0; + + if (getpeercon (fd, &scon) < 0) + { +@@ -372,15 +403,13 @@ nscd_request_avc_has_perm (int fd, request_type req) + goto out; + } + +-#ifndef NSCD__GETSERV +- if (perms[req] == 0) +- { +- dbg_log (_("compile-time support for database policy missing")); +- goto out; +- } +-#endif +- +- rc = avc_has_perm (ssid, tsid, SECCLASS_NSCD, perms[req], &aeref, NULL) < 0; ++ /* The SELinux API for avc_has_perm conflates access denied and error into ++ the return code -1, while nscd_request_avs_has_perm has distinct error ++ (-1) and denied (1) return codes. We map the avc_has_perm access denied or ++ error into an access denied at the nscd interface level (we do accurately ++ report error for the getpeercon, getcon, and avc_context_to_sid interfaces ++ used above). */ ++ rc = avc_has_perm (ssid, tsid, sc_nscd, perm, &aeref, NULL) < 0; + + out: + if (scon) diff --git a/src/patches/glibc/glibc-rh1028285.patch b/src/patches/glibc/glibc-rh1028285.patch new file mode 100644 index 0000000..3bf8c4f --- /dev/null +++ b/src/patches/glibc/glibc-rh1028285.patch @@ -0,0 +1,149 @@ +From a5675717e35a02a3eba7e13701c6f9c0d7222e13 Mon Sep 17 00:00:00 2001 +From: Adhemerval Zanella azanella@linux.vnet.ibm.com +Date: Fri, 7 Jun 2013 14:50:23 -0500 +Subject: [PATCH 2/2] PowerPC: gettimeofday optimization by using IFUNC + +Backport of ef26eece6331a1f6d959818e37c438cc7ce68e53 from master. +--- + sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h | 10 ++++ + sysdeps/unix/sysv/linux/powerpc/gettimeofday.c | 49 +++++++++++++++------- + 2 files changed, 44 insertions(+), 15 deletions(-) + +commit 76a9b9986141b1a7d9fd290c349d27fcee780c7a +Author: Adhemerval Zanella azanella@linux.vnet.ibm.com +Date: Thu Nov 7 05:34:22 2013 -0600 + + PowerPC: Fix vDSO missing ODP entries + + This patch fixes the vDSO symbol used directed in IFUNC resolver where + they do not have an associated ODP entry leading to undefined behavior + in some cases. It adds an artificial OPD static entry to such cases + and set its TOC to non 0 to avoid triggering lazy resolutions. + +commit d98720e07f67fbeec00f9e1347840404240d3c48 +Author: Adhemerval Zanella azanella@linux.vnet.ibm.com +Date: Mon Jan 20 12:29:51 2014 -0600 + + PowerPC: Fix gettimeofday ifunc selection + + The IFUNC selector for gettimeofday runs before _libc_vdso_platform_setup where + __vdso_gettimeofday is set. The selector then sets __gettimeofday (the internal + version used within GLIBC) to use the system call version instead of the vDSO one. + This patch changes the check if vDSO is available to get its value directly + instead of rely on __vdso_gettimeofday. + + This patch changes it by getting the vDSO value directly. + + It fixes BZ#16431. + +diff -pruN a/sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h b/sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h +--- a/sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h 2014-05-20 14:46:51.026871920 +0530 ++++ b/sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h 2014-05-20 14:44:39.294877321 +0530 +@@ -33,6 +33,36 @@ extern void *__vdso_get_tbfreq; + + extern void *__vdso_getcpu; + ++#if defined(__PPC64__) || defined(__powerpc64__) ++/* The correct solution is for _dl_vdso_vsym to return the address of the OPD ++ for the kernel VDSO function. That address would then be stored in the ++ __vdso_* variables and returned as the result of the IFUNC resolver function. ++ Yet, the kernel does not contain any OPD entries for the VDSO functions ++ (incomplete implementation). However, PLT relocations for IFUNCs still expect ++ the address of an OPD to be returned from the IFUNC resolver function (since ++ PLT entries on PPC64 are just copies of OPDs). The solution for now is to ++ create an artificial static OPD for each VDSO function returned by a resolver ++ function. The TOC value is set to a non-zero value to avoid triggering lazy ++ symbol resolution via .glink0/.plt0 for a zero TOC (requires thread-safe PLT ++ sequences) when the dynamic linker isn't prepared for it e.g. RTLD_NOW. None ++ of the kernel VDSO routines use the TOC or AUX values so any non-zero value ++ will work. Note that function pointer comparisons will not use this artificial ++ static OPD since those are resolved via ADDR64 relocations and will point at ++ the non-IFUNC default OPD for the symbol. Lastly, because the IFUNC relocations ++ are processed immediately at startup the resolver functions and this code need ++ not be thread-safe, but if the caller writes to a PLT slot it must do so in a ++ thread-safe manner with all the required barriers. */ ++#define VDSO_IFUNC_RET(value) \ ++ ({ \ ++ static Elf64_FuncDesc vdso_opd = { .fd_toc = ~0x0 }; \ ++ vdso_opd.fd_func = (Elf64_Addr)value; \ ++ &vdso_opd; \ ++ }) ++ ++#else ++#define VDSO_IFUNC_RET(value) ((void *) (value)) ++#endif ++ + #endif + + #endif /* _LIBC_VDSO_H */ +diff -pruN a/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c b/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c +--- a/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c 2010-05-04 16:57:23.000000000 +0530 ++++ b/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c 2014-05-20 14:44:39.298877321 +0530 +@@ -16,27 +16,51 @@ + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +-#include <sysdep.h> +-#include <bp-checks.h> +-#include <stddef.h> + #include <sys/time.h> +-#include <time.h> +-#include <hp-timing.h> + +-#undef __gettimeofday +-#include <bits/libc-vdso.h> ++#ifdef SHARED + +-/* Get the current time of day and timezone information, +- putting it into *TV and *TZ. If TZ is NULL, *TZ is not filled. +- Returns 0 on success, -1 on errors. */ +- +-int +-__gettimeofday (tv, tz) +- struct timeval *tv; +- struct timezone *tz; ++# include <dl-vdso.h> ++# include <bits/libc-vdso.h> ++# include <dl-machine.h> ++ ++void *gettimeofday_ifunc (void) __asm__ ("__gettimeofday"); ++ ++static int ++__gettimeofday_syscall (struct timeval *tv, struct timezone *tz) ++{ ++ return INLINE_SYSCALL (gettimeofday, 2, tv, tz); ++} ++ ++void * ++gettimeofday_ifunc (void) ++{ ++ PREPARE_VERSION (linux2615, "LINUX_2.6.15", 123718565); ++ ++ /* If the vDSO is not available we fall back syscall. */ ++ void *vdso_gettimeofday = _dl_vdso_vsym ("__kernel_gettimeofday", &linux2615); ++ return (vdso_gettimeofday ? VDSO_IFUNC_RET (vdso_gettimeofday) ++ : (void*)__gettimeofday_syscall); ++} ++asm (".type __gettimeofday, %gnu_indirect_function"); ++ ++/* This is doing "libc_hidden_def (__gettimeofday)" but the compiler won't ++ let us do it in C because it doesn't know we're defining __gettimeofday ++ here in this file. */ ++asm (".globl __GI___gettimeofday\n" ++ "__GI___gettimeofday = __gettimeofday"); ++ ++#else ++ ++# include <sysdep.h> ++# include <errno.h> ++ ++int ++__gettimeofday (struct timeval *tv, struct timezone *tz) + { +- return INLINE_VSYSCALL (gettimeofday, 2, CHECK_1 (tv), CHECK_1 (tz)); ++ return INLINE_SYSCALL (gettimeofday, 2, tv, tz); + } + ++#endif + INTDEF (__gettimeofday) + weak_alias (__gettimeofday, gettimeofday) diff --git a/src/patches/glibc/glibc-rh1039988.patch b/src/patches/glibc/glibc-rh1039988.patch new file mode 100644 index 0000000..253b311 --- /dev/null +++ b/src/patches/glibc/glibc-rh1039988.patch @@ -0,0 +1,141 @@ +commit 9a3c6a6ff602c88d7155139a7d7d0000b7b7e946 +Author: Siddhesh Poyarekar siddhesh@redhat.com +Date: Thu Jan 2 10:05:27 2014 +0530 + + Fix return code from getent netgroup when the netgroup is not found (bz #16366) + + nscd incorrectly returns a success even when the netgroup in question + is not found and adds a positive result in the cache. this patch + fixes this behaviour by adding a negative lookup entry to cache and + returning an error when the netgroup is not found. + +diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c +index 50936ee..9fc1664 100644 +--- a/nscd/netgroupcache.c ++++ b/nscd/netgroupcache.c +@@ -65,6 +65,55 @@ struct dataset + char strdata[0]; + }; + ++/* Sends a notfound message and prepares a notfound dataset to write to the ++ cache. Returns true if there was enough memory to allocate the dataset and ++ returns the dataset in DATASETP, total bytes to write in TOTALP and the ++ timeout in TIMEOUTP. KEY_COPY is set to point to the copy of the key in the ++ dataset. */ ++static bool ++do_notfound (struct database_dyn *db, int fd, request_header *req, ++ const char *key, struct dataset **datasetp, ssize_t *totalp, ++ time_t *timeoutp, char **key_copy) ++{ ++ struct dataset *dataset; ++ ssize_t total; ++ time_t timeout; ++ bool cacheable = false; ++ ++ total = sizeof (notfound); ++ timeout = time (NULL) + db->negtimeout; ++ ++ if (fd != -1) ++ TEMP_FAILURE_RETRY (send (fd, ¬found, total, MSG_NOSIGNAL)); ++ ++ dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len, 1); ++ /* If we cannot permanently store the result, so be it. */ ++ if (dataset != NULL) ++ { ++ dataset->head.allocsize = sizeof (struct dataset) + req->key_len; ++ dataset->head.recsize = total; ++ dataset->head.notfound = true; ++ dataset->head.nreloads = 0; ++ dataset->head.usable = true; ++ ++ /* Compute the timeout time. */ ++ timeout = dataset->head.timeout = time (NULL) + db->negtimeout; ++ dataset->head.ttl = db->negtimeout; ++ ++ /* This is the reply. */ ++ memcpy (&dataset->resp, ¬found, total); ++ ++ /* Copy the key data. */ ++ memcpy (dataset->strdata, key, req->key_len); ++ *key_copy = dataset->strdata; ++ ++ cacheable = true; ++ } ++ *timeoutp = timeout; ++ *totalp = total; ++ *datasetp = dataset; ++ return cacheable; ++} + + static time_t + addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, +@@ -84,6 +133,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, + struct dataset *dataset; + bool cacheable = false; + ssize_t total; ++ bool found = false; + + char *key_copy = NULL; + struct __netgrent data; +@@ -103,35 +153,8 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, + && __nss_database_lookup ("netgroup", NULL, NULL, &netgroup_database)) + { + /* No such service. */ +- total = sizeof (notfound); +- timeout = time (NULL) + db->negtimeout; +- +- if (fd != -1) +- TEMP_FAILURE_RETRY (send (fd, ¬found, total, MSG_NOSIGNAL)); +- +- dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len, 1); +- /* If we cannot permanently store the result, so be it. */ +- if (dataset != NULL) +- { +- dataset->head.allocsize = sizeof (struct dataset) + req->key_len; +- dataset->head.recsize = total; +- dataset->head.notfound = true; +- dataset->head.nreloads = 0; +- dataset->head.usable = true; +- +- /* Compute the timeout time. */ +- timeout = dataset->head.timeout = time (NULL) + db->negtimeout; +- dataset->head.ttl = db->negtimeout; +- +- /* This is the reply. */ +- memcpy (&dataset->resp, ¬found, total); +- +- /* Copy the key data. */ +- memcpy (dataset->strdata, key, req->key_len); +- +- cacheable = true; +- } +- ++ cacheable = do_notfound (db, fd, req, key, &dataset, &total, &timeout, ++ &key_copy); + goto writeout; + } + +@@ -167,6 +190,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, + + if (status == NSS_STATUS_SUCCESS) + { ++ found = true; + union + { + enum nss_status (*f) (struct __netgrent *, char *, size_t, +@@ -326,6 +350,15 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, + } + } + ++ /* No results. Return a failure and write out a notfound record in the ++ cache. */ ++ if (!found) ++ { ++ cacheable = do_notfound (db, fd, req, key, &dataset, &total, &timeout, ++ &key_copy); ++ goto writeout; ++ } ++ + total = buffilled; + + /* Fill in the dataset. */ diff --git a/src/patches/glibc/glibc-rh1043557.patch b/src/patches/glibc/glibc-rh1043557.patch new file mode 100644 index 0000000..affbe96 --- /dev/null +++ b/src/patches/glibc/glibc-rh1043557.patch @@ -0,0 +1,145 @@ +commit af37a8a3496327a6e5617a2c76f17aa1e8db835e +Author: Siddhesh Poyarekar siddhesh@redhat.com +Date: Mon Jan 27 11:32:44 2014 +0530 + + Avoid undefined behaviour in netgroupcache + + Using a buffer after it has been reallocated is undefined behaviour, + so get offsets of the triplets in the old buffer before reallocating + it. + +commit 5d41dadf31bc8a2f9c34c40d52a442d3794e405c +Author: Siddhesh Poyarekar siddhesh@redhat.com +Date: Fri Jan 24 13:51:15 2014 +0530 + + Adjust pointers to triplets in netgroup query data (BZ #16474) + + The _nss_*_getnetgrent_r query populates the netgroup results in the + allocated buffer and then sets the result triplet to point to strings + in the buffer. This is a problem when the buffer is reallocated since + the pointers to the triplet strings are no longer valid. The pointers + need to be adjusted so that they now point to strings in the + reallocated buffer. + +commit 980cb5180e1b71224a57ca52b995c959b7148c09 +Author: Siddhesh Poyarekar siddhesh@redhat.com +Date: Thu Jan 16 10:20:22 2014 +0530 + + Don't use alloca in addgetnetgrentX (BZ #16453) + + addgetnetgrentX has a buffer which is grown as per the needs of the + requested size either by using alloca or by falling back to malloc if + the size is larger than 1K. There are two problems with the alloca + bits: firstly, it doesn't really extend the buffer since it does not + use the return value of the extend_alloca macro, which is the location + of the reallocated buffer. Due to this the buffer does not actually + extend itself and hence a subsequent write may overwrite stuff on the + stack. + + The second problem is more subtle - the buffer growth on the stack is + discontinuous due to block scope local variables. Combine that with + the fact that unlike realloc, extend_alloca does not copy over old + content and you have a situation where the buffer just has garbage in + the space where it should have had data. + + This could have been fixed by adding code to copy over old data + whenever we call extend_alloca, but it seems unnecessarily + complicated. This code is not exactly a performance hotspot (it's + called when there is a cache miss, so factors like network lookup or + file reads will dominate over memory allocation/reallocation), so this + premature optimization is unnecessary. + + Thanks Brad Hubbard bhubbard@redhat.com for his help with debugging + the problem. + +diff -pruN glibc-2.12-2-gc4ccff1/nscd/netgroupcache.c glibc-2.12-2-gc4ccff1.patched/nscd/netgroupcache.c +--- glibc-2.12-2-gc4ccff1/nscd/netgroupcache.c 2014-04-09 12:13:58.618582111 +0530 ++++ glibc-2.12-2-gc4ccff1.patched/nscd/netgroupcache.c 2014-04-09 12:07:21.486598665 +0530 +@@ -93,7 +93,6 @@ addgetnetgrentX (struct database_dyn *db + size_t buffilled = sizeof (*dataset); + char *buffer = NULL; + size_t nentries = 0; +- bool use_malloc = false; + size_t group_len = strlen (key) + 1; + union + { +@@ -138,7 +137,7 @@ addgetnetgrentX (struct database_dyn *db + } + + memset (&data, '\0', sizeof (data)); +- buffer = alloca (buflen); ++ buffer = xmalloc (buflen); + first_needed.elem.next = &first_needed.elem; + memcpy (first_needed.elem.name, key, group_len); + data.needed_groups = &first_needed.elem; +@@ -218,21 +217,24 @@ addgetnetgrentX (struct database_dyn *db + + if (buflen - req->key_len - bufused < needed) + { +- size_t newsize = MAX (2 * buflen, +- buflen + 2 * needed); +- if (use_malloc || newsize > 1024 * 1024) +- { +- buflen = newsize; +- char *newbuf = xrealloc (use_malloc +- ? buffer +- : NULL, +- buflen); +- +- buffer = newbuf; +- use_malloc = true; +- } +- else +- extend_alloca (buffer, buflen, newsize); ++ buflen += MAX (buflen, 2 * needed); ++ /* Save offset in the old buffer. We don't ++ bother with the NULL check here since ++ we'll do that later anyway. */ ++ size_t nhostdiff = nhost - buffer; ++ size_t nuserdiff = nuser - buffer; ++ size_t ndomaindiff = ndomain - buffer; ++ ++ char *newbuf = xrealloc (buffer, buflen); ++ /* Fix up the triplet pointers into the new ++ buffer. */ ++ nhost = (nhost ? newbuf + nhostdiff ++ : NULL); ++ nuser = (nuser ? newbuf + nuserdiff ++ : NULL); ++ ndomain = (ndomain ? newbuf + ndomaindiff ++ : NULL); ++ buffer = newbuf; + } + + nhost = memcpy (buffer + bufused, +@@ -299,18 +301,8 @@ addgetnetgrentX (struct database_dyn *db + } + else if (status == NSS_STATUS_UNAVAIL && e == ERANGE) + { +- size_t newsize = 2 * buflen; +- if (use_malloc || newsize > 1024 * 1024) +- { +- buflen = newsize; +- char *newbuf = xrealloc (use_malloc +- ? buffer : NULL, buflen); +- +- buffer = newbuf; +- use_malloc = true; +- } +- else +- extend_alloca (buffer, buflen, newsize); ++ buflen *= 2; ++ buffer = xrealloc (buffer, buflen); + } + } + +@@ -446,8 +438,7 @@ addgetnetgrentX (struct database_dyn *db + } + + out: +- if (use_malloc) +- free (buffer); ++ free (buffer); + + *resultp = dataset; + diff --git a/src/patches/glibc/glibc-rh1053178.patch b/src/patches/glibc/glibc-rh1053178.patch new file mode 100644 index 0000000..a662cfe --- /dev/null +++ b/src/patches/glibc/glibc-rh1053178.patch @@ -0,0 +1,214 @@ +# +# Based on the commit: +# +# commit 6c82a2f8d7c8e21e39237225c819f182ae438db3 +# Author: Carlos O'Donell carlos@redhat.com +# Date: Fri Sep 6 01:02:30 2013 -0400 +# +# Coordinate IPv6 definitions for Linux and glibc +# +# This change synchronizes the glibc headers with the Linux kernel +# headers and arranges to coordinate the definition of structures +# already defined the Linux kernel UAPI headers. +# +# It is now safe to include glibc's netinet/in.h or Linux's linux/in6.h +# in any order in a userspace application and you will get the same +# ABI. The ABI is guaranteed by UAPI and glibc. +# +# 2013-09-05 Carlos O'Donell carlos@redhat.com +# Cong Wang amwang@redhat.com +# +# * sysdeps/unix/sysv/linux/bits/in.h +# [_UAPI_LINUX_IN6_H]: Define __USE_KERNEL_IPV6_DEFS. +# * inet/netinet/in.h: Move in_addr definition and bits/in.h inclusion +# before __USE_KERNEL_IPV6_DEFS uses. +# * inet/netinet/in.h [!__USE_KERNEL_IPV6_DEFS]: Define IPPROTO_MH, and +# IPPROTO_BEETPH. +# [__USE_KERNEL_IPV6_DEFS]: Don't define any of IPPROTO_*, in6_addr, +# sockaddr_in6, or ipv6_mreq. +# +diff -urN glibc-2.12-2-gc4ccff1/inet/netinet/in.h glibc-2.12-2-gc4ccff1.mod/inet/netinet/in.h +--- glibc-2.12-2-gc4ccff1/inet/netinet/in.h 2010-05-04 07:27:23.000000000 -0400 ++++ glibc-2.12-2-gc4ccff1.mod/inet/netinet/in.h 2015-02-18 13:06:56.436802873 -0500 +@@ -28,13 +28,21 @@ + + __BEGIN_DECLS + ++/* Internet address. */ ++typedef uint32_t in_addr_t; ++struct in_addr ++ { ++ in_addr_t s_addr; ++ }; ++ ++/* Get system-specific definitions. */ ++#include <bits/in.h> ++ + /* Standard well-defined IP protocols. */ + enum + { + IPPROTO_IP = 0, /* Dummy protocol for TCP. */ + #define IPPROTO_IP IPPROTO_IP +- IPPROTO_HOPOPTS = 0, /* IPv6 Hop-by-Hop options. */ +-#define IPPROTO_HOPOPTS IPPROTO_HOPOPTS + IPPROTO_ICMP = 1, /* Internet Control Message Protocol. */ + #define IPPROTO_ICMP IPPROTO_ICMP + IPPROTO_IGMP = 2, /* Internet Group Management Protocol. */ +@@ -57,10 +65,6 @@ + #define IPPROTO_DCCP IPPROTO_DCCP + IPPROTO_IPV6 = 41, /* IPv6 header. */ + #define IPPROTO_IPV6 IPPROTO_IPV6 +- IPPROTO_ROUTING = 43, /* IPv6 routing header. */ +-#define IPPROTO_ROUTING IPPROTO_ROUTING +- IPPROTO_FRAGMENT = 44, /* IPv6 fragmentation header. */ +-#define IPPROTO_FRAGMENT IPPROTO_FRAGMENT + IPPROTO_RSVP = 46, /* Reservation Protocol. */ + #define IPPROTO_RSVP IPPROTO_RSVP + IPPROTO_GRE = 47, /* General Routing Encapsulation. */ +@@ -69,14 +73,10 @@ + #define IPPROTO_ESP IPPROTO_ESP + IPPROTO_AH = 51, /* authentication header. */ + #define IPPROTO_AH IPPROTO_AH +- IPPROTO_ICMPV6 = 58, /* ICMPv6. */ +-#define IPPROTO_ICMPV6 IPPROTO_ICMPV6 +- IPPROTO_NONE = 59, /* IPv6 no next header. */ +-#define IPPROTO_NONE IPPROTO_NONE +- IPPROTO_DSTOPTS = 60, /* IPv6 destination options. */ +-#define IPPROTO_DSTOPTS IPPROTO_DSTOPTS + IPPROTO_MTP = 92, /* Multicast Transport Protocol. */ + #define IPPROTO_MTP IPPROTO_MTP ++ IPPROTO_BEETPH = 94, /* IP option pseudo header for BEET. */ ++#define IPPROTO_BEETPH IPPROTO_BEETPH + IPPROTO_ENCAP = 98, /* Encapsulation Header. */ + #define IPPROTO_ENCAP IPPROTO_ENCAP + IPPROTO_PIM = 103, /* Protocol Independent Multicast. */ +@@ -92,6 +92,28 @@ + IPPROTO_MAX + }; + ++/* If __USER_KERNEL_IPV6_DEFS is defined then the user has included the kernel ++ network headers first and we should use those ABI-identical definitions ++ instead of our own. */ ++#ifndef __USE_KERNEL_IPV6_DEFS ++enum ++ { ++ IPPROTO_HOPOPTS = 0, /* IPv6 Hop-by-Hop options. */ ++#define IPPROTO_HOPOPTS IPPROTO_HOPOPTS ++ IPPROTO_ROUTING = 43, /* IPv6 routing header. */ ++#define IPPROTO_ROUTING IPPROTO_ROUTING ++ IPPROTO_FRAGMENT = 44, /* IPv6 fragmentation header. */ ++#define IPPROTO_FRAGMENT IPPROTO_FRAGMENT ++ IPPROTO_ICMPV6 = 58, /* ICMPv6. */ ++#define IPPROTO_ICMPV6 IPPROTO_ICMPV6 ++ IPPROTO_NONE = 59, /* IPv6 no next header. */ ++#define IPPROTO_NONE IPPROTO_NONE ++ IPPROTO_DSTOPTS = 60, /* IPv6 destination options. */ ++#define IPPROTO_DSTOPTS IPPROTO_DSTOPTS ++ IPPROTO_MH = 135, /* IPv6 mobility header. */ ++#define IPPROTO_MH IPPROTO_MH ++ }; ++#endif /* !__USE_KERNEL_IPV6_DEFS */ + + /* Type to represent a port. */ + typedef uint16_t in_port_t; +@@ -136,15 +158,6 @@ + IPPORT_USERRESERVED = 5000 + }; + +- +-/* Internet address. */ +-typedef uint32_t in_addr_t; +-struct in_addr +- { +- in_addr_t s_addr; +- }; +- +- + /* Definitions of the bits in an Internet address integer. + + On subnets, host and network parts are found according to +@@ -193,7 +206,7 @@ + #define INADDR_ALLRTRS_GROUP ((in_addr_t) 0xe0000002) /* 224.0.0.2 */ + #define INADDR_MAX_LOCAL_GROUP ((in_addr_t) 0xe00000ff) /* 224.0.0.255 */ + +- ++#ifndef __USE_KERNEL_IPV6_DEFS + /* IPv6 address */ + struct in6_addr + { +@@ -211,6 +224,7 @@ + # define s6_addr32 __in6_u.__u6_addr32 + #endif + }; ++#endif /* !__USE_KERNEL_IPV6_DEFS */ + + extern const struct in6_addr in6addr_any; /* :: */ + extern const struct in6_addr in6addr_loopback; /* ::1 */ +@@ -235,6 +249,7 @@ + sizeof (struct in_addr)]; + }; + ++#ifndef __USE_KERNEL_IPV6_DEFS + /* Ditto, for IPv6. */ + struct sockaddr_in6 + { +@@ -244,7 +259,7 @@ + struct in6_addr sin6_addr; /* IPv6 address */ + uint32_t sin6_scope_id; /* IPv6 scope-id */ + }; +- ++#endif /* !__USE_KERNEL_IPV6_DEFS */ + + #if defined __USE_MISC || defined __USE_GNU + /* IPv4 multicast request. */ +@@ -270,7 +285,7 @@ + }; + #endif + +- ++#ifndef __USE_KERNEL_IPV6_DEFS + /* Likewise, for IPv6. */ + struct ipv6_mreq + { +@@ -280,7 +295,7 @@ + /* local interface */ + unsigned int ipv6mr_interface; + }; +- ++#endif /* !__USE_KERNEL_IPV6_DEFS */ + + #if defined __USE_MISC || defined __USE_GNU + /* Multicast group request. */ +@@ -351,10 +366,6 @@ + * sizeof (struct sockaddr_storage))) + #endif + +- +-/* Get system-specific definitions. */ +-#include <bits/in.h> +- + /* Functions to convert between host and network byte order. + + Please note that these functions normally take `unsigned long int' or +diff -urN glibc-2.12-2-gc4ccff1/sysdeps/unix/sysv/linux/bits/in.h glibc-2.12-2-gc4ccff1.mod/sysdeps/unix/sysv/linux/bits/in.h +--- glibc-2.12-2-gc4ccff1/sysdeps/unix/sysv/linux/bits/in.h 2015-02-18 13:04:15.547734092 -0500 ++++ glibc-2.12-2-gc4ccff1.mod/sysdeps/unix/sysv/linux/bits/in.h 2015-02-18 13:06:56.436802873 -0500 +@@ -22,6 +22,18 @@ + # error "Never use <bits/in.h> directly; include <netinet/in.h> instead." + #endif + ++/* If the application has already included linux/in6.h from a linux-based ++ kernel then we will not define the IPv6 IPPROTO_* defines, in6_addr (nor the ++ defines), sockaddr_in6, or ipv6_mreq. The ABI used by the linux-kernel and ++ glibc match exactly. Neither the linux kernel nor glibc should break this ++ ABI without coordination. */ ++#ifdef _UAPI_LINUX_IN6_H ++/* This is not quite the same API since the kernel always defines s6_addr16 and ++ s6_addr32. This is not a violation of POSIX since POSIX says "at least the ++ following member" and that holds true. */ ++# define __USE_KERNEL_IPV6_DEFS ++#endif ++ + /* Options for use with `getsockopt' and `setsockopt' at the IP level. + The first word in the comment at the right is the data type used; + "bool" means a boolean value stored in an `int'. */ diff --git a/src/patches/glibc/glibc-rh1054846.patch b/src/patches/glibc/glibc-rh1054846.patch new file mode 100644 index 0000000..50b4109 --- /dev/null +++ b/src/patches/glibc/glibc-rh1054846.patch @@ -0,0 +1,57 @@ +commit fbd6b5a4052316f7eb03c4617eebfaafc59dcc06 +Author: Siddhesh Poyarekar siddhesh@redhat.com +Date: Thu Mar 27 07:15:22 2014 +0530 + + Fix nscd lookup for innetgr when netgroup has wildcards (BZ #16758) + + nscd works correctly when the request in innetgr is a wildcard, + i.e. when one or more of host, user or domain parameters is NULL. + However, it does not work when the the triplet in the netgroup + definition has a wildcard. This is easy to reproduce for a triplet + defined as follows: + + foonet (,foo,) + + Here, an innetgr call that looks like this: + + innetgr ("foonet", "foohost", "foo", NULL); + + should succeed and so should: + + innetgr ("foonet", NULL, "foo", "foodomain"); + + It does succeed with nscd disabled, but not with nscd enabled. This + fix adds this additional check for all three parts of the triplet so + that it gives the correct result. + + [BZ #16758] + * nscd/netgroupcache.c (addinnetgrX): Succeed if triplet has + blank values. + +diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c +index 5ba1e1f..5d15aa4 100644 +--- a/nscd/netgroupcache.c ++++ b/nscd/netgroupcache.c +@@ -560,15 +560,19 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req, + { + bool success = true; + +- if (host != NULL) ++ /* For the host, user and domain in each triplet, we assume success ++ if the value is blank because that is how the wildcard entry to ++ match anything is stored in the netgroup cache. */ ++ if (host != NULL && *triplets != '\0') + success = strcmp (host, triplets) == 0; + triplets = (const char *) rawmemchr (triplets, '\0') + 1; + +- if (success && user != NULL) ++ if (success && user != NULL && *triplets != '\0') + success = strcmp (user, triplets) == 0; + triplets = (const char *) rawmemchr (triplets, '\0') + 1; + +- if (success && (domain == NULL || strcmp (domain, triplets) == 0)) ++ if (success && (domain == NULL || *triplets == '\0' ++ || strcmp (domain, triplets) == 0)) + { + dataset->resp.result = 1; + break; diff --git a/src/patches/glibc/glibc-rh1066724.patch b/src/patches/glibc/glibc-rh1066724.patch new file mode 100644 index 0000000..a03f1d1 --- /dev/null +++ b/src/patches/glibc/glibc-rh1066724.patch @@ -0,0 +1,620 @@ +diff --git a/malloc/Makefile b/malloc/Makefile +index e7ec1ab..5330a3b 100644 +--- a/malloc/Makefile ++++ b/malloc/Makefile +@@ -27,7 +27,8 @@ all: + dist-headers := malloc.h + headers := $(dist-headers) obstack.h mcheck.h + tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \ +- tst-mallocstate tst-mcheck tst-mallocfork tst-trim1 ++ tst-mallocstate tst-mcheck tst-mallocfork tst-trim1 \ ++ tst-malloc-backtrace + test-srcs = tst-mtrace + + distribute = thread-m.h mtrace.pl mcheck-init.c stackinfo.h memusage.h \ +@@ -49,6 +50,9 @@ extra-libs-others = $(extra-libs) + libmemusage-routines = memusage + libmemusage-inhibit-o = $(filter-out .os,$(object-suffixes)) + ++$(objpfx)tst-malloc-backtrace: $(common-objpfx)nptl/libpthread.so \ ++ $(common-objpfx)nptl/libpthread_nonshared.a ++ + # These should be removed by `make clean'. + extra-objs = mcheck-init.o libmcheck.a + +diff --git a/malloc/arena.c b/malloc/arena.c +index 18bea2b..5180516 100644 +--- a/malloc/arena.c ++++ b/malloc/arena.c +@@ -123,7 +123,7 @@ int __malloc_initialized = -1; + + #ifdef PER_THREAD + #define arena_lock(ptr, size) do { \ +- if(ptr) \ ++ if(ptr && !arena_is_corrupt (ptr)) \ + (void)mutex_lock(&ptr->mutex); \ + else \ + ptr = arena_get2(ptr, (size), false); \ +@@ -1011,7 +1011,21 @@ reused_arena (bool retrying) + if (retrying && result == &main_arena) + result = result->next; + +- /* No arena available. Wait for the next in line. */ ++ /* Make sure that the arena we get is not corrupted. */ ++ mstate begin = result; ++ while (arena_is_corrupt (result)) ++ { ++ result = result->next; ++ if (result == begin) ++ break; ++ } ++ ++ /* We could not find any arena that was either not corrupted or not the one ++ we wanted to avoid. */ ++ if (result == begin) ++ return NULL; ++ ++ /* No arena available without contention. Wait for the next in line. */ + (void)mutex_lock(&result->mutex); + + out: +diff --git a/malloc/hooks.c b/malloc/hooks.c +index cc83d21..38d2542 100644 +--- a/malloc/hooks.c ++++ b/malloc/hooks.c +@@ -220,7 +220,8 @@ top_check() + return 0; + + mutex_unlock(&main_arena); +- malloc_printerr (check_action, "malloc: top chunk is corrupt", t); ++ malloc_printerr (check_action, "malloc: top chunk is corrupt", t, ++ &main_arena); + mutex_lock(&main_arena); + + /* Try to set up a new top chunk. */ +@@ -283,7 +284,7 @@ free_check(mem, caller) Void_t* mem; const Void_t *caller; + if(!p) { + (void)mutex_unlock(&main_arena.mutex); + +- malloc_printerr(check_action, "free(): invalid pointer", mem); ++ malloc_printerr(check_action, "free(): invalid pointer", mem, &main_arena); + return; + } + #if HAVE_MMAP +@@ -329,7 +330,8 @@ realloc_check(oldmem, bytes, caller) + const mchunkptr oldp = mem2chunk_check(oldmem, &magic_p); + (void)mutex_unlock(&main_arena.mutex); + if(!oldp) { +- malloc_printerr(check_action, "realloc(): invalid pointer", oldmem); ++ malloc_printerr(check_action, "realloc(): invalid pointer", oldmem, ++ &main_arena); + return malloc_check(bytes, NULL); + } + const INTERNAL_SIZE_T oldsize = chunksize(oldp); +diff --git a/malloc/malloc.c b/malloc/malloc.c +index 597c7b0..20ac534 100644 +--- a/malloc/malloc.c ++++ b/malloc/malloc.c +@@ -1633,7 +1633,7 @@ static size_t mUSABLe(Void_t*); + static void mSTATs(void); + static int mALLOPt(int, int); + static struct mallinfo mALLINFo(mstate); +-static void malloc_printerr(int action, const char *str, void *ptr); ++static void malloc_printerr(int action, const char *str, void *ptr, mstate av); + + static Void_t* internal_function mem2mem_check(Void_t *p, size_t sz); + static int internal_function top_check(void); +@@ -2114,7 +2114,8 @@ typedef struct malloc_chunk* mbinptr; + BK = P->bk; \ + if (__builtin_expect (FD->bk != P || BK->fd != P, 0)) { \ + mutex_unlock(&(AV)->mutex); \ +- malloc_printerr (check_action, "corrupted double-linked list", P); \ ++ malloc_printerr (check_action, "corrupted double-linked list", P, \ ++ AV); \ + mutex_lock(&(AV)->mutex); \ + } else { \ + FD->bk = BK; \ +@@ -2344,6 +2345,15 @@ typedef struct malloc_chunk* mfastbinptr; + #define set_noncontiguous(M) ((M)->flags |= NONCONTIGUOUS_BIT) + #define set_contiguous(M) ((M)->flags &= ~NONCONTIGUOUS_BIT) + ++/* ARENA_CORRUPTION_BIT is set if a memory corruption was detected on the ++ arena. Such an arena is no longer used to allocate chunks. Chunks ++ allocated in that arena before detecting corruption are not freed. */ ++ ++#define ARENA_CORRUPTION_BIT (4U) ++ ++#define arena_is_corrupt(A) (((A)->flags & ARENA_CORRUPTION_BIT)) ++#define set_arena_corrupt(A) ((A)->flags |= ARENA_CORRUPTION_BIT) ++ + /* + Set value of max_fast. + Use impossibly small value if 0. +@@ -3002,8 +3012,9 @@ static Void_t* sYSMALLOc(nb, av) INTERNAL_SIZE_T nb; mstate av; + rather than expanding top. + */ + +- if ((unsigned long)(nb) >= (unsigned long)(mp_.mmap_threshold) && +- (mp_.n_mmaps < mp_.n_mmaps_max)) { ++ if (av == NULL ++ || ((unsigned long)(nb) >= (unsigned long)(mp_.mmap_threshold) && ++ (mp_.n_mmaps < mp_.n_mmaps_max))) { + + char* mm; /* return value from mmap call*/ + +@@ -3079,6 +3090,10 @@ static Void_t* sYSMALLOc(nb, av) INTERNAL_SIZE_T nb; mstate av; + } + #endif + ++ /* There are no usable arenas and mmap also failed. */ ++ if (av == NULL) ++ return 0; ++ + /* Record incoming configuration of top */ + + old_top = av->top; +@@ -3260,7 +3275,7 @@ static Void_t* sYSMALLOc(nb, av) INTERNAL_SIZE_T nb; mstate av; + else if (contiguous(av) && old_size && brk < old_end) { + /* Oops! Someone else killed our space.. Can't touch anything. */ + mutex_unlock(&av->mutex); +- malloc_printerr (3, "break adjusted to free malloc space", brk); ++ malloc_printerr (3, "break adjusted to free malloc space", brk, av); + mutex_lock(&av->mutex); + } + +@@ -3542,7 +3557,7 @@ munmap_chunk(p) mchunkptr p; + if (__builtin_expect (((block | total_size) & (mp_.pagesize - 1)) != 0, 0)) + { + malloc_printerr (check_action, "munmap_chunk(): invalid pointer", +- chunk2mem (p)); ++ chunk2mem (p), NULL); + return; + } + +@@ -3625,65 +3640,31 @@ public_mALLOc(size_t bytes) + if (__builtin_expect (hook != NULL, 0)) + return (*hook)(bytes, RETURN_ADDRESS (0)); + +- arena_lookup(ar_ptr); +-#if 0 +- // XXX We need double-word CAS and fastbins must be extended to also +- // XXX hold a generation counter for each entry. +- if (ar_ptr) { +- INTERNAL_SIZE_T nb; /* normalized request size */ +- checked_request2size(bytes, nb); +- if (nb <= get_max_fast ()) { +- long int idx = fastbin_index(nb); +- mfastbinptr* fb = &fastbin (ar_ptr, idx); +- mchunkptr pp = *fb; +- mchunkptr v; +- do +- { +- v = pp; +- if (v == NULL) +- break; +- } +- while ((pp = catomic_compare_and_exchange_val_acq (fb, v->fd, v)) != v); +- if (v != 0) { +- if (__builtin_expect (fastbin_index (chunksize (v)) != idx, 0)) +- malloc_printerr (check_action, "malloc(): memory corruption (fast)", +- chunk2mem (v)); +- check_remalloced_chunk(ar_ptr, v, nb); +- void *p = chunk2mem(v); +- if (__builtin_expect (perturb_byte, 0)) +- alloc_perturb (p, bytes); +- return p; +- } +- } +- } +-#endif ++ arena_get(ar_ptr, bytes); + +- arena_lock(ar_ptr, bytes); +- if(!ar_ptr) +- return 0; + victim = _int_malloc(ar_ptr, bytes); +- if(!victim) { ++ if(!victim && ar_ptr != NULL) { + /* Maybe the failure is due to running out of mmapped areas. */ + if(ar_ptr != &main_arena) { + (void)mutex_unlock(&ar_ptr->mutex); + ar_ptr = &main_arena; + (void)mutex_lock(&ar_ptr->mutex); + victim = _int_malloc(ar_ptr, bytes); +- (void)mutex_unlock(&ar_ptr->mutex); + } else { + #if USE_ARENAS + /* ... or sbrk() has failed and there is still a chance to mmap() */ + mstate prev = ar_ptr->next ? ar_ptr : 0; + (void)mutex_unlock(&ar_ptr->mutex); + ar_ptr = arena_get2(prev, bytes, true); +- if(ar_ptr) { ++ if(ar_ptr) + victim = _int_malloc(ar_ptr, bytes); +- (void)mutex_unlock(&ar_ptr->mutex); +- } + #endif + } +- } else ++ } ++ ++ if (ar_ptr != NULL) + (void)mutex_unlock(&ar_ptr->mutex); ++ + assert(!victim || chunk_is_mmapped(mem2chunk(victim)) || + ar_ptr == arena_for_chunk(mem2chunk(victim))); + return victim; +@@ -3773,6 +3754,11 @@ public_rEALLOc(Void_t* oldmem, size_t bytes) + /* its size */ + const INTERNAL_SIZE_T oldsize = chunksize(oldp); + ++ if (chunk_is_mmapped (oldp)) ++ ar_ptr = NULL; ++ else ++ ar_ptr = arena_for_chunk (oldp); ++ + /* Little security check which won't hurt performance: the + allocator never wrapps around at the end of the address space. + Therefore we can exclude some size values which might appear +@@ -3780,7 +3766,8 @@ public_rEALLOc(Void_t* oldmem, size_t bytes) + if (__builtin_expect ((uintptr_t) oldp > (uintptr_t) -oldsize, 0) + || __builtin_expect (misaligned_chunk (oldp), 0)) + { +- malloc_printerr (check_action, "realloc(): invalid pointer", oldmem); ++ malloc_printerr (check_action, "realloc(): invalid pointer", oldmem, ++ ar_ptr); + return NULL; + } + +@@ -3806,7 +3793,6 @@ public_rEALLOc(Void_t* oldmem, size_t bytes) + } + #endif + +- ar_ptr = arena_for_chunk(oldp); + #if THREAD_STATS + if(!mutex_trylock(&ar_ptr->mutex)) + ++(ar_ptr->stat_lock_direct); +@@ -3887,31 +3873,29 @@ public_mEMALIGn(size_t alignment, size_t bytes) + } + + arena_get(ar_ptr, bytes + alignment + MINSIZE); +- if(!ar_ptr) +- return 0; + p = _int_memalign(ar_ptr, alignment, bytes); +- if(!p) { ++ if(!p && ar_ptr != NULL) { + /* Maybe the failure is due to running out of mmapped areas. */ + if(ar_ptr != &main_arena) { + (void)mutex_unlock(&ar_ptr->mutex); + ar_ptr = &main_arena; + (void)mutex_lock(&ar_ptr->mutex); + p = _int_memalign(ar_ptr, alignment, bytes); +- (void)mutex_unlock(&ar_ptr->mutex); + } else { + #if USE_ARENAS + /* ... or sbrk() has failed and there is still a chance to mmap() */ + mstate prev = ar_ptr->next ? ar_ptr : 0; + (void)mutex_unlock(&ar_ptr->mutex); + ar_ptr = arena_get2(prev, bytes, true); +- if(ar_ptr) { ++ if(ar_ptr) + p = _int_memalign(ar_ptr, alignment, bytes); +- (void)mutex_unlock(&ar_ptr->mutex); +- } + #endif + } +- } else ++ } ++ ++ if (ar_ptr != NULL) + (void)mutex_unlock(&ar_ptr->mutex); ++ + assert(!p || chunk_is_mmapped(mem2chunk(p)) || + ar_ptr == arena_for_chunk(mem2chunk(p))); + return p; +@@ -3945,31 +3929,29 @@ public_vALLOc(size_t bytes) + return (*hook)(pagesz, bytes, RETURN_ADDRESS (0)); + + arena_get(ar_ptr, bytes + pagesz + MINSIZE); +- if(!ar_ptr) +- return 0; + p = _int_valloc(ar_ptr, bytes); +- if(!p) { ++ if(!p && ar_ptr != NULL) { + /* Maybe the failure is due to running out of mmapped areas. */ + if(ar_ptr != &main_arena) { + (void)mutex_unlock(&ar_ptr->mutex); + ar_ptr = &main_arena; + (void)mutex_lock(&ar_ptr->mutex); + p = _int_memalign(ar_ptr, pagesz, bytes); +- (void)mutex_unlock(&ar_ptr->mutex); + } else { + #if USE_ARENAS + /* ... or sbrk() has failed and there is still a chance to mmap() */ + mstate prev = ar_ptr->next ? ar_ptr : 0; + (void)mutex_unlock(&ar_ptr->mutex); + ar_ptr = arena_get2(prev, bytes, true); +- if(ar_ptr) { ++ if(ar_ptr) + p = _int_memalign(ar_ptr, pagesz, bytes); +- (void)mutex_unlock(&ar_ptr->mutex); +- } + #endif + } +- } else ++ } ++ ++ if (ar_ptr != NULL) + (void)mutex_unlock(&ar_ptr->mutex); ++ + assert(!p || chunk_is_mmapped(mem2chunk(p)) || + ar_ptr == arena_for_chunk(mem2chunk(p))); + +@@ -4004,28 +3986,28 @@ public_pVALLOc(size_t bytes) + + arena_get(ar_ptr, bytes + 2*pagesz + MINSIZE); + p = _int_pvalloc(ar_ptr, bytes); +- if(!p) { ++ if(!p && ar_ptr != NULL) { + /* Maybe the failure is due to running out of mmapped areas. */ + if(ar_ptr != &main_arena) { + (void)mutex_unlock(&ar_ptr->mutex); + ar_ptr = &main_arena; + (void)mutex_lock(&ar_ptr->mutex); + p = _int_memalign(ar_ptr, pagesz, rounded_bytes); +- (void)mutex_unlock(&ar_ptr->mutex); + } else { + #if USE_ARENAS + /* ... or sbrk() has failed and there is still a chance to mmap() */ + mstate prev = ar_ptr->next ? ar_ptr : 0; + (void)mutex_unlock(&ar_ptr->mutex); + ar_ptr = arena_get2(prev, bytes + 2*pagesz + MINSIZE, true); +- if(ar_ptr) { ++ if(ar_ptr) + p = _int_memalign(ar_ptr, pagesz, rounded_bytes); +- (void)mutex_unlock(&ar_ptr->mutex); +- } + #endif + } +- } else ++ } ++ ++ if (ar_ptr != NULL) + (void)mutex_unlock(&ar_ptr->mutex); ++ + assert(!p || chunk_is_mmapped(mem2chunk(p)) || + ar_ptr == arena_for_chunk(mem2chunk(p))); + +@@ -4072,55 +4054,65 @@ public_cALLOc(size_t n, size_t elem_size) + sz = bytes; + + arena_get(av, sz); +- if(!av) +- return 0; + +- /* Check if we hand out the top chunk, in which case there may be no +- need to clear. */ ++ if (av) ++ { ++ /* Check if we hand out the top chunk, in which case there may be no ++ need to clear. */ + #if MORECORE_CLEARS +- oldtop = top(av); +- oldtopsize = chunksize(top(av)); ++ oldtop = top(av); ++ oldtopsize = chunksize(top(av)); + #if MORECORE_CLEARS < 2 +- /* Only newly allocated memory is guaranteed to be cleared. */ +- if (av == &main_arena && +- oldtopsize < mp_.sbrk_base + av->max_system_mem - (char *)oldtop) +- oldtopsize = (mp_.sbrk_base + av->max_system_mem - (char *)oldtop); ++ /* Only newly allocated memory is guaranteed to be cleared. */ ++ if (av == &main_arena && ++ oldtopsize < mp_.sbrk_base + av->max_system_mem - (char *)oldtop) ++ oldtopsize = (mp_.sbrk_base + av->max_system_mem - (char *)oldtop); + #endif +- if (av != &main_arena) ++ if (av != &main_arena) ++ { ++ heap_info *heap = heap_for_ptr (oldtop); ++ if (oldtopsize < (char *) heap + heap->mprotect_size - (char *) oldtop) ++ oldtopsize = (char *) heap + heap->mprotect_size - (char *) oldtop; ++ } ++#endif ++ } ++ else + { +- heap_info *heap = heap_for_ptr (oldtop); +- if (oldtopsize < (char *) heap + heap->mprotect_size - (char *) oldtop) +- oldtopsize = (char *) heap + heap->mprotect_size - (char *) oldtop; ++ /* No usable arenas. */ ++ oldtop = 0; ++ oldtopsize = 0; + } +-#endif + mem = _int_malloc(av, sz); + +- + assert(!mem || chunk_is_mmapped(mem2chunk(mem)) || + av == arena_for_chunk(mem2chunk(mem))); + +- if (mem == 0) { ++ if (mem == 0 && av != NULL) { + /* Maybe the failure is due to running out of mmapped areas. */ + if(av != &main_arena) { + (void)mutex_unlock(&av->mutex); + (void)mutex_lock(&main_arena.mutex); + mem = _int_malloc(&main_arena, sz); +- (void)mutex_unlock(&main_arena.mutex); + } else { + #if USE_ARENAS + /* ... or sbrk() has failed and there is still a chance to mmap() */ + mstate prev = av->next ? av : 0; + (void)mutex_unlock(&av->mutex); + av = arena_get2(prev, sz, true); +- if(av) { ++ if(av) + mem = _int_malloc(av, sz); +- (void)mutex_unlock(&av->mutex); +- } + #endif + } + if (mem == 0) return 0; +- } else ++ } ++ ++ if (av != NULL) + (void)mutex_unlock(&av->mutex); ++ ++ /* Allocation failed even after a retry. */ ++ if (mem == 0) ++ return 0; ++ + p = mem2chunk(mem); + + /* Two optional cases in which clearing not necessary */ +@@ -4175,6 +4167,8 @@ public_cALLOc(size_t n, size_t elem_size) + } + + #ifndef _LIBC ++/* XXX These functions are not patched to detect arena corruption because they ++ are not built in glibc. */ + + Void_t** + public_iCALLOc(size_t n, size_t elem_size, Void_t** chunks) +@@ -4309,6 +4303,16 @@ _int_malloc(mstate av, size_t bytes) + + checked_request2size(bytes, nb); + ++ /* There are no usable arenas. Fall back to sysmalloc to get a chunk from ++ mmap. */ ++ if (__glibc_unlikely (av == NULL)) ++ { ++ void *p = sYSMALLOc (nb, av); ++ if (p != NULL) ++ alloc_perturb (p, bytes); ++ return p; ++ } ++ + /* + If the size qualifies as a fastbin, first check corresponding bin. + This code is safe to execute even if av is not yet initialized, so we +@@ -4337,7 +4341,7 @@ _int_malloc(mstate av, size_t bytes) + errstr = "malloc(): memory corruption (fast)"; + errout: + mutex_unlock(&av->mutex); +- malloc_printerr (check_action, errstr, chunk2mem (victim)); ++ malloc_printerr (check_action, errstr, chunk2mem (victim), av); + mutex_lock(&av->mutex); + return NULL; + } +@@ -4429,7 +4433,7 @@ _int_malloc(mstate av, size_t bytes) + { + void *p = chunk2mem(victim); + mutex_unlock(&av->mutex); +- malloc_printerr (check_action, "malloc(): memory corruption", p); ++ malloc_printerr (check_action, "malloc(): memory corruption", p, av); + mutex_lock(&av->mutex); + } + size = chunksize(victim); +@@ -4829,7 +4833,7 @@ _int_free(mstate av, mchunkptr p) + if (have_lock || locked) + (void)mutex_unlock(&av->mutex); + #endif +- malloc_printerr (check_action, errstr, chunk2mem(p)); ++ malloc_printerr (check_action, errstr, chunk2mem(p), av); + #ifdef ATOMIC_FASTBINS + if (have_lock) + mutex_lock(&av->mutex); +@@ -5281,7 +5285,7 @@ _int_realloc(mstate av, mchunkptr oldp, INTERNAL_SIZE_T oldsize, + errstr = "realloc(): invalid old size"; + errout: + mutex_unlock(&av->mutex); +- malloc_printerr (check_action, errstr, chunk2mem(oldp)); ++ malloc_printerr (check_action, errstr, chunk2mem(oldp), av); + mutex_lock(&av->mutex); + return NULL; + } +@@ -5881,6 +5885,10 @@ static int mTRIm(mstate av, size_t pad) + static int mTRIm(av, pad) mstate av; size_t pad; + #endif + { ++ /* Don't touch corrupt arenas. */ ++ if (arena_is_corrupt (av)) ++ return 0; ++ + /* Ensure initialization/consolidation */ + malloc_consolidate (av); + +@@ -6320,8 +6328,14 @@ int mALLOPt(param_number, value) int param_number; int value; + extern char **__libc_argv attribute_hidden; + + static void +-malloc_printerr(int action, const char *str, void *ptr) ++malloc_printerr(int action, const char *str, void *ptr, mstate ar_ptr) + { ++ /* Avoid using this arena in future. We do not attempt to synchronize this ++ with anything else because we minimally want to ensure that __libc_message ++ gets its resources safely without stumbling on the current corruption. */ ++ if (ar_ptr) ++ set_arena_corrupt (ar_ptr); ++ + if ((action & 5) == 5) + __libc_message (action & 2, "%s\n", str); + else if (action & 1) +diff --git a/malloc/tst-malloc-backtrace.c b/malloc/tst-malloc-backtrace.c +new file mode 100644 +index 0000000..796a42f +--- /dev/null ++++ b/malloc/tst-malloc-backtrace.c +@@ -0,0 +1,50 @@ ++/* Verify that backtrace does not deadlock on itself on memory corruption. ++ Copyright (C) 2015 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 <stdlib.h> ++ ++#define SIZE 4096 ++ ++/* Wrap free with a function to prevent gcc from optimizing it out. */ ++static void ++__attribute__((noinline)) ++call_free (void *ptr) ++{ ++ free (ptr); ++ *(size_t *)(ptr - sizeof (size_t)) = 1; ++} ++ ++int ++do_test (void) ++{ ++ void *ptr1 = malloc (SIZE); ++ void *ptr2 = malloc (SIZE); ++ ++ call_free ((void *) ptr1); ++ ptr1 = malloc (SIZE); ++ ++ /* Not reached. The return statement is to put ptr2 into use so that gcc ++ doesn't optimize out that malloc call. */ ++ return (ptr1 == ptr2); ++} ++ ++#define TEST_FUNCTION do_test () ++#define EXPECTED_SIGNAL SIGABRT ++ ++#include "../test-skeleton.c" diff --git a/src/patches/glibc/glibc-rh1074342.patch b/src/patches/glibc/glibc-rh1074342.patch new file mode 100644 index 0000000..121127e --- /dev/null +++ b/src/patches/glibc/glibc-rh1074342.patch @@ -0,0 +1,26 @@ +commit c44496df2f090a56d3bf75df930592dac6bba46f +Author: Siddhesh Poyarekar siddhesh@redhat.com +Date: Wed Mar 12 17:27:22 2014 +0530 + + Provide correct buffer length to netgroup queries in nscd (BZ #16695) + + The buffer to query netgroup entries is allocated sufficient space for + the netgroup entries and the key to be appended at the end, but it + sends in an incorrect available length to the NSS netgroup query + functions, resulting in overflow of the buffer in some special cases. + The fix here is to factor in the key length when sending the available + buffer and buffer length to the query functions. + +diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c +index 426d3c5..5ba1e1f 100644 +--- a/nscd/netgroupcache.c ++++ b/nscd/netgroupcache.c +@@ -202,7 +202,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, + { + int e; + status = getfct.f (&data, buffer + buffilled, +- buflen - buffilled, &e); ++ buflen - buffilled - req->key_len, &e); + if (status == NSS_STATUS_RETURN + || status == NSS_STATUS_NOTFOUND) + /* This was either the last one for this group or the diff --git a/src/patches/glibc/glibc-rh1074353.patch b/src/patches/glibc/glibc-rh1074353.patch new file mode 100644 index 0000000..c8aa8b0 --- /dev/null +++ b/src/patches/glibc/glibc-rh1074353.patch @@ -0,0 +1,398 @@ +commit bc8f194c8c29e46e8ee4034f06e46988dfff38f7 +Author: Siddhesh Poyarekar siddhesh@redhat.com +Date: Wed Apr 30 12:00:39 2014 +0530 + + Initialize all of datahead structure in nscd (BZ #16791) + + The datahead structure has an unused padding field that remains + uninitialized. Valgrind prints out a warning for it on querying a + netgroups entry. This is harmless, but is a potential data leak since + it would result in writing out an uninitialized byte to the cache + file. Besides, this happens only when there is a cache miss, so we're + not adding computation to any fast path. + +commit 1cdeb2372ddecac0dfe0c132a033e9590ffa07d2 +Author: Siddhesh Poyarekar siddhesh@redhat.com +Date: Wed Apr 30 11:57:09 2014 +0530 + + Consolidate code to initialize nscd dataset header + + This patch consolidates the code to initialize the header of a dataset + into a single set of functions (one for positive and another for + negative datasets) primarily to reduce repetition of code. The + secondary reason is to simplify Patch 2/2 which fixes the problem of + an uninitialized byte in the header by initializing an unused field in + the structure and hence preventing a possible data leak into the cache + file. + +diff --git a/nscd/aicache.c b/nscd/aicache.c +index 98d40a1..d7966bd 100644 +--- a/nscd/aicache.c ++++ b/nscd/aicache.c +@@ -383,17 +383,12 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req, + cp = family; + } + +- /* Fill in the rest of the dataset. */ +- dataset->head.allocsize = total + req->key_len; +- dataset->head.recsize = total - offsetof (struct dataset, resp); +- dataset->head.notfound = false; +- dataset->head.nreloads = he == NULL ? 0 : (dh->nreloads + 1); +- dataset->head.usable = true; +- +- /* Compute the timeout time. */ +- dataset->head.ttl = ttl == INT32_MAX ? db->postimeout : ttl; +- timeout = dataset->head.timeout = time (NULL) + dataset->head.ttl; ++ timeout = datahead_init_pos (&dataset->head, total + req->key_len, ++ total - offsetof (struct dataset, resp), ++ he == NULL ? 0 : dh->nreloads + 1, ++ ttl == INT32_MAX ? db->postimeout : ttl); + ++ /* Fill in the rest of the dataset. */ + dataset->resp.version = NSCD_VERSION; + dataset->resp.found = 1; + dataset->resp.naddrs = naddrs; +@@ -528,15 +523,9 @@ next_nip: + else if ((dataset = mempool_alloc (db, (sizeof (struct dataset) + + req->key_len), 1)) != NULL) + { +- dataset->head.allocsize = sizeof (struct dataset) + req->key_len; +- dataset->head.recsize = total; +- dataset->head.notfound = true; +- dataset->head.nreloads = 0; +- dataset->head.usable = true; +- +- /* Compute the timeout time. */ +- timeout = dataset->head.timeout = time (NULL) + db->negtimeout; +- dataset->head.ttl = db->negtimeout; ++ timeout = datahead_init_neg (&dataset->head, ++ sizeof (struct dataset) + req->key_len, ++ total, db->negtimeout); + + /* This is the reply. */ + memcpy (&dataset->resp, ¬found, total); +diff --git a/nscd/grpcache.c b/nscd/grpcache.c +index b5a33eb..df59fa7 100644 +--- a/nscd/grpcache.c ++++ b/nscd/grpcache.c +@@ -128,14 +128,10 @@ cache_addgr (struct database_dyn *db, int fd, request_header *req, + } + else if ((dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len, 1)) != NULL) + { +- dataset->head.allocsize = sizeof (struct dataset) + req->key_len; +- dataset->head.recsize = total; +- dataset->head.notfound = true; +- dataset->head.nreloads = 0; +- dataset->head.usable = true; +- +- /* Compute the timeout time. */ +- timeout = dataset->head.timeout = t + db->negtimeout; ++ timeout = datahead_init_neg (&dataset->head, ++ (sizeof (struct dataset) ++ + req->key_len), total, ++ db->negtimeout); + + /* This is the reply. */ + memcpy (&dataset->resp, ¬found, total); +@@ -232,14 +228,10 @@ cache_addgr (struct database_dyn *db, int fd, request_header *req, + dataset_temporary = true; + } + +- dataset->head.allocsize = total + n; +- dataset->head.recsize = total - offsetof (struct dataset, resp); +- dataset->head.notfound = false; +- dataset->head.nreloads = he == NULL ? 0 : (dh->nreloads + 1); +- dataset->head.usable = true; +- +- /* Compute the timeout time. */ +- timeout = dataset->head.timeout = t + db->postimeout; ++ timeout = datahead_init_pos (&dataset->head, total + n, ++ total - offsetof (struct dataset, resp), ++ he == NULL ? 0 : dh->nreloads + 1, ++ db->postimeout); + + dataset->resp.version = NSCD_VERSION; + dataset->resp.found = 1; +diff --git a/nscd/hstcache.c b/nscd/hstcache.c +index a79b67a..d4f1ad2 100644 +--- a/nscd/hstcache.c ++++ b/nscd/hstcache.c +@@ -152,15 +152,11 @@ cache_addhst (struct database_dyn *db, int fd, request_header *req, + else if ((dataset = mempool_alloc (db, (sizeof (struct dataset) + + req->key_len), 1)) != NULL) + { +- dataset->head.allocsize = sizeof (struct dataset) + req->key_len; +- dataset->head.recsize = total; +- dataset->head.notfound = true; +- dataset->head.nreloads = 0; +- dataset->head.usable = true; +- +- /* Compute the timeout time. */ +- dataset->head.ttl = ttl == INT32_MAX ? db->negtimeout : ttl; +- timeout = dataset->head.timeout = t + dataset->head.ttl; ++ timeout = datahead_init_neg (&dataset->head, ++ (sizeof (struct dataset) ++ + req->key_len), total, ++ (ttl == INT32_MAX ++ ? db->negtimeout : ttl)); + + /* This is the reply. */ + memcpy (&dataset->resp, resp, total); +@@ -257,15 +253,10 @@ cache_addhst (struct database_dyn *db, int fd, request_header *req, + alloca_used = true; + } + +- dataset->head.allocsize = total + req->key_len; +- dataset->head.recsize = total - offsetof (struct dataset, resp); +- dataset->head.notfound = false; +- dataset->head.nreloads = he == NULL ? 0 : (dh->nreloads + 1); +- dataset->head.usable = true; +- +- /* Compute the timeout time. */ +- dataset->head.ttl = ttl == INT32_MAX ? db->postimeout : ttl; +- timeout = dataset->head.timeout = t + dataset->head.ttl; ++ timeout = datahead_init_pos (&dataset->head, total + req->key_len, ++ total - offsetof (struct dataset, resp), ++ he == NULL ? 0 : dh->nreloads + 1, ++ ttl == INT32_MAX ? db->postimeout : ttl); + + dataset->resp.version = NSCD_VERSION; + dataset->resp.found = 1; +diff --git a/nscd/initgrcache.c b/nscd/initgrcache.c +index 1bf9f0d..361319f 100644 +--- a/nscd/initgrcache.c ++++ b/nscd/initgrcache.c +@@ -213,14 +213,10 @@ addinitgroupsX (struct database_dyn *db, int fd, request_header *req, + else if ((dataset = mempool_alloc (db, (sizeof (struct dataset) + + req->key_len), 1)) != NULL) + { +- dataset->head.allocsize = sizeof (struct dataset) + req->key_len; +- dataset->head.recsize = total; +- dataset->head.notfound = true; +- dataset->head.nreloads = 0; +- dataset->head.usable = true; +- +- /* Compute the timeout time. */ +- timeout = dataset->head.timeout = time (NULL) + db->negtimeout; ++ timeout = datahead_init_neg (&dataset->head, ++ (sizeof (struct dataset) ++ + req->key_len), total, ++ db->negtimeout); + + /* This is the reply. */ + memcpy (&dataset->resp, ¬found, total); +@@ -276,14 +272,10 @@ addinitgroupsX (struct database_dyn *db, int fd, request_header *req, + alloca_used = true; + } + +- dataset->head.allocsize = total + req->key_len; +- dataset->head.recsize = total - offsetof (struct dataset, resp); +- dataset->head.notfound = false; +- dataset->head.nreloads = he == NULL ? 0 : (dh->nreloads + 1); +- dataset->head.usable = true; +- +- /* Compute the timeout time. */ +- timeout = dataset->head.timeout = time (NULL) + db->postimeout; ++ timeout = datahead_init_pos (&dataset->head, total + req->key_len, ++ total - offsetof (struct dataset, resp), ++ he == NULL ? 0 : dh->nreloads + 1, ++ db->postimeout); + + dataset->resp.version = NSCD_VERSION; + dataset->resp.found = 1; +diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c +index 820d823..b3d40e9 100644 +--- a/nscd/netgroupcache.c ++++ b/nscd/netgroupcache.c +@@ -90,15 +90,9 @@ do_notfound (struct database_dyn *db, int fd, request_header *req, + /* If we cannot permanently store the result, so be it. */ + if (dataset != NULL) + { +- dataset->head.allocsize = sizeof (struct dataset) + req->key_len; +- dataset->head.recsize = total; +- dataset->head.notfound = true; +- dataset->head.nreloads = 0; +- dataset->head.usable = true; +- +- /* Compute the timeout time. */ +- timeout = dataset->head.timeout = time (NULL) + db->negtimeout; +- dataset->head.ttl = db->negtimeout; ++ timeout = datahead_init_neg (&dataset->head, ++ sizeof (struct dataset) + req->key_len, ++ total, db->negtimeout); + + /* This is the reply. */ + memcpy (&dataset->resp, ¬found, total); +@@ -359,13 +353,10 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, + + /* Fill in the dataset. */ + dataset = (struct dataset *) buffer; +- dataset->head.allocsize = total + req->key_len; +- dataset->head.recsize = total - offsetof (struct dataset, resp); +- dataset->head.notfound = false; +- dataset->head.nreloads = he == NULL ? 0 : (dh->nreloads + 1); +- dataset->head.usable = true; +- dataset->head.ttl = db->postimeout; +- timeout = dataset->head.timeout = time (NULL) + dataset->head.ttl; ++ timeout = datahead_init_pos (&dataset->head, total + req->key_len, ++ total - offsetof (struct dataset, resp), ++ he == NULL ? 0 : dh->nreloads + 1, ++ db->postimeout); + + dataset->resp.version = NSCD_VERSION; + dataset->resp.found = 1; +@@ -541,12 +532,12 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req, + dataset = &dataset_mem; + } + +- dataset->head.allocsize = sizeof (*dataset) + req->key_len; +- dataset->head.recsize = sizeof (innetgroup_response_header); ++ datahead_init_pos (&dataset->head, sizeof (*dataset) + req->key_len, ++ sizeof (innetgroup_response_header), ++ he == NULL ? 0 : dh->nreloads + 1, result->head.ttl); ++ /* Set the notfound status and timeout based on the result from ++ getnetgrent. */ + dataset->head.notfound = result->head.notfound; +- dataset->head.nreloads = he == NULL ? 0 : (dh->nreloads + 1); +- dataset->head.usable = true; +- dataset->head.ttl = result->head.ttl; + dataset->head.timeout = timeout; + + dataset->resp.version = NSCD_VERSION; +diff --git a/nscd/nscd-client.h b/nscd/nscd-client.h +index 98f77e7..ee16df6 100644 +--- a/nscd/nscd-client.h ++++ b/nscd/nscd-client.h +@@ -236,6 +236,48 @@ struct datahead + } data[0]; + }; + ++static inline time_t ++datahead_init_common (struct datahead *head, nscd_ssize_t allocsize, ++ nscd_ssize_t recsize, uint32_t ttl) ++{ ++ /* Initialize so that we don't write out junk in uninitialized data to the ++ cache. */ ++ memset (head, 0, sizeof (*head)); ++ ++ head->allocsize = allocsize; ++ head->recsize = recsize; ++ head->usable = true; ++ ++ head->ttl = ttl; ++ ++ /* Compute and return the timeout time. */ ++ return head->timeout = time (NULL) + ttl; ++} ++ ++static inline time_t ++datahead_init_pos (struct datahead *head, nscd_ssize_t allocsize, ++ nscd_ssize_t recsize, uint8_t nreloads, uint32_t ttl) ++{ ++ time_t ret = datahead_init_common (head, allocsize, recsize, ttl); ++ ++ head->notfound = false; ++ head->nreloads = nreloads; ++ ++ return ret; ++} ++ ++static inline time_t ++datahead_init_neg (struct datahead *head, nscd_ssize_t allocsize, ++ nscd_ssize_t recsize, uint32_t ttl) ++{ ++ time_t ret = datahead_init_common (head, allocsize, recsize, ttl); ++ ++ /* We don't need to touch nreloads here since it is set to our desired value ++ (0) when we clear the structure. */ ++ head->notfound = true; ++ ++ return ret; ++} + + /* Structure for one hash table entry. */ + struct hashentry +diff --git a/nscd/pwdcache.c b/nscd/pwdcache.c +index fa355c3..41c245b 100644 +--- a/nscd/pwdcache.c ++++ b/nscd/pwdcache.c +@@ -135,14 +135,10 @@ cache_addpw (struct database_dyn *db, int fd, request_header *req, + else if ((dataset = mempool_alloc (db, (sizeof (struct dataset) + + req->key_len), 1)) != NULL) + { +- dataset->head.allocsize = sizeof (struct dataset) + req->key_len; +- dataset->head.recsize = total; +- dataset->head.notfound = true; +- dataset->head.nreloads = 0; +- dataset->head.usable = true; +- +- /* Compute the timeout time. */ +- timeout = dataset->head.timeout = t + db->negtimeout; ++ timeout = datahead_init_neg (&dataset->head, ++ (sizeof (struct dataset) ++ + req->key_len), total, ++ db->negtimeout); + + /* This is the reply. */ + memcpy (&dataset->resp, ¬found, total); +@@ -215,14 +211,10 @@ cache_addpw (struct database_dyn *db, int fd, request_header *req, + alloca_used = true; + } + +- dataset->head.allocsize = total + n; +- dataset->head.recsize = total - offsetof (struct dataset, resp); +- dataset->head.notfound = false; +- dataset->head.nreloads = he == NULL ? 0 : (dh->nreloads + 1); +- dataset->head.usable = true; +- +- /* Compute the timeout time. */ +- timeout = dataset->head.timeout = t + db->postimeout; ++ timeout = datahead_init_pos (&dataset->head, total + n, ++ total - offsetof (struct dataset, resp), ++ he == NULL ? 0 : dh->nreloads + 1, ++ db->postimeout); + + dataset->resp.version = NSCD_VERSION; + dataset->resp.found = 1; +diff --git a/nscd/servicescache.c b/nscd/servicescache.c +index 12ce9b2..95bdcfe 100644 +--- a/nscd/servicescache.c ++++ b/nscd/servicescache.c +@@ -120,14 +120,10 @@ cache_addserv (struct database_dyn *db, int fd, request_header *req, + else if ((dataset = mempool_alloc (db, (sizeof (struct dataset) + + req->key_len), 1)) != NULL) + { +- dataset->head.allocsize = sizeof (struct dataset) + req->key_len; +- dataset->head.recsize = total; +- dataset->head.notfound = true; +- dataset->head.nreloads = 0; +- dataset->head.usable = true; +- +- /* Compute the timeout time. */ +- timeout = dataset->head.timeout = t + db->negtimeout; ++ timeout = datahead_init_neg (&dataset->head, ++ (sizeof (struct dataset) ++ + req->key_len), total, ++ db->negtimeout); + + /* This is the reply. */ + memcpy (&dataset->resp, ¬found, total); +@@ -207,14 +203,10 @@ cache_addserv (struct database_dyn *db, int fd, request_header *req, + alloca_used = true; + } + +- dataset->head.allocsize = total + req->key_len; +- dataset->head.recsize = total - offsetof (struct dataset, resp); +- dataset->head.notfound = false; +- dataset->head.nreloads = he == NULL ? 0 : (dh->nreloads + 1); +- dataset->head.usable = true; +- +- /* Compute the timeout time. */ +- timeout = dataset->head.timeout = t + db->postimeout; ++ timeout = datahead_init_pos (&dataset->head, total + req->key_len, ++ total - offsetof (struct dataset, resp), ++ he == NULL ? 0 : dh->nreloads + 1, ++ db->postimeout); + + dataset->resp.version = NSCD_VERSION; + dataset->resp.found = 1; diff --git a/src/patches/glibc/glibc-rh1082379.patch b/src/patches/glibc/glibc-rh1082379.patch new file mode 100644 index 0000000..60a0ece --- /dev/null +++ b/src/patches/glibc/glibc-rh1082379.patch @@ -0,0 +1,63 @@ +commit ea7d8b95e2fcb81f68b04ed7787a3dbda023991a +Author: Siddhesh Poyarekar siddhesh@redhat.com +Date: Thu Mar 27 19:48:15 2014 +0530 + + Avoid overlapping addresses to stpcpy calls in nscd (BZ #16760) + + Calls to stpcpy from nscd netgroups code will have overlapping source + and destination when all three values in the returned triplet are + non-NULL and in the expected (host,user,domain) order. This is seen + in valgrind as: + + ==3181== Source and destination overlap in stpcpy(0x19973b48, 0x19973b48) + ==3181== at 0x4C2F30A: stpcpy (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so) + ==3181== by 0x12567A: addgetnetgrentX (string3.h:111) + ==3181== by 0x12722D: addgetnetgrent (netgroupcache.c:665) + ==3181== by 0x11114C: nscd_run_worker (connections.c:1338) + ==3181== by 0x4E3C102: start_thread (pthread_create.c:309) + ==3181== by 0x59B81AC: clone (clone.S:111) + ==3181== + + Fix this by using memmove instead of stpcpy. + +diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c +index 5d15aa4..820d823 100644 +--- a/nscd/netgroupcache.c ++++ b/nscd/netgroupcache.c +@@ -216,6 +216,10 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, + const char *nuser = data.val.triple.user; + const char *ndomain = data.val.triple.domain; + ++ size_t hostlen = strlen (nhost ?: "") + 1; ++ size_t userlen = strlen (nuser ?: "") + 1; ++ size_t domainlen = strlen (ndomain ?: "") + 1; ++ + if (nhost == NULL || nuser == NULL || ndomain == NULL + || nhost > nuser || nuser > ndomain) + { +@@ -233,9 +237,6 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, + : last + strlen (last) + 1 - buffer); + + /* We have to make temporary copies. */ +- size_t hostlen = strlen (nhost ?: "") + 1; +- size_t userlen = strlen (nuser ?: "") + 1; +- size_t domainlen = strlen (ndomain ?: "") + 1; + size_t needed = hostlen + userlen + domainlen; + + if (buflen - req->key_len - bufused < needed) +@@ -269,9 +270,12 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, + } + + char *wp = buffer + buffilled; +- wp = stpcpy (wp, nhost) + 1; +- wp = stpcpy (wp, nuser) + 1; +- wp = stpcpy (wp, ndomain) + 1; ++ wp = memmove (wp, nhost ?: "", hostlen); ++ wp += hostlen; ++ wp = memmove (wp, nuser ?: "", userlen); ++ wp += userlen; ++ wp = memmove (wp, ndomain ?: "", domainlen); ++ wp += domainlen; + buffilled = wp - buffer; + ++nentries; + } diff --git a/src/patches/glibc/glibc-rh1085273.patch b/src/patches/glibc/glibc-rh1085273.patch new file mode 100644 index 0000000..ee0f289 --- /dev/null +++ b/src/patches/glibc/glibc-rh1085273.patch @@ -0,0 +1,31 @@ +commit d41242129ba693cdbc8db85b846fcaccf9f0b7c4 +Author: Siddhesh Poyarekar siddhesh@redhat.com +Date: Thu Jan 2 10:03:12 2014 +0530 + + Fix infinite loop in nscd when netgroup is empty (bz #16365) + + Currently, when a user looks up a netgroup that does not have any + members, nscd goes into an infinite loop trying to find members in the + group. This is because it does not handle cases when getnetgrent + returns an NSS_STATUS_NOTFOUND (which is what it does on empty group). + Fixed to handle this in the same way as NSS_STATUS_RETURN, similar to + what getgrent does by itself. + +diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c +index baebdd7..50936ee 100644 +--- a/nscd/netgroupcache.c ++++ b/nscd/netgroupcache.c +@@ -180,9 +180,10 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, + int e; + status = getfct.f (&data, buffer + buffilled, + buflen - buffilled, &e); +- if (status == NSS_STATUS_RETURN) +- /* This was the last one for this group. Look +- at next group if available. */ ++ if (status == NSS_STATUS_RETURN ++ || status == NSS_STATUS_NOTFOUND) ++ /* This was either the last one for this group or the ++ group was empty. Look at next group if available. */ + break; + if (status == NSS_STATUS_SUCCESS) + { diff --git a/src/patches/glibc/glibc-rh1085289.patch b/src/patches/glibc/glibc-rh1085289.patch new file mode 100644 index 0000000..9bd284e --- /dev/null +++ b/src/patches/glibc/glibc-rh1085289.patch @@ -0,0 +1,60 @@ +commit dd3022d75e6fb8957843d6d84257a5d8457822d5 +Author: Siddhesh Poyarekar siddhesh@redhat.com +Date: Thu Mar 27 19:49:51 2014 +0530 + + Return NULL for wildcard values in getnetgrent from nscd (BZ #16759) + + getnetgrent is supposed to return NULL for values that are wildcards + in the (host, user, domain) triplet. This works correctly with nscd + disabled, but with it enabled, it returns a blank ("") instead of a + NULL. This is easily seen with the output of `getent netgroup foonet` + for a netgroup foonet defined as follows in /etc/netgroup: + + foonet (,foo,) + + The output with nscd disabled is: + + foonet ( ,foo,) + + while with nscd enabled, it is: + + foonet (,foo,) + + The extra space with nscd disabled is due to the fact that `getent + netgroup` adds it if the return value from getnetgrent is NULL for + either host or user. + +diff --git a/inet/getnetgrent_r.c b/inet/getnetgrent_r.c +index 62cdfda..f6d064d 100644 +--- a/inet/getnetgrent_r.c ++++ b/inet/getnetgrent_r.c +@@ -235,6 +235,14 @@ endnetgrent (void) + libc_hidden_proto (internal_getnetgrent_r) + + ++static const char * ++get_nonempty_val (const char *in) ++{ ++ if (*in == '\0') ++ return NULL; ++ return in; ++} ++ + static enum nss_status + nscd_getnetgrent (struct __netgrent *datap, char *buffer, size_t buflen, + int *errnop) +@@ -243,11 +251,11 @@ nscd_getnetgrent (struct __netgrent *datap, char *buffer, size_t buflen, + return NSS_STATUS_UNAVAIL; + + datap->type = triple_val; +- datap->val.triple.host = datap->cursor; ++ datap->val.triple.host = get_nonempty_val (datap->cursor); + datap->cursor = (char *) __rawmemchr (datap->cursor, '\0') + 1; +- datap->val.triple.user = datap->cursor; ++ datap->val.triple.user = get_nonempty_val (datap->cursor); + datap->cursor = (char *) __rawmemchr (datap->cursor, '\0') + 1; +- datap->val.triple.domain = datap->cursor; ++ datap->val.triple.domain = get_nonempty_val (datap->cursor); + datap->cursor = (char *) __rawmemchr (datap->cursor, '\0') + 1; + + return NSS_STATUS_SUCCESS; diff --git a/src/patches/glibc/glibc-rh1085312.patch b/src/patches/glibc/glibc-rh1085312.patch new file mode 100644 index 0000000..bafb303 --- /dev/null +++ b/src/patches/glibc/glibc-rh1085312.patch @@ -0,0 +1,34 @@ +commit 58b930ae216bfa98cd60212b954b07b9963d6d04 +Author: Siddhesh Poyarekar siddhesh@redhat.com +Date: Wed Sep 10 21:51:50 2014 +0530 + + Return failure in getnetgrent only when all netgroups have been searched (#17363) + + The netgroups lookup code fails when one of the groups in the search + tree is empty. In such a case it only returns the leaves of the tree + after the blank netgroup. This is because the line parser returns a + NOTFOUND status when the netgroup exists but is empty. The + __getnetgrent_internal implementation needs to be fixed to try + remaining groups if the current group is entry. This patch implements + this fix. Tested on x86_64. + + [BZ #17363] + * inet/getnetgrent_r.c (__internal_getnetgrent_r): Try next + group if the current group is empty. + +diff --git a/inet/getnetgrent_r.c b/inet/getnetgrent_r.c +index f6d064d..e101537 100644 +--- a/inet/getnetgrent_r.c ++++ b/inet/getnetgrent_r.c +@@ -297,7 +297,10 @@ __internal_getnetgrent_r (char **hostp, char **userp, char **domainp, + { + status = (*fct) (datap, buffer, buflen, &errno); + +- if (status == NSS_STATUS_RETURN) ++ if (status == NSS_STATUS_RETURN ++ /* The service returned a NOTFOUND, but there are more groups that we ++ need to resolve before we give up. */ ++ || (status == NSS_STATUS_NOTFOUND && datap->needed_groups != NULL)) + { + /* This was the last one for this group. Look at next group + if available. */ diff --git a/src/patches/glibc/glibc-rh1087833.patch b/src/patches/glibc/glibc-rh1087833.patch new file mode 100644 index 0000000..ca8f1f0 --- /dev/null +++ b/src/patches/glibc/glibc-rh1087833.patch @@ -0,0 +1,65 @@ +commit c3ec475c5dd16499aa040908e11d382c3ded9692 +Author: Siddhesh Poyarekar siddhesh@redhat.com +Date: Mon May 26 11:40:08 2014 +0530 + + Use NSS_STATUS_TRYAGAIN to indicate insufficient buffer (BZ #16878) + + The netgroups nss modules in the glibc tree use NSS_STATUS_UNAVAIL + (with errno as ERANGE) when the supplied buffer does not have + sufficient space for the result. This is wrong, because the canonical + way to indicate insufficient buffer is to set the errno to ERANGE and + the status to NSS_STATUS_TRYAGAIN, as is used by all other modules. + + This fixes nscd behaviour when the nss_ldap module returns + NSS_STATUS_TRYAGAIN to indicate that a netgroup entry is too long to + fit into the supplied buffer. + +diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c +index b3d40e9..edab174 100644 +--- a/nscd/netgroupcache.c ++++ b/nscd/netgroupcache.c +@@ -197,11 +197,6 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, + int e; + status = getfct.f (&data, buffer + buffilled, + buflen - buffilled - req->key_len, &e); +- if (status == NSS_STATUS_RETURN +- || status == NSS_STATUS_NOTFOUND) +- /* This was either the last one for this group or the +- group was empty. Look at next group if available. */ +- break; + if (status == NSS_STATUS_SUCCESS) + { + if (data.type == triple_val) +@@ -320,11 +315,18 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, + } + } + } +- else if (status == NSS_STATUS_UNAVAIL && e == ERANGE) ++ else if (status == NSS_STATUS_TRYAGAIN && e == ERANGE) + { + buflen *= 2; + buffer = xrealloc (buffer, buflen); + } ++ else if (status == NSS_STATUS_RETURN ++ || status == NSS_STATUS_NOTFOUND ++ || status == NSS_STATUS_UNAVAIL) ++ /* This was either the last one for this group or the ++ group was empty or the NSS module had an internal ++ failure. Look at next group if available. */ ++ break; + } + + enum nss_status (*endfct) (struct __netgrent *); +diff --git a/nss/nss_files/files-netgrp.c b/nss/nss_files/files-netgrp.c +index 34eae4c..bc0b367 100644 +--- a/nss/nss_files/files-netgrp.c ++++ b/nss/nss_files/files-netgrp.c +@@ -252,7 +252,7 @@ _nss_netgroup_parseline (char **cursor, struct __netgrent *result, + if (cp - host > buflen) + { + *errnop = ERANGE; +- status = NSS_STATUS_UNAVAIL; ++ status = NSS_STATUS_TRYAGAIN; + } + else + { diff --git a/src/patches/glibc/glibc-rh1088301.patch b/src/patches/glibc/glibc-rh1088301.patch new file mode 100644 index 0000000..d26eb14 --- /dev/null +++ b/src/patches/glibc/glibc-rh1088301.patch @@ -0,0 +1,142 @@ +diff --git a/resolv/arpa/nameser.h b/resolv/arpa/nameser.h +index fb8513b..372d5cd 100644 +--- a/resolv/arpa/nameser.h ++++ b/resolv/arpa/nameser.h +@@ -293,6 +293,9 @@ typedef enum __ns_type { + ns_t_sink = 40, /*%< Kitchen sink (experimentatl) */ + ns_t_opt = 41, /*%< EDNS0 option (meta-RR) */ + ns_t_apl = 42, /*%< Address prefix list (RFC3123) */ ++ ns_t_rrsig = 46, /*%< DNSSEC RRset Signature (RFC4034) */ ++ ns_t_nsec = 47, /*%< DNSSEC Next-Secure Record (RFC4034)*/ ++ ns_t_dnskey = 48, /*%< DNSSEC key record (RFC4034) */ + ns_t_tkey = 249, /*%< Transaction key */ + ns_t_tsig = 250, /*%< Transaction signature. */ + ns_t_ixfr = 251, /*%< Incremental zone transfer. */ +diff --git a/resolv/arpa/nameser_compat.h b/resolv/arpa/nameser_compat.h +index d59c9e4..284bff7 100644 +--- a/resolv/arpa/nameser_compat.h ++++ b/resolv/arpa/nameser_compat.h +@@ -164,6 +164,9 @@ typedef struct { + #define T_NAPTR ns_t_naptr + #define T_A6 ns_t_a6 + #define T_DNAME ns_t_dname ++#define T_RRSIG ns_t_rrsig ++#define T_NSEC ns_t_nsec ++#define T_DNSKEY ns_t_dnskey + #define T_TSIG ns_t_tsig + #define T_IXFR ns_t_ixfr + #define T_AXFR ns_t_axfr +diff --git a/resolv/gethnamaddr.c b/resolv/gethnamaddr.c +index a861a84..ae55fac 100644 +--- a/resolv/gethnamaddr.c ++++ b/resolv/gethnamaddr.c +@@ -331,23 +331,36 @@ getanswer (const querybuf *answer, int anslen, const char *qname, int qtype) + buflen -= n; + continue; + } +- if ((type == T_SIG) || (type == T_KEY) || (type == T_NXT)) { +- /* We don't support DNSSEC yet. For now, ignore +- * the record and send a low priority message +- * to syslog. +- */ +- syslog(LOG_DEBUG|LOG_AUTH, ++ if ((type == T_SIG) || (type == T_KEY) || (type == T_NXT) ++ || (type == T_RRSIG) || (type == T_NSEC) ++ || (type == T_DNSKEY)) { ++ /* We don't support DNSSEC responses yet, but we do ++ * allow setting the DO bit. If the DNS server sent us ++ * these records without us asking for it, ignore the ++ * record and send a low priority message to syslog. ++ */ ++ if ((_res.options & RES_USE_DNSSEC) == 0) { ++ syslog(LOG_DEBUG|LOG_AUTH, + "gethostby*.getanswer: asked for "%s %s %s", got type "%s"", +- qname, p_class(C_IN), p_type(qtype), +- p_type(type)); ++ qname, p_class(C_IN), p_type(qtype), ++ p_type(type)); ++ } + cp += n; + continue; + } + if (type != qtype) { +- syslog(LOG_NOTICE|LOG_AUTH, ++ /* Skip logging if we received a DNAME when we have set ++ * the DO bit. DNAME records are a convenient way to ++ * set up DNSSEC records and such setups can make this ++ * log message needlessly noisy. ++ */ ++ if (!((_res.options & RES_USE_DNSSEC) ++ && type == T_DNAME)) { ++ syslog(LOG_NOTICE|LOG_AUTH, + "gethostby*.getanswer: asked for "%s %s %s", got type "%s"", +- qname, p_class(C_IN), p_type(qtype), +- p_type(type)); ++ qname, p_class(C_IN), p_type(qtype), ++ p_type(type)); ++ } + cp += n; + continue; /* XXX - had_error++ ? */ + } +diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c +index f715ab0..510d388 100644 +--- a/resolv/nss_dns/dns-host.c ++++ b/resolv/nss_dns/dns-host.c +@@ -822,13 +822,20 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype, + } + if (__builtin_expect (type == T_SIG, 0) + || __builtin_expect (type == T_KEY, 0) +- || __builtin_expect (type == T_NXT, 0)) ++ || __builtin_expect (type == T_NXT, 0) ++ || __builtin_expect (type == T_RRSIG, 0) ++ || __builtin_expect (type == T_NSEC, 0) ++ || __builtin_expect (type == T_DNSKEY, 0)) + { +- /* We don't support DNSSEC yet. For now, ignore the record +- and send a low priority message to syslog. */ +- syslog (LOG_DEBUG | LOG_AUTH, +- "gethostby*.getanswer: asked for "%s %s %s", got type "%s"", +- qname, p_class (C_IN), p_type(qtype), p_type (type)); ++ /* We don't support DNSSEC responses yet, but we do allow setting the ++ DO bit. If the DNS server sent us these records without us asking ++ for it, ignore the record and send a low priority message to ++ syslog. */ ++ if ((_res.options & RES_USE_DNSSEC) == 0) ++ syslog (LOG_DEBUG | LOG_AUTH, ++ "gethostby*.getanswer: asked for "%s %s %s", " ++ "got type "%s"", ++ qname, p_class (C_IN), p_type(qtype), p_type (type)); + cp += n; + continue; + } +@@ -837,9 +844,14 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype, + have_to_map = 1; + else if (__builtin_expect (type != qtype, 0)) + { +- syslog (LOG_NOTICE | LOG_AUTH, +- "gethostby*.getanswer: asked for "%s %s %s", got type "%s"", +- qname, p_class (C_IN), p_type (qtype), p_type (type)); ++ /* Skip logging if we received a DNAME when we have set the DO bit. ++ DNAME records are a convenient way to set up DNSSEC records and ++ such setups can make this log message needlessly noisy. */ ++ if (!((_res.options & RES_USE_DNSSEC) && type == T_DNAME)) ++ syslog (LOG_NOTICE | LOG_AUTH, ++ "gethostby*.getanswer: asked for "%s %s %s", " ++ "got type "%s"", ++ qname, p_class (C_IN), p_type (qtype), p_type (type)); + cp += n; + continue; /* XXX - had_error++ ? */ + } +diff --git a/resolv/res_debug.c b/resolv/res_debug.c +index 7843439..4a49629 100644 +--- a/resolv/res_debug.c ++++ b/resolv/res_debug.c +@@ -450,6 +450,8 @@ const struct res_sym __p_type_syms[] = { + {ns_t_kx, "KX", "Key Exchange"}, + {ns_t_cert, "CERT", "Certificate"}, + {ns_t_any, "ANY", ""any""}, ++ /* TODO Add RRSIG, NSEC and DNSKEY once we actually do something with ++ them. */ + {0, NULL, NULL} + }; + libresolv_hidden_data_def (__p_type_syms) diff --git a/src/patches/glibc/glibc-rh1091915.patch b/src/patches/glibc/glibc-rh1091915.patch new file mode 100644 index 0000000..d1af874 --- /dev/null +++ b/src/patches/glibc/glibc-rh1091915.patch @@ -0,0 +1,40 @@ +commit 3cb26316b45b23dc5cfecbafdc489b28c3a52029 +Author: Siddhesh Poyarekar siddhesh@redhat.com +Date: Thu Jan 29 10:30:09 2015 +0530 + + Initialize nscd stats data [BZ #17892] + + The padding bytes in the statsdata struct are not initialized, due to + which valgrind throws a warning: + + ==11384== Memcheck, a memory error detector + ==11384== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al. + ==11384== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info + ==11384== Command: nscd -d + ==11384== + Fri 25 Apr 2014 10:34:53 AM CEST - 11384: handle_request: request received (Version = 2) from PID 11396 + Fri 25 Apr 2014 10:34:53 AM CEST - 11384: GETSTAT + ==11384== Thread 6: + ==11384== Syscall param socketcall.sendto(msg) points to uninitialised byte(s) + ==11384== at 0x4E4ACDC: send (in /lib64/libpthread-2.12.so) + ==11384== by 0x11AF6B: send_stats (in /usr/sbin/nscd) + ==11384== by 0x112F75: nscd_run_worker (in /usr/sbin/nscd) + ==11384== by 0x4E439D0: start_thread (in /lib64/libpthread-2.12.so) + ==11384== by 0x599AB6C: clone (in /lib64/libc-2.12.so) + ==11384== Address 0x15708395 is on thread 6's stack + + Fix the warning by initializing the structure. + +diff --git a/nscd/nscd_stat.c b/nscd/nscd_stat.c +index 0f1f3c0..7aaa21b 100644 +--- a/nscd/nscd_stat.c ++++ b/nscd/nscd_stat.c +@@ -94,6 +94,8 @@ send_stats (int fd, struct database_dyn dbs[lastdb]) + struct statdata data; + int cnt; + ++ memset (&data, 0, sizeof (data)); ++ + memcpy (data.version, compilation, sizeof (compilation)); + data.debug_level = debug_level; + data.runtime = time (NULL) - start_time; diff --git a/src/patches/glibc/glibc-rh1099025-2.patch b/src/patches/glibc/glibc-rh1099025-2.patch new file mode 100644 index 0000000..58fe121 --- /dev/null +++ b/src/patches/glibc/glibc-rh1099025-2.patch @@ -0,0 +1,159 @@ +commit d6c33fda03457ca8ca87a562fa2681af16ca4ea5 +Author: Roland McGrath roland@hack.frob.com +Date: Thu May 24 11:37:30 2012 -0700 + + Switch gettimeofday from INTUSE to libc_hidden_proto. + +diff --git a/include/sys/time.h b/include/sys/time.h +index d5de942..599e189 100644 +--- a/include/sys/time.h ++++ b/include/sys/time.h +@@ -4,9 +4,8 @@ + /* Now document the internal interfaces. */ + extern int __gettimeofday (struct timeval *__tv, + struct timezone *__tz); +-extern int __gettimeofday_internal (struct timeval *__tv, +- struct timezone *__tz) +- attribute_hidden; ++libc_hidden_proto (__gettimeofday) ++libc_hidden_proto (gettimeofday) + extern int __settimeofday (__const struct timeval *__tv, + __const struct timezone *__tz) + attribute_hidden; +@@ -22,8 +21,4 @@ extern int __utimes (const char *__file, const struct timeval __tvp[2]) + attribute_hidden; + extern int __futimes (int fd, __const struct timeval tvp[2]) attribute_hidden; + +-#ifndef NOT_IN_libc +-# define __gettimeofday(tv, tz) INTUSE(__gettimeofday) (tv, tz) +-#endif +- + #endif +diff --git a/sysdeps/mach/gettimeofday.c b/sysdeps/mach/gettimeofday.c +index 88dca8e..293a775 100644 +--- a/sysdeps/mach/gettimeofday.c ++++ b/sysdeps/mach/gettimeofday.c +@@ -20,8 +20,6 @@ + #include <sys/time.h> + #include <mach.h> + +-#undef __gettimeofday +- + /* Get the current time of day and timezone information, + putting it into *TV and *TZ. If TZ is NULL, *TZ is not filled. + Returns 0 on success, -1 on errors. */ +@@ -42,6 +40,6 @@ __gettimeofday (tv, tz) + } + return 0; + } +- +-INTDEF(__gettimeofday) ++libc_hidden_def (__gettimeofday) + weak_alias (__gettimeofday, gettimeofday) ++libc_hidden_weak (gettimeofday) +diff --git a/sysdeps/posix/gettimeofday.c b/sysdeps/posix/gettimeofday.c +index 31b3dd3..1108ff0 100644 +--- a/sysdeps/posix/gettimeofday.c ++++ b/sysdeps/posix/gettimeofday.c +@@ -19,8 +19,6 @@ + #include <time.h> + #include <sys/time.h> + +-#undef __gettimeofday +- + /* Get the current time of day and timezone information, + putting it into *TV and *TZ. If TZ is NULL, *TZ is not filled. + Returns 0 on success, -1 on errors. */ +@@ -66,6 +64,6 @@ __gettimeofday (tv, tz) + + return 0; + } +- +-INTDEF(__gettimeofday) ++libc_hidden_def (__gettimeofday) + weak_alias (__gettimeofday, gettimeofday) ++libc_hidden_weak (gettimeofday) +diff --git a/sysdeps/unix/syscalls.list b/sysdeps/unix/syscalls.list +index 39c40ed..bd780f5 100644 +--- a/sysdeps/unix/common/syscalls.list ++++ b/sysdeps/unix/common/syscalls.list +@@ -5,7 +5,7 @@ getpid - getpid Ei: __getpid getpid + fchown - fchown i:iii __fchown fchown + ftruncate - ftruncate i:ii __ftruncate ftruncate + getrusage - getrusage i:ip __getrusage getrusage +-gettimeofday - gettimeofday i:PP __gettimeofday gettimeofday __gettimeofday_internal ++gettimeofday - gettimeofday i:pP __gettimeofday gettimeofday + settimeofday - settimeofday i:PP __settimeofday settimeofday + setpgid - setpgrp i:ii __setpgid setpgid + setregid - setregid i:ii __setregid setregid +diff --git a/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c b/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c +index b2ef2da..7376135 100644 +--- a/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c ++++ b/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c +@@ -35,5 +35,6 @@ __gettimeofday (tv, tz) + } +- +-#endif +-INTDEF (__gettimeofday) ++libc_hidden_def (__gettimeofday) ++ ++#endif + weak_alias (__gettimeofday, gettimeofday) ++libc_hidden_weak (gettimeofday) +diff --git a/sysdeps/unix/sysv/linux/s390/gettimeofday.c b/sysdeps/unix/sysv/linux/s390/gettimeofday.c +index 63faef8..efbf1e8 100644 +--- a/sysdeps/unix/sysv/linux/s390/gettimeofday.c ++++ b/sysdeps/unix/sysv/linux/s390/gettimeofday.c +@@ -22,7 +22,6 @@ + #include <time.h> + #include <hp-timing.h> + +-#undef __gettimeofday + #include <bits/libc-vdso.h> + + /* Get the current time of day and timezone information, +@@ -36,6 +35,6 @@ __gettimeofday (tv, tz) + { + return INLINE_VSYSCALL (gettimeofday, 2, CHECK_1 (tv), CHECK_1 (tz)); + } +- +-INTDEF (__gettimeofday) ++libc_hidden_def (__gettimeofday) + weak_alias (__gettimeofday, gettimeofday) ++libc_hidden_weak (gettimeofday) +diff --git a/time/gettimeofday.c b/time/gettimeofday.c +index cfe6549..7eb770c 100644 +--- a/time/gettimeofday.c ++++ b/time/gettimeofday.c +@@ -18,8 +18,6 @@ + #include <errno.h> + #include <sys/time.h> + +-#undef __gettimeofday +- + /* Get the current time of day and timezone information, + putting it into *TV and *TZ. If TZ is NULL, *TZ is not filled. + Returns 0 on success, -1 on errors. */ +@@ -31,8 +29,9 @@ __gettimeofday (tv, tz) + __set_errno (ENOSYS); + return -1; + } +-stub_warning (gettimeofday) +- +-INTDEF(__gettimeofday) ++libc_hidden_def (__gettimeofday) + weak_alias (__gettimeofday, gettimeofday) ++libc_hidden_weak (gettimeofday) ++ ++stub_warning (gettimeofday) + #include <stub-tag.h> +--- a/sysdeps/unix/sysv/linux/x86_64/gettimeofday.S 2014-07-28 14:40:24.640144825 +0530 ++++ b/sysdeps/unix/sysv/linux/x86_64/gettimeofday.S 2014-07-28 14:40:21.320120072 +0530 +@@ -45,5 +45,6 @@ + ret + PSEUDO_END(__gettimeofday) + +-strong_alias (__gettimeofday, __gettimeofday_internal) ++libc_hidden_def (__gettimeofday) + weak_alias (__gettimeofday, gettimeofday) ++libc_hidden_weak (gettimeofday) diff --git a/src/patches/glibc/glibc-rh1099025.patch b/src/patches/glibc/glibc-rh1099025.patch new file mode 100644 index 0000000..d075be8 --- /dev/null +++ b/src/patches/glibc/glibc-rh1099025.patch @@ -0,0 +1,47 @@ +commit 736c304a1ab4cee36a2f3343f1698bc0abae4608 +Author: Adhemerval Zanella azanella@linux.vnet.ibm.com +Date: Thu Jan 16 06:53:18 2014 -0600 + + PowerPC: Fix ftime gettimeofday internal call returning bogus data + + This patches fixes BZ#16430 by setting a different symbol for internal + GLIBC calls that points to ifunc resolvers. For PPC32, if the symbol + is defined as hidden (which is the case for gettimeofday and time) the + compiler will create local branches (symbol@local) and linker will not + create PLT calls (required for IFUNC). This will leads to internal symbol + calling the IFUNC resolver instead of the resolved symbol. + For PPC64 this behavior does not occur because a call to a function in + another translation unit might use a different toc pointer thus requiring + a PLT call. + +diff --git a/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c b/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c +index 29a5e08..2085b68 100644 +--- a/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c ++++ b/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c +@@ -44,8 +44,24 @@ asm (".type __gettimeofday, %gnu_indirect_function"); + /* This is doing "libc_hidden_def (__gettimeofday)" but the compiler won't + let us do it in C because it doesn't know we're defining __gettimeofday + here in this file. */ +-asm (".globl __GI___gettimeofday\n" +- "__GI___gettimeofday = __gettimeofday"); ++asm (".globl __GI___gettimeofday"); ++ ++/* __GI___gettimeofday is defined as hidden and for ppc32 it enables the ++ compiler make a local call (symbol@local) for internal GLIBC usage. It ++ means the PLT won't be used and the ifunc resolver will be called directly. ++ For ppc64 a call to a function in another translation unit might use a ++ different toc pointer thus disallowing direct branchess and making internal ++ ifuncs calls safe. */ ++#ifdef __powerpc64__ ++asm ("__GI___gettimeofday = __gettimeofday"); ++#else ++int ++__gettimeofday_vsyscall (struct timeval *tv, struct timezone *tz) ++{ ++ return INLINE_VSYSCALL (gettimeofday, 2, tv, tz); ++} ++asm ("__GI___gettimeofday = __gettimeofday_vsyscall"); ++#endif + + #else + diff --git a/src/patches/glibc/glibc-rh1116050-1.patch b/src/patches/glibc/glibc-rh1116050-1.patch new file mode 100644 index 0000000..439cf6d --- /dev/null +++ b/src/patches/glibc/glibc-rh1116050-1.patch @@ -0,0 +1,57 @@ +# +# In rhel-6.x the Makerules are not entirely as mature as they are +# in glibc 2.21 (from which the example link-libc-args is taken from). +# In rhel-6.x the applications are not built like their counterpart +# real applications, and because of that compiling DSOs that use TLS +# will fail with undefined references to __tls_get_addr which resides +# in ld.so and is never included in the link. This patch enhances +# only the build-module and build-module-asneeded targets to include +# a more fully and correct link line as the compiler driver would use +# when constructing an application or DSO. We do not adjust the link +# lines used to build lib* targets. +# +diff -urN glibc-2.12-2-gc4ccff1.orig/Makerules glibc-2.12-2-gc4ccff1/Makerules +--- glibc-2.12-2-gc4ccff1.orig/Makerules 2015-02-18 19:53:00.000000000 -0500 ++++ glibc-2.12-2-gc4ccff1/Makerules 2015-02-18 20:08:33.299000028 -0500 +@@ -443,6 +443,25 @@ + load-map-file = $(map-file:%=-Wl,--version-script=%) + endif + ++# Compiler arguments to use to link a shared object with libc and ++# ld.so. This is intended to be as similar as possible to a default ++# link with an installed libc. ++link-libc-args = -Wl,--start-group \ ++ $(libc-for-link) \ ++ $(common-objpfx)libc_nonshared.a \ ++ $(as-needed) $(elf-objpfx)ld.so $(no-as-needed) \ ++ -Wl,--end-group ++ ++# The corresponding shared libc to use. This may be modified for a ++# particular target. ++libc-for-link = $(common-objpfx)libc.so ++ ++# The corresponding dependencies. As these are used in dependencies, ++# not just commands, they cannot use target-specific variables so need ++# to name both possible libc.so objects. ++link-libc-deps = $(common-objpfx)libc.so $(common-objpfx)linkobj/libc.so \ ++ $(common-objpfx)libc_nonshared.a $(elf-objpfx)ld.so ++ + # Pattern rule to build a shared object from an archive of PIC objects. + # This must come after the installation rules so Make doesn't try to + # build shared libraries in place from the installed *_pic.a files. +@@ -557,12 +576,13 @@ + # not for shared objects + define build-module + $(build-module-helper) -o $@ -T $(common-objpfx)shlib.lds \ +- $(csu-objpfx)abi-note.o $(build-module-objlist) ++ $(csu-objpfx)abi-note.o $(build-module-objlist) $(link-libc-args) + endef + define build-module-asneeded + $(build-module-helper) -o $@ -T $(common-objpfx)shlib.lds \ + $(csu-objpfx)abi-note.o \ +- -Wl,--as-needed $(build-module-objlist) -Wl,--no-as-needed ++ -Wl,--as-needed $(build-module-objlist) -Wl,--no-as-needed \ ++ $(link-libc-args) + endef + else + ifneq (,$(findstring aix,$(config-os))) diff --git a/src/patches/glibc/glibc-rh1116050.patch b/src/patches/glibc/glibc-rh1116050.patch new file mode 100644 index 0000000..7631312 --- /dev/null +++ b/src/patches/glibc/glibc-rh1116050.patch @@ -0,0 +1,407 @@ +# +# Based on this upstream commit: +# +# commit d8dd00805b8f3a011735d7a407097fb1c408d867 +# Author: H.J. Lu hjl.tools@gmail.com +# Date: Fri Nov 28 07:54:07 2014 -0800 +# +# Resize DTV if the current DTV isn't big enough +# +# This patch changes _dl_allocate_tls_init to resize DTV if the current DTV +# isn't big enough. Tested on X86-64, x32 and ia32. +# +# [BZ #13862] +# * elf/dl-tls.c: Include <atomic.h>. +# (oom): Remove #ifdef SHARED/#endif. +# (_dl_static_dtv, _dl_initial_dtv): Moved before ... +# (_dl_resize_dtv): This. Extracted from _dl_update_slotinfo. +# (_dl_allocate_tls_init): Resize DTV if the current DTV isn't +# big enough. +# (_dl_update_slotinfo): Call _dl_resize_dtv to resize DTV. +# * nptl/Makefile (tests): Add tst-stack4. +# (modules-names): Add tst-stack4mod. +# ($(objpfx)tst-stack4): New. +# (tst-stack4mod.sos): Likewise. +# ($(objpfx)tst-stack4.out): Likewise. +# ($(tst-stack4mod.sos)): Likewise. +# (clean): Likewise. +# * nptl/tst-stack4.c: New file. +# * nptl/tst-stack4mod.c: Likewise. +# +diff -urN glibc-2.12-2-gc4ccff1/elf/dl-tls.c glibc-2.12-2-gc4ccff1.mod/elf/dl-tls.c +--- glibc-2.12-2-gc4ccff1/elf/dl-tls.c 2015-02-18 14:15:28.078461873 -0500 ++++ glibc-2.12-2-gc4ccff1.mod/elf/dl-tls.c 2015-02-18 14:38:37.630374771 -0500 +@@ -24,6 +24,7 @@ + #include <stdlib.h> + #include <unistd.h> + #include <sys/param.h> ++#include <atomic.h> + + #include <tls.h> + #include <dl-tls.h> +@@ -35,14 +36,12 @@ + + + /* Out-of-memory handler. */ +-#ifdef SHARED + static void + __attribute__ ((__noreturn__)) + oom (void) + { + _dl_fatal_printf ("cannot allocate memory for thread-local data: ABORT\n"); + } +-#endif + + + size_t +@@ -392,6 +391,52 @@ + return result; + } + ++static dtv_t * ++_dl_resize_dtv (dtv_t *dtv) ++{ ++ /* Resize the dtv. */ ++ dtv_t *newp; ++ /* Load GL(dl_tls_max_dtv_idx) atomically since it may be written to by ++ other threads concurrently. -- We don't have the required atomic ++ infrastructure to load dl_tls_max_dtv_idx atomically, but on all the ++ architectures we care about it should load atomically. If this had ++ an atomic_load_acquire we would still be missing the releases for ++ the writes. */ ++ size_t newsize = GL(dl_tls_max_dtv_idx) + DTV_SURPLUS; ++ size_t oldsize = dtv[-1].counter; ++ ++#if SHARED ++ if (dtv == GL(dl_initial_dtv)) ++ { ++ /* This is the initial dtv that was either statically allocated in ++ __libc_setup_tls or allocated during rtld startup using the ++ dl-minimal.c malloc instead of the real malloc. We can't free ++ it, we have to abandon the old storage. */ ++ ++ newp = malloc ((2 + newsize) * sizeof (dtv_t)); ++ if (newp == NULL) ++ oom (); ++ memcpy (newp, &dtv[-1], (2 + oldsize) * sizeof (dtv_t)); ++ } ++ else ++#endif ++ { ++ newp = realloc (&dtv[-1], ++ (2 + newsize) * sizeof (dtv_t)); ++ if (newp == NULL) ++ oom (); ++ } ++ ++ newp[0].counter = newsize; ++ ++ /* Clear the newly allocated part. */ ++ memset (newp + 2 + oldsize, '\0', ++ (newsize - oldsize) * sizeof (dtv_t)); ++ ++ /* Return the generation counter. */ ++ return &newp[1]; ++} ++ + + void * + internal_function +@@ -406,6 +451,16 @@ + size_t total = 0; + size_t maxgen = 0; + ++ /* Check if the current dtv is big enough. */ ++ if (dtv[-1].counter < GL(dl_tls_max_dtv_idx)) ++ { ++ /* Resize the dtv. */ ++ dtv = _dl_resize_dtv (dtv); ++ ++ /* Install this new dtv in the thread data structures. */ ++ INSTALL_DTV (result, &dtv[-1]); ++ } ++ + /* We have to prepare the dtv for all currently loaded modules using + TLS. For those which are dynamically loaded we add the values + indicating deferred allocation. */ +@@ -637,41 +692,10 @@ + assert (total + cnt == modid); + if (dtv[-1].counter < modid) + { +- /* Reallocate the dtv. */ +- dtv_t *newp; +- size_t newsize = GL(dl_tls_max_dtv_idx) + DTV_SURPLUS; +- size_t oldsize = dtv[-1].counter; +- +- assert (map->l_tls_modid <= newsize); +- +- if (dtv == GL(dl_initial_dtv)) +- { +- /* This is the initial dtv that was allocated +- during rtld startup using the dl-minimal.c +- malloc instead of the real malloc. We can't +- free it, we have to abandon the old storage. */ +- +- newp = malloc ((2 + newsize) * sizeof (dtv_t)); +- if (newp == NULL) +- oom (); +- memcpy (newp, &dtv[-1], (2 + oldsize) * sizeof (dtv_t)); +- } +- else +- { +- newp = realloc (&dtv[-1], +- (2 + newsize) * sizeof (dtv_t)); +- if (newp == NULL) +- oom (); +- } +- +- newp[0].counter = newsize; +- +- /* Clear the newly allocated part. */ +- memset (newp + 2 + oldsize, '\0', +- (newsize - oldsize) * sizeof (dtv_t)); ++ /* Resize the dtv. */ ++ dtv = _dl_resize_dtv (dtv); + +- /* Point dtv to the generation counter. */ +- dtv = &newp[1]; ++ assert (modid <= dtv[-1].counter); + + /* Install this new dtv in the thread data + structures. */ +diff -urN glibc-2.12-2-gc4ccff1/nptl/Makefile glibc-2.12-2-gc4ccff1.mod/nptl/Makefile +--- glibc-2.12-2-gc4ccff1/nptl/Makefile 2015-02-18 14:15:28.073462028 -0500 ++++ glibc-2.12-2-gc4ccff1.mod/nptl/Makefile 2015-02-18 14:15:49.817786667 -0500 +@@ -245,7 +245,7 @@ + tst-exec1 tst-exec2 tst-exec3 tst-exec4 \ + tst-exit1 tst-exit2 tst-exit3 \ + tst-stdio1 tst-stdio2 \ +- tst-stack1 tst-stack2 tst-stack3 \ ++ tst-stack1 tst-stack2 tst-stack3 tst-stack4 \ + tst-unload \ + tst-dlsym1 \ + tst-sysconf \ +@@ -304,7 +304,7 @@ + + modules-names = tst-atfork2mod tst-tls3mod tst-tls4moda tst-tls4modb \ + tst-tls5mod tst-tls5moda tst-tls5modb tst-tls5modc \ +- tst-tls5modd tst-tls5mode tst-tls5modf \ ++ tst-tls5modd tst-tls5mode tst-tls5modf tst-stack4mod \ + tst-_res1mod1 tst-_res1mod2 tst-execstack-mod tst-fini1mod + extra-test-objs += $(addsuffix .os,$(strip $(modules-names))) tst-cleanup4aux.o + test-extras += $(modules-names) +@@ -459,6 +459,19 @@ + $(common-objpfx)malloc/mtrace $(objpfx)tst-stack3.mtrace > $@ + generated += tst-stack3-mem tst-stack3.mtrace + ++$(objpfx)tst-stack4: $(libdl) $(shared-thread-library) ++tst-stack4mod.sos=$(shell for i in 0 1 2 3 4 5 6 7 8 9 10 \ ++ 11 12 13 14 15 16 17 18 19; do \ ++ for j in 0 1 2 3 4 5 6 7 8 9 10 \ ++ 11 12 13 14 15 16 17 18 19; do \ ++ echo $(objpfx)tst-stack4mod-$$i-$$j.so; \ ++ done; done) ++$(objpfx)tst-stack4.out: $(tst-stack4mod.sos) ++$(tst-stack4mod.sos): $(objpfx)tst-stack4mod.so ++ cp -f $< $@ ++clean: ++ rm -f $(tst-stack4mod.sos) ++ + $(objpfx)tst-cleanup4: $(objpfx)tst-cleanup4aux.o $(shared-thread-library) + $(objpfx)tst-cleanupx4: $(objpfx)tst-cleanup4aux.o $(shared-thread-library) + +diff -urN glibc-2.12-2-gc4ccff1/nptl/tst-stack4.c glibc-2.12-2-gc4ccff1.mod/nptl/tst-stack4.c +--- glibc-2.12-2-gc4ccff1/nptl/tst-stack4.c 1969-12-31 19:00:00.000000000 -0500 ++++ glibc-2.12-2-gc4ccff1.mod/nptl/tst-stack4.c 2015-02-18 14:15:49.817786667 -0500 +@@ -0,0 +1,159 @@ ++/* Test DTV size oveflow when pthread_create reuses old DTV and TLS is ++ used by dlopened shared object. ++ 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 <stdio.h> ++#include <stdint.h> ++#include <dlfcn.h> ++#include <assert.h> ++#include <pthread.h> ++ ++/* The choices of thread count, and file counts are arbitary. ++ The point is simply to run enough threads that an exiting ++ thread has it's stack reused by another thread at the same ++ time as new libraries have been loaded. */ ++#define DSO_SHARED_FILES 20 ++#define DSO_OPEN_THREADS 20 ++#define DSO_EXEC_THREADS 2 ++ ++/* Used to make sure that only one thread is calling dlopen and dlclose ++ at a time. */ ++pthread_mutex_t g_lock; ++ ++typedef void (*function) (void); ++ ++void * ++dso_invoke(void *dso_fun) ++{ ++ function *fun_vec = (function *) dso_fun; ++ int dso; ++ ++ for (dso = 0; dso < DSO_SHARED_FILES; dso++) ++ (*fun_vec[dso]) (); ++ ++ pthread_exit (NULL); ++} ++ ++void * ++dso_process (void * p) ++{ ++ void *handle[DSO_SHARED_FILES]; ++ function fun_vec[DSO_SHARED_FILES]; ++ char dso_path[DSO_SHARED_FILES][100]; ++ int dso; ++ uintptr_t t = (uintptr_t) p; ++ ++ /* Open DSOs and get a function. */ ++ for (dso = 0; dso < DSO_SHARED_FILES; dso++) ++ { ++ sprintf (dso_path[dso], "tst-stack4mod-%i-%i.so", t, dso); ++ ++ pthread_mutex_lock (&g_lock); ++ ++ handle[dso] = dlopen (dso_path[dso], RTLD_NOW); ++ assert (handle[dso]); ++ ++ fun_vec[dso] = (function) dlsym (handle[dso], "function"); ++ assert (fun_vec[dso]); ++ ++ pthread_mutex_unlock (&g_lock); ++ } ++ ++ /* Spawn workers. */ ++ pthread_t thread[DSO_EXEC_THREADS]; ++ int i, ret; ++ uintptr_t result = 0; ++ for (i = 0; i < DSO_EXEC_THREADS; i++) ++ { ++ pthread_mutex_lock (&g_lock); ++ ret = pthread_create (&thread[i], NULL, dso_invoke, (void *) fun_vec); ++ if (ret != 0) ++ { ++ printf ("pthread_create failed: %d\n", ret); ++ result = 1; ++ } ++ pthread_mutex_unlock (&g_lock); ++ } ++ ++ if (!result) ++ for (i = 0; i < DSO_EXEC_THREADS; i++) ++ { ++ ret = pthread_join (thread[i], NULL); ++ if (ret != 0) ++ { ++ printf ("pthread_join failed: %d\n", ret); ++ result = 1; ++ } ++ } ++ ++ /* Close all DSOs. */ ++ for (dso = 0; dso < DSO_SHARED_FILES; dso++) ++ { ++ pthread_mutex_lock (&g_lock); ++ dlclose (handle[dso]); ++ pthread_mutex_unlock (&g_lock); ++ } ++ ++ /* Exit. */ ++ pthread_exit ((void *) result); ++} ++ ++static int ++do_test (void) ++{ ++ pthread_t thread[DSO_OPEN_THREADS]; ++ int i,j; ++ int ret; ++ int result = 0; ++ ++ pthread_mutex_init (&g_lock, NULL); ++ ++ /* 100 is arbitrary here and is known to trigger PR 13862. */ ++ for (j = 0; j < 100; j++) ++ { ++ for (i = 0; i < DSO_OPEN_THREADS; i++) ++ { ++ ret = pthread_create (&thread[i], NULL, dso_process, ++ (void *) (uintptr_t) i); ++ if (ret != 0) ++ { ++ printf ("pthread_create failed: %d\n", ret); ++ result = 1; ++ } ++ } ++ ++ if (result) ++ break; ++ ++ for (i = 0; i < DSO_OPEN_THREADS; i++) ++ { ++ ret = pthread_join (thread[i], NULL); ++ if (ret != 0) ++ { ++ printf ("pthread_join failed: %d\n", ret); ++ result = 1; ++ } ++ } ++ } ++ ++ return result; ++} ++ ++#define TEST_FUNCTION do_test () ++#define TIMEOUT 100 ++#include "../test-skeleton.c" +diff -urN glibc-2.12-2-gc4ccff1/nptl/tst-stack4mod.c glibc-2.12-2-gc4ccff1.mod/nptl/tst-stack4mod.c +--- glibc-2.12-2-gc4ccff1/nptl/tst-stack4mod.c 1969-12-31 19:00:00.000000000 -0500 ++++ glibc-2.12-2-gc4ccff1.mod/nptl/tst-stack4mod.c 2015-02-18 14:15:49.817786667 -0500 +@@ -0,0 +1,28 @@ ++/* This tests DTV usage with TLS in dlopened shared object. ++ 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/. */ ++ ++/* 256 is arbitrary here and is known to trigger PR 13862. */ ++__thread int var[256] attribute_hidden = {0}; ++ ++void ++function (void) ++{ ++ int i; ++ for (i = 0; i < sizeof (var) / sizeof (int); i++) ++ var[i] = i; ++} diff --git a/src/patches/glibc/glibc-rh1124204.patch b/src/patches/glibc/glibc-rh1124204.patch new file mode 100644 index 0000000..f14c4cb --- /dev/null +++ b/src/patches/glibc/glibc-rh1124204.patch @@ -0,0 +1,47 @@ +# +# Derived from this upstream commit: +# +# commit 58a1335e76a553e1cf4edeebc27f16fc9b53d6e6 +# Author: Petr Baudis pasky@ucw.cz +# Date: Thu Mar 14 01:16:53 2013 +0100 +# +# Fix __times() handling of EFAULT when buf is NULL +# +# 2013-03-14 Petr Baudis pasky@ucw.cz +# +# * sysdeps/unix/sysv/linux/times.c (__times): On EFAULT, test +# for non-NULL pointer before the memory validity test. Pointed +# out by Holger Brunck holger.brunck@keymile.com. +# +diff --git a/sysdeps/unix/sysv/linux/times.c b/sysdeps/unix/sysv/linux/times.c +index f3b5f01..e59bb4e 100644 +--- a/sysdeps/unix/sysv/linux/times.c ++++ b/sysdeps/unix/sysv/linux/times.c +@@ -26,13 +26,14 @@ __times (struct tms *buf) + INTERNAL_SYSCALL_DECL (err); + clock_t ret = INTERNAL_SYSCALL (times, err, 1, buf); + if (INTERNAL_SYSCALL_ERROR_P (ret, err) +- && __builtin_expect (INTERNAL_SYSCALL_ERRNO (ret, err) == EFAULT, 0)) ++ && __builtin_expect (INTERNAL_SYSCALL_ERRNO (ret, err) == EFAULT, 0) ++ && buf) + { + /* This might be an error or not. For architectures which have + no separate return value and error indicators we cannot + distinguish a return value of -1 from an error. Do it the +- hard way. We crash applications which pass in an invalid BUF +- pointer. */ ++ hard way. We crash applications which pass in an invalid ++ non-NULL BUF pointer. Linux allows BUF to be NULL. */ + #define touch(v) \ + do { \ + clock_t temp = v; \ +@@ -44,7 +45,8 @@ __times (struct tms *buf) + touch (buf->tms_cutime); + touch (buf->tms_cstime); + +- /* If we come here the memory is valid and the kernel did not ++ /* If we come here the memory is valid (or BUF is NULL, which is ++ * a valid condition for the kernel syscall) and the kernel did not + return an EFAULT error. Return the value given by the kernel. */ + } + diff --git a/src/patches/glibc/glibc-rh1125307.patch b/src/patches/glibc/glibc-rh1125307.patch new file mode 100644 index 0000000..72ba01d --- /dev/null +++ b/src/patches/glibc/glibc-rh1125307.patch @@ -0,0 +1,19 @@ +commit a11892631d92f594c690d0d50a642b0d1aba58b8 +Author: OndÅej BÃlka neleai@seznam.cz +Date: Wed May 7 14:08:57 2014 +0200 + + Fix typo in nscd/selinux.c + +diff --git a/nscd/selinux.c b/nscd/selinux.c +index 9a8a5a8..eaed6dd 100644 +--- a/nscd/selinux.c ++++ b/nscd/selinux.c +@@ -372,7 +372,7 @@ nscd_request_avc_has_perm (int fd, request_type req) + /* Get the security class for nscd. If this fails we will likely be + unable to do anything unless avc_deny_unknown is 0. */ + sc_nscd = string_to_security_class ("nscd"); +- if (perm == 0 && avc_deny_unknown == 1) ++ if (sc_nscd == 0 && avc_deny_unknown == 1) + dbg_log (_("Error getting security class for nscd.")); + + /* Convert permission to AVC bits. */ diff --git a/src/patches/glibc/glibc-rh1133809-1.patch b/src/patches/glibc/glibc-rh1133809-1.patch deleted file mode 100644 index 12b9949..0000000 --- a/src/patches/glibc/glibc-rh1133809-1.patch +++ /dev/null @@ -1,199 +0,0 @@ -2014-08-21 Florian Weimer fweimer@redhat.com - - [BZ #17187] - * iconv/gconv_trans.c (struct known_trans, search_tree, lock, - trans_compare, open_translit, __gconv_translit_find): - Remove module loading code. - -diff --git a/iconv/gconv_trans.c b/iconv/gconv_trans.c -index 1e25854..d71c029 100644 ---- a/iconv/gconv_trans.c -+++ b/iconv/gconv_trans.c -@@ -238,181 +238,11 @@ __gconv_transliterate (struct __gconv_step *step, - return __GCONV_ILLEGAL_INPUT; - } - -- --/* Structure to represent results of found (or not) transliteration -- modules. */ --struct known_trans --{ -- /* This structure must remain the first member. */ -- struct trans_struct info; -- -- char *fname; -- void *handle; -- int open_count; --}; -- -- --/* Tree with results of previous calls to __gconv_translit_find. */ --static void *search_tree; -- --/* We modify global data. */ --__libc_lock_define_initialized (static, lock); -- -- --/* Compare two transliteration entries. */ --static int --trans_compare (const void *p1, const void *p2) --{ -- const struct known_trans *s1 = (const struct known_trans *) p1; -- const struct known_trans *s2 = (const struct known_trans *) p2; -- -- return strcmp (s1->info.name, s2->info.name); --} -- -- --/* Open (maybe reopen) the module named in the struct. Get the function -- and data structure pointers we need. */ --static int --open_translit (struct known_trans *trans) --{ -- __gconv_trans_query_fct queryfct; -- -- trans->handle = __libc_dlopen (trans->fname); -- if (trans->handle == NULL) -- /* Not available. */ -- return 1; -- -- /* Find the required symbol. */ -- queryfct = __libc_dlsym (trans->handle, "gconv_trans_context"); -- if (queryfct == NULL) -- { -- /* We cannot live with that. */ -- close_and_out: -- __libc_dlclose (trans->handle); -- trans->handle = NULL; -- return 1; -- } -- -- /* Get the context. */ -- if (queryfct (trans->info.name, &trans->info.csnames, &trans->info.ncsnames) -- != 0) -- goto close_and_out; -- -- /* Of course we also have to have the actual function. */ -- trans->info.trans_fct = __libc_dlsym (trans->handle, "gconv_trans"); -- if (trans->info.trans_fct == NULL) -- goto close_and_out; -- -- /* Now the optional functions. */ -- trans->info.trans_init_fct = -- __libc_dlsym (trans->handle, "gconv_trans_init"); -- trans->info.trans_context_fct = -- __libc_dlsym (trans->handle, "gconv_trans_context"); -- trans->info.trans_end_fct = -- __libc_dlsym (trans->handle, "gconv_trans_end"); -- -- trans->open_count = 1; -- -- return 0; --} -- -- - int - internal_function - __gconv_translit_find (struct trans_struct *trans) - { -- struct known_trans **found; -- const struct path_elem *runp; -- int res = 1; -- -- /* We have to have a name. */ -- assert (trans->name != NULL); -- -- /* Acquire the lock. */ -- __libc_lock_lock (lock); -- -- /* See whether we know this module already. */ -- found = __tfind (trans, &search_tree, trans_compare); -- if (found != NULL) -- { -- /* Is this module available? */ -- if ((*found)->handle != NULL) -- { -- /* Maybe we have to reopen the file. */ -- if ((*found)->handle != (void *) -1) -- /* The object is not unloaded. */ -- res = 0; -- else if (open_translit (*found) == 0) -- { -- /* Copy the data. */ -- *trans = (*found)->info; -- (*found)->open_count++; -- res = 0; -- } -- } -- } -- else -- { -- size_t name_len = strlen (trans->name) + 1; -- int need_so = 0; -- struct known_trans *newp; -- -- /* We have to continue looking for the module. */ -- if (__gconv_path_elem == NULL) -- __gconv_get_path (); -- -- /* See whether we have to append .so. */ -- if (name_len <= 4 || memcmp (&trans->name[name_len - 4], ".so", 3) != 0) -- need_so = 1; -- -- /* Create a new entry. */ -- newp = (struct known_trans *) malloc (sizeof (struct known_trans) -- + (__gconv_max_path_elem_len -- + name_len + 3) -- + name_len); -- if (newp != NULL) -- { -- char *cp; -- -- /* Clear the struct. */ -- memset (newp, '\0', sizeof (struct known_trans)); -- -- /* Store a copy of the module name. */ -- newp->info.name = cp = (char *) (newp + 1); -- cp = __mempcpy (cp, trans->name, name_len); -- -- newp->fname = cp; -- -- /* Search in all the directories. */ -- for (runp = __gconv_path_elem; runp->name != NULL; ++runp) -- { -- cp = __mempcpy (__stpcpy ((char *) newp->fname, runp->name), -- trans->name, name_len); -- if (need_so) -- memcpy (cp, ".so", sizeof (".so")); -- -- if (open_translit (newp) == 0) -- { -- /* We found a module. */ -- res = 0; -- break; -- } -- } -- -- if (res) -- newp->fname = NULL; -- -- /* In any case we'll add the entry to our search tree. */ -- if (__tsearch (newp, &search_tree, trans_compare) == NULL) -- { -- /* Yickes, this should not happen. Unload the object. */ -- res = 1; -- /* XXX unload here. */ -- } -- } -- } -- -- __libc_lock_unlock (lock); -- -- return res; -+ /* This function always fails. Transliteration module loading is -+ not implemented. */ -+ return 1; - } --- -1.9.3 - diff --git a/src/patches/glibc/glibc-rh1133809-2.patch b/src/patches/glibc/glibc-rh1133809-2.patch deleted file mode 100644 index 8148abb..0000000 --- a/src/patches/glibc/glibc-rh1133809-2.patch +++ /dev/null @@ -1,625 +0,0 @@ -commit 585367266923156ac6fb789939a923641ba5aaf4 -Author: Florian Weimer fweimer@redhat.com -Date: Wed May 28 14:05:03 2014 +0200 - - manual: Update the locale documentation - -commit 4e8f95a0df7c2300b830ec12c0ae1e161bc8a8a3 -Author: Florian Weimer fweimer@redhat.com -Date: Mon May 12 15:24:12 2014 +0200 - - _nl_find_locale: Improve handling of crafted locale names [BZ #17137] - - Prevent directory traversal in locale-related environment variables - (CVE-2014-0475). - -commit d183645616b0533b3acee28f1a95570bffbdf50f -Author: Florian Weimer fweimer@redhat.com -Date: Wed May 28 14:41:52 2014 +0200 - - setlocale: Use the heap for the copy of the locale argument - - This avoids alloca calls with potentially large arguments. - -diff -pruN glibc-2.18/locale/findlocale.c glibc-2.18.patched/locale/findlocale.c ---- glibc-2.18/locale/findlocale.c 2013-08-11 04:22:55.000000000 +0530 -+++ glibc-2.18.patched/locale/findlocale.c 2014-08-26 16:14:50.403253778 +0530 -@@ -17,6 +17,7 @@ - 02111-1307 USA. */ - - #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_ - - 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 (__builtin_expect (namelen > 255, 0)) -+ return 0; -+ /* Directory traversal attempt. */ -+ static const char slashdot[4] = {'/', '.', '.', '/'}; -+ if (__builtin_expect (memmem (name, namelen, -+ slashdot, sizeof (slashdot)) != NULL, 0)) -+ return 0; -+ if (namelen == 2 && __builtin_expect (name[0] == '.' && name [1] == '.', 0)) -+ return 0; -+ if (namelen >= 3 -+ && __builtin_expect (((name[0] == '.' -+ && name[1] == '.' -+ && name[2] == '/') -+ || (name[namelen - 3] == '/' -+ && name[namelen - 2] == '.' -+ && name[namelen - 1] == '.')), 0)) -+ return 0; -+ /* If there is a slash in the name, it must start with one. */ -+ if (__builtin_expect (memchr (name, '/', namelen) != NULL, 0) && name[0] != '/') -+ return 0; -+ return 1; -+} - - struct __locale_data * - internal_function -@@ -65,7 +105,7 @@ _nl_find_locale (const char *locale_path - { - 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 - 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 -pruN glibc-2.18/locale/setlocale.c glibc-2.18.patched/locale/setlocale.c ---- glibc-2.18/locale/setlocale.c 2013-08-11 04:22:55.000000000 +0530 -+++ glibc-2.18.patched/locale/setlocale.c 2014-08-26 16:14:50.401253764 +0530 -@@ -272,6 +272,8 @@ setlocale (int category, const char *loc - 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 *loc - 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 (__builtin_expect (locale_copy == NULL, 0)) -+ { -+ __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 *loc - { - 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 *loc - /* 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; - } -diff -pruN glibc-2.18/localedata/Makefile glibc-2.18.patched/localedata/Makefile ---- glibc-2.18/localedata/Makefile 2014-08-26 16:15:22.656474571 +0530 -+++ glibc-2.18.patched/localedata/Makefile 2014-08-26 16:14:50.403253778 +0530 -@@ -77,7 +77,7 @@ locale_test_suite := tst_iswalnum tst_is - - 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 tst-strptime -+ tst-strfmon1 tst-sscanf tst-strptime tst-setlocale3 - ifeq (yes,$(build-shared)) - ifneq (no,$(PERL)) - tests: $(objpfx)mtrace-tst-leaks -@@ -288,6 +288,7 @@ tst-strfmon1-ENV = $(TEST_MBWC_ENV) - tst-strptime-ENV = $(TEST_MBWC_ENV) - - tst-setlocale-ENV = LOCPATH=$(common-objpfx)localedata LC_ALL=ja_JP.EUC-JP -+tst-setlocale3-ENV = LOCPATH=$(common-objpfx)localedata - - bug-iconv-trans-ENV = LOCPATH=$(common-objpfx)localedata - -diff -pruN glibc-2.18/localedata/tst-setlocale3.c glibc-2.18.patched/localedata/tst-setlocale3.c ---- glibc-2.18/localedata/tst-setlocale3.c 1970-01-01 05:30:00.000000000 +0530 -+++ glibc-2.18.patched/localedata/tst-setlocale3.c 2014-08-26 16:14:50.403253778 +0530 -@@ -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" -diff -pruN glibc-2.18/manual/locale.texi glibc-2.18.patched/manual/locale.texi ---- glibc-2.18/manual/locale.texi 2013-08-11 04:22:55.000000000 +0530 -+++ glibc-2.18.patched/manual/locale.texi 2014-08-26 16:14:50.404253785 +0530 -@@ -29,6 +29,7 @@ will follow the conventions preferred by - * 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 - 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 - 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 grou - 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}. -@@ -225,13 +232,7 @@ The symbols in this section are defined - @comment ISO - @deftypefun {char *} setlocale (int @var{category}, const char *@var{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 -@@ -256,10 +257,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 -@@ -275,6 +275,11 @@ 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 -@@ -328,7 +323,7 @@ locale categories, and future versions o - 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 -@@ -362,7 +357,94 @@ with the environment, rather than trying - 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, -+the GNU C Library 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 diff --git a/src/patches/glibc/glibc-rh1133810-1.patch b/src/patches/glibc/glibc-rh1133810-1.patch new file mode 100644 index 0000000..12b9949 --- /dev/null +++ b/src/patches/glibc/glibc-rh1133810-1.patch @@ -0,0 +1,199 @@ +2014-08-21 Florian Weimer fweimer@redhat.com + + [BZ #17187] + * iconv/gconv_trans.c (struct known_trans, search_tree, lock, + trans_compare, open_translit, __gconv_translit_find): + Remove module loading code. + +diff --git a/iconv/gconv_trans.c b/iconv/gconv_trans.c +index 1e25854..d71c029 100644 +--- a/iconv/gconv_trans.c ++++ b/iconv/gconv_trans.c +@@ -238,181 +238,11 @@ __gconv_transliterate (struct __gconv_step *step, + return __GCONV_ILLEGAL_INPUT; + } + +- +-/* Structure to represent results of found (or not) transliteration +- modules. */ +-struct known_trans +-{ +- /* This structure must remain the first member. */ +- struct trans_struct info; +- +- char *fname; +- void *handle; +- int open_count; +-}; +- +- +-/* Tree with results of previous calls to __gconv_translit_find. */ +-static void *search_tree; +- +-/* We modify global data. */ +-__libc_lock_define_initialized (static, lock); +- +- +-/* Compare two transliteration entries. */ +-static int +-trans_compare (const void *p1, const void *p2) +-{ +- const struct known_trans *s1 = (const struct known_trans *) p1; +- const struct known_trans *s2 = (const struct known_trans *) p2; +- +- return strcmp (s1->info.name, s2->info.name); +-} +- +- +-/* Open (maybe reopen) the module named in the struct. Get the function +- and data structure pointers we need. */ +-static int +-open_translit (struct known_trans *trans) +-{ +- __gconv_trans_query_fct queryfct; +- +- trans->handle = __libc_dlopen (trans->fname); +- if (trans->handle == NULL) +- /* Not available. */ +- return 1; +- +- /* Find the required symbol. */ +- queryfct = __libc_dlsym (trans->handle, "gconv_trans_context"); +- if (queryfct == NULL) +- { +- /* We cannot live with that. */ +- close_and_out: +- __libc_dlclose (trans->handle); +- trans->handle = NULL; +- return 1; +- } +- +- /* Get the context. */ +- if (queryfct (trans->info.name, &trans->info.csnames, &trans->info.ncsnames) +- != 0) +- goto close_and_out; +- +- /* Of course we also have to have the actual function. */ +- trans->info.trans_fct = __libc_dlsym (trans->handle, "gconv_trans"); +- if (trans->info.trans_fct == NULL) +- goto close_and_out; +- +- /* Now the optional functions. */ +- trans->info.trans_init_fct = +- __libc_dlsym (trans->handle, "gconv_trans_init"); +- trans->info.trans_context_fct = +- __libc_dlsym (trans->handle, "gconv_trans_context"); +- trans->info.trans_end_fct = +- __libc_dlsym (trans->handle, "gconv_trans_end"); +- +- trans->open_count = 1; +- +- return 0; +-} +- +- + int + internal_function + __gconv_translit_find (struct trans_struct *trans) + { +- struct known_trans **found; +- const struct path_elem *runp; +- int res = 1; +- +- /* We have to have a name. */ +- assert (trans->name != NULL); +- +- /* Acquire the lock. */ +- __libc_lock_lock (lock); +- +- /* See whether we know this module already. */ +- found = __tfind (trans, &search_tree, trans_compare); +- if (found != NULL) +- { +- /* Is this module available? */ +- if ((*found)->handle != NULL) +- { +- /* Maybe we have to reopen the file. */ +- if ((*found)->handle != (void *) -1) +- /* The object is not unloaded. */ +- res = 0; +- else if (open_translit (*found) == 0) +- { +- /* Copy the data. */ +- *trans = (*found)->info; +- (*found)->open_count++; +- res = 0; +- } +- } +- } +- else +- { +- size_t name_len = strlen (trans->name) + 1; +- int need_so = 0; +- struct known_trans *newp; +- +- /* We have to continue looking for the module. */ +- if (__gconv_path_elem == NULL) +- __gconv_get_path (); +- +- /* See whether we have to append .so. */ +- if (name_len <= 4 || memcmp (&trans->name[name_len - 4], ".so", 3) != 0) +- need_so = 1; +- +- /* Create a new entry. */ +- newp = (struct known_trans *) malloc (sizeof (struct known_trans) +- + (__gconv_max_path_elem_len +- + name_len + 3) +- + name_len); +- if (newp != NULL) +- { +- char *cp; +- +- /* Clear the struct. */ +- memset (newp, '\0', sizeof (struct known_trans)); +- +- /* Store a copy of the module name. */ +- newp->info.name = cp = (char *) (newp + 1); +- cp = __mempcpy (cp, trans->name, name_len); +- +- newp->fname = cp; +- +- /* Search in all the directories. */ +- for (runp = __gconv_path_elem; runp->name != NULL; ++runp) +- { +- cp = __mempcpy (__stpcpy ((char *) newp->fname, runp->name), +- trans->name, name_len); +- if (need_so) +- memcpy (cp, ".so", sizeof (".so")); +- +- if (open_translit (newp) == 0) +- { +- /* We found a module. */ +- res = 0; +- break; +- } +- } +- +- if (res) +- newp->fname = NULL; +- +- /* In any case we'll add the entry to our search tree. */ +- if (__tsearch (newp, &search_tree, trans_compare) == NULL) +- { +- /* Yickes, this should not happen. Unload the object. */ +- res = 1; +- /* XXX unload here. */ +- } +- } +- } +- +- __libc_lock_unlock (lock); +- +- return res; ++ /* This function always fails. Transliteration module loading is ++ not implemented. */ ++ return 1; + } +-- +1.9.3 + diff --git a/src/patches/glibc/glibc-rh1133810-2.patch b/src/patches/glibc/glibc-rh1133810-2.patch new file mode 100644 index 0000000..8148abb --- /dev/null +++ b/src/patches/glibc/glibc-rh1133810-2.patch @@ -0,0 +1,625 @@ +commit 585367266923156ac6fb789939a923641ba5aaf4 +Author: Florian Weimer fweimer@redhat.com +Date: Wed May 28 14:05:03 2014 +0200 + + manual: Update the locale documentation + +commit 4e8f95a0df7c2300b830ec12c0ae1e161bc8a8a3 +Author: Florian Weimer fweimer@redhat.com +Date: Mon May 12 15:24:12 2014 +0200 + + _nl_find_locale: Improve handling of crafted locale names [BZ #17137] + + Prevent directory traversal in locale-related environment variables + (CVE-2014-0475). + +commit d183645616b0533b3acee28f1a95570bffbdf50f +Author: Florian Weimer fweimer@redhat.com +Date: Wed May 28 14:41:52 2014 +0200 + + setlocale: Use the heap for the copy of the locale argument + + This avoids alloca calls with potentially large arguments. + +diff -pruN glibc-2.18/locale/findlocale.c glibc-2.18.patched/locale/findlocale.c +--- glibc-2.18/locale/findlocale.c 2013-08-11 04:22:55.000000000 +0530 ++++ glibc-2.18.patched/locale/findlocale.c 2014-08-26 16:14:50.403253778 +0530 +@@ -17,6 +17,7 @@ + 02111-1307 USA. */ + + #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_ + + 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 (__builtin_expect (namelen > 255, 0)) ++ return 0; ++ /* Directory traversal attempt. */ ++ static const char slashdot[4] = {'/', '.', '.', '/'}; ++ if (__builtin_expect (memmem (name, namelen, ++ slashdot, sizeof (slashdot)) != NULL, 0)) ++ return 0; ++ if (namelen == 2 && __builtin_expect (name[0] == '.' && name [1] == '.', 0)) ++ return 0; ++ if (namelen >= 3 ++ && __builtin_expect (((name[0] == '.' ++ && name[1] == '.' ++ && name[2] == '/') ++ || (name[namelen - 3] == '/' ++ && name[namelen - 2] == '.' ++ && name[namelen - 1] == '.')), 0)) ++ return 0; ++ /* If there is a slash in the name, it must start with one. */ ++ if (__builtin_expect (memchr (name, '/', namelen) != NULL, 0) && name[0] != '/') ++ return 0; ++ return 1; ++} + + struct __locale_data * + internal_function +@@ -65,7 +105,7 @@ _nl_find_locale (const char *locale_path + { + 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 + 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 -pruN glibc-2.18/locale/setlocale.c glibc-2.18.patched/locale/setlocale.c +--- glibc-2.18/locale/setlocale.c 2013-08-11 04:22:55.000000000 +0530 ++++ glibc-2.18.patched/locale/setlocale.c 2014-08-26 16:14:50.401253764 +0530 +@@ -272,6 +272,8 @@ setlocale (int category, const char *loc + 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 *loc + 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 (__builtin_expect (locale_copy == NULL, 0)) ++ { ++ __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 *loc + { + 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 *loc + /* 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; + } +diff -pruN glibc-2.18/localedata/Makefile glibc-2.18.patched/localedata/Makefile +--- glibc-2.18/localedata/Makefile 2014-08-26 16:15:22.656474571 +0530 ++++ glibc-2.18.patched/localedata/Makefile 2014-08-26 16:14:50.403253778 +0530 +@@ -77,7 +77,7 @@ locale_test_suite := tst_iswalnum tst_is + + 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 tst-strptime ++ tst-strfmon1 tst-sscanf tst-strptime tst-setlocale3 + ifeq (yes,$(build-shared)) + ifneq (no,$(PERL)) + tests: $(objpfx)mtrace-tst-leaks +@@ -288,6 +288,7 @@ tst-strfmon1-ENV = $(TEST_MBWC_ENV) + tst-strptime-ENV = $(TEST_MBWC_ENV) + + tst-setlocale-ENV = LOCPATH=$(common-objpfx)localedata LC_ALL=ja_JP.EUC-JP ++tst-setlocale3-ENV = LOCPATH=$(common-objpfx)localedata + + bug-iconv-trans-ENV = LOCPATH=$(common-objpfx)localedata + +diff -pruN glibc-2.18/localedata/tst-setlocale3.c glibc-2.18.patched/localedata/tst-setlocale3.c +--- glibc-2.18/localedata/tst-setlocale3.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.18.patched/localedata/tst-setlocale3.c 2014-08-26 16:14:50.403253778 +0530 +@@ -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" +diff -pruN glibc-2.18/manual/locale.texi glibc-2.18.patched/manual/locale.texi +--- glibc-2.18/manual/locale.texi 2013-08-11 04:22:55.000000000 +0530 ++++ glibc-2.18.patched/manual/locale.texi 2014-08-26 16:14:50.404253785 +0530 +@@ -29,6 +29,7 @@ will follow the conventions preferred by + * 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 + 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 + 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 grou + 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}. +@@ -225,13 +232,7 @@ The symbols in this section are defined + @comment ISO + @deftypefun {char *} setlocale (int @var{category}, const char *@var{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 +@@ -256,10 +257,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 +@@ -275,6 +275,11 @@ 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 +@@ -328,7 +323,7 @@ locale categories, and future versions o + 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 +@@ -362,7 +357,94 @@ with the environment, rather than trying + 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, ++the GNU C Library 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 diff --git a/src/patches/glibc/glibc-rh1138769.patch b/src/patches/glibc/glibc-rh1138769.patch new file mode 100644 index 0000000..94a7d2a --- /dev/null +++ b/src/patches/glibc/glibc-rh1138769.patch @@ -0,0 +1,45 @@ +commit e35c53e397e7abbd41fedacdedcfa5af7b5c2c52 +Author: Siddhesh Poyarekar siddhesh@redhat.com +Date: Tue Jul 8 16:40:24 2014 +0530 + + Check value at resplen2 if it is not NULL + + There was a typo in the previous patch due to which resplen2 was + checked for non-zero instead of the value at resplen2. Fix that and + improve the condition by checking resplen2 for non-NULL (instead of + answerp2) and also adding the check in a third place. + +diff --git a/resolv/res_query.c b/resolv/res_query.c +index 4e6612c..e4ee2a6 100644 +--- a/resolv/res_query.c ++++ b/resolv/res_query.c +@@ -384,7 +384,7 @@ __libc_res_nsearch(res_state statp, + answerp2, nanswerp2, resplen2); + if (ret > 0 || trailing_dot + /* If the second response is valid then we use that. */ +- || (ret == 0 && answerp2 != NULL && resplen2 > 0)) ++ || (ret == 0 && resplen2 != NULL && *resplen2 > 0)) + return (ret); + saved_herrno = h_errno; + tried_as_is++; +@@ -424,8 +424,8 @@ __libc_res_nsearch(res_state statp, + answer, anslen, answerp, + answerp2, nanswerp2, + resplen2); +- if (ret > 0 || (ret == 0 && answerp2 != NULL +- && resplen2 > 0)) ++ if (ret > 0 || (ret == 0 && resplen2 != NULL ++ && *resplen2 > 0)) + return (ret); + + if (answerp && *answerp != answer) { +@@ -494,7 +494,8 @@ __libc_res_nsearch(res_state statp, + ret = __libc_res_nquerydomain(statp, name, NULL, class, type, + answer, anslen, answerp, + answerp2, nanswerp2, resplen2); +- if (ret > 0) ++ if (ret > 0 || (ret == 0 && resplen2 != NULL ++ && *resplen2 > 0)) + return (ret); + } + diff --git a/src/patches/glibc/glibc-rh1139571.patch b/src/patches/glibc/glibc-rh1139571.patch deleted file mode 100644 index b1320a7..0000000 --- a/src/patches/glibc/glibc-rh1139571.patch +++ /dev/null @@ -1,154 +0,0 @@ -commit 41488498b6d9440ee66ab033808cce8323bba7ac -Author: Florian Weimer fweimer@redhat.com -Date: Wed Sep 3 19:45:43 2014 +0200 - - CVE-2014-6040: Crashes on invalid input in IBM gconv modules [BZ #17325] - - These changes are based on the fix for BZ #14134 in commit - 6e230d11837f3ae7b375ea69d7905f0d18eb79e5. - -diff --git a/iconvdata/Makefile b/iconvdata/Makefile -index 0a410a1..b6327d6 100644 ---- a/iconvdata/Makefile -+++ b/iconvdata/Makefile -@@ -297,6 +297,7 @@ $(objpfx)tst-iconv7.out: $(objpfx)gconv-modules \ - $(objpfx)iconv-test.out: run-iconv-test.sh $(objpfx)gconv-modules \ - $(addprefix $(objpfx),$(modules.so)) \ - $(common-objdir)/iconv/iconv_prog TESTS -+ iconv_modules="$(modules)" \ - $(SHELL) -e $< $(common-objdir) > $@ - - $(objpfx)tst-tables.out: tst-tables.sh $(objpfx)gconv-modules \ -diff --git a/iconvdata/ibm1364.c b/iconvdata/ibm1364.c -index 0b5484f..cf80993 100644 ---- a/iconvdata/ibm1364.c -+++ b/iconvdata/ibm1364.c -@@ -221,7 +221,8 @@ enum - ++rp2; \ - \ - uint32_t res; \ -- if (__builtin_expect (ch < rp2->start, 0) \ -+ if (__builtin_expect (rp2->start == 0xffff, 0) \ -+ || __builtin_expect (ch < rp2->start, 0) \ - || (res = DB_TO_UCS4[ch + rp2->idx], \ - __builtin_expect (res, L'\1') == L'\0' && ch != '\0')) \ - { \ -diff --git a/iconvdata/ibm932.c b/iconvdata/ibm932.c -index f5dca59..aa69d65 100644 ---- a/iconvdata/ibm932.c -+++ b/iconvdata/ibm932.c -@@ -74,11 +74,12 @@ - } \ - \ - ch = (ch * 0x100) + inptr[1]; \ -+ /* ch was less than 0xfd. */ \ -+ assert (ch < 0xfd00); \ - while (ch > rp2->end) \ - ++rp2; \ - \ -- if (__builtin_expect (rp2 == NULL, 0) \ -- || __builtin_expect (ch < rp2->start, 0) \ -+ if (__builtin_expect (ch < rp2->start, 0) \ - || (res = __ibm932db_to_ucs4[ch + rp2->idx], \ - __builtin_expect (res, '\1') == 0 && ch !=0)) \ - { \ -diff --git a/iconvdata/ibm933.c b/iconvdata/ibm933.c -index f46dfb5..461fb5e 100644 ---- a/iconvdata/ibm933.c -+++ b/iconvdata/ibm933.c -@@ -162,7 +162,7 @@ enum - while (ch > rp2->end) \ - ++rp2; \ - \ -- if (__builtin_expect (rp2 == NULL, 0) \ -+ if (__builtin_expect (rp2->start == 0xffff, 0) \ - || __builtin_expect (ch < rp2->start, 0) \ - || (res = __ibm933db_to_ucs4[ch + rp2->idx], \ - __builtin_expect (res, L'\1') == L'\0' && ch != '\0')) \ -diff --git a/iconvdata/ibm935.c b/iconvdata/ibm935.c -index a8e4e6c..132d816 100644 ---- a/iconvdata/ibm935.c -+++ b/iconvdata/ibm935.c -@@ -162,7 +162,7 @@ enum - while (ch > rp2->end) \ - ++rp2; \ - \ -- if (__builtin_expect (rp2 == NULL, 0) \ -+ if (__builtin_expect (rp2->start == 0xffff, 0) \ - || __builtin_expect (ch < rp2->start, 0) \ - || (res = __ibm935db_to_ucs4[ch + rp2->idx], \ - __builtin_expect (res, L'\1') == L'\0' && ch != '\0')) \ -diff --git a/iconvdata/ibm937.c b/iconvdata/ibm937.c -index 239be61..69b154d 100644 ---- a/iconvdata/ibm937.c -+++ b/iconvdata/ibm937.c -@@ -162,7 +162,7 @@ enum - while (ch > rp2->end) \ - ++rp2; \ - \ -- if (__builtin_expect (rp2 == NULL, 0) \ -+ if (__builtin_expect (rp2->start == 0xffff, 0) \ - || __builtin_expect (ch < rp2->start, 0) \ - || (res = __ibm937db_to_ucs4[ch + rp2->idx], \ - __builtin_expect (res, L'\1') == L'\0' && ch != '\0')) \ -diff --git a/iconvdata/ibm939.c b/iconvdata/ibm939.c -index 5d0db36..9936e2c 100644 ---- a/iconvdata/ibm939.c -+++ b/iconvdata/ibm939.c -@@ -162,7 +162,7 @@ enum - while (ch > rp2->end) \ - ++rp2; \ - \ -- if (__builtin_expect (rp2 == NULL, 0) \ -+ if (__builtin_expect (rp2->start == 0xffff, 0) \ - || __builtin_expect (ch < rp2->start, 0) \ - || (res = __ibm939db_to_ucs4[ch + rp2->idx], \ - __builtin_expect (res, L'\1') == L'\0' && ch != '\0')) \ -diff --git a/iconvdata/ibm943.c b/iconvdata/ibm943.c -index be0c14f..c5d5742 100644 ---- a/iconvdata/ibm943.c -+++ b/iconvdata/ibm943.c -@@ -75,11 +75,12 @@ - } \ - \ - ch = (ch * 0x100) + inptr[1]; \ -+ /* ch was less than 0xfd. */ \ -+ assert (ch < 0xfd00); \ - while (ch > rp2->end) \ - ++rp2; \ - \ -- if (__builtin_expect (rp2 == NULL, 0) \ -- || __builtin_expect (ch < rp2->start, 0) \ -+ if (__builtin_expect (ch < rp2->start, 0) \ - || (res = __ibm943db_to_ucs4[ch + rp2->idx], \ - __builtin_expect (res, '\1') == 0 && ch !=0)) \ - { \ -diff --git a/iconvdata/run-iconv-test.sh b/iconvdata/run-iconv-test.sh -index c98c929..5dfb69f 100755 ---- a/iconvdata/run-iconv-test.sh -+++ b/iconvdata/run-iconv-test.sh -@@ -184,6 +184,24 @@ while read utf8 from filename; do - - done < TESTS2 - -+# Check for crashes in decoders. -+printf '\016\377\377\377\377\377\377\377' > $temp1 -+for from in $iconv_modules ; do -+ echo $ac_n "test decoder $from $ac_c" -+ PROG=`eval echo $ICONV` -+ if $PROG < $temp1 >/dev/null 2>&1 ; then -+ : # fall through -+ else -+ status=$? -+ if test $status -gt 1 ; then -+ echo "/FAILED" -+ failed=1 -+ continue -+ fi -+ fi -+ echo "OK" -+done -+ - exit $failed - # Local Variables: - # mode:shell-script diff --git a/src/patches/glibc/glibc-rh1144019.patch b/src/patches/glibc/glibc-rh1144019.patch new file mode 100644 index 0000000..1732de6 --- /dev/null +++ b/src/patches/glibc/glibc-rh1144019.patch @@ -0,0 +1,27 @@ +# +# Based on the following commit: +# +# commit f9d2d03254a58d92635a311a42253eeed5a40a47 +# Author: Andreas Schwab schwab@suse.de +# Date: Mon May 26 18:01:31 2014 +0200 +# +# Fix invalid file descriptor reuse while sending DNS query (BZ #15946) +# +# 2014-06-03 Andreas Schwab schwab@suse.de +# +# [BZ #15946] +# * resolv/res_send.c (send_dg): Reload file descriptor after +# calling reopen. +# +diff --git a/resolv/res_send.c b/resolv/res_send.c +index 3273d55..af42b8a 100644 +--- a/resolv/res_send.c ++++ b/resolv/res_send.c +@@ -1410,6 +1410,7 @@ send_dg(res_state statp, + retval = reopen (statp, terrno, ns); + if (retval <= 0) + return retval; ++ pfd[0].fd = EXT(statp).nssocks[ns]; + } + } + goto wait; diff --git a/src/patches/glibc/glibc-rh1144132.patch b/src/patches/glibc/glibc-rh1144132.patch new file mode 100644 index 0000000..4114b58 --- /dev/null +++ b/src/patches/glibc/glibc-rh1144132.patch @@ -0,0 +1,58 @@ +# +# Based on this commit: +# +# commit 62058ce612ed3459501b4c4332e268edfe977f59 +# Author: Carlos O'Donell carlos@redhat.com +# Date: Mon Sep 29 13:14:21 2014 -0400 +# +# Correctly size profiling reloc table (bug 17411) +# +# During auditing or profiling modes the dynamic loader +# builds a cache of the relocated PLT entries in order +# to reuse them when called again through the same PLT +# entry. This way the PLT entry is never completed and +# the call into the resolver always results in profiling +# or auditing code running. +# +# The problem is that the PLT relocation cache size +# is not computed correctly. The size of the cache +# should be "Size of a relocation result structure" +# x "Number of PLT-related relocations". Instead the +# code erroneously computes "Size of a relocation +# result" x "Number of bytes worth of PLT-related +# relocations". I can only assume this was a mistake +# in the understanding of the value of DT_PLTRELSZ +# which is the number of bytes of PLT-related relocs. +# We do have a DT_RELACOUNT entry, which is a count +# for dynamic relative relocs, but we have no +# DT_PLTRELCOUNT and thus we need to compute it. +# +# This patch corrects the computation of the size of the +# relocation table used by the glibc profiling code. +# +# For more details see: +# https://sourceware.org/ml/libc-alpha/2014-09/msg00513.html +# +# [BZ #17411] +# * elf/dl-reloc.c (_dl_relocate_object): Allocate correct amount for +# l_reloc_result. +# +diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c +index d2c6dac..97a7119 100644 +--- a/elf/dl-reloc.c ++++ b/elf/dl-reloc.c +@@ -279,8 +279,12 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[], + l->l_name); + } + +- l->l_reloc_result = calloc (sizeof (l->l_reloc_result[0]), +- l->l_info[DT_PLTRELSZ]->d_un.d_val); ++ size_t sizeofrel = l->l_info[DT_PLTREL]->d_un.d_val == DT_RELA ++ ? sizeof (ElfW(Rela)) ++ : sizeof (ElfW(Rel)); ++ size_t relcount = l->l_info[DT_PLTRELSZ]->d_un.d_val / sizeofrel; ++ l->l_reloc_result = calloc (sizeof (l->l_reloc_result[0]), relcount); ++ + if (l->l_reloc_result == NULL) + { + errstring = N_("\ diff --git a/src/patches/glibc/glibc-rh1159167.patch b/src/patches/glibc/glibc-rh1159167.patch new file mode 100644 index 0000000..59f4a6f --- /dev/null +++ b/src/patches/glibc/glibc-rh1159167.patch @@ -0,0 +1,15 @@ +diff --git a/sunrpc/svc.c b/sunrpc/svc.c +index ccf0902..30c3a93 100644 +--- a/sunrpc/svc.c ++++ b/sunrpc/svc.c +@@ -97,8 +97,8 @@ xprt_register (SVCXPRT *xprt) + + if (xports == NULL) + { +- xports = (SVCXPRT **) malloc (_rpc_dtablesize () * sizeof (SVCXPRT *)); +- if (xports == NULL) /* DonŽt add handle */ ++ xports = (SVCXPRT **) calloc (_rpc_dtablesize (), sizeof (SVCXPRT *)); ++ if (xports == NULL) /* Don't add handle */ + return; + } + diff --git a/src/patches/glibc/glibc-rh1170121.patch b/src/patches/glibc/glibc-rh1170121.patch deleted file mode 100644 index 1accbf3..0000000 --- a/src/patches/glibc/glibc-rh1170121.patch +++ /dev/null @@ -1,163 +0,0 @@ -# -# 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/src/patches/glibc/glibc-rh1171296.patch b/src/patches/glibc/glibc-rh1171296.patch new file mode 100644 index 0000000..1accbf3 --- /dev/null +++ b/src/patches/glibc/glibc-rh1171296.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/src/patches/glibc/glibc-rh1172044.patch b/src/patches/glibc/glibc-rh1172044.patch new file mode 100644 index 0000000..b1320a7 --- /dev/null +++ b/src/patches/glibc/glibc-rh1172044.patch @@ -0,0 +1,154 @@ +commit 41488498b6d9440ee66ab033808cce8323bba7ac +Author: Florian Weimer fweimer@redhat.com +Date: Wed Sep 3 19:45:43 2014 +0200 + + CVE-2014-6040: Crashes on invalid input in IBM gconv modules [BZ #17325] + + These changes are based on the fix for BZ #14134 in commit + 6e230d11837f3ae7b375ea69d7905f0d18eb79e5. + +diff --git a/iconvdata/Makefile b/iconvdata/Makefile +index 0a410a1..b6327d6 100644 +--- a/iconvdata/Makefile ++++ b/iconvdata/Makefile +@@ -297,6 +297,7 @@ $(objpfx)tst-iconv7.out: $(objpfx)gconv-modules \ + $(objpfx)iconv-test.out: run-iconv-test.sh $(objpfx)gconv-modules \ + $(addprefix $(objpfx),$(modules.so)) \ + $(common-objdir)/iconv/iconv_prog TESTS ++ iconv_modules="$(modules)" \ + $(SHELL) -e $< $(common-objdir) > $@ + + $(objpfx)tst-tables.out: tst-tables.sh $(objpfx)gconv-modules \ +diff --git a/iconvdata/ibm1364.c b/iconvdata/ibm1364.c +index 0b5484f..cf80993 100644 +--- a/iconvdata/ibm1364.c ++++ b/iconvdata/ibm1364.c +@@ -221,7 +221,8 @@ enum + ++rp2; \ + \ + uint32_t res; \ +- if (__builtin_expect (ch < rp2->start, 0) \ ++ if (__builtin_expect (rp2->start == 0xffff, 0) \ ++ || __builtin_expect (ch < rp2->start, 0) \ + || (res = DB_TO_UCS4[ch + rp2->idx], \ + __builtin_expect (res, L'\1') == L'\0' && ch != '\0')) \ + { \ +diff --git a/iconvdata/ibm932.c b/iconvdata/ibm932.c +index f5dca59..aa69d65 100644 +--- a/iconvdata/ibm932.c ++++ b/iconvdata/ibm932.c +@@ -74,11 +74,12 @@ + } \ + \ + ch = (ch * 0x100) + inptr[1]; \ ++ /* ch was less than 0xfd. */ \ ++ assert (ch < 0xfd00); \ + while (ch > rp2->end) \ + ++rp2; \ + \ +- if (__builtin_expect (rp2 == NULL, 0) \ +- || __builtin_expect (ch < rp2->start, 0) \ ++ if (__builtin_expect (ch < rp2->start, 0) \ + || (res = __ibm932db_to_ucs4[ch + rp2->idx], \ + __builtin_expect (res, '\1') == 0 && ch !=0)) \ + { \ +diff --git a/iconvdata/ibm933.c b/iconvdata/ibm933.c +index f46dfb5..461fb5e 100644 +--- a/iconvdata/ibm933.c ++++ b/iconvdata/ibm933.c +@@ -162,7 +162,7 @@ enum + while (ch > rp2->end) \ + ++rp2; \ + \ +- if (__builtin_expect (rp2 == NULL, 0) \ ++ if (__builtin_expect (rp2->start == 0xffff, 0) \ + || __builtin_expect (ch < rp2->start, 0) \ + || (res = __ibm933db_to_ucs4[ch + rp2->idx], \ + __builtin_expect (res, L'\1') == L'\0' && ch != '\0')) \ +diff --git a/iconvdata/ibm935.c b/iconvdata/ibm935.c +index a8e4e6c..132d816 100644 +--- a/iconvdata/ibm935.c ++++ b/iconvdata/ibm935.c +@@ -162,7 +162,7 @@ enum + while (ch > rp2->end) \ + ++rp2; \ + \ +- if (__builtin_expect (rp2 == NULL, 0) \ ++ if (__builtin_expect (rp2->start == 0xffff, 0) \ + || __builtin_expect (ch < rp2->start, 0) \ + || (res = __ibm935db_to_ucs4[ch + rp2->idx], \ + __builtin_expect (res, L'\1') == L'\0' && ch != '\0')) \ +diff --git a/iconvdata/ibm937.c b/iconvdata/ibm937.c +index 239be61..69b154d 100644 +--- a/iconvdata/ibm937.c ++++ b/iconvdata/ibm937.c +@@ -162,7 +162,7 @@ enum + while (ch > rp2->end) \ + ++rp2; \ + \ +- if (__builtin_expect (rp2 == NULL, 0) \ ++ if (__builtin_expect (rp2->start == 0xffff, 0) \ + || __builtin_expect (ch < rp2->start, 0) \ + || (res = __ibm937db_to_ucs4[ch + rp2->idx], \ + __builtin_expect (res, L'\1') == L'\0' && ch != '\0')) \ +diff --git a/iconvdata/ibm939.c b/iconvdata/ibm939.c +index 5d0db36..9936e2c 100644 +--- a/iconvdata/ibm939.c ++++ b/iconvdata/ibm939.c +@@ -162,7 +162,7 @@ enum + while (ch > rp2->end) \ + ++rp2; \ + \ +- if (__builtin_expect (rp2 == NULL, 0) \ ++ if (__builtin_expect (rp2->start == 0xffff, 0) \ + || __builtin_expect (ch < rp2->start, 0) \ + || (res = __ibm939db_to_ucs4[ch + rp2->idx], \ + __builtin_expect (res, L'\1') == L'\0' && ch != '\0')) \ +diff --git a/iconvdata/ibm943.c b/iconvdata/ibm943.c +index be0c14f..c5d5742 100644 +--- a/iconvdata/ibm943.c ++++ b/iconvdata/ibm943.c +@@ -75,11 +75,12 @@ + } \ + \ + ch = (ch * 0x100) + inptr[1]; \ ++ /* ch was less than 0xfd. */ \ ++ assert (ch < 0xfd00); \ + while (ch > rp2->end) \ + ++rp2; \ + \ +- if (__builtin_expect (rp2 == NULL, 0) \ +- || __builtin_expect (ch < rp2->start, 0) \ ++ if (__builtin_expect (ch < rp2->start, 0) \ + || (res = __ibm943db_to_ucs4[ch + rp2->idx], \ + __builtin_expect (res, '\1') == 0 && ch !=0)) \ + { \ +diff --git a/iconvdata/run-iconv-test.sh b/iconvdata/run-iconv-test.sh +index c98c929..5dfb69f 100755 +--- a/iconvdata/run-iconv-test.sh ++++ b/iconvdata/run-iconv-test.sh +@@ -184,6 +184,24 @@ while read utf8 from filename; do + + done < TESTS2 + ++# Check for crashes in decoders. ++printf '\016\377\377\377\377\377\377\377' > $temp1 ++for from in $iconv_modules ; do ++ echo $ac_n "test decoder $from $ac_c" ++ PROG=`eval echo $ICONV` ++ if $PROG < $temp1 >/dev/null 2>&1 ; then ++ : # fall through ++ else ++ status=$? ++ if test $status -gt 1 ; then ++ echo "/FAILED" ++ failed=1 ++ continue ++ fi ++ fi ++ echo "OK" ++done ++ + exit $failed + # Local Variables: + # mode:shell-script diff --git a/src/patches/glibc/glibc-rh1176907.patch b/src/patches/glibc/glibc-rh1176907.patch new file mode 100644 index 0000000..29cdacf --- /dev/null +++ b/src/patches/glibc/glibc-rh1176907.patch @@ -0,0 +1,22 @@ +commit 7d81e8d6db95c112c297930a8f2f9617c305529a +Author: Florian Weimer fweimer@redhat.com +Date: Tue Dec 23 16:16:32 2014 +0100 + + iconvdata/run-iconv-test.sh: Actually test iconv modules + + Arjun Shankar noticed that this test case was not testing anything + because iconv was invoked without the required arguments. + +diff --git a/iconvdata/run-iconv-test.sh b/iconvdata/run-iconv-test.sh +index 5dfb69f..1d0bf52 100755 +--- a/iconvdata/run-iconv-test.sh ++++ b/iconvdata/run-iconv-test.sh +@@ -189,7 +189,7 @@ printf '\016\377\377\377\377\377\377\377' > $temp1 + for from in $iconv_modules ; do + echo $ac_n "test decoder $from $ac_c" + PROG=`eval echo $ICONV` +- if $PROG < $temp1 >/dev/null 2>&1 ; then ++ if $PROG -f $from -t UTF8 < $temp1 >/dev/null 2>&1 ; then + : # fall through + else + status=$? diff --git a/src/patches/glibc/glibc-rh1183533.patch b/src/patches/glibc/glibc-rh1183533.patch deleted file mode 100644 index 9263cd5..0000000 --- a/src/patches/glibc/glibc-rh1183533.patch +++ /dev/null @@ -1,210 +0,0 @@ -commit d5dd6189d506068ed11c8bfa1e1e9bffde04decd -Author: Andreas Schwab schwab@suse.de -Date: Mon Jan 21 17:41:28 2013 +0100 - - Fix parsing of numeric hosts in gethostbyname_r - -diff --git a/nss/digits_dots.c b/nss/digits_dots.c -index 2b86295..e007ef4 100644 ---- a/nss/digits_dots.c -+++ b/nss/digits_dots.c -@@ -46,7 +46,10 @@ __nss_hostname_digits_dots (const char *name, struct hostent *resbuf, - { - if (h_errnop) - *h_errnop = NETDB_INTERNAL; -- *result = NULL; -+ if (buffer_size == NULL) -+ *status = NSS_STATUS_TRYAGAIN; -+ else -+ *result = NULL; - return -1; - } - -@@ -83,14 +86,16 @@ __nss_hostname_digits_dots (const char *name, struct hostent *resbuf, - } - - size_needed = (sizeof (*host_addr) -- + sizeof (*h_addr_ptrs) + strlen (name) + 1); -+ + sizeof (*h_addr_ptrs) -+ + sizeof (*h_alias_ptr) + strlen (name) + 1); - - if (buffer_size == NULL) - { - if (buflen < size_needed) - { -+ *status = NSS_STATUS_TRYAGAIN; - if (h_errnop != NULL) -- *h_errnop = TRY_AGAIN; -+ *h_errnop = NETDB_INTERNAL; - __set_errno (ERANGE); - goto done; - } -@@ -109,7 +114,7 @@ __nss_hostname_digits_dots (const char *name, struct hostent *resbuf, - *buffer_size = 0; - __set_errno (save); - if (h_errnop != NULL) -- *h_errnop = TRY_AGAIN; -+ *h_errnop = NETDB_INTERNAL; - *result = NULL; - goto done; - } -@@ -149,7 +154,9 @@ __nss_hostname_digits_dots (const char *name, struct hostent *resbuf, - if (! ok) - { - *h_errnop = HOST_NOT_FOUND; -- if (buffer_size) -+ if (buffer_size == NULL) -+ *status = NSS_STATUS_NOTFOUND; -+ else - *result = NULL; - goto done; - } -@@ -190,7 +197,7 @@ __nss_hostname_digits_dots (const char *name, struct hostent *resbuf, - if (buffer_size == NULL) - *status = NSS_STATUS_SUCCESS; - else -- *result = resbuf; -+ *result = resbuf; - goto done; - } - -@@ -201,15 +208,6 @@ __nss_hostname_digits_dots (const char *name, struct hostent *resbuf, - - if ((isxdigit (name[0]) && strchr (name, ':') != NULL) || name[0] == ':') - { -- const char *cp; -- char *hostname; -- typedef unsigned char host_addr_t[16]; -- host_addr_t *host_addr; -- typedef char *host_addr_list_t[2]; -- host_addr_list_t *h_addr_ptrs; -- size_t size_needed; -- int addr_size; -- - switch (af) - { - default: -@@ -225,7 +223,10 @@ __nss_hostname_digits_dots (const char *name, struct hostent *resbuf, - /* This is not possible. We cannot represent an IPv6 address - in an `struct in_addr' variable. */ - *h_errnop = HOST_NOT_FOUND; -- *result = NULL; -+ if (buffer_size == NULL) -+ *status = NSS_STATUS_NOTFOUND; -+ else -+ *result = NULL; - goto done; - - case AF_INET6: -@@ -233,42 +234,6 @@ __nss_hostname_digits_dots (const char *name, struct hostent *resbuf, - break; - } - -- size_needed = (sizeof (*host_addr) -- + sizeof (*h_addr_ptrs) + strlen (name) + 1); -- -- if (buffer_size == NULL && buflen < size_needed) -- { -- if (h_errnop != NULL) -- *h_errnop = TRY_AGAIN; -- __set_errno (ERANGE); -- goto done; -- } -- else if (buffer_size != NULL && *buffer_size < size_needed) -- { -- char *new_buf; -- *buffer_size = size_needed; -- new_buf = realloc (*buffer, *buffer_size); -- -- if (new_buf == NULL) -- { -- save = errno; -- free (*buffer); -- __set_errno (save); -- *buffer = NULL; -- *buffer_size = 0; -- *result = NULL; -- goto done; -- } -- *buffer = new_buf; -- } -- -- memset (*buffer, '\0', size_needed); -- -- host_addr = (host_addr_t *) *buffer; -- h_addr_ptrs = (host_addr_list_t *) -- ((char *) host_addr + sizeof (*host_addr)); -- hostname = (char *) h_addr_ptrs + sizeof (*h_addr_ptrs); -- - for (cp = name;; ++cp) - { - if (!*cp) -@@ -281,7 +246,9 @@ __nss_hostname_digits_dots (const char *name, struct hostent *resbuf, - if (inet_pton (AF_INET6, name, host_addr) <= 0) - { - *h_errnop = HOST_NOT_FOUND; -- if (buffer_size) -+ if (buffer_size == NULL) -+ *status = NSS_STATUS_NOTFOUND; -+ else - *result = NULL; - goto done; - } -diff --git a/nss/getXXbyYY_r.c b/nss/getXXbyYY_r.c -index 1067744..44d00f4 100644 ---- a/nss/getXXbyYY_r.c -+++ b/nss/getXXbyYY_r.c -@@ -179,6 +179,9 @@ INTERNAL (REENTRANT_NAME) (ADD_PARAMS, LOOKUP_TYPE *resbuf, char *buffer, - case -1: - return errno; - case 1: -+#ifdef NEED_H_ERRNO -+ any_service = true; -+#endif - goto done; - } - #endif -diff --git a/nss/test-digits-dots.c b/nss/test-digits-dots.c -new file mode 100644 -index 0000000..1efa344 ---- /dev/null -+++ b/nss/test-digits-dots.c -@@ -0,0 +1,38 @@ -+/* 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 -+ http://www.gnu.org/licenses/. */ -+ -+/* Testcase for BZ #15014 */ -+ -+#include <stdlib.h> -+#include <netdb.h> -+#include <errno.h> -+ -+static int -+do_test (void) -+{ -+ char buf[32]; -+ struct hostent *result = NULL; -+ struct hostent ret; -+ int h_err = 0; -+ int err; -+ -+ err = gethostbyname_r ("1.2.3.4", &ret, buf, sizeof (buf), &result, &h_err); -+ return err == ERANGE && h_err == NETDB_INTERNAL ? EXIT_SUCCESS : EXIT_FAILURE; -+} -+ -+#define TEST_FUNCTION do_test () -+#include "../test-skeleton.c" diff --git a/src/patches/glibc/glibc-rh1183534.patch b/src/patches/glibc/glibc-rh1183534.patch new file mode 100644 index 0000000..eab7a3f --- /dev/null +++ b/src/patches/glibc/glibc-rh1183534.patch @@ -0,0 +1,223 @@ +commit d5dd6189d506068ed11c8bfa1e1e9bffde04decd +Author: Andreas Schwab schwab@suse.de +Date: Mon Jan 21 17:41:28 2013 +0100 + + Fix parsing of numeric hosts in gethostbyname_r + +diff --git a/nss/Makefile b/nss/Makefile +index 449a258..553eafa 100644 +--- a/nss/Makefile ++++ b/nss/Makefile +@@ -37,7 +37,7 @@ install-bin := getent makedb + others := getent + install-bin := getent + +-tests = test-netdb tst-nss-test1 ++tests = test-netdb tst-nss-test1 test-digits-dots + xtests = bug-erange + + include ../Makeconfig +diff --git a/nss/digits_dots.c b/nss/digits_dots.c +index 2b86295..e007ef4 100644 +--- a/nss/digits_dots.c ++++ b/nss/digits_dots.c +@@ -46,7 +46,10 @@ __nss_hostname_digits_dots (const char *name, struct hostent *resbuf, + { + if (h_errnop) + *h_errnop = NETDB_INTERNAL; +- *result = NULL; ++ if (buffer_size == NULL) ++ *status = NSS_STATUS_TRYAGAIN; ++ else ++ *result = NULL; + return -1; + } + +@@ -83,14 +86,16 @@ __nss_hostname_digits_dots (const char *name, struct hostent *resbuf, + } + + size_needed = (sizeof (*host_addr) +- + sizeof (*h_addr_ptrs) + strlen (name) + 1); ++ + sizeof (*h_addr_ptrs) ++ + sizeof (*h_alias_ptr) + strlen (name) + 1); + + if (buffer_size == NULL) + { + if (buflen < size_needed) + { ++ *status = NSS_STATUS_TRYAGAIN; + if (h_errnop != NULL) +- *h_errnop = TRY_AGAIN; ++ *h_errnop = NETDB_INTERNAL; + __set_errno (ERANGE); + goto done; + } +@@ -109,7 +114,7 @@ __nss_hostname_digits_dots (const char *name, struct hostent *resbuf, + *buffer_size = 0; + __set_errno (save); + if (h_errnop != NULL) +- *h_errnop = TRY_AGAIN; ++ *h_errnop = NETDB_INTERNAL; + *result = NULL; + goto done; + } +@@ -149,7 +154,9 @@ __nss_hostname_digits_dots (const char *name, struct hostent *resbuf, + if (! ok) + { + *h_errnop = HOST_NOT_FOUND; +- if (buffer_size) ++ if (buffer_size == NULL) ++ *status = NSS_STATUS_NOTFOUND; ++ else + *result = NULL; + goto done; + } +@@ -190,7 +197,7 @@ __nss_hostname_digits_dots (const char *name, struct hostent *resbuf, + if (buffer_size == NULL) + *status = NSS_STATUS_SUCCESS; + else +- *result = resbuf; ++ *result = resbuf; + goto done; + } + +@@ -201,15 +208,6 @@ __nss_hostname_digits_dots (const char *name, struct hostent *resbuf, + + if ((isxdigit (name[0]) && strchr (name, ':') != NULL) || name[0] == ':') + { +- const char *cp; +- char *hostname; +- typedef unsigned char host_addr_t[16]; +- host_addr_t *host_addr; +- typedef char *host_addr_list_t[2]; +- host_addr_list_t *h_addr_ptrs; +- size_t size_needed; +- int addr_size; +- + switch (af) + { + default: +@@ -225,7 +223,10 @@ __nss_hostname_digits_dots (const char *name, struct hostent *resbuf, + /* This is not possible. We cannot represent an IPv6 address + in an `struct in_addr' variable. */ + *h_errnop = HOST_NOT_FOUND; +- *result = NULL; ++ if (buffer_size == NULL) ++ *status = NSS_STATUS_NOTFOUND; ++ else ++ *result = NULL; + goto done; + + case AF_INET6: +@@ -233,42 +234,6 @@ __nss_hostname_digits_dots (const char *name, struct hostent *resbuf, + break; + } + +- size_needed = (sizeof (*host_addr) +- + sizeof (*h_addr_ptrs) + strlen (name) + 1); +- +- if (buffer_size == NULL && buflen < size_needed) +- { +- if (h_errnop != NULL) +- *h_errnop = TRY_AGAIN; +- __set_errno (ERANGE); +- goto done; +- } +- else if (buffer_size != NULL && *buffer_size < size_needed) +- { +- char *new_buf; +- *buffer_size = size_needed; +- new_buf = realloc (*buffer, *buffer_size); +- +- if (new_buf == NULL) +- { +- save = errno; +- free (*buffer); +- __set_errno (save); +- *buffer = NULL; +- *buffer_size = 0; +- *result = NULL; +- goto done; +- } +- *buffer = new_buf; +- } +- +- memset (*buffer, '\0', size_needed); +- +- host_addr = (host_addr_t *) *buffer; +- h_addr_ptrs = (host_addr_list_t *) +- ((char *) host_addr + sizeof (*host_addr)); +- hostname = (char *) h_addr_ptrs + sizeof (*h_addr_ptrs); +- + for (cp = name;; ++cp) + { + if (!*cp) +@@ -281,7 +246,9 @@ __nss_hostname_digits_dots (const char *name, struct hostent *resbuf, + if (inet_pton (AF_INET6, name, host_addr) <= 0) + { + *h_errnop = HOST_NOT_FOUND; +- if (buffer_size) ++ if (buffer_size == NULL) ++ *status = NSS_STATUS_NOTFOUND; ++ else + *result = NULL; + goto done; + } +diff --git a/nss/getXXbyYY_r.c b/nss/getXXbyYY_r.c +index 1067744..44d00f4 100644 +--- a/nss/getXXbyYY_r.c ++++ b/nss/getXXbyYY_r.c +@@ -179,6 +179,9 @@ INTERNAL (REENTRANT_NAME) (ADD_PARAMS, LOOKUP_TYPE *resbuf, char *buffer, + case -1: + return errno; + case 1: ++#ifdef NEED_H_ERRNO ++ any_service = true; ++#endif + goto done; + } + #endif +diff --git a/nss/test-digits-dots.c b/nss/test-digits-dots.c +new file mode 100644 +index 0000000..1efa344 +--- /dev/null ++++ b/nss/test-digits-dots.c +@@ -0,0 +1,38 @@ ++/* 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 ++ http://www.gnu.org/licenses/. */ ++ ++/* Testcase for BZ #15014 */ ++ ++#include <stdlib.h> ++#include <netdb.h> ++#include <errno.h> ++ ++static int ++do_test (void) ++{ ++ char buf[32]; ++ struct hostent *result = NULL; ++ struct hostent ret; ++ int h_err = 0; ++ int err; ++ ++ err = gethostbyname_r ("1.2.3.4", &ret, buf, sizeof (buf), &result, &h_err); ++ return err == ERANGE && h_err == NETDB_INTERNAL ? EXIT_SUCCESS : EXIT_FAILURE; ++} ++ ++#define TEST_FUNCTION do_test () ++#include "../test-skeleton.c" diff --git a/src/patches/glibc/glibc-rh1195453-avx512.patch b/src/patches/glibc/glibc-rh1195453-avx512.patch new file mode 100644 index 0000000..4c70e5e --- /dev/null +++ b/src/patches/glibc/glibc-rh1195453-avx512.patch @@ -0,0 +1,481 @@ +# +# Based on AVX-512 support for glibc, but heavaily modified for rhel-6.7. +# Without assembler support we drop all of the configure checks and simply +# output using .byte directives the minimal AVX512 instructsion required +# by the loader. Likewise testing is also impossible, so instead we use +# the Intel emulator running in `-skx` (Skylake Xeon) emulation mode and +# verify that a pre-built set of tests passes. +# +# commit 6986b98a18490e76b16911d1c6b1ba013598d40d +# Author: Ulrich Drepper drepper@gmail.com +# Date: Wed Jul 20 14:20:00 2011 -0400 +# +# Force :a_x86_64_ymm to be 16-byte aligned +# +# commit aa4de9cea5c07d43caeaca9722c2d417e9a2919c +# Author: H.J. Lu hjl.tools@gmail.com +# Date: Fri Mar 14 08:51:25 2014 -0700 +# +# Check AVX-512 assembler support first +# +# It checks AVX-512 assembler support first and sets libc_cv_cc_avx512 to +# $libc_cv_asm_avx512, instead of yes. GCC won't support AVX-512 if +# assembler doesn't support it. +# +# * sysdeps/x86_64/configure.ac: Check AVX-512 assembler support +# first. Disable AVX-512 GCC support if assembler doesn't support +# it. +# * sysdeps/x86_64/configure: Regenerated. +# +# commit 2d63a517e4084ec80403cd9f278690fa8b676cc4 +# Author: Igor Zamyatin igor.zamyatin@intel.com +# Date: Thu Mar 13 11:10:22 2014 -0700 +# +# Save and restore AVX-512 zmm registers to x86-64 ld.so +# +# AVX-512 ISA adds 512-bit zmm registers. This patch updates +# _dl_runtime_profile to pass zmm registers to run-time audit. It also +# changes _dl_x86_64_save_sse and _dl_x86_64_restore_sse to upport zmm +# registers, which are called when only when RTLD_PREPARE_FOREIGN_CALL +# is used. Its performance impact is minimum. +# +# * config.h.in (HAVE_AVX512_SUPPORT): New #undef. +# (HAVE_AVX512_ASM_SUPPORT): Likewise. +# * sysdeps/x86_64/bits/link.h (La_x86_64_zmm): New. +# (La_x86_64_vector): Add zmm. +# * sysdeps/x86_64/Makefile (tests): Add tst-audit10. +# (modules-names): Add tst-auditmod10a and tst-auditmod10b. +# ($(objpfx)tst-audit10): New target. +# ($(objpfx)tst-audit10.out): Likewise. +# (tst-audit10-ENV): New. +# (AVX512-CFLAGS): Likewise. +# (CFLAGS-tst-audit10.c): Likewise. +# (CFLAGS-tst-auditmod10a.c): Likewise. +# (CFLAGS-tst-auditmod10b.c): Likewise. +# * sysdeps/x86_64/configure.ac: Set config-cflags-avx512, +# HAVE_AVX512_SUPPORT and HAVE_AVX512_ASM_SUPPORT. +# * sysdeps/x86_64/configure: Regenerated. +# * sysdeps/x86_64/dl-trampoline.S (_dl_runtime_profile): Add +# AVX-512 zmm register support. +# (_dl_x86_64_save_sse): Likewise. +# (_dl_x86_64_restore_sse): Likewise. +# * sysdeps/x86_64/dl-trampoline.h: Updated to support different +# size vector registers. +# * sysdeps/x86_64/link-defines.sym (YMM_SIZE): New. +# (ZMM_SIZE): Likewise. +# * sysdeps/x86_64/tst-audit10.c: New file. +# * sysdeps/x86_64/tst-auditmod10a.c: Likewise. +# * sysdeps/x86_64/tst-auditmod10b.c: Likewise. +# +# In addition adds: +# https://sourceware.org/ml/libc-alpha/2014-09/msg00228.html +# To extend zmm register checking. +# +diff -urN glibc-2.12-2-gc4ccff1/sysdeps/x86_64/bits/link.h glibc-2.12-2-gc4ccff1.mod/sysdeps/x86_64/bits/link.h +--- glibc-2.12-2-gc4ccff1/sysdeps/x86_64/bits/link.h 2010-05-04 07:27:23.000000000 -0400 ++++ glibc-2.12-2-gc4ccff1.mod/sysdeps/x86_64/bits/link.h 2015-03-03 23:03:25.041829238 -0500 +@@ -65,7 +65,10 @@ + /* Registers for entry into PLT on x86-64. */ + # if __GNUC_PREREQ (4,0) + typedef float La_x86_64_xmm __attribute__ ((__vector_size__ (16))); +-typedef float La_x86_64_ymm __attribute__ ((__vector_size__ (32))); ++typedef float La_x86_64_ymm __attribute__ ((__vector_size__ (32), ++ __aligned__ (16))); ++typedef double La_x86_64_zmm __attribute__ ((__vector_size__ (64), ++ __aligned__ (16))); + # else + typedef float La_x86_64_xmm __attribute__ ((__mode__ (__V4SF__))); + # endif +@@ -74,9 +77,10 @@ + { + # if __GNUC_PREREQ (4,0) + La_x86_64_ymm ymm[2]; ++ La_x86_64_zmm zmm[1]; + # endif + La_x86_64_xmm xmm[4]; +-} La_x86_64_vector __attribute__ ((aligned(16))); ++} La_x86_64_vector __attribute__ ((__aligned__(16))); + + typedef struct La_x86_64_regs + { +diff -urN glibc-2.12-2-gc4ccff1/sysdeps/x86_64/dl-trampoline.h glibc-2.12-2-gc4ccff1.mod/sysdeps/x86_64/dl-trampoline.h +--- glibc-2.12-2-gc4ccff1/sysdeps/x86_64/dl-trampoline.h 2015-03-03 23:03:05.109457627 -0500 ++++ glibc-2.12-2-gc4ccff1.mod/sysdeps/x86_64/dl-trampoline.h 2015-03-03 23:06:58.434101818 -0500 +@@ -20,14 +20,26 @@ + + #ifdef RESTORE_AVX + /* This is to support AVX audit modules. */ +- vmovdqu %ymm0, (LR_VECTOR_OFFSET)(%rsp) +- vmovdqu %ymm1, (LR_VECTOR_OFFSET + VECTOR_SIZE)(%rsp) +- vmovdqu %ymm2, (LR_VECTOR_OFFSET + VECTOR_SIZE*2)(%rsp) +- vmovdqu %ymm3, (LR_VECTOR_OFFSET + VECTOR_SIZE*3)(%rsp) +- vmovdqu %ymm4, (LR_VECTOR_OFFSET + VECTOR_SIZE*4)(%rsp) +- vmovdqu %ymm5, (LR_VECTOR_OFFSET + VECTOR_SIZE*5)(%rsp) +- vmovdqu %ymm6, (LR_VECTOR_OFFSET + VECTOR_SIZE*6)(%rsp) +- vmovdqu %ymm7, (LR_VECTOR_OFFSET + VECTOR_SIZE*7)(%rsp) ++# if HAVE_NO_AVX512_ASM_SUPPORT ++ /* Restore AVX-512 registers. Use .byte becaues we lack assembler support. */ ++ .byte 0x62,0xf1,0xfe,0x48,0x7f,0x44,0x24,0x03 # vmovdqu64 %zmm0,0xc0(%rsp) ++ .byte 0x62,0xf1,0xfe,0x48,0x7f,0x4c,0x24,0x04 # vmovdqu64 %zmm1,0x100(%rsp) ++ .byte 0x62,0xf1,0xfe,0x48,0x7f,0x54,0x24,0x05 # vmovdqu64 %zmm2,0x140(%rsp) ++ .byte 0x62,0xf1,0xfe,0x48,0x7f,0x5c,0x24,0x06 # vmovdqu64 %zmm3,0x180(%rsp) ++ .byte 0x62,0xf1,0xfe,0x48,0x7f,0x64,0x24,0x07 # vmovdqu64 %zmm4,0x1c0(%rsp) ++ .byte 0x62,0xf1,0xfe,0x48,0x7f,0x6c,0x24,0x08 # vmovdqu64 %zmm5,0x200(%rsp) ++ .byte 0x62,0xf1,0xfe,0x48,0x7f,0x74,0x24,0x09 # vmovdqu64 %zmm6,0x240(%rsp) ++ .byte 0x62,0xf1,0xfe,0x48,0x7f,0x7c,0x24,0x0a # vmovdqu64 %zmm7,0x280(%rsp) ++# else ++ VMOV %VEC(0), (LR_VECTOR_OFFSET)(%rsp) ++ VMOV %VEC(1), (LR_VECTOR_OFFSET + VECTOR_SIZE)(%rsp) ++ VMOV %VEC(2), (LR_VECTOR_OFFSET + VECTOR_SIZE*2)(%rsp) ++ VMOV %VEC(3), (LR_VECTOR_OFFSET + VECTOR_SIZE*3)(%rsp) ++ VMOV %VEC(4), (LR_VECTOR_OFFSET + VECTOR_SIZE*4)(%rsp) ++ VMOV %VEC(5), (LR_VECTOR_OFFSET + VECTOR_SIZE*5)(%rsp) ++ VMOV %VEC(6), (LR_VECTOR_OFFSET + VECTOR_SIZE*6)(%rsp) ++ VMOV %VEC(7), (LR_VECTOR_OFFSET + VECTOR_SIZE*7)(%rsp) ++# endif + + /* Save xmm0-xmm7 registers to detect if any of them are + changed by audit module. */ +@@ -73,7 +85,11 @@ + je 2f + vmovdqa %xmm0, (LR_VECTOR_OFFSET)(%rsp) + jmp 1f +-2: vmovdqu (LR_VECTOR_OFFSET)(%rsp), %ymm0 ++# if HAVE_NO_AVX512_ASM_SUPPORT ++2: .byte 0x62,0xf1,0xfe,0x48,0x6f,0x44,0x24,0x03 # vmovdqu64 0xc0(%rsp),%zmm0 ++# else ++2: VMOV (LR_VECTOR_OFFSET)(%rsp), %VEC(0) ++# endif + vmovdqa %xmm0, (LR_XMM_OFFSET)(%rsp) + + 1: vpcmpeqq (LR_SIZE + XMM_SIZE)(%rsp), %xmm1, %xmm8 +@@ -82,7 +98,11 @@ + je 2f + vmovdqa %xmm1, (LR_VECTOR_OFFSET + VECTOR_SIZE)(%rsp) + jmp 1f +-2: vmovdqu (LR_VECTOR_OFFSET + VECTOR_SIZE)(%rsp), %ymm1 ++# if HAVE_NO_AVX512_ASM_SUPPORT ++2: .byte 0x62,0xf1,0xfe,0x48,0x6f,0x4c,0x24,0x04 # vmovdqu64 0x100(%rsp),%zmm1 ++# else ++2: VMOV (LR_VECTOR_OFFSET + VECTOR_SIZE)(%rsp), %VEC(1) ++# endif + vmovdqa %xmm1, (LR_XMM_OFFSET + XMM_SIZE)(%rsp) + + 1: vpcmpeqq (LR_SIZE + XMM_SIZE*2)(%rsp), %xmm2, %xmm8 +@@ -91,7 +111,11 @@ + je 2f + vmovdqa %xmm2, (LR_VECTOR_OFFSET + VECTOR_SIZE*2)(%rsp) + jmp 1f +-2: vmovdqu (LR_VECTOR_OFFSET + VECTOR_SIZE*2)(%rsp), %ymm2 ++# if HAVE_NO_AVX512_ASM_SUPPORT ++2: .byte 0x62,0xf1,0xfe,0x48,0x6f,0x54,0x24,0x05 # vmovdqu64 0x140(%rsp),%zmm2 ++# else ++2: VMOV (LR_VECTOR_OFFSET + VECTOR_SIZE*2)(%rsp), %VEC(2) ++# endif + vmovdqa %xmm2, (LR_XMM_OFFSET + XMM_SIZE*2)(%rsp) + + 1: vpcmpeqq (LR_SIZE + XMM_SIZE*3)(%rsp), %xmm3, %xmm8 +@@ -100,7 +124,11 @@ + je 2f + vmovdqa %xmm3, (LR_VECTOR_OFFSET + VECTOR_SIZE*3)(%rsp) + jmp 1f +-2: vmovdqu (LR_VECTOR_OFFSET + VECTOR_SIZE*3)(%rsp), %ymm3 ++# if HAVE_NO_AVX512_ASM_SUPPORT ++2: .byte 0x62,0xf1,0xfe,0x48,0x6f,0x5c,0x24,0x06 # vmovdqu64 0x180(%rsp),%zmm3 ++# else ++2: VMOV (LR_VECTOR_OFFSET + VECTOR_SIZE*3)(%rsp), %VEC(3) ++# endif + vmovdqa %xmm3, (LR_XMM_OFFSET + XMM_SIZE*3)(%rsp) + + 1: vpcmpeqq (LR_SIZE + XMM_SIZE*4)(%rsp), %xmm4, %xmm8 +@@ -109,7 +137,11 @@ + je 2f + vmovdqa %xmm4, (LR_VECTOR_OFFSET + VECTOR_SIZE*4)(%rsp) + jmp 1f +-2: vmovdqu (LR_VECTOR_OFFSET + VECTOR_SIZE*4)(%rsp), %ymm4 ++# if HAVE_NO_AVX512_ASM_SUPPORT ++2: .byte 0x62,0xf1,0xfe,0x48,0x6f,0x64,0x24,0x07 # vmovdqu64 0x1c0(%rsp),%zmm4 ++# else ++2: VMOV (LR_VECTOR_OFFSET + VECTOR_SIZE*4)(%rsp), %VEC(4) ++# endif + vmovdqa %xmm4, (LR_XMM_OFFSET + XMM_SIZE*4)(%rsp) + + 1: vpcmpeqq (LR_SIZE + XMM_SIZE*5)(%rsp), %xmm5, %xmm8 +@@ -118,7 +150,11 @@ + je 2f + vmovdqa %xmm5, (LR_VECTOR_OFFSET + VECTOR_SIZE*5)(%rsp) + jmp 1f +-2: vmovdqu (LR_VECTOR_OFFSET + VECTOR_SIZE*5)(%rsp), %ymm5 ++# if HAVE_NO_AVX512_ASM_SUPPORT ++2: .byte 0x62,0xf1,0xfe,0x48,0x6f,0x6c,0x24,0x08 # vmovdqu64 0x200(%rsp),%zmm5 ++# else ++2: VMOV (LR_VECTOR_OFFSET + VECTOR_SIZE*5)(%rsp), %VEC(5) ++# endif + vmovdqa %xmm5, (LR_XMM_OFFSET + XMM_SIZE*5)(%rsp) + + 1: vpcmpeqq (LR_SIZE + XMM_SIZE*6)(%rsp), %xmm6, %xmm8 +@@ -127,7 +163,11 @@ + je 2f + vmovdqa %xmm6, (LR_VECTOR_OFFSET + VECTOR_SIZE*6)(%rsp) + jmp 1f +-2: vmovdqu (LR_VECTOR_OFFSET + VECTOR_SIZE*6)(%rsp), %ymm6 ++# if HAVE_NO_AVX512_ASM_SUPPORT ++2: .byte 0x62,0xf1,0xfe,0x48,0x6f,0x74,0x24,0x09 # vmovdqu64 0x240(%rsp),%zmm6 ++# else ++2: VMOV (LR_VECTOR_OFFSET + VECTOR_SIZE*6)(%rsp), %VEC(6) ++# endif + vmovdqa %xmm6, (LR_XMM_OFFSET + XMM_SIZE*6)(%rsp) + + 1: vpcmpeqq (LR_SIZE + XMM_SIZE*7)(%rsp), %xmm7, %xmm8 +@@ -136,7 +176,11 @@ + je 2f + vmovdqa %xmm7, (LR_VECTOR_OFFSET + VECTOR_SIZE*7)(%rsp) + jmp 1f +-2: vmovdqu (LR_VECTOR_OFFSET + VECTOR_SIZE*7)(%rsp), %ymm7 ++# if HAVE_NO_AVX512_ASM_SUPPORT ++2: .byte 0x62,0xf1,0xfe,0x48,0x6f,0x7c,0x24,0x0a # vmovdqu64 0x280(%rsp),%zmm7 ++# else ++2: VMOV (LR_VECTOR_OFFSET + VECTOR_SIZE*7)(%rsp), %VEC(7) ++# endif + vmovdqa %xmm7, (LR_XMM_OFFSET + XMM_SIZE*7)(%rsp) + + 1: +@@ -214,8 +258,13 @@ + + #ifdef RESTORE_AVX + /* This is to support AVX audit modules. */ +- vmovdqu %ymm0, LRV_VECTOR0_OFFSET(%rcx) +- vmovdqu %ymm1, LRV_VECTOR1_OFFSET(%rcx) ++# if HAVE_NO_AVX512_ASM_SUPPORT ++ .byte 0x62,0xf1,0xfe,0x48,0x7f,0x81,0x50,0x00,0x00,0x00 # vmovdqu64 %zmm0,0x50(%rcx) ++ .byte 0x62,0xf1,0xfe,0x48,0x7f,0x89,0x90,0x00,0x00,0x00 # vmovdqu64 %zmm1,0x90(%rcx) ++# else ++ VMOV %VEC(0), LRV_VECTOR0_OFFSET(%rcx) ++ VMOV %VEC(1), LRV_VECTOR1_OFFSET(%rcx) ++# endif + + /* Save xmm0/xmm1 registers to detect if they are changed + by audit module. */ +@@ -244,13 +293,21 @@ + vpmovmskb %xmm2, %esi + cmpl $0xffff, %esi + jne 1f +- vmovdqu LRV_VECTOR0_OFFSET(%rsp), %ymm0 ++# if HAVE_NO_AVX512_ASM_SUPPORT ++ .byte 0x62,0xf1,0xfe,0x48,0x6f,0x84,0x24,0x50,0x00,0x00,0x00 # vmovdqu64 0x50(%rsp),%zmm0 ++# else ++ VMOV LRV_VECTOR0_OFFSET(%rsp), %VEC(0) ++# endif + + 1: vpcmpeqq (LRV_SIZE + XMM_SIZE)(%rsp), %xmm1, %xmm2 + vpmovmskb %xmm2, %esi + cmpl $0xffff, %esi + jne 1f +- vmovdqu LRV_VECTOR1_OFFSET(%rsp), %ymm1 ++# if HAVE_NO_AVX512_ASM_SUPPORT ++ .byte 0x62,0xf1,0xfe,0x48,0x6f,0x8c,0x24,0x90,0x00,0x00,0x00 # vmovdqu64 0x90(%rsp),%zmm1 ++# else ++ VMOV LRV_VECTOR1_OFFSET(%rsp), %VEC(1) ++# endif + + 1: + #endif +diff -urN glibc-2.12-2-gc4ccff1/sysdeps/x86_64/dl-trampoline.S glibc-2.12-2-gc4ccff1.mod/sysdeps/x86_64/dl-trampoline.S +--- glibc-2.12-2-gc4ccff1/sysdeps/x86_64/dl-trampoline.S 2015-03-03 23:03:05.108457659 -0500 ++++ glibc-2.12-2-gc4ccff1.mod/sysdeps/x86_64/dl-trampoline.S 2015-03-03 23:07:31.799049953 -0500 +@@ -134,7 +134,7 @@ + .previous + + cmpl $0, L(have_avx)(%rip) +- jne 1f ++ jne L(defined) + movq %rbx, %r11 # Save rbx + movl $1, %eax + cpuid +@@ -143,18 +143,51 @@ + // AVX and XSAVE supported? + andl $((1 << 28) | (1 << 27)), %ecx + cmpl $((1 << 28) | (1 << 27)), %ecx +- jne 2f ++ jne 10f ++ // AVX512 supported in processor? ++ movq %rbx, %r11 # Save rbx ++ xorl %ecx, %ecx ++ mov $0x7, %eax ++ cpuid ++ andl $(1 << 16), %ebx + xorl %ecx, %ecx + // Get XFEATURE_ENABLED_MASK + xgetbv +- andl $0x6, %eax +-2: subl $0x5, %eax ++ test %ebx, %ebx ++ movq %r11, %rbx # Restore rbx ++ je 20f ++ // Verify that XCR0[7:5] = '111b' and ++ // XCR0[2:1] = '11b' which means ++ // that zmm state is enabled ++ andl $0xe6, %eax ++ cmpl $0xe6, %eax ++ jne 20f ++ movl %eax, L(have_avx)(%rip) ++L(avx512): ++# define RESTORE_AVX ++# define HAVE_NO_AVX512_ASM_SUPPORT 1 ++# define VMOV vmovdqu64 ++# define VEC(i) zmm##i ++# define MORE_CODE ++# include "dl-trampoline.h" ++# undef VMOV ++# undef VEC ++# undef RESTORE_AVX ++# undef HAVE_NO_AVX512_ASM_SUPPORT ++20: andl $0x6, %eax ++10: subl $0x5, %eax + movl %eax, L(have_avx)(%rip) + cmpl $0, %eax + +-1: js L(no_avx) ++L(defined): ++ js L(no_avx) ++ cmpl $0xe6, L(have_avx)(%rip) ++ je L(avx512) ++ + + # define RESTORE_AVX ++# define VMOV vmovdqu ++# define VEC(i) ymm##i + # define MORE_CODE + # include "dl-trampoline.h" + +@@ -178,7 +211,7 @@ + _dl_x86_64_save_sse: + # ifdef HAVE_AVX_SUPPORT + cmpl $0, L(have_avx)(%rip) +- jne 1f ++ jne L(defined_5) + movq %rbx, %r11 # Save rbx + movl $1, %eax + cpuid +@@ -187,21 +220,37 @@ + // AVX and XSAVE supported? + andl $((1 << 28) | (1 << 27)), %ecx + cmpl $((1 << 28) | (1 << 27)), %ecx +- jne 2f ++ jne 1f ++ // AVX512 supported in a processor? ++ movq %rbx, %r11 # Save rbx ++ xorl %ecx,%ecx ++ mov $0x7,%eax ++ cpuid ++ andl $(1 << 16), %ebx + xorl %ecx, %ecx + // Get XFEATURE_ENABLED_MASK + xgetbv +- andl $0x6, %eax +- cmpl $0x6, %eax +- // Nonzero if SSE and AVX state saving is enabled. +- sete %al +-2: leal -1(%eax,%eax), %eax ++ test %ebx, %ebx ++ movq %r11, %rbx # Restore rbx ++ je 2f ++ // Verify that XCR0[7:5] = '111b' and ++ // XCR0[2:1] = '11b' which means ++ // that zmm state is enabled ++ andl $0xe6, %eax + movl %eax, L(have_avx)(%rip) +- cmpl $0, %eax ++ cmpl $0xe6, %eax ++ je L(avx512_5) + +-1: js L(no_avx5) ++2: andl $0x6, %eax ++1: subl $0x5, %eax ++ movl %eax, L(have_avx)(%rip) ++ cmpl $0, %eax + +-# define YMM_SIZE 32 ++L(defined_5): ++ js L(no_avx5) ++ cmpl $0xe6, L(have_avx)(%rip) ++ je L(avx512_5) ++ + vmovdqa %ymm0, %fs:RTLD_SAVESPACE_SSE+0*YMM_SIZE + vmovdqa %ymm1, %fs:RTLD_SAVESPACE_SSE+1*YMM_SIZE + vmovdqa %ymm2, %fs:RTLD_SAVESPACE_SSE+2*YMM_SIZE +@@ -211,6 +260,26 @@ + vmovdqa %ymm6, %fs:RTLD_SAVESPACE_SSE+6*YMM_SIZE + vmovdqa %ymm7, %fs:RTLD_SAVESPACE_SSE+7*YMM_SIZE + ret ++L(avx512_5): ++# Original instructions: ++# vmovdqu64 %zmm0, %fs:RTLD_SAVESPACE_SSE+0*ZMM_SIZE ++# vmovdqu64 %zmm1, %fs:RTLD_SAVESPACE_SSE+1*ZMM_SIZE ++# vmovdqu64 %zmm2, %fs:RTLD_SAVESPACE_SSE+2*ZMM_SIZE ++# vmovdqu64 %zmm3, %fs:RTLD_SAVESPACE_SSE+3*ZMM_SIZE ++# vmovdqu64 %zmm4, %fs:RTLD_SAVESPACE_SSE+4*ZMM_SIZE ++# vmovdqu64 %zmm5, %fs:RTLD_SAVESPACE_SSE+5*ZMM_SIZE ++# vmovdqu64 %zmm6, %fs:RTLD_SAVESPACE_SSE+6*ZMM_SIZE ++# vmovdqu64 %zmm7, %fs:RTLD_SAVESPACE_SSE+7*ZMM_SIZE ++# Assembled instructions: ++ .byte 0x64,0x62,0xf1,0xfe,0x48,0x7f,0x04,0x25,0x80,0x00,0x00,0x00 # vmovdqu64 %zmm0,%fs:0x80 ++ .byte 0x64,0x62,0xf1,0xfe,0x48,0x7f,0x0c,0x25,0xc0,0x00,0x00,0x00 # vmovdqu64 %zmm1,%fs:0xc0 ++ .byte 0x64,0x62,0xf1,0xfe,0x48,0x7f,0x14,0x25,0x00,0x01,0x00,0x00 # vmovdqu64 %zmm2,%fs:0x100 ++ .byte 0x64,0x62,0xf1,0xfe,0x48,0x7f,0x1c,0x25,0x40,0x01,0x00,0x00 # vmovdqu64 %zmm3,%fs:0x140 ++ .byte 0x64,0x62,0xf1,0xfe,0x48,0x7f,0x24,0x25,0x80,0x01,0x00,0x00 # vmovdqu64 %zmm4,%fs:0x180 ++ .byte 0x64,0x62,0xf1,0xfe,0x48,0x7f,0x2c,0x25,0xc0,0x01,0x00,0x00 # vmovdqu64 %zmm5,%fs:0x1c0 ++ .byte 0x64,0x62,0xf1,0xfe,0x48,0x7f,0x34,0x25,0x00,0x02,0x00,0x00 # vmovdqu64 %zmm6,%fs:0x200 ++ .byte 0x64,0x62,0xf1,0xfe,0x48,0x7f,0x3c,0x25,0x40,0x02,0x00,0x00 # vmovdqu64 %zmm7,%fs:0x240 ++ ret + L(no_avx5): + # endif + movdqa %xmm0, %fs:RTLD_SAVESPACE_SSE+0*XMM_SIZE +@@ -234,6 +303,8 @@ + # ifdef HAVE_AVX_SUPPORT + cmpl $0, L(have_avx)(%rip) + js L(no_avx6) ++ cmpl $0xe6, L(have_avx)(%rip) ++ je L(avx512_6) + + vmovdqa %fs:RTLD_SAVESPACE_SSE+0*YMM_SIZE, %ymm0 + vmovdqa %fs:RTLD_SAVESPACE_SSE+1*YMM_SIZE, %ymm1 +@@ -244,6 +315,26 @@ + vmovdqa %fs:RTLD_SAVESPACE_SSE+6*YMM_SIZE, %ymm6 + vmovdqa %fs:RTLD_SAVESPACE_SSE+7*YMM_SIZE, %ymm7 + ret ++L(avx512_6): ++# Original instructions: ++# vmovdqu64 %fs:RTLD_SAVESPACE_SSE+0*ZMM_SIZE, %zmm0 ++# vmovdqu64 %fs:RTLD_SAVESPACE_SSE+1*ZMM_SIZE, %zmm1 ++# vmovdqu64 %fs:RTLD_SAVESPACE_SSE+2*ZMM_SIZE, %zmm2 ++# vmovdqu64 %fs:RTLD_SAVESPACE_SSE+3*ZMM_SIZE, %zmm3 ++# vmovdqu64 %fs:RTLD_SAVESPACE_SSE+4*ZMM_SIZE, %zmm4 ++# vmovdqu64 %fs:RTLD_SAVESPACE_SSE+5*ZMM_SIZE, %zmm5 ++# vmovdqu64 %fs:RTLD_SAVESPACE_SSE+6*ZMM_SIZE, %zmm6 ++# vmovdqu64 %fs:RTLD_SAVESPACE_SSE+7*ZMM_SIZE, %zmm7 ++# Assembled instructions: ++ .byte 0x64,0x62,0xf1,0xfe,0x48,0x6f,0x04,0x25,0x80,0x00,0x00,0x00 # vmovdqu64 %fs:0x80,%zmm0 ++ .byte 0x64,0x62,0xf1,0xfe,0x48,0x6f,0x0c,0x25,0xc0,0x00,0x00,0x00 # vmovdqu64 %fs:0xc0,%zmm1 ++ .byte 0x64,0x62,0xf1,0xfe,0x48,0x6f,0x14,0x25,0x00,0x01,0x00,0x00 # vmovdqu64 %fs:0x100,%zmm2 ++ .byte 0x64,0x62,0xf1,0xfe,0x48,0x6f,0x1c,0x25,0x40,0x01,0x00,0x00 # vmovdqu64 %fs:0x140,%zmm3 ++ .byte 0x64,0x62,0xf1,0xfe,0x48,0x6f,0x24,0x25,0x80,0x01,0x00,0x00 # vmovdqu64 %fs:0x180,%zmm4 ++ .byte 0x64,0x62,0xf1,0xfe,0x48,0x6f,0x2c,0x25,0xc0,0x01,0x00,0x00 # vmovdqu64 %fs:0x1c0,%zmm5 ++ .byte 0x64,0x62,0xf1,0xfe,0x48,0x6f,0x34,0x25,0x00,0x02,0x00,0x00 # vmovdqu64 %fs:0x200,%zmm6 ++ .byte 0x64,0x62,0xf1,0xfe,0x48,0x6f,0x3c,0x25,0x40,0x02,0x00,0x00 # vmovdqu64 %fs:0x240,%zmm7 ++ ret + L(no_avx6): + # endif + movdqa %fs:RTLD_SAVESPACE_SSE+0*XMM_SIZE, %xmm0 +diff -urN glibc-2.12-2-gc4ccff1/sysdeps/x86_64/link-defines.sym glibc-2.12-2-gc4ccff1.mod/sysdeps/x86_64/link-defines.sym +--- glibc-2.12-2-gc4ccff1/sysdeps/x86_64/link-defines.sym 2010-05-04 07:27:23.000000000 -0400 ++++ glibc-2.12-2-gc4ccff1.mod/sysdeps/x86_64/link-defines.sym 2015-03-03 23:03:25.042829206 -0500 +@@ -4,6 +4,8 @@ + -- + VECTOR_SIZE sizeof (La_x86_64_vector) + XMM_SIZE sizeof (La_x86_64_xmm) ++YMM_SIZE sizeof (La_x86_64_ymm) ++ZMM_SIZE sizeof (La_x86_64_zmm) + + LR_SIZE sizeof (struct La_x86_64_regs) + LR_RDX_OFFSET offsetof (struct La_x86_64_regs, lr_rdx) diff --git a/src/patches/glibc/glibc-rh1207236.patch b/src/patches/glibc/glibc-rh1207236.patch new file mode 100644 index 0000000..5671fd8 --- /dev/null +++ b/src/patches/glibc/glibc-rh1207236.patch @@ -0,0 +1,12 @@ +diff -pruN glibc-2.12-2-gc4ccff1/malloc/malloc.c glibc-2.12-2-gc4ccff1.new/malloc/malloc.c +--- glibc-2.12-2-gc4ccff1/malloc/malloc.c 2015-04-10 12:02:54.011106386 +0530 ++++ glibc-2.12-2-gc4ccff1.new/malloc/malloc.c 2015-04-10 12:02:35.867958292 +0530 +@@ -5850,7 +5850,7 @@ _int_valloc(av, bytes) mstate av; size_t + #endif + { + /* Ensure initialization/consolidation */ +- if (have_fastchunks(av)) malloc_consolidate(av); ++ if (av && have_fastchunks(av)) malloc_consolidate(av); + return _int_memalign(av, mp_.pagesize, bytes); + } + diff --git a/src/patches/glibc/glibc-rh1207995.patch b/src/patches/glibc/glibc-rh1207995.patch deleted file mode 100644 index 1732de6..0000000 --- a/src/patches/glibc/glibc-rh1207995.patch +++ /dev/null @@ -1,27 +0,0 @@ -# -# Based on the following commit: -# -# commit f9d2d03254a58d92635a311a42253eeed5a40a47 -# Author: Andreas Schwab schwab@suse.de -# Date: Mon May 26 18:01:31 2014 +0200 -# -# Fix invalid file descriptor reuse while sending DNS query (BZ #15946) -# -# 2014-06-03 Andreas Schwab schwab@suse.de -# -# [BZ #15946] -# * resolv/res_send.c (send_dg): Reload file descriptor after -# calling reopen. -# -diff --git a/resolv/res_send.c b/resolv/res_send.c -index 3273d55..af42b8a 100644 ---- a/resolv/res_send.c -+++ b/resolv/res_send.c -@@ -1410,6 +1410,7 @@ send_dg(res_state statp, - retval = reopen (statp, terrno, ns); - if (retval <= 0) - return retval; -+ pfd[0].fd = EXT(statp).nssocks[ns]; - } - } - goto wait; diff --git a/src/patches/glibc/glibc-rh1209375.patch b/src/patches/glibc/glibc-rh1209375.patch deleted file mode 100644 index 74393f0..0000000 --- a/src/patches/glibc/glibc-rh1209375.patch +++ /dev/null @@ -1,18 +0,0 @@ -@@ -, +, @@ - resolv/nss_dns/dns-host.c:getanswer_r. ---- - resolv/nss_dns/dns-host.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) ---- a/resolv/nss_dns/dns-host.c -+++ a/resolv/nss_dns/dns-host.c -@@ -615,7 +615,8 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype, - int have_to_map = 0; - uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct host_data); - buffer += pad; -- if (__builtin_expect (buflen < sizeof (struct host_data) + pad, 0)) -+ buflen = buflen > pad ? buflen - pad : 0; -+ if (__builtin_expect (buflen < sizeof (struct host_data), 0)) - { - /* The buffer is too small. */ - too_small: --- diff --git a/src/patches/glibc/glibc-rh1209376.patch b/src/patches/glibc/glibc-rh1209376.patch new file mode 100644 index 0000000..74393f0 --- /dev/null +++ b/src/patches/glibc/glibc-rh1209376.patch @@ -0,0 +1,18 @@ +@@ -, +, @@ + resolv/nss_dns/dns-host.c:getanswer_r. +--- + resolv/nss_dns/dns-host.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) +--- a/resolv/nss_dns/dns-host.c ++++ a/resolv/nss_dns/dns-host.c +@@ -615,7 +615,8 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype, + int have_to_map = 0; + uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct host_data); + buffer += pad; +- if (__builtin_expect (buflen < sizeof (struct host_data) + pad, 0)) ++ buflen = buflen > pad ? buflen - pad : 0; ++ if (__builtin_expect (buflen < sizeof (struct host_data), 0)) + { + /* The buffer is too small. */ + too_small: +-- diff --git a/src/patches/glibc/glibc-rh1256812-2.patch b/src/patches/glibc/glibc-rh1256812-2.patch new file mode 100644 index 0000000..5596de7 --- /dev/null +++ b/src/patches/glibc/glibc-rh1256812-2.patch @@ -0,0 +1,15 @@ +diff -pruN glibc-2.12-2-gc4ccff1/malloc/malloc.c glibc-2.12-2-gc4ccff1.new/malloc/malloc.c +--- glibc-2.12-2-gc4ccff1/malloc/malloc.c 2015-07-28 22:28:22.517107147 +0530 ++++ glibc-2.12-2-gc4ccff1.new/malloc/malloc.c 2015-07-28 22:24:59.541394493 +0530 +@@ -4087,8 +4087,9 @@ public_cALLOc(size_t n, size_t elem_size + /* Maybe the failure is due to running out of mmapped areas. */ + if(av != &main_arena) { + (void)mutex_unlock(&av->mutex); +- (void)mutex_lock(&main_arena.mutex); +- mem = _int_malloc(&main_arena, sz); ++ av = &main_arena; ++ (void)mutex_lock(&av->mutex); ++ mem = _int_malloc(av, sz); + } else { + #if USE_ARENAS + /* ... or sbrk() has failed and there is still a chance to mmap() */ diff --git a/src/patches/glibc/glibc-rh1256812-3.patch b/src/patches/glibc/glibc-rh1256812-3.patch new file mode 100644 index 0000000..e8fbb1b --- /dev/null +++ b/src/patches/glibc/glibc-rh1256812-3.patch @@ -0,0 +1,138 @@ +commit fdc0f374bcd2d0513569aa8d600f960e43e8af1d +Author: Ulrich Drepper drepper@redhat.com +Date: Sun Oct 24 22:37:00 2010 -0400 + + Fix perturbing in malloc on free. + +commit e8349efd466cfedc0aa98be61d88ca8795c9e565 +Author: OndÅej BÃlka neleai@seznam.cz +Date: Mon Dec 9 17:25:19 2013 +0100 + + Simplify perturb_byte logic. + +diff --git a/malloc/malloc.c b/malloc/malloc.c +index 4821deb..ac8c3f6 100644 +--- a/malloc/malloc.c ++++ b/malloc/malloc.c +@@ -1870,8 +1870,20 @@ static int check_action = DEFAULT_CHECK_ACTION; + + static int perturb_byte; + +-#define alloc_perturb(p, n) memset (p, (perturb_byte ^ 0xff) & 0xff, n) +-#define free_perturb(p, n) memset (p, perturb_byte & 0xff, n) ++static inline void ++alloc_perturb (char *p, size_t n) ++{ ++ if (__glibc_unlikely (perturb_byte)) ++ memset (p, perturb_byte ^ 0xff, n); ++} ++ ++static inline void ++free_perturb (char *p, size_t n) ++{ ++ if (__glibc_unlikely (perturb_byte)) ++ memset (p, perturb_byte, n); ++} ++ + + + /* ------------------- Support for multiple arenas -------------------- */ +@@ -3287,8 +3299,7 @@ _int_malloc(mstate av, size_t bytes) + #endif + check_remalloced_chunk(av, victim, nb); + void *p = chunk2mem(victim); +- if (__builtin_expect (perturb_byte, 0)) +- alloc_perturb (p, bytes); ++ alloc_perturb (p, bytes); + return p; + } + } +@@ -3323,8 +3334,7 @@ _int_malloc(mstate av, size_t bytes) + victim->size |= NON_MAIN_ARENA; + check_malloced_chunk(av, victim, nb); + void *p = chunk2mem(victim); +- if (__builtin_expect (perturb_byte, 0)) +- alloc_perturb (p, bytes); ++ alloc_perturb (p, bytes); + return p; + } + } +@@ -3403,8 +3413,7 @@ _int_malloc(mstate av, size_t bytes) + + check_malloced_chunk(av, victim, nb); + void *p = chunk2mem(victim); +- if (__builtin_expect (perturb_byte, 0)) +- alloc_perturb (p, bytes); ++ alloc_perturb (p, bytes); + return p; + } + +@@ -3420,8 +3429,7 @@ _int_malloc(mstate av, size_t bytes) + victim->size |= NON_MAIN_ARENA; + check_malloced_chunk(av, victim, nb); + void *p = chunk2mem(victim); +- if (__builtin_expect (perturb_byte, 0)) +- alloc_perturb (p, bytes); ++ alloc_perturb (p, bytes); + return p; + } + +@@ -3545,8 +3553,7 @@ _int_malloc(mstate av, size_t bytes) + } + check_malloced_chunk(av, victim, nb); + void *p = chunk2mem(victim); +- if (__builtin_expect (perturb_byte, 0)) +- alloc_perturb (p, bytes); ++ alloc_perturb (p, bytes); + return p; + } + } +@@ -3649,8 +3656,7 @@ _int_malloc(mstate av, size_t bytes) + } + check_malloced_chunk(av, victim, nb); + void *p = chunk2mem(victim); +- if (__builtin_expect (perturb_byte, 0)) +- alloc_perturb (p, bytes); ++ alloc_perturb (p, bytes); + return p; + } + } +@@ -3684,8 +3690,7 @@ _int_malloc(mstate av, size_t bytes) + + check_malloced_chunk(av, victim, nb); + void *p = chunk2mem(victim); +- if (__builtin_expect (perturb_byte, 0)) +- alloc_perturb (p, bytes); ++ alloc_perturb (p, bytes); + return p; + } + +@@ -3705,7 +3710,7 @@ _int_malloc(mstate av, size_t bytes) + */ + else { + void *p = sYSMALLOc(nb, av); +- if (p != NULL && __builtin_expect (perturb_byte, 0)) ++ if (p != NULL) + alloc_perturb (p, bytes); + return p; + } +@@ -3798,8 +3803,7 @@ _int_free(mstate av, mchunkptr p, int have_lock) + #endif + } + +- if (__builtin_expect (perturb_byte, 0)) +- free_perturb (chunk2mem(p), size - SIZE_SZ); ++ free_perturb (chunk2mem(p), size - 2 * SIZE_SZ); + + set_fastchunks(av); + unsigned int idx = fastbin_index(size); +@@ -3881,8 +3885,7 @@ _int_free(mstate av, mchunkptr p, int have_lock) + goto errout; + } + +- if (__builtin_expect (perturb_byte, 0)) +- free_perturb (chunk2mem(p), size - SIZE_SZ); ++ free_perturb (chunk2mem(p), size - 2 * SIZE_SZ); + + /* consolidate backward */ + if (!prev_inuse(p)) { diff --git a/src/patches/glibc/glibc-rh1256812-4.patch b/src/patches/glibc/glibc-rh1256812-4.patch new file mode 100644 index 0000000..1e497f3 --- /dev/null +++ b/src/patches/glibc/glibc-rh1256812-4.patch @@ -0,0 +1,45 @@ +commit 55765a349a96482207fbf927d3666a51878f973b +Author: Josef Bacik josef@toxicpanda.com +Date: Wed Aug 19 14:06:56 2015 +0530 + + Don't fall back to mmap if the original arena is not corrupt + + The new logic to find an uncontended non-corrupt arena misses a case + where the current arena is contended, but is not corrupt. In the + degenerate case, this is the only arena. In both cases, the logic + falls back to using mmap despite there being an available arena. + + Attached patch by Josef Bacik makes sure that all arenas are indeed + corrupt before falling back to malloc. Verified on x86_64. + + * malloc/arena.c (reused_arena): return NULL only if all + arenas are corrupt. + +diff --git a/malloc/arena.c b/malloc/arena.c +index 21ecc5a1..0424273 100644 +--- a/malloc/arena.c ++++ b/malloc/arena.c +@@ -823,16 +823,21 @@ reused_arena (mstate avoid_arena) + + /* Make sure that the arena we get is not corrupted. */ + mstate begin = result; ++ bool looped = false; ++ + while (arena_is_corrupt (result)) + { + result = result->next; + if (result == begin) +- break; ++ { ++ looped = true; ++ break; ++ } + } + + /* We could not find any arena that was either not corrupted or not the one + we wanted to avoid. */ +- if (result == begin) ++ if (looped) + return NULL; + + /* No arena available without contention. Wait for the next in line. */ diff --git a/src/patches/glibc/glibc-rh1256812.patch b/src/patches/glibc/glibc-rh1256812.patch new file mode 100644 index 0000000..1eafcc1 --- /dev/null +++ b/src/patches/glibc/glibc-rh1256812.patch @@ -0,0 +1,56 @@ +diff -pruN glibc-2.12-2-gc4ccff1/malloc/malloc.c glibc-2.12-2-gc4ccff1.v2/malloc/malloc.c +--- glibc-2.12-2-gc4ccff1/malloc/malloc.c 2015-07-24 19:29:37.679907396 +0530 ++++ glibc-2.12-2-gc4ccff1.v2/malloc/malloc.c 2015-07-24 18:59:59.928055174 +0530 +@@ -3737,8 +3737,7 @@ public_mALLOc(size_t bytes) + mstate prev = ar_ptr->next ? ar_ptr : 0; + (void)mutex_unlock(&ar_ptr->mutex); + ar_ptr = arena_get2(prev, bytes, true); +- if(ar_ptr) +- victim = _int_malloc(ar_ptr, bytes); ++ victim = _int_malloc(ar_ptr, bytes); + #endif + } + } +@@ -3968,8 +3967,7 @@ public_mEMALIGn(size_t alignment, size_t + mstate prev = ar_ptr->next ? ar_ptr : 0; + (void)mutex_unlock(&ar_ptr->mutex); + ar_ptr = arena_get2(prev, bytes, true); +- if(ar_ptr) +- p = _int_memalign(ar_ptr, alignment, bytes); ++ p = _int_memalign(ar_ptr, alignment, bytes); + #endif + } + } +@@ -4024,8 +4022,7 @@ public_vALLOc(size_t bytes) + mstate prev = ar_ptr->next ? ar_ptr : 0; + (void)mutex_unlock(&ar_ptr->mutex); + ar_ptr = arena_get2(prev, bytes, true); +- if(ar_ptr) +- p = _int_memalign(ar_ptr, pagesz, bytes); ++ p = _int_memalign(ar_ptr, pagesz, bytes); + #endif + } + } +@@ -4080,8 +4077,7 @@ public_pVALLOc(size_t bytes) + mstate prev = ar_ptr->next ? ar_ptr : 0; + (void)mutex_unlock(&ar_ptr->mutex); + ar_ptr = arena_get2(prev, bytes + 2*pagesz + MINSIZE, true); +- if(ar_ptr) +- p = _int_memalign(ar_ptr, pagesz, rounded_bytes); ++ p = _int_memalign(ar_ptr, pagesz, rounded_bytes); + #endif + } + } +@@ -4180,11 +4176,9 @@ public_cALLOc(size_t n, size_t elem_size + mstate prev = av->next ? av : 0; + (void)mutex_unlock(&av->mutex); + av = arena_get2(prev, sz, true); +- if(av) +- mem = _int_malloc(av, sz); ++ mem = _int_malloc(av, sz); + #endif + } +- if (mem == 0) return 0; + } + + if (av != NULL) diff --git a/src/patches/glibc/glibc-rh1256890.patch b/src/patches/glibc/glibc-rh1256890.patch new file mode 100644 index 0000000..4683dc4 --- /dev/null +++ b/src/patches/glibc/glibc-rh1256890.patch @@ -0,0 +1,12 @@ +diff -pruN glibc-2.12-2-gc4ccff1/malloc/malloc.c glibc-2.12-2-gc4ccff1.new/malloc/malloc.c +--- glibc-2.12-2-gc4ccff1/malloc/malloc.c 2015-08-19 23:13:52.826205930 +0530 ++++ glibc-2.12-2-gc4ccff1.new/malloc/malloc.c 2015-08-19 23:13:40.021049289 +0530 +@@ -5867,7 +5867,7 @@ _int_pvalloc(av, bytes) mstate av, size_ + size_t pagesz; + + /* Ensure initialization/consolidation */ +- if (have_fastchunks(av)) malloc_consolidate(av); ++ if (av && have_fastchunks(av)) malloc_consolidate(av); + pagesz = mp_.pagesize; + return _int_memalign(av, pagesz, (bytes + pagesz - 1) & ~(pagesz - 1)); + } diff --git a/src/patches/glibc/glibc-rh1256891.patch b/src/patches/glibc/glibc-rh1256891.patch new file mode 100644 index 0000000..5364dba --- /dev/null +++ b/src/patches/glibc/glibc-rh1256891.patch @@ -0,0 +1,26 @@ +commit 5c44738353ecaa1c81efca063ee8b55e092d7a43 +Author: Alexandre Oliva aoliva@redhat.com +Date: Wed Sep 5 15:43:04 2012 -0300 + + Don't change no_dyn_threshold on mallopt failure + + * malloc/malloc.c (__libc_mallopt) <M_MMAP_THRESHOLD>: Do not + change internal state upon failure. + +diff --git a/malloc/malloc.c b/malloc/malloc.c +index bd562df..c69e281 100644 +--- a/malloc/malloc.c ++++ b/malloc/malloc.c +@@ -4769,8 +4769,10 @@ int __libc_mallopt(int param_number, int value) + res = 0; + else + #endif +- mp_.mmap_threshold = value; +- mp_.no_dyn_threshold = 1; ++ { ++ mp_.mmap_threshold = value; ++ mp_.no_dyn_threshold = 1; ++ } + break; + + case M_MMAP_MAX: diff --git a/src/patches/glibc/glibc-rh1291270.patch b/src/patches/glibc/glibc-rh1291270.patch new file mode 100644 index 0000000..8d12d95 --- /dev/null +++ b/src/patches/glibc/glibc-rh1291270.patch @@ -0,0 +1,41 @@ +Description: Allow loading more libraries with static TLS. +Author: Carlos O'Donell codonell@redhat.com +Origin: PATCH +Bug-RHEL: #1291270 (rhel-6.7.z), #1198802 (rhel-6.8), #1202952 (rhel-7.2) +Bug-Fedora: #1124987 (F21) +Bug-Upstream: #17090, #17620, #17621, #17628 (2.22) +Upstream status: not-needed +# +# The correct fix for this is already upstream and involves +# changing the heuristics for DTV slot increases. In RHEL6 +# we take the conservative approach and provide a larger +# slot surplus. This matches what was done in Fedora 21 before +# we had the upstream fix: f8aeae347377f3dfa8cbadde057adf1827fb1d44. +# In RHEL7 we have the upstream fix. This is fixed upstream as of +# glibc 2.22. +# +Index: glibc-2.12-2-gc4ccff1/sysdeps/generic/ldsodefs.h +=================================================================== +--- glibc-2.12-2-gc4ccff1.orig/sysdeps/generic/ldsodefs.h ++++ glibc-2.12-2-gc4ccff1/sysdeps/generic/ldsodefs.h +@@ -496,8 +496,18 @@ struct rtld_global + have to iterate beyond the first element in the slotinfo list. */ + #define TLS_SLOTINFO_SURPLUS (62) + +-/* Number of additional slots in the dtv allocated. */ +-#define DTV_SURPLUS (14) ++/* Number of additional allocated dtv slots. This was initially ++ 14, but problems with python, MESA, and X11's uses of static TLS meant ++ that most distributions were very close to this limit when they loaded ++ dynamically interpreted languages that used graphics. The simplest ++ solution was to roughly double the number of slots. The actual static ++ image space usage was relatively small, for example in MESA you ++ had only two dispatch pointers for a total of 16 bytes. If we hit up ++ against this limit again we should start a campaign with the ++ distributions to coordinate the usage of static TLS. Any user of this ++ resource is effectively coordinating a global resource since this ++ surplus is allocated for each thread at startup. */ ++#define DTV_SURPLUS (32) + + /* Initial dtv of the main thread, not allocated with normal malloc. */ + EXTERN void *_dl_initial_dtv; diff --git a/src/patches/glibc/glibc-rh1296031-0.patch b/src/patches/glibc/glibc-rh1296031-0.patch new file mode 100644 index 0000000..d44e491 --- /dev/null +++ b/src/patches/glibc/glibc-rh1296031-0.patch @@ -0,0 +1,465 @@ +Sourceware bug 16574 + +commit d668061994a7486a3ba9c7d5e7882d85a2883707 +Author: Andreas Schwab schwab@suse.de +Date: Thu Feb 13 11:01:57 2014 +0100 + + Fix memory leak in _nss_dns_gethostbyname4_r with big DNS answer + +commit ab7ac0f2cf8731fe4c3f3aea6088a7c0127b5725 +Author: OndÅej BÃlka neleai@seznam.cz +Date: Sun Feb 16 12:59:23 2014 +0100 + + Deduplicate resolv/nss_dns/dns-host.c + + In resolv/nss_dns/dns-host.c one of code path duplicated code after + that. We merge these paths. + +commit ab09bf616ad527b249aca5f2a4956fd526f0712f +Author: Andreas Schwab schwab@suse.de +Date: Tue Feb 18 10:57:25 2014 +0100 + + Properly fix memory leak in _nss_dns_gethostbyname4_r with big DNS answer + + Instead of trying to guess whether the second buffer needs to be freed + set a flag at the place it is allocated + +Index: glibc-2.12-2-gc4ccff1/include/resolv.h +=================================================================== +--- glibc-2.12-2-gc4ccff1.orig/include/resolv.h ++++ glibc-2.12-2-gc4ccff1/include/resolv.h +@@ -58,11 +58,11 @@ libc_hidden_proto (__res_randomid) + libc_hidden_proto (__res_state) + + int __libc_res_nquery (res_state, const char *, int, int, u_char *, int, +- u_char **, u_char **, int *, int *); ++ u_char **, u_char **, int *, int *, int *); + int __libc_res_nsearch (res_state, const char *, int, int, u_char *, int, +- u_char **, u_char **, int *, int *); ++ u_char **, u_char **, int *, int *, int *); + int __libc_res_nsend (res_state, const u_char *, int, const u_char *, int, +- u_char *, int, u_char **, u_char **, int *, int *) ++ u_char *, int, u_char **, u_char **, int *, int *, int *) + attribute_hidden; + + libresolv_hidden_proto (_sethtent) +Index: glibc-2.12-2-gc4ccff1/resolv/gethnamaddr.c +=================================================================== +--- glibc-2.12-2-gc4ccff1.orig/resolv/gethnamaddr.c ++++ glibc-2.12-2-gc4ccff1/resolv/gethnamaddr.c +@@ -634,7 +634,7 @@ gethostbyname2(name, af) + buf.buf = origbuf = (querybuf *) alloca (1024); + + if ((n = __libc_res_nsearch(&_res, name, C_IN, type, buf.buf->buf, 1024, +- &buf.ptr, NULL, NULL, NULL)) < 0) { ++ &buf.ptr, NULL, NULL, NULL, NULL)) < 0) { + if (buf.buf != origbuf) + free (buf.buf); + Dprintf("res_nsearch failed (%d)\n", n); +@@ -729,12 +729,12 @@ gethostbyaddr(addr, len, af) + buf.buf = orig_buf = (querybuf *) alloca (1024); + + n = __libc_res_nquery(&_res, qbuf, C_IN, T_PTR, buf.buf->buf, 1024, +- &buf.ptr, NULL, NULL, NULL); ++ &buf.ptr, NULL, NULL, NULL, NULL); + if (n < 0 && af == AF_INET6 && (_res.options & RES_NOIP6DOTINT) == 0) { + strcpy(qp, "ip6.int"); + n = __libc_res_nquery(&_res, qbuf, C_IN, T_PTR, buf.buf->buf, + buf.buf != orig_buf ? MAXPACKET : 1024, +- &buf.ptr, NULL, NULL, NULL); ++ &buf.ptr, NULL, NULL, NULL, NULL); + } + if (n < 0) { + if (buf.buf != orig_buf) +Index: glibc-2.12-2-gc4ccff1/resolv/nss_dns/dns-canon.c +=================================================================== +--- glibc-2.12-2-gc4ccff1.orig/resolv/nss_dns/dns-canon.c ++++ glibc-2.12-2-gc4ccff1/resolv/nss_dns/dns-canon.c +@@ -62,7 +62,7 @@ _nss_dns_getcanonname_r (const char *nam + { + int r = __libc_res_nquery (&_res, name, ns_c_in, qtypes[i], + buf, sizeof (buf), &ansp.ptr, NULL, NULL, +- NULL); ++ NULL, NULL); + if (r > 0) + { + /* We need to decode the response. Just one question record. +Index: glibc-2.12-2-gc4ccff1/resolv/nss_dns/dns-host.c +=================================================================== +--- glibc-2.12-2-gc4ccff1.orig/resolv/nss_dns/dns-host.c ++++ glibc-2.12-2-gc4ccff1/resolv/nss_dns/dns-host.c +@@ -191,7 +191,7 @@ _nss_dns_gethostbyname3_r (const char *n + host_buffer.buf = orig_host_buffer = (querybuf *) alloca (1024); + + n = __libc_res_nsearch (&_res, name, C_IN, type, host_buffer.buf->buf, +- 1024, &host_buffer.ptr, NULL, NULL, NULL); ++ 1024, &host_buffer.ptr, NULL, NULL, NULL, NULL); + if (n < 0) + { + switch (errno) +@@ -221,7 +221,7 @@ _nss_dns_gethostbyname3_r (const char *n + n = __libc_res_nsearch (&_res, name, C_IN, T_A, host_buffer.buf->buf, + host_buffer.buf != orig_host_buffer + ? MAXPACKET : 1024, &host_buffer.ptr, +- NULL, NULL, NULL); ++ NULL, NULL, NULL, NULL); + + if (n < 0) + { +@@ -304,13 +304,20 @@ _nss_dns_gethostbyname4_r (const char *n + u_char *ans2p = NULL; + int nans2p = 0; + int resplen2 = 0; ++ int ans2p_malloced = 0; + + int olderr = errno; + enum nss_status status; + int n = __libc_res_nsearch (&_res, name, C_IN, T_UNSPEC, + host_buffer.buf->buf, 2048, &host_buffer.ptr, +- &ans2p, &nans2p, &resplen2); +- if (n < 0) ++ &ans2p, &nans2p, &resplen2, &ans2p_malloced); ++ if (n >= 0) ++ { ++ status = gaih_getanswer (host_buffer.buf, n, (const querybuf *) ans2p, ++ resplen2, name, pat, buffer, buflen, ++ errnop, herrnop, ttlp); ++ } ++ else + { + if (errno == ESRCH) + { +@@ -325,16 +332,11 @@ _nss_dns_gethostbyname4_r (const char *n + *errnop = EAGAIN; + else + __set_errno (olderr); +- +- if (host_buffer.buf != orig_host_buffer) +- free (host_buffer.buf); +- +- return status; + } + +- status = gaih_getanswer(host_buffer.buf, n, (const querybuf *) ans2p, +- resplen2, name, pat, buffer, buflen, +- errnop, herrnop, ttlp); ++ /* Check whether ans2p was separately allocated. */ ++ if (ans2p_malloced) ++ free (ans2p); + + if (host_buffer.buf != orig_host_buffer) + free (host_buffer.buf); +@@ -444,7 +446,7 @@ _nss_dns_gethostbyaddr2_r (const void *a + strcpy (qp, "].ip6.arpa"); + n = __libc_res_nquery (&_res, qbuf, C_IN, T_PTR, + host_buffer.buf->buf, 1024, &host_buffer.ptr, +- NULL, NULL, NULL); ++ NULL, NULL, NULL, NULL); + if (n >= 0) + goto got_it_already; + } +@@ -465,14 +467,14 @@ _nss_dns_gethostbyaddr2_r (const void *a + } + + n = __libc_res_nquery (&_res, qbuf, C_IN, T_PTR, host_buffer.buf->buf, +- 1024, &host_buffer.ptr, NULL, NULL, NULL); ++ 1024, &host_buffer.ptr, NULL, NULL, NULL, NULL); + if (n < 0 && af == AF_INET6 && (_res.options & RES_NOIP6DOTINT) == 0) + { + strcpy (qp, "ip6.int"); + n = __libc_res_nquery (&_res, qbuf, C_IN, T_PTR, host_buffer.buf->buf, + host_buffer.buf != orig_host_buffer + ? MAXPACKET : 1024, &host_buffer.ptr, +- NULL, NULL, NULL); ++ NULL, NULL, NULL, NULL); + } + if (n < 0) + { +Index: glibc-2.12-2-gc4ccff1/resolv/nss_dns/dns-network.c +=================================================================== +--- glibc-2.12-2-gc4ccff1.orig/resolv/nss_dns/dns-network.c ++++ glibc-2.12-2-gc4ccff1/resolv/nss_dns/dns-network.c +@@ -130,7 +130,7 @@ _nss_dns_getnetbyname_r (const char *nam + net_buffer.buf = orig_net_buffer = (querybuf *) alloca (1024); + + anslen = __libc_res_nsearch (&_res, qbuf, C_IN, T_PTR, net_buffer.buf->buf, +- 1024, &net_buffer.ptr, NULL, NULL, NULL); ++ 1024, &net_buffer.ptr, NULL, NULL, NULL, NULL); + if (anslen < 0) + { + /* Nothing found. */ +@@ -206,7 +206,7 @@ _nss_dns_getnetbyaddr_r (uint32_t net, i + net_buffer.buf = orig_net_buffer = (querybuf *) alloca (1024); + + anslen = __libc_res_nquery (&_res, qbuf, C_IN, T_PTR, net_buffer.buf->buf, +- 1024, &net_buffer.ptr, NULL, NULL, NULL); ++ 1024, &net_buffer.ptr, NULL, NULL, NULL, NULL); + if (anslen < 0) + { + /* Nothing found. */ +Index: glibc-2.12-2-gc4ccff1/resolv/res_query.c +=================================================================== +--- glibc-2.12-2-gc4ccff1.orig/resolv/res_query.c ++++ glibc-2.12-2-gc4ccff1/resolv/res_query.c +@@ -98,7 +98,7 @@ static int + __libc_res_nquerydomain(res_state statp, const char *name, const char *domain, + int class, int type, u_char *answer, int anslen, + u_char **answerp, u_char **answerp2, int *nanswerp2, +- int *resplen2); ++ int *resplen2, int *answerp2_malloced); + + /* + * Formulate a normal query, send, and await answer. +@@ -119,7 +119,8 @@ __libc_res_nquery(res_state statp, + u_char **answerp, /* if buffer needs to be enlarged */ + u_char **answerp2, + int *nanswerp2, +- int *resplen2) ++ int *resplen2, ++ int *answerp2_malloced) + { + HEADER *hp = (HEADER *) answer; + HEADER *hp2; +@@ -224,7 +225,8 @@ __libc_res_nquery(res_state statp, + } + assert (answerp == NULL || (void *) *answerp == (void *) answer); + n = __libc_res_nsend(statp, query1, nquery1, query2, nquery2, answer, +- anslen, answerp, answerp2, nanswerp2, resplen2); ++ anslen, answerp, answerp2, nanswerp2, resplen2, ++ answerp2_malloced); + if (use_malloc) + free (buf); + if (n < 0) { +@@ -316,7 +318,7 @@ res_nquery(res_state statp, + int anslen) /* size of answer buffer */ + { + return __libc_res_nquery(statp, name, class, type, answer, anslen, +- NULL, NULL, NULL, NULL); ++ NULL, NULL, NULL, NULL, NULL); + } + libresolv_hidden_def (res_nquery) + +@@ -335,7 +337,8 @@ __libc_res_nsearch(res_state statp, + u_char **answerp, + u_char **answerp2, + int *nanswerp2, +- int *resplen2) ++ int *resplen2, ++ int *answerp2_malloced) + { + const char *cp, * const *domain; + HEADER *hp = (HEADER *) answer; +@@ -359,7 +362,7 @@ __libc_res_nsearch(res_state statp, + if (!dots && (cp = res_hostalias(statp, name, tmp, sizeof tmp))!= NULL) + return (__libc_res_nquery(statp, cp, class, type, answer, + anslen, answerp, answerp2, +- nanswerp2, resplen2)); ++ nanswerp2, resplen2, answerp2_malloced)); + + #ifdef DEBUG + if (statp->options & RES_DEBUG) +@@ -376,7 +379,8 @@ __libc_res_nsearch(res_state statp, + if (dots >= statp->ndots || trailing_dot) { + ret = __libc_res_nquerydomain(statp, name, NULL, class, type, + answer, anslen, answerp, +- answerp2, nanswerp2, resplen2); ++ answerp2, nanswerp2, resplen2, ++ answerp2_malloced); + if (ret > 0 || trailing_dot + /* If the second response is valid then we use that. */ + || (ret == 0 && resplen2 != NULL && *resplen2 > 0)) +@@ -387,12 +391,12 @@ __libc_res_nsearch(res_state statp, + answer = *answerp; + anslen = MAXPACKET; + } +- if (answerp2 +- && (*answerp2 < answer || *answerp2 >= answer + anslen)) ++ if (answerp2 && *answerp2_malloced) + { + free (*answerp2); + *nanswerp2 = 0; + *answerp2 = NULL; ++ *answerp2_malloced = 0; + } + } + +@@ -418,7 +422,7 @@ __libc_res_nsearch(res_state statp, + class, type, + answer, anslen, answerp, + answerp2, nanswerp2, +- resplen2); ++ resplen2, answerp2_malloced); + if (ret > 0 || (ret == 0 && resplen2 != NULL + && *resplen2 > 0)) + return (ret); +@@ -427,13 +431,12 @@ __libc_res_nsearch(res_state statp, + answer = *answerp; + anslen = MAXPACKET; + } +- if (answerp2 +- && (*answerp2 < answer +- || *answerp2 >= answer + anslen)) ++ if (answerp2 && *answerp2_malloced) + { + free (*answerp2); + *nanswerp2 = 0; + *answerp2 = NULL; ++ *answerp2_malloced = 0; + } + + /* +@@ -489,7 +492,8 @@ __libc_res_nsearch(res_state statp, + if (dots && !(tried_as_is || root_on_list)) { + ret = __libc_res_nquerydomain(statp, name, NULL, class, type, + answer, anslen, answerp, +- answerp2, nanswerp2, resplen2); ++ answerp2, nanswerp2, resplen2, ++ answerp2_malloced); + if (ret > 0 || (ret == 0 && resplen2 != NULL + && *resplen2 > 0)) + return (ret); +@@ -502,11 +506,12 @@ __libc_res_nsearch(res_state statp, + * else send back meaningless H_ERRNO, that being the one from + * the last DNSRCH we did. + */ +- if (answerp2 && (*answerp2 < answer || *answerp2 >= answer + anslen)) ++ if (answerp2 && *answerp2_malloced) + { + free (*answerp2); +- *nanswerp2 = NULL; ++ *nanswerp2 = 0; + *answerp2 = NULL; ++ *answerp2_malloced = 0; + } + if (saved_herrno != -1) + RES_SET_H_ERRNO(statp, saved_herrno); +@@ -526,7 +531,7 @@ res_nsearch(res_state statp, + int anslen) /* size of answer */ + { + return __libc_res_nsearch(statp, name, class, type, answer, +- anslen, NULL, NULL, NULL, NULL); ++ anslen, NULL, NULL, NULL, NULL, NULL); + } + libresolv_hidden_def (res_nsearch) + +@@ -544,7 +549,8 @@ __libc_res_nquerydomain(res_state statp, + u_char **answerp, + u_char **answerp2, + int *nanswerp2, +- int *resplen2) ++ int *resplen2, ++ int *answerp2_malloced) + { + char nbuf[MAXDNAME]; + const char *longname = nbuf; +@@ -582,7 +588,7 @@ __libc_res_nquerydomain(res_state statp, + } + return (__libc_res_nquery(statp, longname, class, type, answer, + anslen, answerp, answerp2, nanswerp2, +- resplen2)); ++ resplen2, answerp2_malloced)); + } + + int +@@ -594,7 +600,8 @@ res_nquerydomain(res_state statp, + int anslen) /* size of answer */ + { + return __libc_res_nquerydomain(statp, name, domain, class, type, +- answer, anslen, NULL, NULL, NULL, NULL); ++ answer, anslen, NULL, NULL, NULL, NULL, ++ NULL); + } + libresolv_hidden_def (res_nquerydomain) + +Index: glibc-2.12-2-gc4ccff1/resolv/res_send.c +=================================================================== +--- glibc-2.12-2-gc4ccff1.orig/resolv/res_send.c ++++ glibc-2.12-2-gc4ccff1/resolv/res_send.c +@@ -203,12 +203,12 @@ evNowTime(struct timespec *res) { + static int send_vc(res_state, const u_char *, int, + const u_char *, int, + u_char **, int *, int *, int, u_char **, +- u_char **, int *, int *); ++ u_char **, int *, int *, int *); + static int send_dg(res_state, const u_char *, int, + const u_char *, int, + u_char **, int *, int *, int, + int *, int *, u_char **, +- u_char **, int *, int *); ++ u_char **, int *, int *, int *); + #ifdef DEBUG + static void Aerror(const res_state, FILE *, const char *, int, + const struct sockaddr *); +@@ -360,7 +360,7 @@ int + __libc_res_nsend(res_state statp, const u_char *buf, int buflen, + const u_char *buf2, int buflen2, + u_char *ans, int anssiz, u_char **ansp, u_char **ansp2, +- int *nansp2, int *resplen2) ++ int *nansp2, int *resplen2, int *ansp2_malloced) + { + int gotsomewhere, terrno, try, v_circuit, resplen, ns, n; + +@@ -565,7 +565,8 @@ __libc_res_nsend(res_state statp, const + try = statp->retry; + n = send_vc(statp, buf, buflen, buf2, buflen2, + &ans, &anssiz, &terrno, +- ns, ansp, ansp2, nansp2, resplen2); ++ ns, ansp, ansp2, nansp2, resplen2, ++ ansp2_malloced); + if (n < 0) + return (-1); + if (n == 0 && (buf2 == NULL || *resplen2 == 0)) +@@ -575,7 +576,7 @@ __libc_res_nsend(res_state statp, const + n = send_dg(statp, buf, buflen, buf2, buflen2, + &ans, &anssiz, &terrno, + ns, &v_circuit, &gotsomewhere, ansp, +- ansp2, nansp2, resplen2); ++ ansp2, nansp2, resplen2, ansp2_malloced); + if (n < 0) + return (-1); + if (n == 0 && (buf2 == NULL || *resplen2 == 0)) +@@ -665,7 +666,7 @@ res_nsend(res_state statp, + const u_char *buf, int buflen, u_char *ans, int anssiz) + { + return __libc_res_nsend(statp, buf, buflen, NULL, 0, ans, anssiz, +- NULL, NULL, NULL, NULL); ++ NULL, NULL, NULL, NULL, NULL); + } + libresolv_hidden_def (res_nsend) + +@@ -747,7 +748,7 @@ send_vc(res_state statp, + const u_char *buf, int buflen, const u_char *buf2, int buflen2, + u_char **ansp, int *anssizp, + int *terrno, int ns, u_char **anscp, u_char **ansp2, int *anssizp2, +- int *resplen2) ++ int *resplen2, int *ansp2_malloced) + { + const HEADER *hp = (HEADER *) buf; + const HEADER *hp2 = (HEADER *) buf2; +@@ -896,6 +897,8 @@ send_vc(res_state statp, + } + *thisanssizp = MAXPACKET; + *thisansp = newp; ++ if (thisansp == ansp2) ++ *ansp2_malloced = 1; + anhp = (HEADER *) newp; + /* A uint16_t can't be larger than MAXPACKET + thus it's safe to allocate MAXPACKET but +@@ -1128,7 +1131,7 @@ send_dg(res_state statp, + const u_char *buf, int buflen, const u_char *buf2, int buflen2, + u_char **ansp, int *anssizp, + int *terrno, int ns, int *v_circuit, int *gotsomewhere, u_char **anscp, +- u_char **ansp2, int *anssizp2, int *resplen2) ++ u_char **ansp2, int *anssizp2, int *resplen2, int *ansp2_malloced) + { + const HEADER *hp = (HEADER *) buf; + const HEADER *hp2 = (HEADER *) buf2; +@@ -1289,6 +1292,8 @@ send_dg(res_state statp, + if (newp != NULL) { + *thisanssizp = MAXPACKET; + *thisansp = newp; ++ if (thisansp == ansp2) ++ *ansp2_malloced = 1; + } + } + /* We could end up with truncation if anscp was NULL diff --git a/src/patches/glibc/glibc-rh1296031.patch b/src/patches/glibc/glibc-rh1296031.patch new file mode 100644 index 0000000..c430abb --- /dev/null +++ b/src/patches/glibc/glibc-rh1296031.patch @@ -0,0 +1,544 @@ +Index: glibc-2.12-2-gc4ccff1/resolv/nss_dns/dns-host.c +=================================================================== +--- glibc-2.12-2-gc4ccff1.orig/resolv/nss_dns/dns-host.c ++++ glibc-2.12-2-gc4ccff1/resolv/nss_dns/dns-host.c +@@ -1043,7 +1043,10 @@ gaih_getanswer_slice (const querybuf *an + int h_namelen = 0; + + if (ancount == 0) +- return NSS_STATUS_NOTFOUND; ++ { ++ *h_errnop = HOST_NOT_FOUND; ++ return NSS_STATUS_NOTFOUND; ++ } + + while (ancount-- > 0 && cp < end_of_message && had_error == 0) + { +@@ -1217,7 +1220,14 @@ gaih_getanswer_slice (const querybuf *an + /* Special case here: if the resolver sent a result but it only + contains a CNAME while we are looking for a T_A or T_AAAA record, + we fail with NOTFOUND instead of TRYAGAIN. */ +- return canon == NULL ? NSS_STATUS_TRYAGAIN : NSS_STATUS_NOTFOUND; ++ if (canon != NULL) ++ { ++ *h_errnop = HOST_NOT_FOUND; ++ return NSS_STATUS_NOTFOUND; ++ } ++ ++ *h_errnop = NETDB_INTERNAL; ++ return NSS_STATUS_TRYAGAIN; + } + + +@@ -1231,11 +1241,101 @@ gaih_getanswer (const querybuf *answer1, + + enum nss_status status = NSS_STATUS_NOTFOUND; + ++ /* Combining the NSS status of two distinct queries requires some ++ compromise and attention to symmetry (A or AAAA queries can be ++ returned in any order). What follows is a breakdown of how this ++ code is expected to work and why. We discuss only SUCCESS, ++ TRYAGAIN, NOTFOUND and UNAVAIL, since they are the only returns ++ that apply (though RETURN and MERGE exist). We make a distinction ++ between TRYAGAIN (recoverable) and TRYAGAIN' (not-recoverable). ++ A recoverable TRYAGAIN is almost always due to buffer size issues ++ and returns ERANGE in errno and the caller is expected to retry ++ with a larger buffer. ++ ++ Lastly, you may be tempted to make significant changes to the ++ conditions in this code to bring about symmetry between responses. ++ Please don't change anything without due consideration for ++ expected application behaviour. Some of the synthesized responses ++ aren't very well thought out and sometimes appear to imply that ++ IPv4 responses are always answer 1, and IPv6 responses are always ++ answer 2, but that's not true (see the implemetnation of send_dg ++ and send_vc to see response can arrive in any order, particlarly ++ for UDP). However, we expect it holds roughly enough of the time ++ that this code works, but certainly needs to be fixed to make this ++ a more robust implementation. ++ ++ ---------------------------------------------- ++ | Answer 1 Status / | Synthesized | Reason | ++ | Answer 2 Status | Status | | ++ |--------------------------------------------| ++ | SUCCESS/SUCCESS | SUCCESS | [1] | ++ | SUCCESS/TRYAGAIN | TRYAGAIN | [5] | ++ | SUCCESS/TRYAGAIN' | SUCCESS | [1] | ++ | SUCCESS/NOTFOUND | SUCCESS | [1] | ++ | SUCCESS/UNAVAIL | SUCCESS | [1] | ++ | TRYAGAIN/SUCCESS | TRYAGAIN | [2] | ++ | TRYAGAIN/TRYAGAIN | TRYAGAIN | [2] | ++ | TRYAGAIN/TRYAGAIN' | TRYAGAIN | [2] | ++ | TRYAGAIN/NOTFOUND | TRYAGAIN | [2] | ++ | TRYAGAIN/UNAVAIL | TRYAGAIN | [2] | ++ | TRYAGAIN'/SUCCESS | SUCCESS | [3] | ++ | TRYAGAIN'/TRYAGAIN | TRYAGAIN | [3] | ++ | TRYAGAIN'/TRYAGAIN' | TRYAGAIN' | [3] | ++ | TRYAGAIN'/NOTFOUND | TRYAGAIN' | [3] | ++ | TRYAGAIN'/UNAVAIL | UNAVAIL | [3] | ++ | NOTFOUND/SUCCESS | SUCCESS | [3] | ++ | NOTFOUND/TRYAGAIN | TRYAGAIN | [3] | ++ | NOTFOUND/TRYAGAIN' | TRYAGAIN' | [3] | ++ | NOTFOUND/NOTFOUND | NOTFOUND | [3] | ++ | NOTFOUND/UNAVAIL | UNAVAIL | [3] | ++ | UNAVAIL/SUCCESS | UNAVAIL | [4] | ++ | UNAVAIL/TRYAGAIN | UNAVAIL | [4] | ++ | UNAVAIL/TRYAGAIN' | UNAVAIL | [4] | ++ | UNAVAIL/NOTFOUND | UNAVAIL | [4] | ++ | UNAVAIL/UNAVAIL | UNAVAIL | [4] | ++ ---------------------------------------------- ++ ++ [1] If the first response is a success we return success. ++ This ignores the state of the second answer and in fact ++ incorrectly sets errno and h_errno to that of the second ++ answer. However because the response is a success we ignore ++ *errnop and *h_errnop (though that means you touched errno on ++ success). We are being conservative here and returning the ++ likely IPv4 response in the first answer as a success. ++ ++ [2] If the first response is a recoverable TRYAGAIN we return ++ that instead of looking at the second response. The ++ expectation here is that we have failed to get an IPv4 response ++ and should retry both queries. ++ ++ [3] If the first response was not a SUCCESS and the second ++ response is not NOTFOUND (had a SUCCESS, need to TRYAGAIN, ++ or failed entirely e.g. TRYAGAIN' and UNAVAIL) then use the ++ result from the second response, otherwise the first responses ++ status is used. Again we have some odd side-effects when the ++ second response is NOTFOUND because we overwrite *errnop and ++ *h_errnop that means that a first answer of NOTFOUND might see ++ its *errnop and *h_errnop values altered. Whether it matters ++ in practice that a first response NOTFOUND has the wrong ++ *errnop and *h_errnop is undecided. ++ ++ [4] If the first response is UNAVAIL we return that instead of ++ looking at the second response. The expectation here is that ++ it will have failed similarly e.g. configuration failure. ++ ++ [5] Testing this code is complicated by the fact that truncated ++ second response buffers might be returned as SUCCESS if the ++ first answer is a SUCCESS. To fix this we add symmetry to ++ TRYAGAIN with the second response. If the second response ++ is a recoverable error we now return TRYAGIN even if the first ++ response was SUCCESS. */ ++ + if (anslen1 > 0) + status = gaih_getanswer_slice(answer1, anslen1, qname, + &pat, &buffer, &buflen, + errnop, h_errnop, ttlp, + &first); ++ + if ((status == NSS_STATUS_SUCCESS || status == NSS_STATUS_NOTFOUND + || (status == NSS_STATUS_TRYAGAIN + && (*errnop != ERANGE || *h_errnop == NO_RECOVERY))) +@@ -1245,8 +1345,15 @@ gaih_getanswer (const querybuf *answer1, + &pat, &buffer, &buflen, + errnop, h_errnop, ttlp, + &first); ++ /* Use the second response status in some cases. */ + if (status != NSS_STATUS_SUCCESS && status2 != NSS_STATUS_NOTFOUND) + status = status2; ++ /* Do not return a truncated second response (unless it was ++ unavoidable e.g. unrecoverable TRYAGAIN). */ ++ if (status == NSS_STATUS_SUCCESS ++ && (status2 == NSS_STATUS_TRYAGAIN ++ && *errnop == ERANGE && *h_errnop != NO_RECOVERY)) ++ status = NSS_STATUS_TRYAGAIN; + } + + return status; +Index: glibc-2.12-2-gc4ccff1/resolv/res_send.c +=================================================================== +--- glibc-2.12-2-gc4ccff1.orig/resolv/res_send.c ++++ glibc-2.12-2-gc4ccff1/resolv/res_send.c +@@ -1,3 +1,20 @@ ++/* Copyright (C) 2016 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/. */ ++ + /* + * Copyright (c) 1985, 1989, 1993 + * The Regents of the University of California. All rights reserved. +@@ -360,6 +377,8 @@ __libc_res_nsend(res_state statp, const + #ifdef USE_HOOKS + if (__builtin_expect (statp->qhook || statp->rhook, 0)) { + if (anssiz < MAXPACKET && ansp) { ++ /* Always allocate MAXPACKET, callers expect ++ this specific size. */ + u_char *buf = malloc (MAXPACKET); + if (buf == NULL) + return (-1); +@@ -652,6 +671,77 @@ libresolv_hidden_def (res_nsend) + + /* Private */ + ++/* The send_vc function is responsible for sending a DNS query over TCP ++ to the nameserver numbered NS from the res_state STATP i.e. ++ EXT(statp).nssocks[ns]. The function supports sending both IPv4 and ++ IPv6 queries at the same serially on the same socket. ++ ++ Please note that for TCP there is no way to disable sending both ++ queries, unlike UDP, which honours RES_SNGLKUP and RES_SNGLKUPREOP ++ and sends the queries serially and waits for the result after each ++ sent query. This implemetnation should be corrected to honour these ++ options. ++ ++ Please also note that for TCP we send both queries over the same ++ socket one after another. This technically violates best practice ++ since the server is allowed to read the first query, respond, and ++ then close the socket (to service another client). If the server ++ does this, then the remaining second query in the socket data buffer ++ will cause the server to send the client an RST which will arrive ++ asynchronously and the client's OS will likely tear down the socket ++ receive buffer resulting in a potentially short read and lost ++ response data. This will force the client to retry the query again, ++ and this process may repeat until all servers and connection resets ++ are exhausted and then the query will fail. It's not known if this ++ happens with any frequency in real DNS server implementations. This ++ implementation should be corrected to use two sockets by default for ++ parallel queries. ++ ++ The query stored in BUF of BUFLEN length is sent first followed by ++ the query stored in BUF2 of BUFLEN2 length. Queries are sent ++ serially on the same socket. ++ ++ Answers to the query are stored firstly in *ANSP up to a max of ++ *ANSSIZP bytes. If more than *ANSSIZP bytes are needed and ANSCP ++ is non-NULL (to indicate that modifying the answer buffer is allowed) ++ then malloc is used to allocate a new response buffer and ANSCP and ++ ANSP will both point to the new buffer. If more than *ANSSIZP bytes ++ are needed but ANSCP is NULL, then as much of the response as ++ possible is read into the buffer, but the results will be truncated. ++ When truncation happens because of a small answer buffer the DNS ++ packets header feild TC will bet set to 1, indicating a truncated ++ message and the rest of the socket data will be read and discarded. ++ ++ Answers to the query are stored secondly in *ANSP2 up to a max of ++ *ANSSIZP2 bytes, with the actual response length stored in ++ *RESPLEN2. If more than *ANSSIZP bytes are needed and ANSP2 ++ is non-NULL (required for a second query) then malloc is used to ++ allocate a new response buffer, *ANSSIZP2 is set to the new buffer ++ size and *ANSP2_MALLOCED is set to 1. ++ ++ The ANSP2_MALLOCED argument will eventually be removed as the ++ change in buffer pointer can be used to detect the buffer has ++ changed and that the caller should use free on the new buffer. ++ ++ Note that the answers may arrive in any order from the server and ++ therefore the first and second answer buffers may not correspond to ++ the first and second queries. ++ ++ It is not supported to call this function with a non-NULL ANSP2 ++ but a NULL ANSCP. Put another way, you can call send_vc with a ++ single unmodifiable buffer or two modifiable buffers, but no other ++ combination is supported. ++ ++ It is the caller's responsibility to free the malloc allocated ++ buffers by detecting that the pointers have changed from their ++ original values i.e. *ANSCP or *ANSP2 has changed. ++ ++ If errors are encountered then *TERRNO is set to an appropriate ++ errno value and a zero result is returned for a recoverable error, ++ and a less-than zero result is returned for a non-recoverable error. ++ ++ If no errors are encountered then *TERRNO is left unmodified and ++ a the length of the first response in bytes is returned. */ + static int + send_vc(res_state statp, + const u_char *buf, int buflen, const u_char *buf2, int buflen2, +@@ -661,11 +751,7 @@ send_vc(res_state statp, + { + const HEADER *hp = (HEADER *) buf; + const HEADER *hp2 = (HEADER *) buf2; +- u_char *ans = *ansp; +- int orig_anssizp = *anssizp; +- // XXX REMOVE +- // int anssiz = *anssizp; +- HEADER *anhp = (HEADER *) ans; ++ HEADER *anhp = (HEADER *) *ansp; + struct sockaddr_in6 *nsap = EXT(statp).nsaddrs[ns]; + int truncating, connreset, resplen, n; + struct iovec iov[4]; +@@ -741,6 +827,8 @@ send_vc(res_state statp, + * Receive length & response + */ + int recvresp1 = 0; ++ /* Skip the second response if there is no second query. ++ To do that we mark the second response as received. */ + int recvresp2 = buf2 == NULL; + uint16_t rlen16; + read_len: +@@ -777,33 +865,14 @@ send_vc(res_state statp, + u_char **thisansp; + int *thisresplenp; + if ((recvresp1 | recvresp2) == 0 || buf2 == NULL) { ++ /* We have not received any responses ++ yet or we only have one response to ++ receive. */ + thisanssizp = anssizp; + thisansp = anscp ?: ansp; + assert (anscp != NULL || ansp2 == NULL); + thisresplenp = &resplen; + } else { +- if (*anssizp != MAXPACKET) { +- /* No buffer allocated for the first +- reply. We can try to use the rest +- of the user-provided buffer. */ +-#ifdef _STRING_ARCH_unaligned +- *anssizp2 = orig_anssizp - resplen; +- *ansp2 = *ansp + resplen; +-#else +- int aligned_resplen +- = ((resplen + __alignof__ (HEADER) - 1) +- & ~(__alignof__ (HEADER) - 1)); +- *anssizp2 = orig_anssizp - aligned_resplen; +- *ansp2 = *ansp + aligned_resplen; +-#endif +- } else { +- /* The first reply did not fit into the +- user-provided buffer. Maybe the second +- answer will. */ +- *anssizp2 = orig_anssizp; +- *ansp2 = *ansp; +- } +- + thisanssizp = anssizp2; + thisansp = ansp2; + thisresplenp = resplen2; +@@ -811,10 +880,14 @@ send_vc(res_state statp, + anhp = (HEADER *) *thisansp; + + *thisresplenp = rlen; +- if (rlen > *thisanssizp) { +- /* Yes, we test ANSCP here. If we have two buffers +- both will be allocatable. */ +- if (__builtin_expect (anscp != NULL, 1)) { ++ /* Is the answer buffer too small? */ ++ if (*thisanssizp < rlen) { ++ /* If the current buffer is non-NULL and it's not ++ pointing at the static user-supplied buffer then ++ we can reallocate it. */ ++ if (thisansp != NULL && thisansp != ansp) { ++ /* Always allocate MAXPACKET, callers expect ++ this specific size. */ + u_char *newp = malloc (MAXPACKET); + if (newp == NULL) { + *terrno = ENOMEM; +@@ -824,6 +897,9 @@ send_vc(res_state statp, + *thisanssizp = MAXPACKET; + *thisansp = newp; + anhp = (HEADER *) newp; ++ /* A uint16_t can't be larger than MAXPACKET ++ thus it's safe to allocate MAXPACKET but ++ read RLEN bytes instead. */ + len = rlen; + } else { + Dprint(statp->options & RES_DEBUG, +@@ -987,6 +1063,66 @@ reopen (res_state statp, int *terrno, in + return 1; + } + ++/* The send_dg function is responsible for sending a DNS query over UDP ++ to the nameserver numbered NS from the res_state STATP i.e. ++ EXT(statp).nssocks[ns]. The function supports IPv4 and IPv6 queries ++ along with the ability to send the query in parallel for both stacks ++ (default) or serially (RES_SINGLKUP). It also supports serial lookup ++ with a close and reopen of the socket used to talk to the server ++ (RES_SNGLKUPREOP) to work around broken name servers. ++ ++ The query stored in BUF of BUFLEN length is sent first followed by ++ the query stored in BUF2 of BUFLEN2 length. Queries are sent ++ in parallel (default) or serially (RES_SINGLKUP or RES_SNGLKUPREOP). ++ ++ Answers to the query are stored firstly in *ANSP up to a max of ++ *ANSSIZP bytes. If more than *ANSSIZP bytes are needed and ANSCP ++ is non-NULL (to indicate that modifying the answer buffer is allowed) ++ then malloc is used to allocate a new response buffer and ANSCP and ++ ANSP will both point to the new buffer. If more than *ANSSIZP bytes ++ are needed but ANSCP is NULL, then as much of the response as ++ possible is read into the buffer, but the results will be truncated. ++ When truncation happens because of a small answer buffer the DNS ++ packets header feild TC will bet set to 1, indicating a truncated ++ message, while the rest of the UDP packet is discarded. ++ ++ Answers to the query are stored secondly in *ANSP2 up to a max of ++ *ANSSIZP2 bytes, with the actual response length stored in ++ *RESPLEN2. If more than *ANSSIZP bytes are needed and ANSP2 ++ is non-NULL (required for a second query) then malloc is used to ++ allocate a new response buffer, *ANSSIZP2 is set to the new buffer ++ size and *ANSP2_MALLOCED is set to 1. ++ ++ The ANSP2_MALLOCED argument will eventually be removed as the ++ change in buffer pointer can be used to detect the buffer has ++ changed and that the caller should use free on the new buffer. ++ ++ Note that the answers may arrive in any order from the server and ++ therefore the first and second answer buffers may not correspond to ++ the first and second queries. ++ ++ It is not supported to call this function with a non-NULL ANSP2 ++ but a NULL ANSCP. Put another way, you can call send_vc with a ++ single unmodifiable buffer or two modifiable buffers, but no other ++ combination is supported. ++ ++ It is the caller's responsibility to free the malloc allocated ++ buffers by detecting that the pointers have changed from their ++ original values i.e. *ANSCP or *ANSP2 has changed. ++ ++ If an answer is truncated because of UDP datagram DNS limits then ++ *V_CIRCUIT is set to 1 and the return value non-zero to indicate to ++ the caller to retry with TCP. The value *GOTSOMEWHERE is set to 1 ++ if any progress was made reading a response from the nameserver and ++ is used by the caller to distinguish between ECONNREFUSED and ++ ETIMEDOUT (the latter if *GOTSOMEWHERE is 1). ++ ++ If errors are encountered then *TERRNO is set to an appropriate ++ errno value and a zero result is returned for a recoverable error, ++ and a less-than zero result is returned for a non-recoverable error. ++ ++ If no errors are encountered then *TERRNO is left unmodified and ++ a the length of the first response in bytes is returned. */ + static int + send_dg(res_state statp, + const u_char *buf, int buflen, const u_char *buf2, int buflen2, +@@ -996,8 +1132,6 @@ send_dg(res_state statp, + { + const HEADER *hp = (HEADER *) buf; + const HEADER *hp2 = (HEADER *) buf2; +- u_char *ans = *ansp; +- int orig_anssizp = *anssizp; + struct timespec now, timeout, finish; + struct pollfd pfd[1]; + int ptimeout; +@@ -1029,6 +1163,8 @@ send_dg(res_state statp, + int need_recompute = 0; + int nwritten = 0; + int recvresp1 = 0; ++ /* Skip the second response if there is no second query. ++ To do that we mark the second response as received. */ + int recvresp2 = buf2 == NULL; + pfd[0].fd = EXT(statp).nssocks[ns]; + pfd[0].events = POLLOUT; +@@ -1125,50 +1261,52 @@ send_dg(res_state statp, + int *thisresplenp; + + if ((recvresp1 | recvresp2) == 0 || buf2 == NULL) { ++ /* We have not received any responses ++ yet or we only have one response to ++ receive. */ + thisanssizp = anssizp; + thisansp = anscp ?: ansp; + assert (anscp != NULL || ansp2 == NULL); + thisresplenp = &resplen; + } else { +- if (*anssizp != MAXPACKET) { +- /* No buffer allocated for the first +- reply. We can try to use the rest +- of the user-provided buffer. */ +-#ifdef _STRING_ARCH_unaligned +- *anssizp2 = orig_anssizp - resplen; +- *ansp2 = *ansp + resplen; +-#else +- int aligned_resplen +- = ((resplen + __alignof__ (HEADER) - 1) +- & ~(__alignof__ (HEADER) - 1)); +- *anssizp2 = orig_anssizp - aligned_resplen; +- *ansp2 = *ansp + aligned_resplen; +-#endif +- } else { +- /* The first reply did not fit into the +- user-provided buffer. Maybe the second +- answer will. */ +- *anssizp2 = orig_anssizp; +- *ansp2 = *ansp; +- } +- + thisanssizp = anssizp2; + thisansp = ansp2; + thisresplenp = resplen2; + } + + if (*thisanssizp < MAXPACKET +- /* Yes, we test ANSCP here. If we have two buffers +- both will be allocatable. */ +- && anscp ++ /* If the current buffer is non-NULL and it's not ++ pointing at the static user-supplied buffer then ++ we can reallocate it. */ ++ && (thisansp != NULL && thisansp != ansp) ++ /* Is the size too small? */ + && (ioctl (pfd[0].fd, FIONREAD, thisresplenp) < 0 +- || *thisanssizp < *thisresplenp)) { ++ || *thisanssizp < *thisresplenp) ++ ) { ++ /* Always allocate MAXPACKET, callers expect ++ this specific size. */ + u_char *newp = malloc (MAXPACKET); + if (newp != NULL) { +- *anssizp = MAXPACKET; +- *thisansp = ans = newp; ++ *thisanssizp = MAXPACKET; ++ *thisansp = newp; + } + } ++ /* We could end up with truncation if anscp was NULL ++ (not allowed to change caller's buffer) and the ++ response buffer size is too small. This isn't a ++ reliable way to detect truncation because the ioctl ++ may be an inaccurate report of the UDP message size. ++ Therefore we use this only to issue debug output. ++ To do truncation accurately with UDP we need ++ MSG_TRUNC which is only available on Linux. We ++ can abstract out the Linux-specific feature in the ++ future to detect truncation. */ ++ if (__glibc_unlikely (*thisanssizp < *thisresplenp)) { ++ Dprint(statp->options & RES_DEBUG, ++ (stdout, ";; response may be truncated (UDP)\n") ++ ); ++ } ++ + HEADER *anhp = (HEADER *) *thisansp; + socklen_t fromlen = sizeof(struct sockaddr_in6); + assert (sizeof(from) <= fromlen); +Index: glibc-2.12-2-gc4ccff1/resolv/res_query.c +=================================================================== +--- glibc-2.12-2-gc4ccff1.orig/resolv/res_query.c ++++ glibc-2.12-2-gc4ccff1/resolv/res_query.c +@@ -391,6 +391,7 @@ __libc_res_nsearch(res_state statp, + && (*answerp2 < answer || *answerp2 >= answer + anslen)) + { + free (*answerp2); ++ *nanswerp2 = 0; + *answerp2 = NULL; + } + } +@@ -431,6 +432,7 @@ __libc_res_nsearch(res_state statp, + || *answerp2 >= answer + anslen)) + { + free (*answerp2); ++ *nanswerp2 = 0; + *answerp2 = NULL; + } + +@@ -503,6 +505,7 @@ __libc_res_nsearch(res_state statp, + if (answerp2 && (*answerp2 < answer || *answerp2 >= answer + anslen)) + { + free (*answerp2); ++ *nanswerp2 = NULL; + *answerp2 = NULL; + } + if (saved_herrno != -1) diff --git a/src/patches/glibc/glibc-rh1299319-0.patch b/src/patches/glibc/glibc-rh1299319-0.patch new file mode 100644 index 0000000..f27eccd --- /dev/null +++ b/src/patches/glibc/glibc-rh1299319-0.patch @@ -0,0 +1,61 @@ +commit 2c1094bd700e63a8d7f547b3f5495bedb55c0a08 +Author: Ulrich Drepper drepper@gmail.com +Date: Thu Dec 22 22:43:39 2011 -0500 + + Create internal threads with sufficient stack size + +Index: glibc-2.12-2-gc4ccff1/nptl/Versions +=================================================================== +--- glibc-2.12-2-gc4ccff1.orig/nptl/Versions ++++ glibc-2.12-2-gc4ccff1/nptl/Versions +@@ -255,6 +255,6 @@ libpthread { + GLIBC_PRIVATE { + __pthread_initialize_minimal; + __pthread_clock_gettime; __pthread_clock_settime; +- __pthread_unwind; ++ __pthread_unwind; __pthread_get_minstack; + } + } +Index: glibc-2.12-2-gc4ccff1/nptl/nptl-init.c +=================================================================== +--- glibc-2.12-2-gc4ccff1.orig/nptl/nptl-init.c ++++ glibc-2.12-2-gc4ccff1/nptl/nptl-init.c +@@ -507,3 +507,13 @@ __pthread_initialize_minimal_internal (i + } + strong_alias (__pthread_initialize_minimal_internal, + __pthread_initialize_minimal) ++ ++ ++size_t ++__pthread_get_minstack (const pthread_attr_t *attr) ++{ ++ struct pthread_attr *iattr = (struct pthread_attr *) attr; ++ ++ return (GLRO(dl_pagesize) + __static_tls_size + PTHREAD_STACK_MIN ++ + iattr->guardsize); ++} +Index: glibc-2.12-2-gc4ccff1/nptl/pthreadP.h +=================================================================== +--- glibc-2.12-2-gc4ccff1.orig/nptl/pthreadP.h ++++ glibc-2.12-2-gc4ccff1/nptl/pthreadP.h +@@ -397,6 +397,7 @@ weak_function; + + extern void __pthread_init_static_tls (struct link_map *) attribute_hidden; + ++extern size_t __pthread_get_minstack (const pthread_attr_t *attr); + + /* Namespace save aliases. */ + extern int __pthread_getschedparam (pthread_t thread_id, int *policy, +Index: glibc-2.12-2-gc4ccff1/nptl/sysdeps/unix/sysv/linux/timer_routines.c +=================================================================== +--- glibc-2.12-2-gc4ccff1.orig/nptl/sysdeps/unix/sysv/linux/timer_routines.c ++++ glibc-2.12-2-gc4ccff1/nptl/sysdeps/unix/sysv/linux/timer_routines.c +@@ -165,7 +165,7 @@ __start_helper_thread (void) + and should go away automatically when canceled. */ + pthread_attr_t attr; + (void) pthread_attr_init (&attr); +- (void) pthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN); ++ (void) pthread_attr_setstacksize (&attr, __pthread_get_minstack (&attr)); + + /* Block all signals in the helper thread but SIGSETXID. To do this + thoroughly we temporarily have to block all signals here. The diff --git a/src/patches/glibc/glibc-rh1299319-1.patch b/src/patches/glibc/glibc-rh1299319-1.patch new file mode 100644 index 0000000..e6288a2 --- /dev/null +++ b/src/patches/glibc/glibc-rh1299319-1.patch @@ -0,0 +1,19 @@ +commit 232872379ee82cd040a52a48cbbae65a249b5765 +Author: Adhemerval Zanella azanella@linux.vnet.ibm.com +Date: Sun Jan 8 19:56:52 2012 -0500 + + Use __pthread_get_minstack for AIO helper thread + +diff --git a/nptl/sysdeps/unix/sysv/linux/aio_misc.h b/nptl/sysdeps/unix/sysv/linux/aio_misc.h +index 406d96e..8011c3e 100644 +--- a/nptl/sysdeps/unix/sysv/linux/aio_misc.h ++++ b/nptl/sysdeps/unix/sysv/linux/aio_misc.h +@@ -47,7 +47,7 @@ __aio_create_helper_thread (pthread_t *threadp, void *(*tf) (void *), + pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); + + /* The helper thread needs only very little resources. */ +- (void) pthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN); ++ (void) pthread_attr_setstacksize (&attr, __pthread_get_minstack (&attr)); + + /* Block all signals in the helper thread. To do this thoroughly we + temporarily have to block all signals here. */ diff --git a/src/patches/glibc/glibc-rh552960.patch b/src/patches/glibc/glibc-rh552960.patch new file mode 100644 index 0000000..41eccb7 --- /dev/null +++ b/src/patches/glibc/glibc-rh552960.patch @@ -0,0 +1,1213 @@ +diff -pruN glibc-2.12-2-gc4ccff1/nptl/Makefile glibc-2.12-2-gc4ccff1.fixed/nptl/Makefile +--- glibc-2.12-2-gc4ccff1/nptl/Makefile 2013-07-09 10:18:22.267421846 +0530 ++++ glibc-2.12-2-gc4ccff1.fixed/nptl/Makefile 2013-07-09 10:16:22.043427519 +0530 +@@ -207,7 +207,8 @@ tests = tst-typesizes \ + tst-cond1 tst-cond2 tst-cond3 tst-cond4 tst-cond5 tst-cond6 tst-cond7 \ + tst-cond8 tst-cond9 tst-cond10 tst-cond11 tst-cond12 tst-cond13 \ + tst-cond14 tst-cond15 tst-cond16 tst-cond17 tst-cond18 tst-cond19 \ +- tst-cond20 tst-cond21 tst-cond22 tst-cond23 \ ++ tst-cond20 tst-cond21 tst-cond22 tst-cond23 tst-cond24 tst-cond25 \ ++ tst-cond-except \ + tst-robust1 tst-robust2 tst-robust3 tst-robust4 tst-robust5 \ + tst-robust6 tst-robust7 tst-robust8 tst-robust9 \ + tst-robustpi1 tst-robustpi2 tst-robustpi3 tst-robustpi4 tst-robustpi5 \ +@@ -275,6 +276,8 @@ gen-as-const-headers = pthread-errnos.sy + + LDFLAGS-pthread.so = -Wl,--enable-new-dtags,-z,nodelete,-z,initfirst + ++LDFLAGS-tst-cond24 = -lrt ++LDFLAGS-tst-cond25 = -lrt + + include ../Makeconfig + +diff -pruN glibc-2.12-2-gc4ccff1/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S glibc-2.12-2-gc4ccff1.fixed/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S +--- glibc-2.12-2-gc4ccff1/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S 2010-05-04 16:57:23.000000000 +0530 ++++ glibc-2.12-2-gc4ccff1.fixed/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S 2013-07-09 10:16:22.044427519 +0530 +@@ -203,9 +203,11 @@ __pthread_cond_timedwait: + 42: leal (%ebp), %esi + movl 28(%esp), %edx + addl $cond_futex, %ebx ++.Ladd_cond_futex_pi: + movl $SYS_futex, %eax + ENTER_KERNEL + subl $cond_futex, %ebx ++.Lsub_cond_futex_pi: + movl %eax, %esi + /* Set the pi-requeued flag only if the kernel has returned 0. The + kernel does not hold the mutex on ETIMEDOUT or any other error. */ +@@ -213,8 +215,23 @@ __pthread_cond_timedwait: + sete 24(%esp) + je 41f + +- /* Normal and PI futexes dont mix. Use normal futex functions only +- if the kernel does not support the PI futex functions. */ ++ /* When a futex syscall with FUTEX_WAIT_REQUEUE_PI returns ++ successfully, it has already locked the mutex for us and the ++ pi_flag (24(%esp)) is set to denote that fact. However, if another ++ thread changed the futex value before we entered the wait, the ++ syscall may return an EAGAIN and the mutex is not locked. We go ++ ahead with a success anyway since later we look at the pi_flag to ++ decide if we got the mutex or not. The sequence numbers then make ++ sure that only one of the threads actually wake up. We retry using ++ normal FUTEX_WAIT only if the kernel returned ENOSYS, since normal ++ and PI futexes don't mix. ++ ++ Note that we don't check for EAGAIN specifically; we assume that the ++ only other error the futex function could return is EAGAIN (barring ++ the ETIMEOUT of course, for the timeout case in futex) since ++ anything else would mean an error in our function. It is too ++ expensive to do that check for every call (which is quite common in ++ case of a large number of threads), so it has been skipped. */ + cmpl $-ENOSYS, %eax + jne 41f + xorl %ecx, %ecx +@@ -274,9 +291,24 @@ __pthread_cond_timedwait: + jne 9f + + 15: cmpl $-ETIMEDOUT, %esi +- jne 8b ++ je 28f + +- addl $1, wakeup_seq(%ebx) ++ /* We need to go back to futex_wait. If we're using requeue_pi, then ++ release the mutex we had acquired and go back. */ ++ movl 24(%esp), %edx ++ test %edx, %edx ++ jz 8b ++ ++ /* Adjust the mutex values first and then unlock it. The unlock ++ should always succeed or else the kernel did not lock the mutex ++ correctly. */ ++ movl dep_mutex(%ebx), %eax ++ call __pthread_mutex_cond_lock_adjust ++ xorl %edx, %edx ++ call __pthread_mutex_unlock_usercnt ++ jmp 8b ++ ++28: addl $1, wakeup_seq(%ebx) + adcl $0, wakeup_seq+4(%ebx) + addl $1, cond_futex(%ebx) + movl $ETIMEDOUT, %esi +@@ -644,10 +676,27 @@ __condvar_tw_cleanup: + movl $0x7fffffff, %edx + ENTER_KERNEL + ++ /* Lock the mutex only if we don't own it already. This only happens ++ in case of PI mutexes, if we got cancelled after a successful ++ return of the futex syscall and before disabling async ++ cancellation. */ + 5: movl 24+FRAME_SIZE(%esp), %eax +- call __pthread_mutex_cond_lock ++ movl MUTEX_KIND(%eax), %ebx ++ andl $(ROBUST_BIT|PI_BIT), %ebx ++ cmpl $PI_BIT, %ebx ++ jne 8f ++ ++ movl (%eax), %ebx ++ andl $TID_MASK, %ebx ++ cmpl %ebx, %gs:TID ++ jne 8f ++ /* We managed to get the lock. Fix it up before returning. */ ++ call __pthread_mutex_cond_lock_adjust ++ jmp 9f ++ ++8: call __pthread_mutex_cond_lock + +- movl %esi, (%esp) ++9: movl %esi, (%esp) + .LcallUR: + call _Unwind_Resume + hlt +@@ -665,7 +714,15 @@ __condvar_tw_cleanup: + .uleb128 .Lcstend-.Lcstbegin + .Lcstbegin: + .long .LcleanupSTART-.LSTARTCODE +- .long .Ladd_cond_futex-.LcleanupSTART ++ .long .Ladd_cond_futex_pi-.LcleanupSTART ++ .long __condvar_tw_cleanup-.LSTARTCODE ++ .uleb128 0 ++ .long .Ladd_cond_futex_pi-.LSTARTCODE ++ .long .Lsub_cond_futex_pi-.Ladd_cond_futex_pi ++ .long __condvar_tw_cleanup2-.LSTARTCODE ++ .uleb128 0 ++ .long .Lsub_cond_futex_pi-.LSTARTCODE ++ .long .Ladd_cond_futex-.Lsub_cond_futex_pi + .long __condvar_tw_cleanup-.LSTARTCODE + .uleb128 0 + .long .Ladd_cond_futex-.LSTARTCODE +diff -pruN glibc-2.12-2-gc4ccff1/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S glibc-2.12-2-gc4ccff1.fixed/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S +--- glibc-2.12-2-gc4ccff1/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S 2010-05-04 16:57:23.000000000 +0530 ++++ glibc-2.12-2-gc4ccff1.fixed/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S 2013-07-09 10:16:22.046427519 +0530 +@@ -138,17 +138,33 @@ __pthread_cond_wait: + movl %ebp, %edx + xorl %esi, %esi + addl $cond_futex, %ebx ++.Ladd_cond_futex_pi: + movl $SYS_futex, %eax + ENTER_KERNEL + subl $cond_futex, %ebx ++.Lsub_cond_futex_pi: + /* Set the pi-requeued flag only if the kernel has returned 0. The + kernel does not hold the mutex on error. */ + cmpl $0, %eax + sete 16(%esp) + je 19f + +- /* Normal and PI futexes dont mix. Use normal futex functions only +- if the kernel does not support the PI futex functions. */ ++ /* When a futex syscall with FUTEX_WAIT_REQUEUE_PI returns ++ successfully, it has already locked the mutex for us and the ++ pi_flag (16(%esp)) is set to denote that fact. However, if another ++ thread changed the futex value before we entered the wait, the ++ syscall may return an EAGAIN and the mutex is not locked. We go ++ ahead with a success anyway since later we look at the pi_flag to ++ decide if we got the mutex or not. The sequence numbers then make ++ sure that only one of the threads actually wake up. We retry using ++ normal FUTEX_WAIT only if the kernel returned ENOSYS, since normal ++ and PI futexes don't mix. ++ ++ Note that we don't check for EAGAIN specifically; we assume that the ++ only other error the futex function could return is EAGAIN since ++ anything else would mean an error in our function. It is too ++ expensive to do that check for every call (which is quite common in ++ case of a large number of threads), so it has been skipped. */ + cmpl $-ENOSYS, %eax + jne 19f + xorl %ecx, %ecx +@@ -198,12 +214,12 @@ __pthread_cond_wait: + cmpl 8(%esp), %edx + jne 7f + cmpl 4(%esp), %edi +- je 8b ++ je 22f + + 7: cmpl %ecx, %edx + jne 9f + cmp %eax, %edi +- je 8b ++ je 22f + + 9: addl $1, woken_seq(%ebx) + adcl $0, woken_seq+4(%ebx) +@@ -279,6 +295,22 @@ __pthread_cond_wait: + jmp 20b + + cfi_adjust_cfa_offset(-FRAME_SIZE); ++ ++ /* We need to go back to futex_wait. If we're using requeue_pi, then ++ release the mutex we had acquired and go back. */ ++22: movl 16(%esp), %edx ++ test %edx, %edx ++ jz 8b ++ ++ /* Adjust the mutex values first and then unlock it. The unlock ++ should always succeed or else the kernel did not lock the mutex ++ correctly. */ ++ movl dep_mutex(%ebx), %eax ++ call __pthread_mutex_cond_lock_adjust ++ xorl %edx, %edx ++ call __pthread_mutex_unlock_usercnt ++ jmp 8b ++ + /* Initial locking failed. */ + 1: + #if cond_lock == 0 +@@ -391,6 +423,7 @@ __pthread_cond_wait: + #endif + call __lll_unlock_wake + jmp 11b ++ + .size __pthread_cond_wait, .-__pthread_cond_wait + versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait, + GLIBC_2_3_2) +@@ -531,10 +564,27 @@ __condvar_w_cleanup: + movl $0x7fffffff, %edx + ENTER_KERNEL + ++ /* Lock the mutex only if we don't own it already. This only happens ++ in case of PI mutexes, if we got cancelled after a successful ++ return of the futex syscall and before disabling async ++ cancellation. */ + 5: movl 24+FRAME_SIZE(%esp), %eax +- call __pthread_mutex_cond_lock ++ movl MUTEX_KIND(%eax), %ebx ++ andl $(ROBUST_BIT|PI_BIT), %ebx ++ cmpl $PI_BIT, %ebx ++ jne 8f ++ ++ movl (%eax), %ebx ++ andl $TID_MASK, %ebx ++ cmpl %ebx, %gs:TID ++ jne 8f ++ /* We managed to get the lock. Fix it up before returning. */ ++ call __pthread_mutex_cond_lock_adjust ++ jmp 9f + +- movl %esi, (%esp) ++8: call __pthread_mutex_cond_lock ++ ++9: movl %esi, (%esp) + .LcallUR: + call _Unwind_Resume + hlt +@@ -552,7 +602,15 @@ __condvar_w_cleanup: + .uleb128 .Lcstend-.Lcstbegin + .Lcstbegin: + .long .LcleanupSTART-.LSTARTCODE +- .long .Ladd_cond_futex-.LcleanupSTART ++ .long .Ladd_cond_futex_pi-.LcleanupSTART ++ .long __condvar_w_cleanup-.LSTARTCODE ++ .uleb128 0 ++ .long .Ladd_cond_futex_pi-.LSTARTCODE ++ .long .Lsub_cond_futex_pi-.Ladd_cond_futex_pi ++ .long __condvar_w_cleanup2-.LSTARTCODE ++ .uleb128 0 ++ .long .Lsub_cond_futex_pi-.LSTARTCODE ++ .long .Ladd_cond_futex-.Lsub_cond_futex_pi + .long __condvar_w_cleanup-.LSTARTCODE + .uleb128 0 + .long .Ladd_cond_futex-.LSTARTCODE +diff -pruN glibc-2.12-2-gc4ccff1/nptl/sysdeps/unix/sysv/linux/pthread-pi-defines.sym glibc-2.12-2-gc4ccff1.fixed/nptl/sysdeps/unix/sysv/linux/pthread-pi-defines.sym +--- glibc-2.12-2-gc4ccff1/nptl/sysdeps/unix/sysv/linux/pthread-pi-defines.sym 2010-05-04 16:57:23.000000000 +0530 ++++ glibc-2.12-2-gc4ccff1.fixed/nptl/sysdeps/unix/sysv/linux/pthread-pi-defines.sym 2013-07-09 10:16:22.047427519 +0530 +@@ -6,3 +6,4 @@ MUTEX_KIND offsetof (pthread_mutex_t, __ + ROBUST_BIT PTHREAD_MUTEX_ROBUST_NORMAL_NP + PI_BIT PTHREAD_MUTEX_PRIO_INHERIT_NP + PS_BIT PTHREAD_MUTEX_PSHARED_BIT ++TID_MASK FUTEX_TID_MASK +diff -pruN glibc-2.12-2-gc4ccff1/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S glibc-2.12-2-gc4ccff1.fixed/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S +--- glibc-2.12-2-gc4ccff1/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S 2013-07-09 10:18:22.506421835 +0530 ++++ glibc-2.12-2-gc4ccff1.fixed/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S 2013-07-09 10:16:22.048427519 +0530 +@@ -104,6 +104,8 @@ __pthread_cond_timedwait: + movq %rsi, dep_mutex(%rdi) + + 22: ++ xorb %r15b, %r15b ++ + #ifndef __ASSUME_FUTEX_CLOCK_REALTIME + # ifdef PIC + cmpl $0, __have_futex_clock_realtime(%rip) +@@ -189,18 +191,39 @@ __pthread_cond_timedwait: + movl $SYS_futex, %eax + syscall + +- movl $1, %r15d ++ cmpl $0, %eax ++ sete %r15b ++ + #ifdef __ASSUME_REQUEUE_PI + jmp 62f + #else +- cmpq $-4095, %rax +- jnae 62f ++ je 62f ++ ++ /* When a futex syscall with FUTEX_WAIT_REQUEUE_PI returns ++ successfully, it has already locked the mutex for us and the ++ pi_flag (%r15b) is set to denote that fact. However, if another ++ thread changed the futex value before we entered the wait, the ++ syscall may return an EAGAIN and the mutex is not locked. We go ++ ahead with a success anyway since later we look at the pi_flag to ++ decide if we got the mutex or not. The sequence numbers then make ++ sure that only one of the threads actually wake up. We retry using ++ normal FUTEX_WAIT only if the kernel returned ENOSYS, since normal ++ and PI futexes don't mix. ++ ++ Note that we don't check for EAGAIN specifically; we assume that the ++ only other error the futex function could return is EAGAIN (barring ++ the ETIMEOUT of course, for the timeout case in futex) since ++ anything else would mean an error in our function. It is too ++ expensive to do that check for every call (which is quite common in ++ case of a large number of threads), so it has been skipped. */ ++ cmpl $-ENOSYS, %eax ++ jne 62f + + subq $cond_futex, %rdi + #endif + + 61: movl $(FUTEX_WAIT_BITSET|FUTEX_PRIVATE_FLAG), %esi +-60: xorl %r15d, %r15d ++60: xorb %r15b, %r15b + xorl %eax, %eax + /* The following only works like this because we only support + two clocks, represented using a single bit. */ +@@ -247,7 +270,23 @@ __pthread_cond_timedwait: + ja 39f + + 45: cmpq $-ETIMEDOUT, %r14 +- jne 38b ++ je 99f ++ ++ /* We need to go back to futex_wait. If we're using requeue_pi, then ++ release the mutex we had acquired and go back. */ ++ test %r15b, %r15b ++ jz 38b ++ ++ /* Adjust the mutex values first and then unlock it. The unlock ++ should always succeed or else the kernel did not lock the ++ mutex correctly. */ ++ movq %r8, %rdi ++ callq __pthread_mutex_cond_lock_adjust ++ xorl %esi, %esi ++ callq __pthread_mutex_unlock_usercnt ++ /* Reload cond_var. */ ++ movq 8(%rsp), %rdi ++ jmp 38b + + 99: incq wakeup_seq(%rdi) + incl cond_futex(%rdi) +@@ -297,7 +336,7 @@ __pthread_cond_timedwait: + /* If requeue_pi is used the kernel performs the locking of the + mutex. */ + 41: movq 16(%rsp), %rdi +- testl %r15d, %r15d ++ testb %r15b, %r15b + jnz 64f + + callq __pthread_mutex_cond_lock +@@ -405,8 +444,6 @@ __pthread_cond_timedwait: + + #ifndef __ASSUME_FUTEX_CLOCK_REALTIME + .Lreltmo: +- xorl %r15d, %r15d +- + /* Get internal lock. */ + movl $1, %esi + xorl %eax, %eax +@@ -765,10 +802,27 @@ __condvar_cleanup2: + movl $SYS_futex, %eax + syscall + ++ /* Lock the mutex only if we don't own it already. This only happens ++ in case of PI mutexes, if we got cancelled after a successful ++ return of the futex syscall and before disabling async ++ cancellation. */ + 5: movq 16(%rsp), %rdi +- callq __pthread_mutex_cond_lock ++ movl MUTEX_KIND(%rdi), %eax ++ andl $(ROBUST_BIT|PI_BIT), %eax ++ cmpl $PI_BIT, %eax ++ jne 7f ++ ++ movl (%rdi), %eax ++ andl $TID_MASK, %eax ++ cmpl %eax, %fs:TID ++ jne 7f ++ /* We managed to get the lock. Fix it up before returning. */ ++ callq __pthread_mutex_cond_lock_adjust ++ jmp 8f ++ ++7: callq __pthread_mutex_cond_lock + +- movq 24(%rsp), %rdi ++8: movq 24(%rsp), %rdi + movq FRAME_SIZE(%rsp), %r15 + movq FRAME_SIZE+8(%rsp), %r14 + movq FRAME_SIZE+16(%rsp), %r13 +diff -pruN glibc-2.12-2-gc4ccff1/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S glibc-2.12-2-gc4ccff1.fixed/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S +--- glibc-2.12-2-gc4ccff1/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S 2013-07-09 10:18:22.507421834 +0530 ++++ glibc-2.12-2-gc4ccff1.fixed/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S 2013-07-09 10:16:22.048427519 +0530 +@@ -23,6 +23,7 @@ + #include <lowlevelcond.h> + #include <tcb-offsets.h> + #include <pthread-pi-defines.h> ++#include <pthread-errnos.h> + + #include <kernel-features.h> + +@@ -137,12 +138,32 @@ __pthread_cond_wait: + movl $SYS_futex, %eax + syscall + +- movl $1, %r8d ++ cmpl $0, %eax ++ sete %r8b ++ + #ifdef __ASSUME_REQUEUE_PI + jmp 62f + #else +- cmpq $-4095, %rax +- jnae 62f ++ je 62f ++ ++ /* When a futex syscall with FUTEX_WAIT_REQUEUE_PI returns ++ successfully, it has already locked the mutex for us and the ++ pi_flag (%r8b) is set to denote that fact. However, if another ++ thread changed the futex value before we entered the wait, the ++ syscall may return an EAGAIN and the mutex is not locked. We go ++ ahead with a success anyway since later we look at the pi_flag to ++ decide if we got the mutex or not. The sequence numbers then make ++ sure that only one of the threads actually wake up. We retry using ++ normal FUTEX_WAIT only if the kernel returned ENOSYS, since normal ++ and PI futexes don't mix. ++ ++ Note that we don't check for EAGAIN specifically; we assume that the ++ only other error the futex function could return is EAGAIN since ++ anything else would mean an error in our function. It is too ++ expensive to do that check for every call (which is quite common in ++ case of a large number of threads), so it has been skipped. */ ++ cmpl $-ENOSYS, %eax ++ jne 62f + + # ifndef __ASSUME_PRIVATE_FUTEX + movl $FUTEX_WAIT, %esi +@@ -155,7 +176,7 @@ __pthread_cond_wait: + #else + orl %fs:PRIVATE_FUTEX, %esi + #endif +-60: xorl %r8d, %r8d ++60: xorb %r8b, %r8b + movl $SYS_futex, %eax + syscall + +@@ -185,10 +206,10 @@ __pthread_cond_wait: + jne 16f + + cmpq 24(%rsp), %r9 +- jbe 8b ++ jbe 19f + + cmpq %rax, %r9 +- jna 8b ++ jna 19f + + incq woken_seq(%rdi) + +@@ -230,7 +251,7 @@ __pthread_cond_wait: + /* If requeue_pi is used the kernel performs the locking of the + mutex. */ + 11: movq 16(%rsp), %rdi +- testl %r8d, %r8d ++ testb %r8b, %r8b + jnz 18f + + callq __pthread_mutex_cond_lock +@@ -247,6 +268,23 @@ __pthread_cond_wait: + xorl %eax, %eax + jmp 14b + ++ /* We need to go back to futex_wait. If we're using requeue_pi, then ++ release the mutex we had acquired and go back. */ ++19: testb %r8b, %r8b ++ jz 8b ++ ++ /* Adjust the mutex values first and then unlock it. The unlock ++ should always succeed or else the kernel did not lock the mutex ++ correctly. */ ++ movq 16(%rsp), %rdi ++ callq __pthread_mutex_cond_lock_adjust ++ movq %rdi, %r8 ++ xorl %esi, %esi ++ callq __pthread_mutex_unlock_usercnt ++ /* Reload cond_var. */ ++ movq 8(%rsp), %rdi ++ jmp 8b ++ + /* Initial locking failed. */ + 1: + #if cond_lock != 0 +@@ -324,6 +362,7 @@ __pthread_cond_wait: + + 13: movq %r10, %rax + jmp 14b ++ + .size __pthread_cond_wait, .-__pthread_cond_wait + versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait, + GLIBC_2_3_2) +@@ -454,10 +493,28 @@ __condvar_cleanup1: + movl $SYS_futex, %eax + syscall + ++ /* Lock the mutex only if we don't own it already. This only happens ++ in case of PI mutexes, if we got cancelled after a successful ++ return of the futex syscall and before disabling async ++ cancellation. */ + 5: movq 16(%rsp), %rdi +- callq __pthread_mutex_cond_lock ++ movl MUTEX_KIND(%rdi), %eax ++ andl $(ROBUST_BIT|PI_BIT), %eax ++ cmpl $PI_BIT, %eax ++ jne 7f ++ ++ movl (%rdi), %eax ++ andl $TID_MASK, %eax ++ cmpl %eax, %fs:TID ++ jne 7f ++ /* We managed to get the lock. Fix it up before returning. */ ++ callq __pthread_mutex_cond_lock_adjust ++ jmp 8f ++ + +- movq 24(%rsp), %rdi ++7: callq __pthread_mutex_cond_lock ++ ++8: movq 24(%rsp), %rdi + .LcallUR: + call _Unwind_Resume@PLT + hlt +@@ -476,11 +533,11 @@ __condvar_cleanup1: + .uleb128 .LcleanupSTART-.LSTARTCODE + .uleb128 .LcleanupEND-.LcleanupSTART + .uleb128 __condvar_cleanup1-.LSTARTCODE +- .uleb128 0 ++ .uleb128 0 + .uleb128 .LcallUR-.LSTARTCODE + .uleb128 .LENDCODE-.LcallUR + .uleb128 0 +- .uleb128 0 ++ .uleb128 0 + .Lcstend: + + +diff -pruN glibc-2.12-2-gc4ccff1/nptl/tst-cond24.c glibc-2.12-2-gc4ccff1.fixed/nptl/tst-cond24.c +--- glibc-2.12-2-gc4ccff1/nptl/tst-cond24.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.12-2-gc4ccff1.fixed/nptl/tst-cond24.c 2013-07-09 10:19:10.008419593 +0530 +@@ -0,0 +1,249 @@ ++/* Verify that condition variables synchronized by PI mutexes don't hang. ++ Copyright (C) 2012-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 ++ http://www.gnu.org/licenses/. */ ++ ++#include <pthread.h> ++#include <stdio.h> ++#include <stdlib.h> ++#include <string.h> ++#include <errno.h> ++#include <sys/types.h> ++#include <sys/syscall.h> ++#include <unistd.h> ++#include <sys/time.h> ++#include <time.h> ++ ++#define THREADS_NUM 5 ++#define MAXITER 50000 ++ ++static pthread_mutex_t mutex; ++static pthread_mutexattr_t mutex_attr; ++static pthread_cond_t cond; ++static pthread_t threads[THREADS_NUM]; ++static int pending = 0; ++ ++typedef void * (*threadfunc) (void *); ++ ++void * ++thread_fun_timed (void *arg) ++{ ++ int *ret = arg; ++ int rv, i; ++ ++ printf ("Started thread_fun_timed[%d]\n", *ret); ++ ++ for (i = 0; i < MAXITER / THREADS_NUM; i++) ++ { ++ rv = pthread_mutex_lock (&mutex); ++ if (rv) ++ { ++ printf ("pthread_mutex_lock: %s(%d)\n", strerror (rv), rv); ++ *ret = 1; ++ goto out; ++ } ++ ++ while (!pending) ++ { ++ struct timespec ts; ++ clock_gettime(CLOCK_REALTIME, &ts); ++ ts.tv_sec += 20; ++ rv = pthread_cond_timedwait (&cond, &mutex, &ts); ++ ++ /* There should be no timeout either. */ ++ if (rv) ++ { ++ printf ("pthread_cond_wait: %s(%d)\n", strerror (rv), rv); ++ *ret = 1; ++ goto out; ++ } ++ } ++ ++ pending--; ++ ++ rv = pthread_mutex_unlock (&mutex); ++ if (rv) ++ { ++ printf ("pthread_mutex_unlock: %s(%d)\n", strerror (rv), rv); ++ *ret = 1; ++ goto out; ++ } ++ } ++ ++ *ret = 0; ++ ++out: ++ return ret; ++} ++ ++void * ++thread_fun (void *arg) ++{ ++ int *ret = arg; ++ int rv, i; ++ ++ printf ("Started thread_fun[%d]\n", *ret); ++ ++ for (i = 0; i < MAXITER / THREADS_NUM; i++) ++ { ++ rv = pthread_mutex_lock (&mutex); ++ if (rv) ++ { ++ printf ("pthread_mutex_lock: %s(%d)\n", strerror (rv), rv); ++ *ret = 1; ++ goto out; ++ } ++ ++ while (!pending) ++ { ++ rv = pthread_cond_wait (&cond, &mutex); ++ ++ if (rv) ++ { ++ printf ("pthread_cond_wait: %s(%d)\n", strerror (rv), rv); ++ *ret = 1; ++ goto out; ++ } ++ } ++ ++ pending--; ++ ++ rv = pthread_mutex_unlock (&mutex); ++ if (rv) ++ { ++ printf ("pthread_mutex_unlock: %s(%d)\n", strerror (rv), rv); ++ *ret = 1; ++ goto out; ++ } ++ } ++ ++ *ret = 0; ++ ++out: ++ return ret; ++} ++ ++static int ++do_test_wait (threadfunc f) ++{ ++ int i; ++ int rv; ++ int counter = 0; ++ int retval[THREADS_NUM]; ++ ++ puts ("Starting test"); ++ ++ rv = pthread_mutexattr_init (&mutex_attr); ++ if (rv) ++ { ++ printf ("pthread_mutexattr_init: %s(%d)\n", strerror (rv), rv); ++ return 1; ++ } ++ ++ rv = pthread_mutexattr_setprotocol (&mutex_attr, PTHREAD_PRIO_INHERIT); ++ if (rv) ++ { ++ printf ("pthread_mutexattr_setprotocol: %s(%d)\n", strerror (rv), rv); ++ return 1; ++ } ++ ++ rv = pthread_mutex_init (&mutex, &mutex_attr); ++ if (rv) ++ { ++ printf ("pthread_mutex_init: %s(%d)\n", strerror (rv), rv); ++ return 1; ++ } ++ ++ rv = pthread_cond_init (&cond, NULL); ++ if (rv) ++ { ++ printf ("pthread_cond_init: %s(%d)\n", strerror (rv), rv); ++ return 1; ++ } ++ ++ for (i = 0; i < THREADS_NUM; i++) ++ { ++ retval[i] = i; ++ rv = pthread_create (&threads[i], NULL, f, &retval[i]); ++ if (rv) ++ { ++ printf ("pthread_create: %s(%d)\n", strerror (rv), rv); ++ return 1; ++ } ++ } ++ ++ for (; counter < MAXITER; counter++) ++ { ++ rv = pthread_mutex_lock (&mutex); ++ if (rv) ++ { ++ printf ("pthread_mutex_lock: %s(%d)\n", strerror (rv), rv); ++ return 1; ++ } ++ ++ if (!(counter % 100)) ++ printf ("counter: %d\n", counter); ++ pending += 1; ++ ++ rv = pthread_cond_signal (&cond); ++ if (rv) ++ { ++ printf ("pthread_cond_signal: %s(%d)\n", strerror (rv), rv); ++ return 1; ++ } ++ ++ rv = pthread_mutex_unlock (&mutex); ++ if (rv) ++ { ++ printf ("pthread_mutex_unlock: %s(%d)\n", strerror (rv), rv); ++ return 1; ++ } ++ } ++ ++ for (i = 0; i < THREADS_NUM; i++) ++ { ++ void *ret; ++ rv = pthread_join (threads[i], &ret); ++ if (rv) ++ { ++ printf ("pthread_join: %s(%d)\n", strerror (rv), rv); ++ return 1; ++ } ++ if (ret && *(int *)ret) ++ { ++ printf ("Thread %d returned with an error\n", i); ++ return 1; ++ } ++ } ++ ++ return 0; ++} ++ ++static int ++do_test (void) ++{ ++ puts ("Testing pthread_cond_wait"); ++ int ret = do_test_wait (thread_fun); ++ if (ret) ++ return ret; ++ ++ puts ("Testing pthread_cond_timedwait"); ++ return do_test_wait (thread_fun_timed); ++} ++ ++#define TIMEOUT 20 ++#define TEST_FUNCTION do_test () ++#include "../test-skeleton.c" +diff -pruN glibc-2.12-2-gc4ccff1/nptl/tst-cond25.c glibc-2.12-2-gc4ccff1.fixed/nptl/tst-cond25.c +--- glibc-2.12-2-gc4ccff1/nptl/tst-cond25.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.12-2-gc4ccff1.fixed/nptl/tst-cond25.c 2013-07-09 10:19:15.472419335 +0530 +@@ -0,0 +1,281 @@ ++/* Verify that condition variables synchronized by PI mutexes don't hang on ++ on cancellation. ++ Copyright (C) 2012-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 ++ http://www.gnu.org/licenses/. */ ++ ++#include <pthread.h> ++#include <stdio.h> ++#include <stdlib.h> ++#include <stdint.h> ++#include <string.h> ++#include <errno.h> ++#include <sys/types.h> ++#include <sys/syscall.h> ++#include <unistd.h> ++#include <sys/time.h> ++#include <time.h> ++ ++#define NUM 5 ++#define ITERS 10000 ++#define COUNT 100 ++ ++typedef void *(*thr_func) (void *); ++ ++pthread_mutex_t mutex; ++pthread_cond_t cond; ++ ++void cleanup (void *u) ++{ ++ /* pthread_cond_wait should always return with the mutex locked. */ ++ if (pthread_mutex_unlock (&mutex)) ++ abort (); ++} ++ ++void * ++signaller (void *u) ++{ ++ int i, ret = 0; ++ void *tret = NULL; ++ ++ for (i = 0; i < ITERS; i++) ++ { ++ if ((ret = pthread_mutex_lock (&mutex)) != 0) ++ { ++ tret = (void *)1; ++ printf ("signaller:mutex_lock failed: %s\n", strerror (ret)); ++ goto out; ++ } ++ if ((ret = pthread_cond_signal (&cond)) != 0) ++ { ++ tret = (void *)1; ++ printf ("signaller:signal failed: %s\n", strerror (ret)); ++ goto unlock_out; ++ } ++ if ((ret = pthread_mutex_unlock (&mutex)) != 0) ++ { ++ tret = (void *)1; ++ printf ("signaller:mutex_unlock failed: %s\n", strerror (ret)); ++ goto out; ++ } ++ pthread_testcancel (); ++ } ++ ++out: ++ return tret; ++ ++unlock_out: ++ if ((ret = pthread_mutex_unlock (&mutex)) != 0) ++ printf ("signaller:mutex_unlock[2] failed: %s\n", strerror (ret)); ++ goto out; ++} ++ ++void * ++waiter (void *u) ++{ ++ int i, ret = 0; ++ void *tret = NULL; ++ int seq = (uintptr_t) u; ++ ++ for (i = 0; i < ITERS / NUM; i++) ++ { ++ if ((ret = pthread_mutex_lock (&mutex)) != 0) ++ { ++ tret = (void *) (uintptr_t) 1; ++ printf ("waiter[%u]:mutex_lock failed: %s\n", seq, strerror (ret)); ++ goto out; ++ } ++ pthread_cleanup_push (cleanup, NULL); ++ ++ if ((ret = pthread_cond_wait (&cond, &mutex)) != 0) ++ { ++ tret = (void *) (uintptr_t) 1; ++ printf ("waiter[%u]:wait failed: %s\n", seq, strerror (ret)); ++ goto unlock_out; ++ } ++ ++ if ((ret = pthread_mutex_unlock (&mutex)) != 0) ++ { ++ tret = (void *) (uintptr_t) 1; ++ printf ("waiter[%u]:mutex_unlock failed: %s\n", seq, strerror (ret)); ++ goto out; ++ } ++ pthread_cleanup_pop (0); ++ } ++ ++out: ++ puts ("waiter tests done"); ++ return tret; ++ ++unlock_out: ++ if ((ret = pthread_mutex_unlock (&mutex)) != 0) ++ printf ("waiter:mutex_unlock[2] failed: %s\n", strerror (ret)); ++ goto out; ++} ++ ++void * ++timed_waiter (void *u) ++{ ++ int i, ret; ++ void *tret = NULL; ++ int seq = (uintptr_t) u; ++ ++ for (i = 0; i < ITERS / NUM; i++) ++ { ++ struct timespec ts; ++ ++ if ((ret = clock_gettime(CLOCK_REALTIME, &ts)) != 0) ++ { ++ tret = (void *) (uintptr_t) 1; ++ printf ("%u:clock_gettime failed: %s\n", seq, strerror (errno)); ++ goto out; ++ } ++ ts.tv_sec += 20; ++ ++ if ((ret = pthread_mutex_lock (&mutex)) != 0) ++ { ++ tret = (void *) (uintptr_t) 1; ++ printf ("waiter[%u]:mutex_lock failed: %s\n", seq, strerror (ret)); ++ goto out; ++ } ++ pthread_cleanup_push (cleanup, NULL); ++ ++ /* We should not time out either. */ ++ if ((ret = pthread_cond_timedwait (&cond, &mutex, &ts)) != 0) ++ { ++ tret = (void *) (uintptr_t) 1; ++ printf ("waiter[%u]:timedwait failed: %s\n", seq, strerror (ret)); ++ goto unlock_out; ++ } ++ if ((ret = pthread_mutex_unlock (&mutex)) != 0) ++ { ++ tret = (void *) (uintptr_t) 1; ++ printf ("waiter[%u]:mutex_unlock failed: %s\n", seq, strerror (ret)); ++ goto out; ++ } ++ pthread_cleanup_pop (0); ++ } ++ ++out: ++ puts ("timed_waiter tests done"); ++ return tret; ++ ++unlock_out: ++ if ((ret = pthread_mutex_unlock (&mutex)) != 0) ++ printf ("waiter[%u]:mutex_unlock[2] failed: %s\n", seq, strerror (ret)); ++ goto out; ++} ++ ++int ++do_test_wait (thr_func f) ++{ ++ pthread_t w[NUM]; ++ pthread_t s; ++ pthread_mutexattr_t attr; ++ int i, j, ret = 0; ++ void *thr_ret; ++ ++ for (i = 0; i < COUNT; i++) ++ { ++ if ((ret = pthread_mutexattr_init (&attr)) != 0) ++ { ++ printf ("mutexattr_init failed: %s\n", strerror (ret)); ++ goto out; ++ } ++ ++ if ((ret = pthread_mutexattr_setprotocol (&attr, ++ PTHREAD_PRIO_INHERIT)) != 0) ++ { ++ printf ("mutexattr_setprotocol failed: %s\n", strerror (ret)); ++ goto out; ++ } ++ ++ if ((ret = pthread_cond_init (&cond, NULL)) != 0) ++ { ++ printf ("cond_init failed: %s\n", strerror (ret)); ++ goto out; ++ } ++ ++ if ((ret = pthread_mutex_init (&mutex, &attr)) != 0) ++ { ++ printf ("mutex_init failed: %s\n", strerror (ret)); ++ goto out; ++ } ++ ++ for (j = 0; j < NUM; j++) ++ if ((ret = pthread_create (&w[j], NULL, ++ f, (void *) (uintptr_t) j)) != 0) ++ { ++ printf ("waiter[%d]: create failed: %s\n", j, strerror (ret)); ++ goto out; ++ } ++ ++ if ((ret = pthread_create (&s, NULL, signaller, NULL)) != 0) ++ { ++ printf ("signaller: create failed: %s\n", strerror (ret)); ++ goto out; ++ } ++ ++ for (j = 0; j < NUM; j++) ++ { ++ pthread_cancel (w[j]); ++ ++ if ((ret = pthread_join (w[j], &thr_ret)) != 0) ++ { ++ printf ("waiter[%d]: join failed: %s\n", j, strerror (ret)); ++ goto out; ++ } ++ ++ if (thr_ret != NULL && thr_ret != PTHREAD_CANCELED) ++ { ++ ret = 1; ++ goto out; ++ } ++ } ++ ++ /* The signalling thread could have ended before it was cancelled. */ ++ pthread_cancel (s); ++ ++ if ((ret = pthread_join (s, &thr_ret)) != 0) ++ { ++ printf ("signaller: join failed: %s\n", strerror (ret)); ++ goto out; ++ } ++ ++ if (thr_ret != NULL && thr_ret != PTHREAD_CANCELED) ++ { ++ ret = 1; ++ goto out; ++ } ++ } ++ ++out: ++ return ret; ++} ++ ++int ++do_test (int argc, char **argv) ++{ ++ int ret = do_test_wait (waiter); ++ ++ if (ret) ++ return ret; ++ ++ return do_test_wait (timed_waiter); ++} ++ ++#define TIMEOUT 5 ++#include "../test-skeleton.c" +diff -pruN glibc-2.12-2-gc4ccff1/nptl/tst-cond-except.c glibc-2.12-2-gc4ccff1.fixed/nptl/tst-cond-except.c +--- glibc-2.12-2-gc4ccff1/nptl/tst-cond-except.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.12-2-gc4ccff1.fixed/nptl/tst-cond-except.c 2013-07-09 10:19:01.334420002 +0530 +@@ -0,0 +1,110 @@ ++/* Verify that exception table for pthread_cond_wait is correct. ++ Copyright (C) 2012-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 ++ http://www.gnu.org/licenses/. */ ++ ++#include <pthread.h> ++#include <stdio.h> ++#include <stdint.h> ++#include <string.h> ++#include <unistd.h> ++ ++pthread_mutex_t mutex; ++pthread_cond_t cond; ++ ++#define CHECK_RETURN_VAL_OR_FAIL(ret,str) \ ++ ({ if ((ret) != 0) \ ++ { \ ++ printf ("%s failed: %s\n", (str), strerror (ret)); \ ++ ret = 1; \ ++ goto out; \ ++ } \ ++ }) ++ ++ ++void ++clean (void *arg) ++{ ++ puts ("clean: Unlocking mutex..."); ++ pthread_mutex_unlock ((pthread_mutex_t *) arg); ++ puts ("clean: Mutex unlocked..."); ++} ++ ++void * ++thr (void *arg) ++{ ++ int ret = 0; ++ pthread_mutexattr_t mutexAttr; ++ ret = pthread_mutexattr_init (&mutexAttr); ++ CHECK_RETURN_VAL_OR_FAIL (ret, "pthread_mutexattr_init"); ++ ++ ret = pthread_mutexattr_setprotocol (&mutexAttr, PTHREAD_PRIO_INHERIT); ++ CHECK_RETURN_VAL_OR_FAIL (ret, "pthread_mutexattr_setprotocol"); ++ ++ ret = pthread_mutex_init (&mutex, &mutexAttr); ++ CHECK_RETURN_VAL_OR_FAIL (ret, "pthread_mutex_init"); ++ ++ ret = pthread_cond_init (&cond, 0); ++ CHECK_RETURN_VAL_OR_FAIL (ret, "pthread_cond_init"); ++ ++ puts ("th: Init done, entering wait..."); ++ ++ pthread_cleanup_push (clean, (void *) &mutex); ++ ret = pthread_mutex_lock (&mutex); ++ CHECK_RETURN_VAL_OR_FAIL (ret, "pthread_mutex_lock"); ++ while (1) ++ { ++ ret = pthread_cond_wait (&cond, &mutex); ++ CHECK_RETURN_VAL_OR_FAIL (ret, "pthread_cond_wait"); ++ } ++ pthread_cleanup_pop (1); ++ ++out: ++ return (void *) (uintptr_t) ret; ++} ++ ++int ++do_test (void) ++{ ++ pthread_t thread; ++ int ret = 0; ++ void *thr_ret = 0; ++ ret = pthread_create (&thread, 0, thr, &thr_ret); ++ CHECK_RETURN_VAL_OR_FAIL (ret, "pthread_create"); ++ ++ puts ("main: Thread created, waiting a bit..."); ++ sleep (2); ++ ++ puts ("main: Cancelling thread..."); ++ ret = pthread_cancel (thread); ++ CHECK_RETURN_VAL_OR_FAIL (ret, "pthread_cancel"); ++ ++ puts ("main: Joining th..."); ++ ret = pthread_join (thread, NULL); ++ CHECK_RETURN_VAL_OR_FAIL (ret, "pthread_join"); ++ ++ if (thr_ret != NULL) ++ return 1; ++ ++ puts ("main: Joined thread, done!"); ++ ++out: ++ return ret; ++} ++ ++#define TEST_FUNCTION do_test () ++#define TIMEOUT 5 ++#include "../test-skeleton.c" diff --git a/src/patches/glibc/glibc-rh629823-2.patch b/src/patches/glibc/glibc-rh629823-2.patch new file mode 100644 index 0000000..d3e4f45 --- /dev/null +++ b/src/patches/glibc/glibc-rh629823-2.patch @@ -0,0 +1,95 @@ +commit 50fd745b4dec07e8e213cf2703b5cabcfa128225 +Author: Andreas Schwab schwab@suse.de +Date: Mon Jun 10 14:39:09 2013 +0200 + + Fix handling of netgroup cache in nscd + +diff --git a/nscd/connections.c b/nscd/connections.c +index 7099215..69e3e7d 100644 +--- a/nscd/connections.c ++++ b/nscd/connections.c +@@ -1779,7 +1779,7 @@ nscd_run_worker (void *p) + else + { + /* Get the key. */ +- char keybuf[MAXKEYLEN]; ++ char keybuf[MAXKEYLEN + 1]; + + if (__builtin_expect (TEMP_FAILURE_RETRY (read (fd, keybuf, + req.key_len)) +@@ -1791,6 +1791,7 @@ nscd_run_worker (void *p) + strerror_r (errno, buf, sizeof (buf))); + goto close_and_out; + } ++ keybuf[req.key_len] = '\0'; + + if (__builtin_expect (debug_level, 0) > 0) + { +diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c +index 2d6c5aa..dd06ce4 100644 +--- a/nscd/netgroupcache.c ++++ b/nscd/netgroupcache.c +@@ -192,18 +192,26 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, + const char *nuser = data.val.triple.user; + const char *ndomain = data.val.triple.domain; + +- if (data.val.triple.host > data.val.triple.user +- || data.val.triple.user > data.val.triple.domain) ++ if (nhost == NULL || nuser == NULL || ndomain == NULL ++ || nhost > nuser || nuser > ndomain) + { +- const char *last = MAX (nhost, +- MAX (nuser, ndomain)); +- size_t bufused = (last + strlen (last) + 1 +- - buffer); ++ const char *last = nhost; ++ if (last == NULL ++ || (nuser != NULL && nuser > last)) ++ last = nuser; ++ if (last == NULL ++ || (ndomain != NULL && ndomain > last)) ++ last = ndomain; ++ ++ size_t bufused ++ = (last == NULL ++ ? buffilled ++ : last + strlen (last) + 1 - buffer); + + /* We have to make temporary copies. */ +- size_t hostlen = strlen (nhost) + 1; +- size_t userlen = strlen (nuser) + 1; +- size_t domainlen = strlen (ndomain) + 1; ++ size_t hostlen = strlen (nhost ?: "") + 1; ++ size_t userlen = strlen (nuser ?: "") + 1; ++ size_t domainlen = strlen (ndomain ?: "") + 1; + size_t needed = hostlen + userlen + domainlen; + + if (buflen - req->key_len - bufused < needed) +@@ -226,11 +234,11 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, + } + + nhost = memcpy (buffer + bufused, +- nhost, hostlen); ++ nhost ?: "", hostlen); + nuser = memcpy ((char *) nhost + hostlen, +- nuser, userlen); ++ nuser ?: "", userlen); + ndomain = memcpy ((char *) nuser + userlen, +- ndomain, domainlen); ++ ndomain ?: "", domainlen); + } + + char *wp = buffer + buffilled; +diff --git a/nscd/nscd_netgroup.c b/nscd/nscd_netgroup.c +index cac4ebf..acb2c81 100644 +--- a/nscd/nscd_netgroup.c ++++ b/nscd/nscd_netgroup.c +@@ -48,7 +48,7 @@ __nscd_setnetgrent (const char *group, struct __netgrent *datap) + { + int gc_cycle; + int nretries = 0; +- size_t group_len = strlen (group); ++ size_t group_len = strlen (group) + 1; + + /* If the mapping is available, try to search there instead of + communicating with the nscd. */ diff --git a/src/patches/glibc/glibc-rh629823.patch b/src/patches/glibc/glibc-rh629823.patch new file mode 100644 index 0000000..6315246 --- /dev/null +++ b/src/patches/glibc/glibc-rh629823.patch @@ -0,0 +1,1954 @@ +diff -Nrup a/grp/initgroups.c b/grp/initgroups.c +--- a/grp/initgroups.c 2012-08-06 15:07:48.935060494 -0600 ++++ b/grp/initgroups.c 2012-08-23 14:19:49.370442142 -0600 +@@ -1,4 +1,4 @@ +-/* Copyright (C) 1989,91,93,1996-2005,2006,2008 Free Software Foundation, Inc. ++/* Copyright (C) 1989,91,93,1996-2006,2008,2010 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 +@@ -58,7 +58,8 @@ internal_getgrouplist (const char *user, + if (__nss_not_use_nscd_group > 0 + && ++__nss_not_use_nscd_group > NSS_NSCD_RETRY) + __nss_not_use_nscd_group = 0; +- if (!__nss_not_use_nscd_group) ++ if (!__nss_not_use_nscd_group ++ && !__nss_database_custom[NSS_DBSIDX_group]) + { + int n = __nscd_getgrouplist (user, group, size, groupsp, limit); + if (n >= 0) +diff -Nrup a/inet/getnetgrent_r.c b/inet/getnetgrent_r.c +--- a/inet/getnetgrent_r.c 2010-05-04 05:27:23.000000000 -0600 ++++ b/inet/getnetgrent_r.c 2012-08-06 15:10:05.865520055 -0600 +@@ -28,6 +28,7 @@ + #include "netgroup.h" + #include "nsswitch.h" + #include <sysdep.h> ++#include <nscd/nscd_proto.h> + + + /* Protect above variable against multiple uses at the same time. */ +@@ -101,7 +102,7 @@ endnetgrent_hook (struct __netgrent *dat + { + enum nss_status (*endfct) (struct __netgrent *); + +- if (datap->nip == NULL) ++ if (datap->nip == NULL || datap->nip == (service_user *) -1l) + return; + + endfct = __nss_lookup_function (datap->nip, "endnetgrent"); +@@ -189,8 +190,21 @@ setnetgrent (const char *group) + + __libc_lock_lock (lock); + ++ if (__nss_not_use_nscd_netgroup > 0 ++ && ++__nss_not_use_nscd_netgroup > NSS_NSCD_RETRY) ++ __nss_not_use_nscd_netgroup = 0; ++ ++ if (!__nss_not_use_nscd_netgroup ++ && !__nss_database_custom[NSS_DBSIDX_netgroup]) ++ { ++ result = __nscd_setnetgrent (group, &dataset); ++ if (result >= 0) ++ goto out; ++ } ++ + result = internal_setnetgrent (group, &dataset); + ++ out: + __libc_lock_unlock (lock); + + return result; +@@ -226,6 +240,26 @@ int internal_getnetgrent_r (char **hostp + char *buffer, size_t buflen, int *errnop); + libc_hidden_proto (internal_getnetgrent_r) + ++ ++static enum nss_status ++nscd_getnetgrent (struct __netgrent *datap, char *buffer, size_t buflen, ++ int *errnop) ++{ ++ if (datap->cursor >= datap->data + datap->data_size) ++ return NSS_STATUS_UNAVAIL; ++ ++ datap->type = triple_val; ++ datap->val.triple.host = datap->cursor; ++ datap->cursor = (char *) __rawmemchr (datap->cursor, '\0') + 1; ++ datap->val.triple.user = datap->cursor; ++ datap->cursor = (char *) __rawmemchr (datap->cursor, '\0') + 1; ++ datap->val.triple.domain = datap->cursor; ++ datap->cursor = (char *) __rawmemchr (datap->cursor, '\0') + 1; ++ ++ return NSS_STATUS_SUCCESS; ++} ++ ++ + int + internal_getnetgrent_r (char **hostp, char **userp, char **domainp, + struct __netgrent *datap, +@@ -239,9 +273,18 @@ internal_getnetgrent_r (char **hostp, ch + /* Run through available functions, starting with the same function last + run. We will repeat each function as long as it succeeds, and then go + on to the next service action. */ +- int no_more = (datap->nip == NULL +- || (fct = __nss_lookup_function (datap->nip, "getnetgrent_r")) +- == NULL); ++ int no_more = datap->nip == NULL; ++ if (! no_more) ++ { ++ if (datap->nip == (service_user *) -1l) ++ fct = nscd_getnetgrent; ++ else ++ { ++ fct = __nss_lookup_function (datap->nip, "getnetgrent_r"); ++ no_more = fct == NULL; ++ } ++ } ++ + while (! no_more) + { + status = (*fct) (datap, buffer, buflen, &errno); +@@ -337,6 +380,18 @@ int + innetgr (const char *netgroup, const char *host, const char *user, + const char *domain) + { ++ if (__nss_not_use_nscd_netgroup > 0 ++ && ++__nss_not_use_nscd_netgroup > NSS_NSCD_RETRY) ++ __nss_not_use_nscd_netgroup = 0; ++ ++ if (!__nss_not_use_nscd_netgroup ++ && !__nss_database_custom[NSS_DBSIDX_netgroup]) ++ { ++ int result = __nscd_innetgr (netgroup, host, user, domain); ++ if (result >= 0) ++ return result; ++ } ++ + union + { + int (*f) (const char *, struct __netgrent *); +@@ -444,7 +499,7 @@ innetgr (const char *netgroup, const cha + entry.needed_groups = tmp->next; + tmp->next = entry.known_groups; + entry.known_groups = tmp; +- current_group = entry.known_groups->name; ++ current_group = tmp->name; + continue; + } + +diff -Nrup a/nscd/Makefile b/nscd/Makefile +--- a/nscd/Makefile 2010-05-04 05:27:23.000000000 -0600 ++++ b/nscd/Makefile 2012-08-06 15:08:19.045941627 -0600 +@@ -22,7 +22,7 @@ + subdir := nscd + + routines := nscd_getpw_r nscd_getgr_r nscd_gethst_r nscd_getai \ +- nscd_initgroups nscd_getserv_r ++ nscd_initgroups nscd_getserv_r nscd_netgroup + aux := nscd_helper + + include ../Makeconfig +@@ -34,7 +34,8 @@ nscd-modules := nscd connections pwdcach + getgrnam_r getgrgid_r hstcache gethstbyad_r gethstbynm3_r \ + getsrvbynm_r getsrvbypt_r servicescache \ + dbg_log nscd_conf nscd_stat cache mem nscd_setup_thread \ +- xmalloc xstrdup aicache initgrcache gai res_hconf ++ xmalloc xstrdup aicache initgrcache gai res_hconf \ ++ netgroupcache + + ifeq ($(have-thread-library),yes) + +@@ -122,6 +123,7 @@ CFLAGS-servicescache.c += $(nscd-cflags) + CFLAGS-getsrvbynm_r.c += $(nscd-cflags) + CFLAGS-getsrvbypt_r.c += $(nscd-cflags) + CFLAGS-res_hconf.c += $(nscd-cflags) ++CFLAGS-netgroupcache.c += $(nscd-cflags) + + ifeq (yesyes,$(have-fpie)$(build-shared)) + relro-LDFLAGS += -Wl,-z,now +diff -Nrup a/nscd/cache.c b/nscd/cache.c +--- a/nscd/cache.c 2012-08-06 15:07:48.973060344 -0600 ++++ b/nscd/cache.c 2012-08-06 15:08:19.046941626 -0600 +@@ -60,7 +60,9 @@ static time_t (*const readdfcts[LASTREQ] + [GETAI] = readdhstai, + [INITGROUPS] = readdinitgroups, + [GETSERVBYNAME] = readdservbyname, +- [GETSERVBYPORT] = readdservbyport ++ [GETSERVBYPORT] = readdservbyport, ++ [GETNETGRENT] = readdgetnetgrent, ++ [INNETGR] = readdinnetgr + }; + + +@@ -70,7 +72,7 @@ static time_t (*const readdfcts[LASTREQ] + + This function must be called with the read-lock held. */ + struct datahead * +-cache_search (request_type type, void *key, size_t len, ++cache_search (request_type type, const void *key, size_t len, + struct database_dyn *table, uid_t owner) + { + unsigned long int hash = __nis_hash (key, len) % table->head->module; +diff -Nrup a/nscd/connections.c b/nscd/connections.c +--- a/nscd/connections.c 2012-08-06 15:07:49.076059937 -0600 ++++ b/nscd/connections.c 2012-08-21 21:36:10.210358578 -0600 +@@ -57,11 +57,6 @@ + #endif + + +-/* Wrapper functions with error checking for standard functions. */ +-extern void *xmalloc (size_t n); +-extern void *xcalloc (size_t n, size_t s); +-extern void *xrealloc (void *o, size_t n); +- + /* Support to run nscd as an unprivileged user */ + const char *server_user; + static uid_t server_uid; +@@ -100,7 +95,10 @@ const char *const serv2str[LASTREQ] = + [INITGROUPS] = "INITGROUPS", + [GETSERVBYNAME] = "GETSERVBYNAME", + [GETSERVBYPORT] = "GETSERVBYPORT", +- [GETFDSERV] = "GETFDSERV" ++ [GETFDSERV] = "GETFDSERV", ++ [GETNETGRENT] = "GETNETGRENT", ++ [INNETGR] = "INNETGR", ++ [GETFDNETGR] = "GETFDNETGR" + }; + + /* The control data structures for the services. */ +@@ -189,6 +187,27 @@ struct database_dyn dbs[lastdb] = + .wr_fd = -1, + .ro_fd = -1, + .mmap_used = false ++ }, ++ [netgrdb] = { ++ .lock = PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP, ++ .prune_lock = PTHREAD_MUTEX_INITIALIZER, ++ .prune_run_lock = PTHREAD_MUTEX_INITIALIZER, ++ .enabled = 0, ++ .check_file = 1, ++ .persistent = 0, ++ .propagate = 0, /* Not used. */ ++ .shared = 0, ++ .max_db_size = DEFAULT_MAX_DB_SIZE, ++ .suggested_module = DEFAULT_SUGGESTED_MODULE, ++ .reset_res = 0, ++ .filename = "/etc/netgroup", ++ .db_filename = _PATH_NSCD_NETGROUP_DB, ++ .disabled_iov = &netgroup_iov_disabled, ++ .postimeout = 28800, ++ .negtimeout = 20, ++ .wr_fd = -1, ++ .ro_fd = -1, ++ .mmap_used = false + } + }; + +@@ -218,7 +237,10 @@ static struct + [INITGROUPS] = { true, &dbs[grpdb] }, + [GETSERVBYNAME] = { true, &dbs[servdb] }, + [GETSERVBYPORT] = { true, &dbs[servdb] }, +- [GETFDSERV] = { false, &dbs[servdb] } ++ [GETFDSERV] = { false, &dbs[servdb] }, ++ [GETNETGRENT] = { true, &dbs[netgrdb] }, ++ [INNETGR] = { true, &dbs[netgrdb] }, ++ [GETFDNETGR] = { false, &dbs[netgrdb] } + }; + + +@@ -366,7 +388,8 @@ check_use (const char *data, nscd_ssize_ + static int + verify_persistent_db (void *mem, struct database_pers_head *readhead, int dbnr) + { +- assert (dbnr == pwddb || dbnr == grpdb || dbnr == hstdb || dbnr == servdb); ++ assert (dbnr == pwddb || dbnr == grpdb || dbnr == hstdb || dbnr == servdb ++ || dbnr == netgrdb); + + time_t now = time (NULL); + +@@ -1241,6 +1264,14 @@ request from '%s' [%ld] not handled due + addservbyport (db, fd, req, key, uid); + break; + ++ case GETNETGRENT: ++ addgetnetgrent (db, fd, req, key, uid); ++ break; ++ ++ case INNETGR: ++ addinnetgr (db, fd, req, key, uid); ++ break; ++ + case GETSTAT: + case SHUTDOWN: + case INVALIDATE: +@@ -1287,6 +1318,7 @@ request from '%s' [%ld] not handled due + case GETFDGR: + case GETFDHST: + case GETFDSERV: ++ case GETFDNETGR: + #ifdef SCM_RIGHTS + send_ro_fd (reqinfo[req->type].db, key, fd); + #endif +diff -Nrup a/nscd/netgroupcache.c b/nscd/netgroupcache.c +--- a/nscd/netgroupcache.c 1969-12-31 17:00:00.000000000 -0700 ++++ b/nscd/netgroupcache.c 2012-08-24 11:38:05.118254176 -0600 +@@ -0,0 +1,667 @@ ++/* Cache handling for netgroup lookup. ++ Copyright (C) 2011 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ Contributed by Ulrich Drepper drepper@gmail.com, 2011. ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published ++ by the Free Software Foundation; version 2 of the License, or ++ (at your option) any later version. ++ ++ This program 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 General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software Foundation, ++ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ ++ ++#include <alloca.h> ++#include <assert.h> ++#include <errno.h> ++#include <libintl.h> ++#include <stdbool.h> ++#include <unistd.h> ++#include <sys/mman.h> ++ ++#include "../inet/netgroup.h" ++#include "nscd.h" ++#include "dbg_log.h" ++#ifdef HAVE_SENDFILE ++# include <kernel-features.h> ++#endif ++ ++ ++/* This is the standard reply in case the service is disabled. */ ++static const netgroup_response_header disabled = ++{ ++ .version = NSCD_VERSION, ++ .found = -1, ++ .nresults = 0, ++ .result_len = 0 ++}; ++ ++/* This is the struct describing how to write this record. */ ++const struct iovec netgroup_iov_disabled = ++{ ++ .iov_base = (void *) &disabled, ++ .iov_len = sizeof (disabled) ++}; ++ ++ ++/* This is the standard reply in case we haven't found the dataset. */ ++static const netgroup_response_header notfound = ++{ ++ .version = NSCD_VERSION, ++ .found = 0, ++ .nresults = 0, ++ .result_len = 0 ++}; ++ ++ ++struct dataset ++{ ++ struct datahead head; ++ netgroup_response_header resp; ++ char strdata[0]; ++}; ++ ++ ++static time_t ++addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, ++ const char *key, uid_t uid, struct hashentry *he, ++ struct datahead *dh, struct dataset **resultp) ++{ ++ if (__builtin_expect (debug_level > 0, 0)) ++ { ++ if (he == NULL) ++ dbg_log (_("Haven't found "%s" in netgroup cache!"), key); ++ else ++ dbg_log (_("Reloading "%s" in netgroup cache!"), key); ++ } ++ ++ static service_user *netgroup_database; ++ time_t timeout; ++ struct dataset *dataset; ++ bool cacheable = false; ++ ssize_t total; ++ ++ char *key_copy = NULL; ++ struct __netgrent data; ++ size_t buflen = MAX (1024, sizeof (*dataset) + req->key_len); ++ size_t buffilled = sizeof (*dataset); ++ char *buffer = NULL; ++ size_t nentries = 0; ++ bool use_malloc = false; ++ size_t group_len = strlen (key) + 1; ++ union ++ { ++ struct name_list elem; ++ char mem[sizeof (struct name_list) + group_len]; ++ } first_needed; ++ ++ if (netgroup_database == NULL ++ && __nss_database_lookup ("netgroup", NULL, NULL, &netgroup_database)) ++ { ++ /* No such service. */ ++ total = sizeof (notfound); ++ timeout = time (NULL) + db->negtimeout; ++ ++ if (fd != -1) ++ TEMP_FAILURE_RETRY (send (fd, ¬found, total, MSG_NOSIGNAL)); ++ ++ dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len, 1); ++ /* If we cannot permanently store the result, so be it. */ ++ if (dataset != NULL) ++ { ++ dataset->head.allocsize = sizeof (struct dataset) + req->key_len; ++ dataset->head.recsize = total; ++ dataset->head.notfound = true; ++ dataset->head.nreloads = 0; ++ dataset->head.usable = true; ++ ++ /* Compute the timeout time. */ ++ timeout = dataset->head.timeout = time (NULL) + db->negtimeout; ++ dataset->head.ttl = db->negtimeout; ++ ++ /* This is the reply. */ ++ memcpy (&dataset->resp, ¬found, total); ++ ++ /* Copy the key data. */ ++ memcpy (dataset->strdata, key, req->key_len); ++ ++ cacheable = true; ++ } ++ ++ goto writeout; ++ } ++ ++ memset (&data, '\0', sizeof (data)); ++ buffer = alloca (buflen); ++ first_needed.elem.next = &first_needed.elem; ++ memcpy (first_needed.elem.name, key, group_len); ++ data.needed_groups = &first_needed.elem; ++ ++ while (data.needed_groups != NULL) ++ { ++ /* Add the next group to the list of those which are known. */ ++ struct name_list *this_group = data.needed_groups->next; ++ if (this_group == data.needed_groups) ++ data.needed_groups = NULL; ++ else ++ data.needed_groups->next = this_group->next; ++ this_group->next = data.known_groups; ++ data.known_groups = this_group; ++ ++ union ++ { ++ enum nss_status (*f) (const char *, struct __netgrent *); ++ void *ptr; ++ } setfct; ++ ++ service_user *nip = netgroup_database; ++ int no_more = __nss_lookup (&nip, "setnetgrent", NULL, &setfct.ptr); ++ while (!no_more) ++ { ++ enum nss_status status ++ = DL_CALL_FCT (*setfct.f, (data.known_groups->name, &data)); ++ ++ if (status == NSS_STATUS_SUCCESS) ++ { ++ union ++ { ++ enum nss_status (*f) (struct __netgrent *, char *, size_t, ++ int *); ++ void *ptr; ++ } getfct; ++ getfct.ptr = __nss_lookup_function (nip, "getnetgrent_r"); ++ if (getfct.f != NULL) ++ while (1) ++ { ++ int e; ++ status = getfct.f (&data, buffer + buffilled, ++ buflen - buffilled, &e); ++ if (status == NSS_STATUS_RETURN) ++ /* This was the last one for this group. Look ++ at next group if available. */ ++ break; ++ if (status == NSS_STATUS_SUCCESS) ++ { ++ if (data.type == triple_val) ++ { ++ const char *nhost = data.val.triple.host; ++ const char *nuser = data.val.triple.user; ++ const char *ndomain = data.val.triple.domain; ++ ++ if (data.val.triple.host > data.val.triple.user ++ || data.val.triple.user > data.val.triple.domain) ++ { ++ const char *last = MAX (nhost, ++ MAX (nuser, ndomain)); ++ size_t bufused = (last + strlen (last) + 1 ++ - buffer); ++ ++ /* We have to make temporary copies. */ ++ size_t hostlen = strlen (nhost) + 1; ++ size_t userlen = strlen (nuser) + 1; ++ size_t domainlen = strlen (ndomain) + 1; ++ size_t needed = hostlen + userlen + domainlen; ++ ++ if (buflen - req->key_len - bufused < needed) ++ { ++ size_t newsize = MAX (2 * buflen, ++ buflen + 2 * needed); ++ if (use_malloc || newsize > 1024 * 1024) ++ { ++ buflen = newsize; ++ char *newbuf = xrealloc (use_malloc ++ ? buffer ++ : NULL, ++ buflen); ++ ++ buffer = newbuf; ++ use_malloc = true; ++ } ++ else ++ extend_alloca (buffer, buflen, newsize); ++ } ++ ++ nhost = memcpy (buffer + bufused, ++ nhost, hostlen); ++ nuser = memcpy ((char *) nhost + hostlen, ++ nuser, userlen); ++ ndomain = memcpy ((char *) nuser + userlen, ++ ndomain, domainlen); ++ } ++ ++ char *wp = buffer + buffilled; ++ wp = stpcpy (wp, nhost) + 1; ++ wp = stpcpy (wp, nuser) + 1; ++ wp = stpcpy (wp, ndomain) + 1; ++ buffilled = wp - buffer; ++ ++nentries; ++ } ++ else ++ { ++ /* Check that the group has not been ++ requested before. */ ++ struct name_list *runp = data.needed_groups; ++ if (runp != NULL) ++ while (1) ++ { ++ if (strcmp (runp->name, data.val.group) == 0) ++ break; ++ ++ runp = runp->next; ++ if (runp == data.needed_groups) ++ { ++ runp = NULL; ++ break; ++ } ++ } ++ ++ if (runp == NULL) ++ { ++ runp = data.known_groups; ++ while (runp != NULL) ++ if (strcmp (runp->name, data.val.group) == 0) ++ break; ++ else ++ runp = runp->next; ++ } ++ ++ if (runp == NULL) ++ { ++ /* A new group is requested. */ ++ size_t namelen = strlen (data.val.group) + 1; ++ struct name_list *newg = alloca (sizeof (*newg) ++ + namelen); ++ memcpy (newg->name, data.val.group, namelen); ++ if (data.needed_groups == NULL) ++ data.needed_groups = newg->next = newg; ++ else ++ { ++ newg->next = data.needed_groups->next; ++ data.needed_groups->next = newg; ++ data.needed_groups = newg; ++ } ++ } ++ } ++ } ++ else if (status == NSS_STATUS_UNAVAIL && e == ERANGE) ++ { ++ size_t newsize = 2 * buflen; ++ if (use_malloc || newsize > 1024 * 1024) ++ { ++ buflen = newsize; ++ char *newbuf = xrealloc (use_malloc ++ ? buffer : NULL, buflen); ++ ++ buffer = newbuf; ++ use_malloc = true; ++ } ++ else ++ extend_alloca (buffer, buflen, newsize); ++ } ++ } ++ ++ enum nss_status (*endfct) (struct __netgrent *); ++ endfct = __nss_lookup_function (nip, "endnetgrent"); ++ if (endfct != NULL) ++ (void) DL_CALL_FCT (*endfct, (&data)); ++ ++ break; ++ } ++ ++ no_more = __nss_next2 (&nip, "setnetgrent", NULL, &setfct.ptr, ++ status, 0); ++ } ++ } ++ ++ total = buffilled; ++ ++ /* Fill in the dataset. */ ++ dataset = (struct dataset *) buffer; ++ dataset->head.allocsize = total + req->key_len; ++ dataset->head.recsize = total - offsetof (struct dataset, resp); ++ dataset->head.notfound = false; ++ dataset->head.nreloads = he == NULL ? 0 : (dh->nreloads + 1); ++ dataset->head.usable = true; ++ dataset->head.ttl = db->postimeout; ++ timeout = dataset->head.timeout = time (NULL) + dataset->head.ttl; ++ ++ dataset->resp.version = NSCD_VERSION; ++ dataset->resp.found = 1; ++ dataset->resp.nresults = nentries; ++ dataset->resp.result_len = buffilled - sizeof (*dataset); ++ ++ assert (buflen - buffilled >= req->key_len); ++ key_copy = memcpy (buffer + buffilled, key, req->key_len); ++ buffilled += req->key_len; ++ ++ /* Now we can determine whether on refill we have to create a new ++ record or not. */ ++ if (he != NULL) ++ { ++ assert (fd == -1); ++ ++ if (dataset->head.allocsize == dh->allocsize ++ && dataset->head.recsize == dh->recsize ++ && memcmp (&dataset->resp, dh->data, ++ dh->allocsize - offsetof (struct dataset, resp)) == 0) ++ { ++ /* The data has not changed. We will just bump the timeout ++ value. Note that the new record has been allocated on ++ the stack and need not be freed. */ ++ dh->timeout = dataset->head.timeout; ++ dh->ttl = dataset->head.ttl; ++ ++dh->nreloads; ++ dataset = (struct dataset *) dh; ++ ++ goto out; ++ } ++ } ++ ++ { ++ struct dataset *newp ++ = (struct dataset *) mempool_alloc (db, total + req->key_len, 1); ++ if (__builtin_expect (newp != NULL, 1)) ++ { ++ /* Adjust pointer into the memory block. */ ++ key_copy = (char *) newp + (key_copy - buffer); ++ ++ dataset = memcpy (newp, dataset, total + req->key_len); ++ cacheable = true; ++ ++ if (he != NULL) ++ /* Mark the old record as obsolete. */ ++ dh->usable = false; ++ } ++ } ++ ++ if (he == NULL && fd != -1) ++ { ++ /* We write the dataset before inserting it to the database ++ since while inserting this thread might block and so would ++ unnecessarily let the receiver wait. */ ++ writeout: ++#ifdef HAVE_SENDFILE ++ if (__builtin_expect (db->mmap_used, 1) && cacheable) ++ { ++ assert (db->wr_fd != -1); ++ assert ((char *) &dataset->resp > (char *) db->data); ++ assert ((char *) dataset - (char *) db->head + total ++ <= (sizeof (struct database_pers_head) ++ + db->head->module * sizeof (ref_t) ++ + db->head->data_size)); ++# ifndef __ASSUME_SENDFILE ++ ssize_t written = ++# endif ++ sendfileall (fd, db->wr_fd, (char *) &dataset->resp ++ - (char *) db->head, dataset->head.recsize); ++# ifndef __ASSUME_SENDFILE ++ if (written == -1 && errno == ENOSYS) ++ goto use_write; ++# endif ++ } ++ else ++#endif ++ { ++#if defined HAVE_SENDFILE && !defined __ASSUME_SENDFILE ++ use_write: ++#endif ++ writeall (fd, &dataset->resp, dataset->head.recsize); ++ } ++ } ++ ++ if (cacheable) ++ { ++ /* If necessary, we also propagate the data to disk. */ ++ if (db->persistent) ++ { ++ // XXX async OK? ++ uintptr_t pval = (uintptr_t) dataset & ~pagesize_m1; ++ msync ((void *) pval, ++ ((uintptr_t) dataset & pagesize_m1) + total + req->key_len, ++ MS_ASYNC); ++ } ++ ++ (void) cache_add (req->type, key_copy, req->key_len, &dataset->head, ++ true, db, uid, he == NULL); ++ ++ pthread_rwlock_unlock (&db->lock); ++ ++ /* Mark the old entry as obsolete. */ ++ if (dh != NULL) ++ dh->usable = false; ++ } ++ ++ out: ++ if (use_malloc) ++ free (buffer); ++ ++ *resultp = dataset; ++ ++ return timeout; ++} ++ ++ ++static time_t ++addinnetgrX (struct database_dyn *db, int fd, request_header *req, ++ char *key, uid_t uid, struct hashentry *he, ++ struct datahead *dh) ++{ ++ const char *group = key; ++ key = (char *) rawmemchr (key, '\0') + 1; ++ size_t group_len = key - group - 1; ++ const char *host = *key++ ? key : NULL; ++ if (host != NULL) ++ key = (char *) rawmemchr (key, '\0') + 1; ++ const char *user = *key++ ? key : NULL; ++ if (user != NULL) ++ key = (char *) rawmemchr (key, '\0') + 1; ++ const char *domain = *key++ ? key : NULL; ++ ++ if (__builtin_expect (debug_level > 0, 0)) ++ { ++ if (he == NULL) ++ dbg_log (_("Haven't found "%s (%s,%s,%s)" in netgroup cache!"), ++ group, host ?: "", user ?: "", domain ?: ""); ++ else ++ dbg_log (_("Reloading "%s (%s,%s,%s)" in netgroup cache!"), ++ group, host ?: "", user ?: "", domain ?: ""); ++ } ++ ++ struct dataset *result = (struct dataset *) cache_search (GETNETGRENT, ++ group, group_len, ++ db, uid); ++ time_t timeout; ++ if (result != NULL) ++ timeout = result->head.timeout; ++ else ++ { ++ request_header req_get = ++ { ++ .type = GETNETGRENT, ++ .key_len = group_len ++ }; ++ timeout = addgetnetgrentX (db, -1, &req_get, group, uid, NULL, NULL, ++ &result); ++ } ++ ++ struct indataset ++ { ++ struct datahead head; ++ innetgroup_response_header resp; ++ } *dataset ++ = (struct indataset *) mempool_alloc (db, ++ sizeof (*dataset) + req->key_len, ++ 1); ++ struct indataset dataset_mem; ++ bool cacheable = true; ++ if (__builtin_expect (dataset == NULL, 0)) ++ { ++ cacheable = false; ++ dataset = &dataset_mem; ++ } ++ ++ dataset->head.allocsize = sizeof (*dataset) + req->key_len; ++ dataset->head.recsize = sizeof (innetgroup_response_header); ++ dataset->head.notfound = result->head.notfound; ++ dataset->head.nreloads = he == NULL ? 0 : (dh->nreloads + 1); ++ dataset->head.usable = true; ++ dataset->head.ttl = result->head.ttl; ++ dataset->head.timeout = timeout; ++ ++ dataset->resp.version = NSCD_VERSION; ++ dataset->resp.found = result->resp.found; ++ /* Until we find a matching entry the result is 0. */ ++ dataset->resp.result = 0; ++ ++ char *key_copy = memcpy ((char *) (dataset + 1), group, req->key_len); ++ ++ if (dataset->resp.found) ++ { ++ const char *triplets = (const char *) (&result->resp + 1); ++ ++ for (nscd_ssize_t i = result->resp.nresults; i > 0; --i) ++ { ++ bool success = true; ++ ++ if (host != NULL) ++ success = strcmp (host, triplets) == 0; ++ triplets = (const char *) rawmemchr (triplets, '\0') + 1; ++ ++ if (success && user != NULL) ++ success = strcmp (user, triplets) == 0; ++ triplets = (const char *) rawmemchr (triplets, '\0') + 1; ++ ++ if (success && (domain == NULL || strcmp (domain, triplets) == 0)) ++ { ++ dataset->resp.result = 1; ++ break; ++ } ++ triplets = (const char *) rawmemchr (triplets, '\0') + 1; ++ } ++ } ++ ++ if (he != NULL && dh->data[0].innetgroupdata.result == dataset->resp.result) ++ { ++ /* The data has not changed. We will just bump the timeout ++ value. Note that the new record has been allocated on ++ the stack and need not be freed. */ ++ dh->timeout = timeout; ++ dh->ttl = dataset->head.ttl; ++ ++dh->nreloads; ++ return timeout; ++ } ++ ++ if (he == NULL) ++ { ++ /* We write the dataset before inserting it to the database ++ since while inserting this thread might block and so would ++ unnecessarily let the receiver wait. */ ++ assert (fd != -1); ++ ++#ifdef HAVE_SENDFILE ++ if (__builtin_expect (db->mmap_used, 1) && cacheable) ++ { ++ assert (db->wr_fd != -1); ++ assert ((char *) &dataset->resp > (char *) db->data); ++ assert ((char *) dataset - (char *) db->head + sizeof (*dataset) ++ <= (sizeof (struct database_pers_head) ++ + db->head->module * sizeof (ref_t) ++ + db->head->data_size)); ++# ifndef __ASSUME_SENDFILE ++ ssize_t written = ++# endif ++ sendfileall (fd, db->wr_fd, ++ (char *) &dataset->resp - (char *) db->head, ++ sizeof (innetgroup_response_header)); ++# ifndef __ASSUME_SENDFILE ++ if (written == -1 && errno == ENOSYS) ++ goto use_write; ++# endif ++ } ++ else ++# ifndef __ASSUME_SENDFILE ++ use_write: ++# endif ++#endif ++ writeall (fd, &dataset->resp, sizeof (innetgroup_response_header)); ++ } ++ ++ if (cacheable) ++ { ++ /* If necessary, we also propagate the data to disk. */ ++ if (db->persistent) ++ { ++ // XXX async OK? ++ uintptr_t pval = (uintptr_t) dataset & ~pagesize_m1; ++ msync ((void *) pval, ++ ((uintptr_t) dataset & pagesize_m1) + sizeof (*dataset) ++ + req->key_len, ++ MS_ASYNC); ++ } ++ ++ (void) cache_add (req->type, key_copy, req->key_len, &dataset->head, ++ true, db, uid, he == NULL); ++ ++ pthread_rwlock_unlock (&db->lock); ++ ++ /* Mark the old entry as obsolete. */ ++ if (dh != NULL) ++ dh->usable = false; ++ } ++ ++ return timeout; ++} ++ ++ ++void ++addgetnetgrent (struct database_dyn *db, int fd, request_header *req, ++ void *key, uid_t uid) ++{ ++ struct dataset *ignore; ++ ++ addgetnetgrentX (db, fd, req, key, uid, NULL, NULL, &ignore); ++} ++ ++ ++time_t ++readdgetnetgrent (struct database_dyn *db, struct hashentry *he, ++ struct datahead *dh) ++{ ++ request_header req = ++ { ++ .type = GETNETGRENT, ++ .key_len = he->len ++ }; ++ struct dataset *ignore; ++ ++ return addgetnetgrentX (db, -1, &req, db->data + he->key, he->owner, he, dh, ++ &ignore); ++} ++ ++ ++void ++addinnetgr (struct database_dyn *db, int fd, request_header *req, ++ void *key, uid_t uid) ++{ ++ addinnetgrX (db, fd, req, key, uid, NULL, NULL); ++} ++ ++ ++time_t ++readdinnetgr (struct database_dyn *db, struct hashentry *he, ++ struct datahead *dh) ++{ ++ request_header req = ++ { ++ .type = INNETGR, ++ .key_len = he->len ++ }; ++ ++ return addinnetgrX (db, -1, &req, db->data + he->key, he->owner, he, dh); ++} +diff -Nrup a/nscd/nscd-client.h b/nscd/nscd-client.h +--- a/nscd/nscd-client.h 2012-08-06 15:07:49.082059915 -0600 ++++ b/nscd/nscd-client.h 2012-08-06 15:08:19.090941456 -0600 +@@ -70,6 +70,9 @@ typedef enum + GETSERVBYNAME, + GETSERVBYPORT, + GETFDSERV, ++ GETNETGRENT, ++ INNETGR, ++ GETFDNETGR, + LASTREQ + } request_type; + +@@ -171,6 +174,24 @@ typedef struct + } serv_response_header; + + ++/* Structure send in reply to netgroup query. Note that this struct is ++ sent also if the service is disabled or there is no record found. */ ++typedef struct ++{ ++ int32_t version; ++ int32_t found; ++ nscd_ssize_t nresults; ++ nscd_ssize_t result_len; ++} netgroup_response_header; ++ ++typedef struct ++{ ++ int32_t version; ++ int32_t found; ++ int32_t result; ++} innetgroup_response_header; ++ ++ + /* Type for offsets in data part of database. */ + typedef uint32_t ref_t; + /* Value for invalid/no reference. */ +@@ -210,6 +231,8 @@ struct datahead + ai_response_header aidata; + initgr_response_header initgrdata; + serv_response_header servdata; ++ netgroup_response_header netgroupdata; ++ innetgroup_response_header innetgroupdata; + nscd_ssize_t align1; + nscd_time_t align2; + } data[0]; +diff -Nrup a/nscd/nscd.conf b/nscd/nscd.conf +--- a/nscd/nscd.conf 2012-08-06 15:07:48.553062002 -0600 ++++ b/nscd/nscd.conf 2012-08-06 15:08:19.091941452 -0600 +@@ -77,3 +77,12 @@ + persistent services yes + shared services yes + max-db-size services 33554432 ++ ++ enable-cache netgroup yes ++ positive-time-to-live netgroup 28800 ++ negative-time-to-live netgroup 20 ++ suggested-size netgroup 211 ++ check-files netgroup yes ++ persistent netgroup yes ++ shared netgroup yes ++ max-db-size netgroup 33554432 +diff -Nrup a/nscd/nscd.h b/nscd/nscd.h +--- a/nscd/nscd.h 2012-08-06 15:07:49.085059903 -0600 ++++ b/nscd/nscd.h 2012-08-06 15:08:19.093941443 -0600 +@@ -38,6 +38,7 @@ typedef enum + grpdb, + hstdb, + servdb, ++ netgrdb, + lastdb + } dbtype; + +@@ -107,6 +108,7 @@ struct database_dyn + #define _PATH_NSCD_GROUP_DB "/var/db/nscd/group" + #define _PATH_NSCD_HOSTS_DB "/var/db/nscd/hosts" + #define _PATH_NSCD_SERVICES_DB "/var/db/nscd/services" ++#define _PATH_NSCD_NETGROUP_DB "/var/db/nscd/netgroup" + + /* Path used when not using persistent storage. */ + #define _PATH_NSCD_XYZ_DB_TMP "/var/run/nscd/dbXXXXXX" +@@ -140,6 +142,7 @@ extern const struct iovec pwd_iov_disabl + extern const struct iovec grp_iov_disabled; + extern const struct iovec hst_iov_disabled; + extern const struct iovec serv_iov_disabled; ++extern const struct iovec netgroup_iov_disabled; + + + /* Initial number of threads to run. */ +@@ -185,6 +188,11 @@ extern gid_t old_gid; + + /* Prototypes for global functions. */ + ++/* Wrapper functions with error checking for standard functions. */ ++extern void *xmalloc (size_t n); ++extern void *xcalloc (size_t n, size_t s); ++extern void *xrealloc (void *o, size_t n); ++ + /* nscd.c */ + extern void termination_handler (int signum) __attribute__ ((__noreturn__)); + extern int nscd_open_socket (void); +@@ -203,8 +211,8 @@ extern void send_stats (int fd, struct d + extern int receive_print_stats (void) __attribute__ ((__noreturn__)); + + /* cache.c */ +-extern struct datahead *cache_search (request_type, void *key, size_t len, +- struct database_dyn *table, ++extern struct datahead *cache_search (request_type, const void *key, ++ size_t len, struct database_dyn *table, + uid_t owner); + extern int cache_add (int type, const void *key, size_t len, + struct datahead *packet, bool first, +@@ -273,6 +281,16 @@ extern void addservbyport (struct databa + extern time_t readdservbyport (struct database_dyn *db, struct hashentry *he, + struct datahead *dh); + ++/* netgroupcache.c */ ++extern void addinnetgr (struct database_dyn *db, int fd, request_header *req, ++ void *key, uid_t uid); ++extern time_t readdinnetgr (struct database_dyn *db, struct hashentry *he, ++ struct datahead *dh); ++extern void addgetnetgrent (struct database_dyn *db, int fd, ++ request_header *req, void *key, uid_t uid); ++extern time_t readdgetnetgrent (struct database_dyn *db, struct hashentry *he, ++ struct datahead *dh); ++ + /* mem.c */ + extern void *mempool_alloc (struct database_dyn *db, size_t len, + int data_alloc); +diff -Nrup a/nscd/nscd_conf.c b/nscd/nscd_conf.c +--- a/nscd/nscd_conf.c 2010-05-04 05:27:23.000000000 -0600 ++++ b/nscd/nscd_conf.c 2012-08-06 15:08:19.093941443 -0600 +@@ -43,7 +43,8 @@ const char *const dbnames[lastdb] = + [pwddb] = "passwd", + [grpdb] = "group", + [hstdb] = "hosts", +- [servdb] = "services" ++ [servdb] = "services", ++ [netgrdb] = "netgroup" + }; + + +diff -Nrup a/nscd/nscd_netgroup.c b/nscd/nscd_netgroup.c +--- a/nscd/nscd_netgroup.c 1969-12-31 17:00:00.000000000 -0700 ++++ b/nscd/nscd_netgroup.c 2012-08-06 15:08:19.094941439 -0600 +@@ -0,0 +1,290 @@ ++/* Copyright (C) 2011 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ Contributed by Ulrich Drepper drepper@gmail.com, 2011. ++ ++ 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, write to the Free ++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++ 02111-1307 USA. */ ++ ++#include <alloca.h> ++#include <errno.h> ++#include <stdlib.h> ++#include <string.h> ++#include <not-cancel.h> ++ ++#include "nscd-client.h" ++#include "nscd_proto.h" ++ ++int __nss_not_use_nscd_netgroup; ++ ++ ++libc_locked_map_ptr (static, map_handle); ++/* Note that we only free the structure if necessary. The memory ++ mapping is not removed since it is not visible to the malloc ++ handling. */ ++libc_freeres_fn (pw_map_free) ++{ ++ if (map_handle.mapped != NO_MAPPING) ++ { ++ void *p = map_handle.mapped; ++ map_handle.mapped = NO_MAPPING; ++ free (p); ++ } ++} ++ ++ ++int ++__nscd_setnetgrent (const char *group, struct __netgrent *datap) ++{ ++ int gc_cycle; ++ int nretries = 0; ++ size_t group_len = strlen (group); ++ ++ /* If the mapping is available, try to search there instead of ++ communicating with the nscd. */ ++ struct mapped_database *mapped; ++ mapped = __nscd_get_map_ref (GETFDNETGR, "netgroup", &map_handle, &gc_cycle); ++ ++ retry:; ++ char *respdata = NULL; ++ int retval = -1; ++ netgroup_response_header netgroup_resp; ++ ++ if (mapped != NO_MAPPING) ++ { ++ struct datahead *found = __nscd_cache_search (GETNETGRENT, group, ++ group_len, mapped, ++ sizeof netgroup_resp); ++ if (found != NULL) ++ { ++ respdata = (char *) (&found->data[0].netgroupdata + 1); ++ netgroup_resp = found->data[0].netgroupdata; ++ /* Now check if we can trust pw_resp fields. If GC is ++ in progress, it can contain anything. */ ++ if (mapped->head->gc_cycle != gc_cycle) ++ { ++ retval = -2; ++ goto out; ++ } ++ } ++ } ++ ++ int sock = -1; ++ if (respdata == NULL) ++ { ++ sock = __nscd_open_socket (group, group_len, GETNETGRENT, ++ &netgroup_resp, sizeof (netgroup_resp)); ++ if (sock == -1) ++ { ++ /* nscd not running or wrong version. */ ++ __nss_not_use_nscd_netgroup = 1; ++ goto out; ++ } ++ } ++ ++ if (netgroup_resp.found == 1) ++ { ++ size_t datalen = netgroup_resp.result_len; ++ ++ /* If we do not have to read the data here it comes from the ++ mapped data and does not have to be freed. */ ++ if (respdata == NULL) ++ { ++ /* The data will come via the socket. */ ++ respdata = malloc (datalen); ++ if (respdata == NULL) ++ goto out_close; ++ ++ if ((size_t) __readall (sock, respdata, datalen) != datalen) ++ { ++ free (respdata); ++ goto out_close; ++ } ++ } ++ ++ datap->data = respdata; ++ datap->data_size = datalen; ++ datap->cursor = respdata; ++ datap->first = 1; ++ datap->nip = (service_user *) -1l; ++ datap->known_groups = NULL; ++ datap->needed_groups = NULL; ++ ++ retval = 1; ++ } ++ else ++ { ++ if (__builtin_expect (netgroup_resp.found == -1, 0)) ++ { ++ /* The daemon does not cache this database. */ ++ __nss_not_use_nscd_netgroup = 1; ++ goto out_close; ++ } ++ ++ /* Set errno to 0 to indicate no error, just no found record. */ ++ __set_errno (0); ++ /* Even though we have not found anything, the result is zero. */ ++ retval = 0; ++ } ++ ++ out_close: ++ if (sock != -1) ++ close_not_cancel_no_status (sock); ++ out: ++ if (__nscd_drop_map_ref (mapped, &gc_cycle) != 0) ++ { ++ /* When we come here this means there has been a GC cycle while we ++ were looking for the data. This means the data might have been ++ inconsistent. Retry if possible. */ ++ if ((gc_cycle & 1) != 0 || ++nretries == 5 || retval == -1) ++ { ++ /* nscd is just running gc now. Disable using the mapping. */ ++ if (atomic_decrement_val (&mapped->counter) == 0) ++ __nscd_unmap (mapped); ++ mapped = NO_MAPPING; ++ } ++ ++ if (retval != -1) ++ goto retry; ++ } ++ ++ return retval; ++} ++ ++ ++int ++__nscd_innetgr (const char *netgroup, const char *host, const char *user, ++ const char *domain) ++{ ++ size_t key_len = (strlen (netgroup) + strlen (host ?: "") ++ + strlen (user ?: "") + strlen (domain ?: "") + 7); ++ char *key; ++ bool use_alloca = __libc_use_alloca (key_len); ++ if (use_alloca) ++ key = alloca (key_len); ++ else ++ { ++ key = malloc (key_len); ++ if (key == NULL) ++ return -1; ++ } ++ char *wp = stpcpy (key, netgroup) + 1; ++ if (host != NULL) ++ { ++ *wp++ = '\1'; ++ wp = stpcpy (wp, host) + 1; ++ } ++ else ++ *wp++ = '\0'; ++ if (user != NULL) ++ { ++ *wp++ = '\1'; ++ wp = stpcpy (wp, user) + 1; ++ } ++ else ++ *wp++ = '\0'; ++ if (domain != NULL) ++ { ++ *wp++ = '\1'; ++ wp = stpcpy (wp, domain) + 1; ++ } ++ else ++ *wp++ = '\0'; ++ key_len = wp - key; ++ ++ /* If the mapping is available, try to search there instead of ++ communicating with the nscd. */ ++ int gc_cycle; ++ int nretries = 0; ++ struct mapped_database *mapped; ++ mapped = __nscd_get_map_ref (GETFDNETGR, "netgroup", &map_handle, &gc_cycle); ++ ++ retry:; ++ int retval = -1; ++ innetgroup_response_header innetgroup_resp; ++ int sock = -1; ++ ++ if (mapped != NO_MAPPING) ++ { ++ struct datahead *found = __nscd_cache_search (INNETGR, key, ++ key_len, mapped, ++ sizeof innetgroup_resp); ++ if (found != NULL) ++ { ++ innetgroup_resp = found->data[0].innetgroupdata; ++ /* Now check if we can trust pw_resp fields. If GC is ++ in progress, it can contain anything. */ ++ if (mapped->head->gc_cycle != gc_cycle) ++ { ++ retval = -2; ++ goto out; ++ } ++ ++ goto found_entry; ++ } ++ } ++ ++ sock = __nscd_open_socket (key, key_len, INNETGR, ++ &innetgroup_resp, sizeof (innetgroup_resp)); ++ if (sock == -1) ++ { ++ /* nscd not running or wrong version. */ ++ __nss_not_use_nscd_netgroup = 1; ++ goto out; ++ } ++ ++ found_entry: ++ if (innetgroup_resp.found == 1) ++ retval = innetgroup_resp.result; ++ else ++ { ++ if (__builtin_expect (innetgroup_resp.found == -1, 0)) ++ { ++ /* The daemon does not cache this database. */ ++ __nss_not_use_nscd_netgroup = 1; ++ goto out_close; ++ } ++ ++ /* Set errno to 0 to indicate no error, just no found record. */ ++ __set_errno (0); ++ /* Even though we have not found anything, the result is zero. */ ++ retval = 0; ++ } ++ ++ out_close: ++ if (sock != -1) ++ close_not_cancel_no_status (sock); ++ out: ++ if (__nscd_drop_map_ref (mapped, &gc_cycle) != 0) ++ { ++ /* When we come here this means there has been a GC cycle while we ++ were looking for the data. This means the data might have been ++ inconsistent. Retry if possible. */ ++ if ((gc_cycle & 1) != 0 || ++nretries == 5 || retval == -1) ++ { ++ /* nscd is just running gc now. Disable using the mapping. */ ++ if (atomic_decrement_val (&mapped->counter) == 0) ++ __nscd_unmap (mapped); ++ mapped = NO_MAPPING; ++ } ++ ++ if (retval != -1) ++ goto retry; ++ } ++ ++ if (! use_alloca) ++ free (key); ++ ++ return retval; ++} +diff -Nrup a/nscd/nscd_proto.h b/nscd/nscd_proto.h +--- a/nscd/nscd_proto.h 2010-05-04 05:27:23.000000000 -0600 ++++ b/nscd/nscd_proto.h 2012-08-06 15:14:24.446648305 -0600 +@@ -1,4 +1,4 @@ +-/* Copyright (C) 1998-2000, 2002, 2004, 2007 Free Software Foundation, Inc. ++/* Copyright (C) 1998-2000,2002,2004,2007,2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk kukuk@suse.de, 1998. + +@@ -36,6 +36,7 @@ extern int __nss_not_use_nscd_passwd att + extern int __nss_not_use_nscd_group attribute_hidden; + extern int __nss_not_use_nscd_hosts attribute_hidden; + extern int __nss_not_use_nscd_services attribute_hidden; ++extern int __nss_not_use_nscd_netgroup attribute_hidden; + + extern int __nscd_getpwnam_r (const char *name, struct passwd *resultbuf, + char *buffer, size_t buflen, +@@ -71,5 +72,9 @@ extern int __nscd_getservbyname_r (const + extern int __nscd_getservbyport_r (int port, const char *proto, + struct servent *result_buf, char *buf, + size_t buflen, struct servent **result); ++extern int __nscd_innetgr (const char *netgroup, const char *host, ++ const char *user, const char *domain); ++extern int __nscd_setnetgrent (const char *group, struct __netgrent *datap); ++ + + #endif /* _NSCD_PROTO_H */ +diff -Nrup a/nscd/selinux.c b/nscd/selinux.c +--- a/nscd/selinux.c 2010-05-04 05:27:23.000000000 -0600 ++++ b/nscd/selinux.c 2012-08-06 15:08:19.096941431 -0600 +@@ -1,5 +1,5 @@ + /* SELinux access controls for nscd. +- Copyright (C) 2004, 2005, 2006, 2007, 2009 Free Software Foundation, Inc. ++ Copyright (C) 2004,2005,2006,2007,2009,2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Matthew Rickard mjricka@epoch.ncsc.mil, 2004. + +@@ -46,7 +46,7 @@ + int selinux_enabled; + + /* Define mappings of access vector permissions to request types. */ +-static const int perms[LASTREQ] = ++static const access_vector_t perms[LASTREQ] = + { + [GETPWBYNAME] = NSCD__GETPWD, + [GETPWBYUID] = NSCD__GETPWD, +@@ -69,6 +69,11 @@ static const int perms[LASTREQ] = + [GETSERVBYPORT] = NSCD__GETSERV, + [GETFDSERV] = NSCD__SHMEMSERV, + #endif ++#ifdef NSCD__GETNETGRP ++ [GETNETGRENT] = NSCD__GETNETGRP, ++ [INNETGR] = NSCD__GETNETGRP, ++ [GETFDNETGR] = NSCD__SHMEMNETGRP, ++#endif + }; + + /* Store an entry ref to speed AVC decisions. */ +diff -Nrup a/nss/Makefile b/nss/Makefile +--- a/nss/Makefile 2012-08-06 15:07:48.938060482 -0600 ++++ b/nss/Makefile 2012-08-23 14:19:49.382442094 -0600 +@@ -1,4 +1,5 @@ +-# Copyright (C) 1996-1998,2000-2002,2007,2009 Free Software Foundation, Inc. ++# Copyright (C) 1996-1998,2000-2002,2007,2009,2010 ++# 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 +@@ -39,7 +40,7 @@ databases = proto service hosts network + others := getent + install-bin := getent + +-tests = test-netdb ++tests = test-netdb tst-nss-test1 + xtests = bug-erange + + include ../Makeconfig +@@ -85,3 +86,14 @@ endif + # a statically-linked program that hasn't already loaded it. + $(services:%=$(objpfx)libnss_%.so): $(common-objpfx)libc.so \ + $(common-objpfx)libc_nonshared.a ++ ++ ++distribute += nss_test1.c ++ ++CFLAGS-nss_test1.c = -DNOT_IN_libc=1 ++$(objpfx)/libnss_test1.so: $(objpfx)nss_test1.os $(common-objpfx)libc.so \ ++ $(common-objpfx)libc_nonshared.a ++ $(build-module) ++$(objpfx)/libnss_test1.so$(libnss_test1.so-version): $(objpfx)/libnss_test1.so ++ $(make-link) ++$(objpfx)tst-nss-test1.out: $(objpfx)/libnss_test1.so$(libnss_test1.so-version) +diff -Nrup a/nss/Versions b/nss/Versions +--- a/nss/Versions 2012-08-06 15:07:48.939060479 -0600 ++++ b/nss/Versions 2012-08-06 15:08:19.096941431 -0600 +@@ -12,7 +12,7 @@ libc { + __nss_disable_nscd; __nss_lookup_function; _nss_files_parse_sgent; + + __nss_passwd_lookup2; __nss_group_lookup2; __nss_hosts_lookup2; +- __nss_services_lookup2; __nss_next2; ++ __nss_services_lookup2; __nss_next2; __nss_lookup; + } + } + +diff -Nrup a/nss/getXXbyYY_r.c b/nss/getXXbyYY_r.c +--- a/nss/getXXbyYY_r.c 2010-05-04 05:27:23.000000000 -0600 ++++ b/nss/getXXbyYY_r.c 2012-08-23 14:19:49.403442011 -0600 +@@ -1,4 +1,4 @@ +-/* Copyright (C) 1996-2004, 2006, 2007, 2009 Free Software Foundation, Inc. ++/* Copyright (C) 1996-2004,2006,2007,2009,2010 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper drepper@cygnus.com, 1996. + +@@ -87,6 +87,8 @@ + # define NOT_USENSCD_NAME ADD_NOT_NSCDUSE (DATABASE_NAME) + # define ADD_NOT_NSCDUSE(name) ADD_NOT_NSCDUSE1 (name) + # define ADD_NOT_NSCDUSE1(name) __nss_not_use_nscd_##name ++# define CONCAT2(arg1, arg2) CONCAT2_2 (arg1, arg2) ++# define CONCAT2_2(arg1, arg2) arg1##arg2 + #endif + + #define FUNCTION_NAME_STRING STRINGIZE (FUNCTION_NAME) +@@ -186,7 +188,8 @@ INTERNAL (REENTRANT_NAME) (ADD_PARAMS, L + if (NOT_USENSCD_NAME > 0 && ++NOT_USENSCD_NAME > NSS_NSCD_RETRY) + NOT_USENSCD_NAME = 0; + +- if (!NOT_USENSCD_NAME) ++ if (!NOT_USENSCD_NAME ++ && !__nss_database_custom[CONCAT2 (NSS_DBSIDX_, DATABASE_NAME)]) + { + nscd_status = NSCD_NAME (ADD_VARIABLES, resbuf, buffer, buflen, result + H_ERRNO_VAR); +diff -Nrup a/nss/getent.c b/nss/getent.c +--- a/nss/getent.c 2010-05-04 05:27:23.000000000 -0600 ++++ b/nss/getent.c 2012-08-06 15:15:06.479427609 -0600 +@@ -466,7 +466,6 @@ static int + netgroup_keys (int number, char *key[]) + { + int result = 0; +- int i; + + if (number == 0) + { +@@ -474,18 +473,28 @@ netgroup_keys (int number, char *key[]) + return 3; + } + +- for (i = 0; i < number; ++i) ++ if (number == 4) + { +- if (!setnetgrent (key[i])) ++ char *host = strcmp (key[1], "*") == 0 ? NULL : key[1]; ++ char *user = strcmp (key[2], "*") == 0 ? NULL : key[2]; ++ char *domain = strcmp (key[3], "*") == 0 ? NULL : key[3]; ++ ++ printf ("%-21s (%s,%s,%s) = %d\n", ++ key[0], host ?: "", user ?: "", domain ?: "", ++ innetgr (key[0], host, user, domain)); ++ } ++ else if (number == 1) ++ { ++ if (!setnetgrent (key[0])) + result = 2; + else + { + char *p[3]; + +- printf ("%-21s", key[i]); ++ printf ("%-21s", key[0]); + + while (getnetgrent (p, p + 1, p + 2)) +- printf (" (%s, %s, %s)", p[0] ?: " ", p[1] ?: "", p[2] ?: ""); ++ printf (" (%s,%s,%s)", p[0] ?: " ", p[1] ?: "", p[2] ?: ""); + putchar_unlocked ('\n'); + } + } +diff -Nrup a/nss/nss_files/files-parse.c b/nss/nss_files/files-parse.c +--- a/nss/nss_files/files-parse.c 2010-05-04 05:27:23.000000000 -0600 ++++ b/nss/nss_files/files-parse.c 2012-08-23 14:19:49.418441951 -0600 +@@ -1,5 +1,5 @@ + /* Common code for file-based database parsers in nss_files module. +- Copyright (C) 1996-2000, 2003, 2004, 2009 Free Software Foundation, Inc. ++ Copyright (C) 1996-2000,2003,2004,2009,2010 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 +@@ -29,7 +29,7 @@ + DATABASE -- string of the database file's name ("hosts", "passwd"). + + ENTDATA -- if defined, `struct ENTDATA' is used by the parser to store +- things pointed to by the resultant `struct STRUCTURE'. ++ things pointed to by the resultant `struct STRUCTURE'. + + NEED_H_ERRNO - defined iff an arg `int *herrnop' is used. + +@@ -229,7 +229,7 @@ strtou32 (const char *nptr, char **endpt + char **list = parse_list (&line, buf_start, buf_end, '\0', errnop); \ + if (list) \ + result->TRAILING_LIST_MEMBER = list; \ +- else \ ++ else \ + return -1; /* -1 indicates we ran out of space. */ \ + } + +diff -Nrup a/nss/nss_test1.c b/nss/nss_test1.c +--- a/nss/nss_test1.c 1969-12-31 17:00:00.000000000 -0700 ++++ b/nss/nss_test1.c 2012-08-23 14:19:49.418441951 -0600 +@@ -0,0 +1,154 @@ ++#include <errno.h> ++#include <nss.h> ++#include <pthread.h> ++#include <string.h> ++ ++ ++#define COPY_IF_ROOM(s) \ ++ ({ size_t len_ = strlen (s) + 1; \ ++ char *start_ = cp; \ ++ buflen - (cp - buffer) < len_ \ ++ ? NULL \ ++ : (cp = mempcpy (cp, s, len_), start_); }) ++ ++ ++/* Password handling. */ ++#include <pwd.h> ++ ++static struct passwd pwd_data[] = ++ { ++#define PWD(u) \ ++ { .pw_name = (char *) "name" #u, .pw_passwd = (char *) "*", .pw_uid = u, \ ++ .pw_gid = 100, .pw_gecos = (char *) "*", .pw_dir = (char *) "*", \ ++ .pw_shell = (char *) "*" } ++ PWD (100), ++ PWD (30), ++ PWD (200), ++ PWD (60), ++ PWD (20000) ++ }; ++#define npwd_data (sizeof (pwd_data) / sizeof (pwd_data[0])) ++ ++static size_t pwd_iter; ++#define CURPWD pwd_data[pwd_iter] ++ ++static pthread_mutex_t pwd_lock = PTHREAD_MUTEX_INITIALIZER; ++ ++ ++enum nss_status ++_nss_test1_setpwent (int stayopen) ++{ ++ pwd_iter = 0; ++ return NSS_STATUS_SUCCESS; ++} ++ ++ ++enum nss_status ++_nss_test1_endpwent (void) ++{ ++ return NSS_STATUS_SUCCESS; ++} ++ ++ ++enum nss_status ++_nss_test1_getpwent_r (struct passwd *result, char *buffer, size_t buflen, ++ int *errnop) ++{ ++ char *cp = buffer; ++ int res = NSS_STATUS_SUCCESS; ++ ++ pthread_mutex_lock (&pwd_lock); ++ ++ if (pwd_iter >= npwd_data) ++ res = NSS_STATUS_NOTFOUND; ++ else ++ { ++ result->pw_name = COPY_IF_ROOM (CURPWD.pw_name); ++ result->pw_passwd = COPY_IF_ROOM (CURPWD.pw_passwd); ++ result->pw_uid = CURPWD.pw_uid; ++ result->pw_gid = CURPWD.pw_gid; ++ result->pw_gecos = COPY_IF_ROOM (CURPWD.pw_gecos); ++ result->pw_dir = COPY_IF_ROOM (CURPWD.pw_dir); ++ result->pw_shell = COPY_IF_ROOM (CURPWD.pw_shell); ++ ++ if (result->pw_name == NULL || result->pw_passwd == NULL ++ || result->pw_gecos == NULL || result->pw_dir == NULL ++ || result->pw_shell == NULL) ++ { ++ *errnop = ERANGE; ++ res = NSS_STATUS_TRYAGAIN; ++ } ++ ++ ++pwd_iter; ++ } ++ ++ pthread_mutex_unlock (&pwd_lock); ++ ++ return res; ++} ++ ++ ++enum nss_status ++_nss_test1_getpwuid_r (uid_t uid, struct passwd *result, char *buffer, ++ size_t buflen, int *errnop) ++{ ++ for (size_t idx = 0; idx < npwd_data; ++idx) ++ if (pwd_data[idx].pw_uid == uid) ++ { ++ char *cp = buffer; ++ int res = NSS_STATUS_SUCCESS; ++ ++ result->pw_name = COPY_IF_ROOM (pwd_data[idx].pw_name); ++ result->pw_passwd = COPY_IF_ROOM (pwd_data[idx].pw_passwd); ++ result->pw_uid = pwd_data[idx].pw_uid; ++ result->pw_gid = pwd_data[idx].pw_gid; ++ result->pw_gecos = COPY_IF_ROOM (pwd_data[idx].pw_gecos); ++ result->pw_dir = COPY_IF_ROOM (pwd_data[idx].pw_dir); ++ result->pw_shell = COPY_IF_ROOM (pwd_data[idx].pw_shell); ++ ++ if (result->pw_name == NULL || result->pw_passwd == NULL ++ || result->pw_gecos == NULL || result->pw_dir == NULL ++ || result->pw_shell == NULL) ++ { ++ *errnop = ERANGE; ++ res = NSS_STATUS_TRYAGAIN; ++ } ++ ++ return res; ++ } ++ ++ return NSS_STATUS_NOTFOUND; ++} ++ ++ ++enum nss_status ++_nss_test1_getpwnam_r (const char *name, struct passwd *result, char *buffer, ++ size_t buflen, int *errnop) ++{ ++ for (size_t idx = 0; idx < npwd_data; ++idx) ++ if (strcmp (pwd_data[idx].pw_name, name) == 0) ++ { ++ char *cp = buffer; ++ int res = NSS_STATUS_SUCCESS; ++ ++ result->pw_name = COPY_IF_ROOM (pwd_data[idx].pw_name); ++ result->pw_passwd = COPY_IF_ROOM (pwd_data[idx].pw_passwd); ++ result->pw_uid = pwd_data[idx].pw_uid; ++ result->pw_gid = pwd_data[idx].pw_gid; ++ result->pw_gecos = COPY_IF_ROOM (pwd_data[idx].pw_gecos); ++ result->pw_dir = COPY_IF_ROOM (pwd_data[idx].pw_dir); ++ result->pw_shell = COPY_IF_ROOM (pwd_data[idx].pw_shell); ++ ++ if (result->pw_name == NULL || result->pw_passwd == NULL ++ || result->pw_gecos == NULL || result->pw_dir == NULL ++ || result->pw_shell == NULL) ++ { ++ *errnop = ERANGE; ++ res = NSS_STATUS_TRYAGAIN; ++ } ++ ++ return res; ++ } ++ ++ return NSS_STATUS_NOTFOUND; ++} +diff -Nrup a/nss/nsswitch.c b/nss/nsswitch.c +--- a/nss/nsswitch.c 2010-05-04 05:27:23.000000000 -0600 ++++ b/nss/nsswitch.c 2012-08-23 14:19:49.430441903 -0600 +@@ -1,4 +1,4 @@ +-/* Copyright (C) 1996-1999, 2001-2007, 2009 Free Software Foundation, Inc. ++/* Copyright (C) 1996-1999,2001-2007,2009,2010 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper drepper@cygnus.com, 1996. + +@@ -71,6 +71,9 @@ static const struct + }; + #define ndatabases (sizeof (databases) / sizeof (databases[0])) + ++/* Flags whether custom rules for database is set. */ ++bool __nss_database_custom[NSS_DBSIDX_max]; ++ + + __libc_lock_define_initialized (static, lock) + +@@ -165,6 +168,7 @@ __nss_lookup (service_user **ni, const c + + return *fctp != NULL ? 0 : (*ni)->next == NULL ? 1 : -1; + } ++libc_hidden_def (__nss_lookup) + + + /* -1 == not found +@@ -265,6 +269,7 @@ __nss_configure_lookup (const char *dbna + + /* Install new rules. */ + *databases[cnt].dbp = new_db; ++ __nss_database_custom[cnt] = true; + + __libc_lock_unlock (lock); + +@@ -729,6 +734,7 @@ __nss_disable_nscd (void) + __nss_not_use_nscd_group = -1; + __nss_not_use_nscd_hosts = -1; + __nss_not_use_nscd_services = -1; ++ __nss_not_use_nscd_netgroup = -1; + } + + +diff -Nrup a/nss/nsswitch.h b/nss/nsswitch.h +--- a/nss/nsswitch.h 2010-05-04 05:27:23.000000000 -0600 ++++ b/nss/nsswitch.h 2012-08-23 14:19:49.431441899 -0600 +@@ -1,4 +1,4 @@ +-/* Copyright (C) 1996-1999,2001,2002,2003,2004,2007 ++/* Copyright (C) 1996-1999,2001,2002,2003,2004,2007,2010 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + +@@ -28,6 +28,7 @@ + #include <resolv.h> + #include <search.h> + #include <dlfcn.h> ++#include <stdbool.h> + + /* Actions performed after lookup finished. */ + typedef enum +@@ -96,6 +97,19 @@ typedef struct name_database + } name_database; + + ++/* Indices into DATABASES in nsswitch.c and __NSS_DATABASE_CUSTOM. */ ++enum ++ { ++#define DEFINE_DATABASE(arg) NSS_DBSIDX_##arg, ++#include "databases.def" ++#undef DEFINE_DATABASE ++ NSS_DBSIDX_max ++ }; ++ ++/* Flags whether custom rules for database is set. */ ++extern bool __nss_database_custom[NSS_DBSIDX_max]; ++ ++ + /* Interface functions for NSS. */ + + /* Get the data structure representing the specified database. +@@ -111,7 +125,8 @@ libc_hidden_proto (__nss_database_lookup + position is remembered in NI. The function returns a value < 0 if + an error occurred or no such function exists. */ + extern int __nss_lookup (service_user **ni, const char *fct_name, +- const char *fct2_name, void **fctp) attribute_hidden; ++ const char *fct2_name, void **fctp); ++libc_hidden_proto (__nss_lookup) + + /* Determine the next step in the lookup process according to the + result STATUS of the call to the last function returned by +diff -Nrup a/nss/tst-nss-test1.c b/nss/tst-nss-test1.c +--- a/nss/tst-nss-test1.c 1969-12-31 17:00:00.000000000 -0700 ++++ b/nss/tst-nss-test1.c 2012-08-23 14:19:49.432441895 -0600 +@@ -0,0 +1,72 @@ ++#include <nss.h> ++#include <pwd.h> ++#include <stdio.h> ++#include <stdlib.h> ++#include <string.h> ++ ++ ++static int ++do_test (void) ++{ ++ int retval = 0; ++ ++ __nss_configure_lookup ("passwd", "test1"); ++ ++ static const unsigned int pwdids[] = { 100, 30, 200, 60, 20000 }; ++#define npwdids (sizeof (pwdids) / sizeof (pwdids[0])) ++ setpwent (); ++ ++ const unsigned int *np = pwdids; ++ for (struct passwd *p = getpwent (); p != NULL; ++np, p = getpwent ()) ++ if (p->pw_uid != *np || strncmp (p->pw_name, "name", 4) != 0 ++ || atol (p->pw_name + 4) != *np) ++ { ++ printf ("passwd entry %ju wrong (%s, %u)\n", ++ np - pwdids, p->pw_name, p->pw_uid); ++ retval = 1; ++ break; ++ } ++ ++ endpwent (); ++ ++ for (int i = npwdids - 1; i >= 0; --i) ++ { ++ char buf[30]; ++ snprintf (buf, sizeof (buf), "name%u", pwdids[i]); ++ ++ struct passwd *p = getpwnam (buf); ++ if (p == NULL || p->pw_uid != pwdids[i] || strcmp (buf, p->pw_name) != 0) ++ { ++ printf ("passwd entry "%s" wrong\n", buf); ++ retval = 1; ++ } ++ ++ p = getpwuid (pwdids[i]); ++ if (p == NULL || p->pw_uid != pwdids[i] || strcmp (buf, p->pw_name) != 0) ++ { ++ printf ("passwd entry %u wrong\n", pwdids[i]); ++ retval = 1; ++ } ++ ++ snprintf (buf, sizeof (buf), "name%u", pwdids[i] + 1); ++ ++ p = getpwnam (buf); ++ if (p != NULL) ++ { ++ printf ("passwd entry "%s" wrong\n", buf); ++ retval = 1; ++ } ++ ++ p = getpwuid (pwdids[i] + 1); ++ if (p != NULL) ++ { ++ printf ("passwd entry %u wrong\n", pwdids[i] + 1); ++ retval = 1; ++ } ++ } ++ ++ return retval; ++} ++ ++#define TEST_FUNCTION do_test () ++#include "../test-skeleton.c" +diff -Nrup a/shlib-versions b/shlib-versions +--- a/shlib-versions 2010-05-04 05:27:23.000000000 -0600 ++++ b/shlib-versions 2012-08-23 14:19:49.473441732 -0600 +@@ -114,6 +114,10 @@ alpha.*-.*-linux.* libresolv=2.1 + .*-.*-.* libnss_ldap=2 + .*-.*-.* libnss_hesiod=2 + ++# Tests for NSS. They must have the same NSS_SHLIB_REVISION number as ++# the rest. ++.*-.*-.* libnss_test1=2 ++ + # Version for libnsl with YP and NIS+ functions. + alpha.*-.*-linux.* libnsl=1.1 + .*-.*-.* libnsl=1 +diff -Nrup a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c +--- a/sysdeps/posix/getaddrinfo.c 2012-08-06 15:07:49.571057983 -0600 ++++ b/sysdeps/posix/getaddrinfo.c 2012-08-23 14:19:49.541441461 -0600 +@@ -669,7 +669,8 @@ gaih_inet (const char *name, const struc + && ++__nss_not_use_nscd_hosts > NSS_NSCD_RETRY) + __nss_not_use_nscd_hosts = 0; + +- if (!__nss_not_use_nscd_hosts) ++ if (!__nss_not_use_nscd_hosts ++ && !__nss_database_custom[NSS_DBSIDX_hosts]) + { + /* Try to use nscd. */ + struct nscd_ai_result *air = NULL; diff --git a/src/patches/glibc/glibc-rh663641-2.patch b/src/patches/glibc/glibc-rh663641-2.patch new file mode 100644 index 0000000..13c1bee --- /dev/null +++ b/src/patches/glibc/glibc-rh663641-2.patch @@ -0,0 +1,279 @@ +diff -pruN glibc-2.12-2-gc4ccff1/csu/libc-start.c glibc-2.12-2-gc4ccff1.fixed/csu/libc-start.c +--- glibc-2.12-2-gc4ccff1/csu/libc-start.c 2010-05-04 16:57:23.000000000 +0530 ++++ glibc-2.12-2-gc4ccff1.fixed/csu/libc-start.c 2013-07-09 23:34:59.596859295 +0530 +@@ -33,7 +33,7 @@ extern int __libc_multiple_libcs; + #include <tls.h> + #ifndef SHARED + # include <dl-osinfo.h> +-extern void __pthread_initialize_minimal (void); ++extern void __pthread_initialize_minimal (int, char **, char **); + # ifndef THREAD_SET_STACK_GUARD + /* Only exported for architectures that don't store the stack guard canary + in thread local area. */ +@@ -143,7 +143,7 @@ LIBC_START_MAIN (int (*main) (int, char + /* Initialize the thread library at least a bit since the libgcc + functions are using thread functions if these are available and + we need to setup errno. */ +- __pthread_initialize_minimal (); ++ __pthread_initialize_minimal (argc, argv, __environ); + + /* Set up the stack checker's canary. */ + uintptr_t stack_chk_guard = _dl_setup_stack_chk_guard (_dl_random); +diff -pruN glibc-2.12-2-gc4ccff1/csu/libc-tls.c glibc-2.12-2-gc4ccff1.fixed/csu/libc-tls.c +--- glibc-2.12-2-gc4ccff1/csu/libc-tls.c 2010-05-04 16:57:23.000000000 +0530 ++++ glibc-2.12-2-gc4ccff1.fixed/csu/libc-tls.c 2013-07-09 23:34:59.596859295 +0530 +@@ -244,7 +244,7 @@ _dl_tls_setup (void) + not used. */ + void + __attribute__ ((weak)) +-__pthread_initialize_minimal (void) ++__pthread_initialize_minimal (int argc, char **argv, char **envp) + { + __libc_setup_tls (TLS_INIT_TCB_SIZE, TLS_INIT_TCB_ALIGN); + } +diff -pruN glibc-2.12-2-gc4ccff1/nptl/Makefile glibc-2.12-2-gc4ccff1.fixed/nptl/Makefile +--- glibc-2.12-2-gc4ccff1/nptl/Makefile 2013-07-09 23:35:21.692858252 +0530 ++++ glibc-2.12-2-gc4ccff1.fixed/nptl/Makefile 2013-07-09 23:34:59.597859295 +0530 +@@ -197,7 +197,7 @@ CFLAGS-pt-system.c = -fexceptions + + + tests = tst-typesizes \ +- tst-attr1 tst-attr2 tst-attr3 \ ++ tst-attr1 tst-attr2 tst-attr3 tst-default-attr \ + tst-mutex1 tst-mutex2 tst-mutex3 tst-mutex4 tst-mutex5 tst-mutex6 \ + tst-mutex7 tst-mutex8 tst-mutex9 tst-mutex5a tst-mutex7a \ + tst-mutexpi1 tst-mutexpi2 tst-mutexpi3 tst-mutexpi4 tst-mutexpi5 \ +@@ -279,6 +279,13 @@ LDFLAGS-pthread.so = -Wl,--enable-new-dt + LDFLAGS-tst-cond24 = -lrt + LDFLAGS-tst-cond25 = -lrt + ++# The size is 1MB + 4KB. The extra 4KB has been added to prevent allocatestack ++# from resizing the input size to avoid the 64K aliasing conflict on Intel ++# processors. ++DEFAULT_STACKSIZE=1052672 ++CFLAGS-tst-default-attr.c = -DDEFAULT_STACKSIZE=$(DEFAULT_STACKSIZE) ++tst-default-attr-ENV = GLIBC_PTHREAD_STACKSIZE=$(DEFAULT_STACKSIZE) ++ + include ../Makeconfig + + ifeq ($(have-forced-unwind),yes) +diff -pruN glibc-2.12-2-gc4ccff1/nptl/nptl-init.c glibc-2.12-2-gc4ccff1.fixed/nptl/nptl-init.c +--- glibc-2.12-2-gc4ccff1/nptl/nptl-init.c 2013-07-09 23:35:21.723858250 +0530 ++++ glibc-2.12-2-gc4ccff1.fixed/nptl/nptl-init.c 2013-07-09 23:36:35.070854789 +0530 +@@ -36,6 +36,7 @@ + #include <smp.h> + #include <lowlevellock.h> + #include <kernel-features.h> ++#include <libc-internal.h> + + + /* Size and alignment of static TLS block. */ +@@ -288,8 +289,28 @@ extern void **__libc_dl_error_tsd (void) + /* This can be set by the debugger before initialization is complete. */ + static bool __nptl_initial_report_events __attribute_used__; + ++/* Validate and set the default stacksize. */ ++static void ++set_default_stacksize (size_t stacksize) ++{ ++ if (stacksize < PTHREAD_STACK_MIN) ++ stacksize = PTHREAD_STACK_MIN; ++ ++ /* Make sure it meets the minimum size that allocate_stack ++ (allocatestack.c) will demand, which depends on the page size. */ ++ const uintptr_t pagesz = GLRO(dl_pagesize); ++ const size_t minstack = pagesz + __static_tls_size + MINIMAL_REST_STACK; ++ ++ if (stacksize < minstack) ++ stacksize = minstack; ++ ++ /* Round the resource limit up to page size. */ ++ stacksize = ALIGN_UP (stacksize, pagesz); ++ __default_pthread_attr.stacksize = stacksize; ++} ++ + void +-__pthread_initialize_minimal_internal (void) ++__pthread_initialize_minimal_internal (int argc, char **argv, char **envp) + { + #ifndef SHARED + /* Unlike in the dynamically linked case the dynamic linker has not +@@ -413,29 +434,44 @@ __pthread_initialize_minimal_internal (v + + __static_tls_size = roundup (__static_tls_size, static_tls_align); + +- /* Determine the default allowed stack size. This is the size used +- in case the user does not specify one. */ +- struct rlimit limit; +- if (getrlimit (RLIMIT_STACK, &limit) != 0 +- || limit.rlim_cur == RLIM_INFINITY) +- /* The system limit is not usable. Use an architecture-specific +- default. */ +- limit.rlim_cur = ARCH_STACK_DEFAULT_SIZE; +- else if (limit.rlim_cur < PTHREAD_STACK_MIN) +- /* The system limit is unusably small. +- Use the minimal size acceptable. */ +- limit.rlim_cur = PTHREAD_STACK_MIN; ++ /* Initialize the environment. libc.so gets initialized after us due to a ++ circular dependency and hence __environ is not available otherwise. */ ++ __environ = envp; + +- /* Make sure it meets the minimum size that allocate_stack +- (allocatestack.c) will demand, which depends on the page size. */ +- const uintptr_t pagesz = __sysconf (_SC_PAGESIZE); +- const size_t minstack = pagesz + __static_tls_size + MINIMAL_REST_STACK; +- if (limit.rlim_cur < minstack) +- limit.rlim_cur = minstack; ++#ifndef SHARED ++ __libc_init_secure (); ++#endif + +- /* Round the resource limit up to page size. */ +- limit.rlim_cur = (limit.rlim_cur + pagesz - 1) & -pagesz; +- __default_pthread_attr.stacksize = limit.rlim_cur; ++ /* Get the default stack size from the environment variable if it is set and ++ is valid. */ ++ size_t stacksize = 0; ++ char *envval = __secure_getenv ("GLIBC_PTHREAD_STACKSIZE"); ++ ++ if (__builtin_expect (envval != NULL && envval[0] != '\0', 0)) ++ { ++ char *env_conv = envval; ++ size_t ret = strtoul (envval, &env_conv, 0); ++ ++ if (*env_conv == '\0' && env_conv != envval) ++ stacksize = ret; ++ } ++ ++ if (stacksize == 0) ++ { ++ /* Determine the default allowed stack size. */ ++ struct rlimit limit; ++ if (getrlimit (RLIMIT_STACK, &limit) != 0 ++ || limit.rlim_cur == RLIM_INFINITY) ++ /* The system limit is not usable. Use an architecture-specific ++ default. */ ++ stacksize = ARCH_STACK_DEFAULT_SIZE; ++ else ++ stacksize = limit.rlim_cur; ++ } ++ ++ /* Finally, set the default stack size. This size is used when the user does ++ not specify a stack size during thread creation. */ ++ set_default_stacksize (stacksize); + __default_pthread_attr.guardsize = GLRO (dl_pagesize); + + #ifdef SHARED +diff -pruN glibc-2.12-2-gc4ccff1/nptl/tst-default-attr.c glibc-2.12-2-gc4ccff1.fixed/nptl/tst-default-attr.c +--- glibc-2.12-2-gc4ccff1/nptl/tst-default-attr.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.12-2-gc4ccff1.fixed/nptl/tst-default-attr.c 2013-07-09 23:34:59.598859295 +0530 +@@ -0,0 +1,109 @@ ++/* Verify that default stack size gets set correctly from the environment ++ variable. ++ ++ 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 ++ http://www.gnu.org/licenses/. */ ++ ++#include <pthread.h> ++#include <stdio.h> ++#include <stdint.h> ++#include <string.h> ++#include <unistd.h> ++#include <errno.h> ++ ++#define RETURN_IF_FAIL(f, ...) \ ++ ({ \ ++ int ret = f (__VA_ARGS__); \ ++ if (ret != 0) \ ++ { \ ++ printf ("%s:%d: %s returned %d (errno = %d)\n", __FILE__, __LINE__, \ ++ #f, ret, errno); \ ++ return ret; \ ++ } \ ++ }) ++ ++/* DEFAULT_STACKSIZE macro is defined in the Makefile. */ ++static size_t stacksize = DEFAULT_STACKSIZE; ++ ++static int ++verify_stacksize_result (pthread_attr_t *attr) ++{ ++ size_t stack; ++ ++ RETURN_IF_FAIL (pthread_attr_getstacksize, attr, &stack); ++ ++ if (stacksize != stack) ++ { ++ printf ("failed to set default stacksize (%zu, %zu)\n", stacksize, stack); ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static void * ++thr (void *unused __attribute__ ((unused))) ++{ ++ pthread_attr_t attr; ++ int ret; ++ ++ memset (&attr, 0xab, sizeof attr); ++ /* To verify that the attributes actually got applied. */ ++ if ((ret = pthread_getattr_np (pthread_self (), &attr)) != 0) ++ { ++ printf ("pthread_getattr_np failed: %s\n", strerror (ret)); ++ goto out; ++ } ++ ++ ret = verify_stacksize_result (&attr); ++ ++out: ++ return (void *) (uintptr_t) ret; ++} ++ ++static int ++run_threads (void) ++{ ++ pthread_t t; ++ void *tret = NULL; ++ ++ /* Run twice to ensure that the attributes do not get overwritten in the ++ first run somehow. */ ++ for (int i = 0; i < 2; i++) ++ { ++ RETURN_IF_FAIL (pthread_create, &t, NULL, thr, NULL); ++ RETURN_IF_FAIL (pthread_join, t, &tret); ++ ++ if (tret != NULL) ++ { ++ puts ("Thread failed"); ++ return 1; ++ } ++ } ++ ++ return 0; ++} ++ ++static int ++do_test (void) ++{ ++ RETURN_IF_FAIL (run_threads); ++ return 0; ++} ++ ++#define TEST_FUNCTION do_test () ++#include "../test-skeleton.c" diff --git a/src/patches/glibc/glibc-rh663641-3.patch b/src/patches/glibc/glibc-rh663641-3.patch new file mode 100644 index 0000000..182fe99 --- /dev/null +++ b/src/patches/glibc/glibc-rh663641-3.patch @@ -0,0 +1,31 @@ +diff -pruN glibc-2.12-2-gc4ccff1/nptl/sysdeps/pthread/pt-initfini.c glibc-2.12-2-gc4ccff1.fixed/nptl/sysdeps/pthread/pt-initfini.c +--- glibc-2.12-2-gc4ccff1/nptl/sysdeps/pthread/pt-initfini.c 2010-05-04 16:57:23.000000000 +0530 ++++ glibc-2.12-2-gc4ccff1.fixed/nptl/sysdeps/pthread/pt-initfini.c 2013-07-22 21:52:03.519184065 +0530 +@@ -63,21 +63,21 @@ asm ("\n/*@TESTS_END*/"); + asm ("\n/*@_init_PROLOG_BEGINS*/"); + + static void +-call_initialize_minimal (void) ++call_initialize_minimal (int argc, char **argv, char **envp) + { +- extern void __pthread_initialize_minimal_internal (void) ++ extern void __pthread_initialize_minimal_internal (int, char **, char **) + __attribute ((visibility ("hidden"))); + +- __pthread_initialize_minimal_internal (); ++ __pthread_initialize_minimal_internal (argc, argv, envp); + } + + SECTION (".init"); +-extern void __attribute__ ((section (".init"))) _init (void); ++extern void __attribute__ ((section (".init"))) _init (int, char **, char **); + void +-_init (void) ++_init (int argc, char **argv, char **envp) + { + /* The very first thing we must do is to set up the registers. */ +- call_initialize_minimal (); ++ call_initialize_minimal (argc, argv, envp); + + asm ("ALIGN"); + asm("END_INIT"); diff --git a/src/patches/glibc/glibc-rh663641.patch b/src/patches/glibc/glibc-rh663641.patch new file mode 100644 index 0000000..e1ca4f1 --- /dev/null +++ b/src/patches/glibc/glibc-rh663641.patch @@ -0,0 +1,191 @@ +diff -pruN glibc-2.12-2-gc4ccff1/include/libc-internal.h glibc-2.12-2-gc4ccff1.fixed/include/libc-internal.h +--- glibc-2.12-2-gc4ccff1/include/libc-internal.h 2010-05-04 16:57:23.000000000 +0530 ++++ glibc-2.12-2-gc4ccff1.fixed/include/libc-internal.h 2013-07-09 23:44:00.272833779 +0530 +@@ -34,4 +34,24 @@ extern void __libc_thread_freeres (void) + /* Define and initialize `__progname' et. al. */ + extern void __init_misc (int, char **, char **); + ++/* Align a value by rounding down to closest size. ++ e.g. Using size of 4096, we get this behavior: ++ {4095, 4096, 4097} = {0, 4096, 4096}. */ ++#define ALIGN_DOWN(base, size) ((base) & -((__typeof__ (base)) (size))) ++ ++/* Align a value by rounding up to closest size. ++ e.g. Using size of 4096, we get this behavior: ++ {4095, 4096, 4097} = {4096, 4096, 8192}. ++ ++ Note: The size argument has side effects (expanded multiple times). */ ++#define ALIGN_UP(base, size) ALIGN_DOWN ((base) + (size) - 1, (size)) ++ ++/* Same as ALIGN_DOWN(), but automatically casts when base is a pointer. */ ++#define PTR_ALIGN_DOWN(base, size) \ ++ ((__typeof__ (base)) ALIGN_DOWN ((uintptr_t) (base), (size))) ++ ++/* Same as ALIGN_UP(), but automatically casts when base is a pointer. */ ++#define PTR_ALIGN_UP(base, size) \ ++ ((__typeof__ (base)) ALIGN_UP ((uintptr_t) (base), (size))) ++ + #endif /* _LIBC_INTERNAL */ +diff -pruN glibc-2.12-2-gc4ccff1/nptl/allocatestack.c glibc-2.12-2-gc4ccff1.fixed/nptl/allocatestack.c +--- glibc-2.12-2-gc4ccff1/nptl/allocatestack.c 2013-07-09 23:43:09.427836179 +0530 ++++ glibc-2.12-2-gc4ccff1.fixed/nptl/allocatestack.c 2013-07-09 23:43:52.727834136 +0530 +@@ -351,7 +351,7 @@ allocate_stack (const struct pthread_att + + /* Get the stack size from the attribute if it is set. Otherwise we + use the default we determined at start time. */ +- size = attr->stacksize ?: __default_stacksize; ++ size = attr->stacksize ?: __default_pthread_attr.stacksize; + + /* Get memory for the stack. */ + if (__builtin_expect (attr->flags & ATTR_FLAG_STACKADDR, 0)) +diff -pruN glibc-2.12-2-gc4ccff1/nptl/nptl-init.c glibc-2.12-2-gc4ccff1.fixed/nptl/nptl-init.c +--- glibc-2.12-2-gc4ccff1/nptl/nptl-init.c 2013-07-09 23:43:09.553836173 +0530 ++++ glibc-2.12-2-gc4ccff1.fixed/nptl/nptl-init.c 2013-07-09 23:43:52.728834135 +0530 +@@ -435,7 +435,8 @@ __pthread_initialize_minimal_internal (v + + /* Round the resource limit up to page size. */ + limit.rlim_cur = (limit.rlim_cur + pagesz - 1) & -pagesz; +- __default_stacksize = limit.rlim_cur; ++ __default_pthread_attr.stacksize = limit.rlim_cur; ++ __default_pthread_attr.guardsize = GLRO (dl_pagesize); + + #ifdef SHARED + /* Transfer the old value from the dynamic linker's internal location. */ +diff -pruN glibc-2.12-2-gc4ccff1/nptl/pthread_attr_getstacksize.c glibc-2.12-2-gc4ccff1.fixed/nptl/pthread_attr_getstacksize.c +--- glibc-2.12-2-gc4ccff1/nptl/pthread_attr_getstacksize.c 2010-05-04 16:57:23.000000000 +0530 ++++ glibc-2.12-2-gc4ccff1.fixed/nptl/pthread_attr_getstacksize.c 2013-07-09 23:43:52.817834131 +0530 +@@ -33,7 +33,7 @@ __pthread_attr_getstacksize (attr, stack + + /* If the user has not set a stack size we return what the system + will use as the default. */ +- *stacksize = iattr->stacksize ?: __default_stacksize; ++ *stacksize = iattr->stacksize ?: __default_pthread_attr.stacksize; + + return 0; + } +diff -pruN glibc-2.12-2-gc4ccff1/nptl/pthread_barrier_init.c glibc-2.12-2-gc4ccff1.fixed/nptl/pthread_barrier_init.c +--- glibc-2.12-2-gc4ccff1/nptl/pthread_barrier_init.c 2010-05-04 16:57:23.000000000 +0530 ++++ glibc-2.12-2-gc4ccff1.fixed/nptl/pthread_barrier_init.c 2013-07-09 23:43:52.821834131 +0530 +@@ -23,7 +23,7 @@ + #include <kernel-features.h> + + +-static const struct pthread_barrierattr default_attr = ++static const struct pthread_barrierattr default_barrierattr = + { + .pshared = PTHREAD_PROCESS_PRIVATE + }; +@@ -43,7 +43,7 @@ pthread_barrier_init (barrier, attr, cou + const struct pthread_barrierattr *iattr + = (attr != NULL + ? iattr = (struct pthread_barrierattr *) attr +- : &default_attr); ++ : &default_barrierattr); + + if (iattr->pshared != PTHREAD_PROCESS_PRIVATE + && __builtin_expect (iattr->pshared != PTHREAD_PROCESS_SHARED, 0)) +diff -pruN glibc-2.12-2-gc4ccff1/nptl/pthread_create.c glibc-2.12-2-gc4ccff1.fixed/nptl/pthread_create.c +--- glibc-2.12-2-gc4ccff1/nptl/pthread_create.c 2013-07-09 23:43:09.542836173 +0530 ++++ glibc-2.12-2-gc4ccff1.fixed/nptl/pthread_create.c 2013-07-09 23:43:52.822834131 +0530 +@@ -425,15 +425,6 @@ start_thread (void *arg) + } + + +-/* Default thread attributes for the case when the user does not +- provide any. */ +-static const struct pthread_attr default_attr = +- { +- /* Just some value > 0 which gets rounded to the nearest page size. */ +- .guardsize = 1, +- }; +- +- + int + __pthread_create_2_1 (newthread, attr, start_routine, arg) + pthread_t *newthread; +@@ -447,7 +438,7 @@ __pthread_create_2_1 (newthread, attr, s + if (iattr == NULL) + /* Is this the best idea? On NUMA machines this could mean + accessing far-away memory. */ +- iattr = &default_attr; ++ iattr = &__default_pthread_attr; + + struct pthread *pd = NULL; + int err = ALLOCATE_STACK (iattr, &pd); +diff -pruN glibc-2.12-2-gc4ccff1/nptl/pthread_mutex_init.c glibc-2.12-2-gc4ccff1.fixed/nptl/pthread_mutex_init.c +--- glibc-2.12-2-gc4ccff1/nptl/pthread_mutex_init.c 2010-05-04 16:57:23.000000000 +0530 ++++ glibc-2.12-2-gc4ccff1.fixed/nptl/pthread_mutex_init.c 2013-07-09 23:43:52.822834131 +0530 +@@ -24,7 +24,7 @@ + #include <kernel-features.h> + #include "pthreadP.h" + +-static const struct pthread_mutexattr default_attr = ++static const struct pthread_mutexattr default_mutexattr = + { + /* Default is a normal mutex, not shared between processes. */ + .mutexkind = PTHREAD_MUTEX_NORMAL +@@ -45,7 +45,8 @@ __pthread_mutex_init (mutex, mutexattr) + + assert (sizeof (pthread_mutex_t) <= __SIZEOF_PTHREAD_MUTEX_T); + +- imutexattr = (const struct pthread_mutexattr *) mutexattr ?: &default_attr; ++ imutexattr = ((const struct pthread_mutexattr *) mutexattr ++ ?: &default_mutexattr); + + /* Sanity checks. */ + switch (__builtin_expect (imutexattr->mutexkind +diff -pruN glibc-2.12-2-gc4ccff1/nptl/pthreadP.h glibc-2.12-2-gc4ccff1.fixed/nptl/pthreadP.h +--- glibc-2.12-2-gc4ccff1/nptl/pthreadP.h 2013-07-09 23:43:09.553836173 +0530 ++++ glibc-2.12-2-gc4ccff1.fixed/nptl/pthreadP.h 2013-07-09 23:43:52.823834131 +0530 +@@ -148,8 +148,8 @@ enum + /* Internal variables. */ + + +-/* Default stack size. */ +-extern size_t __default_stacksize attribute_hidden; ++/* Default pthread attributes. */ ++extern struct pthread_attr __default_pthread_attr attribute_hidden; + + /* Size and alignment of static TLS block. */ + extern size_t __static_tls_size attribute_hidden; +diff -pruN glibc-2.12-2-gc4ccff1/nptl/pthread_rwlock_init.c glibc-2.12-2-gc4ccff1.fixed/nptl/pthread_rwlock_init.c +--- glibc-2.12-2-gc4ccff1/nptl/pthread_rwlock_init.c 2010-05-04 16:57:23.000000000 +0530 ++++ glibc-2.12-2-gc4ccff1.fixed/nptl/pthread_rwlock_init.c 2013-07-09 23:43:52.823834131 +0530 +@@ -21,7 +21,7 @@ + #include <kernel-features.h> + + +-static const struct pthread_rwlockattr default_attr = ++static const struct pthread_rwlockattr default_rwlockattr = + { + .lockkind = PTHREAD_RWLOCK_DEFAULT_NP, + .pshared = PTHREAD_PROCESS_PRIVATE +@@ -35,7 +35,7 @@ __pthread_rwlock_init (rwlock, attr) + { + const struct pthread_rwlockattr *iattr; + +- iattr = ((const struct pthread_rwlockattr *) attr) ?: &default_attr; ++ iattr = ((const struct pthread_rwlockattr *) attr) ?: &default_rwlockattr; + + memset (rwlock, '\0', sizeof (*rwlock)); + +diff -pruN glibc-2.12-2-gc4ccff1/nptl/vars.c glibc-2.12-2-gc4ccff1.fixed/nptl/vars.c +--- glibc-2.12-2-gc4ccff1/nptl/vars.c 2010-05-04 16:57:23.000000000 +0530 ++++ glibc-2.12-2-gc4ccff1.fixed/nptl/vars.c 2013-07-09 23:43:52.824834131 +0530 +@@ -21,13 +21,9 @@ + #include <tls.h> + #include <unistd.h> + +-/* Default stack size. */ +-size_t __default_stacksize attribute_hidden +-#ifdef SHARED +-; +-#else +- = PTHREAD_STACK_MIN; +-#endif ++/* Default thread attributes for the case when the user does not ++ provide any. */ ++struct pthread_attr __default_pthread_attr attribute_hidden; + + /* Flag whether the machine is SMP or not. */ + int __is_smp attribute_hidden; diff --git a/src/patches/glibc/glibc-rh788959-2.patch b/src/patches/glibc/glibc-rh788959-2.patch index 1064640..1147af6 100644 --- a/src/patches/glibc/glibc-rh788959-2.patch +++ b/src/patches/glibc/glibc-rh788959-2.patch @@ -1,153 +1,92 @@ -diff -rcp a/nscd/grpcache.c b/nscd/grpcache.c -*** a/nscd/grpcache.c Wed Apr 11 12:50:07 2012 ---- b/nscd/grpcache.c Wed Apr 11 21:45:58 2012 -*************** cache_addgr (struct database_dyn *db, in -*** 178,184 **** - char *cp; - const size_t key_len = strlen (key); - const size_t buf_len = 3 * sizeof (grp->gr_gid) + key_len + 1; -! char *buf = alloca (buf_len); - ssize_t n; - size_t cnt; - ---- 178,185 ---- - char *cp; - const size_t key_len = strlen (key); - const size_t buf_len = 3 * sizeof (grp->gr_gid) + key_len + 1; -! size_t alloca_used = 0; -! char *buf = alloca_account (buf_len, alloca_used); - ssize_t n; - size_t cnt; - -*************** cache_addgr (struct database_dyn *db, in -*** 190,196 **** - /* Determine the length of all members. */ - while (grp->gr_mem[gr_mem_cnt]) - ++gr_mem_cnt; -! gr_mem_len = (uint32_t *) alloca (gr_mem_cnt * sizeof (uint32_t)); - for (gr_mem_cnt = 0; grp->gr_mem[gr_mem_cnt]; ++gr_mem_cnt) - { - gr_mem_len[gr_mem_cnt] = strlen (grp->gr_mem[gr_mem_cnt]) + 1; ---- 191,198 ---- - /* Determine the length of all members. */ - while (grp->gr_mem[gr_mem_cnt]) - ++gr_mem_cnt; -! gr_mem_len = (uint32_t *) alloca_account (gr_mem_cnt * sizeof (uint32_t), -! alloca_used); - for (gr_mem_cnt = 0; grp->gr_mem[gr_mem_cnt]; ++gr_mem_cnt) - { - gr_mem_len[gr_mem_cnt] = strlen (grp->gr_mem[gr_mem_cnt]) + 1; -*************** cache_addgr (struct database_dyn *db, in -*** 205,214 **** - change. Allocate memory on the cache since it is likely - discarded anyway. If it turns out to be necessary to have a - new record we can still allocate real memory. */ -! bool alloca_used = false; - dataset = NULL; - -! if (he == NULL) - dataset = (struct dataset *) mempool_alloc (db, total + n, 1); - - if (dataset == NULL) ---- 207,216 ---- - change. Allocate memory on the cache since it is likely - discarded anyway. If it turns out to be necessary to have a - new record we can still allocate real memory. */ -! bool dataset_in_stack_or_freed = false; - dataset = NULL; - -! if (he == NULL || ! __libc_use_alloca (alloca_used + total + n)) - dataset = (struct dataset *) mempool_alloc (db, total + n, 1); - - if (dataset == NULL) -*************** cache_addgr (struct database_dyn *db, in -*** 216,225 **** - /* We cannot permanently add the result in the moment. But - we can provide the result as is. Store the data in some - temporary memory. */ -! dataset = (struct dataset *) alloca (total + n); - - /* We cannot add this record to the permanent database. */ -! alloca_used = true; - } - - dataset->head.allocsize = total + n; ---- 218,227 ---- - /* We cannot permanently add the result in the moment. But - we can provide the result as is. Store the data in some - temporary memory. */ -! dataset = (struct dataset *) alloca_account (total + n, alloca_used); - - /* We cannot add this record to the permanent database. */ -! dataset_in_stack_or_freed = true; - } - - dataset->head.allocsize = total + n; -*************** cache_addgr (struct database_dyn *db, in -*** 273,278 **** ---- 275,288 ---- - allocated on the stack and need not be freed. */ - dh->timeout = dataset->head.timeout; - ++dh->nreloads; -+ -+ /* If the new record was not allocated on the stack, then it must -+ be freed. Note that it can no longer be used. */ -+ if (! dataset_in_stack_or_freed) -+ { -+ free (dataset); -+ dataset_in_stack_or_freed = true; -+ } - } - else - { -*************** cache_addgr (struct database_dyn *db, in -*** 288,294 **** - key_copy = (char *) newp + (key_copy - (char *) dataset); - - dataset = memcpy (newp, dataset, total + n); -! alloca_used = false; - } - - /* Mark the old record as obsolete. */ ---- 298,304 ---- - key_copy = (char *) newp + (key_copy - (char *) dataset); - - dataset = memcpy (newp, dataset, total + n); -! dataset_in_stack_or_freed = false; - } - - /* Mark the old record as obsolete. */ -*************** cache_addgr (struct database_dyn *db, in -*** 303,309 **** - assert (fd != -1); - - #ifdef HAVE_SENDFILE -! if (__builtin_expect (db->mmap_used, 1) && !alloca_used) - { - assert (db->wr_fd != -1); - assert ((char *) &dataset->resp > (char *) db->data); ---- 313,319 ---- - assert (fd != -1); - - #ifdef HAVE_SENDFILE -! if (__builtin_expect (db->mmap_used, 1) && !dataset_in_stack_or_freed) - { - assert (db->wr_fd != -1); - assert ((char *) &dataset->resp > (char *) db->data); -*************** cache_addgr (struct database_dyn *db, in -*** 330,336 **** - - /* Add the record to the database. But only if it has not been - stored on the stack. */ -! if (! alloca_used) - { - /* If necessary, we also propagate the data to disk. */ - if (db->persistent) ---- 340,346 ---- - - /* Add the record to the database. But only if it has not been - stored on the stack. */ -! if (! dataset_in_stack_or_freed) - { - /* If necessary, we also propagate the data to disk. */ - if (db->persistent) +Index: glibc-2.12-2-gc4ccff1/nscd/grpcache.c +=================================================================== +--- glibc-2.12-2-gc4ccff1.orig/nscd/grpcache.c ++++ glibc-2.12-2-gc4ccff1/nscd/grpcache.c +@@ -178,7 +178,8 @@ cache_addgr (struct database_dyn *db, in + char *cp; + const size_t key_len = strlen (key); + const size_t buf_len = 3 * sizeof (grp->gr_gid) + key_len + 1; +- char *buf = alloca (buf_len); ++ size_t alloca_used = 0; ++ char *buf = alloca_account (buf_len, alloca_used); + ssize_t n; + size_t cnt; + +@@ -190,7 +191,8 @@ cache_addgr (struct database_dyn *db, in + /* Determine the length of all members. */ + while (grp->gr_mem[gr_mem_cnt]) + ++gr_mem_cnt; +- gr_mem_len = (uint32_t *) alloca (gr_mem_cnt * sizeof (uint32_t)); ++ gr_mem_len = (uint32_t *) alloca_account (gr_mem_cnt * sizeof (uint32_t), ++ alloca_used); + for (gr_mem_cnt = 0; grp->gr_mem[gr_mem_cnt]; ++gr_mem_cnt) + { + gr_mem_len[gr_mem_cnt] = strlen (grp->gr_mem[gr_mem_cnt]) + 1; +@@ -205,10 +207,10 @@ cache_addgr (struct database_dyn *db, in + change. Allocate memory on the cache since it is likely + discarded anyway. If it turns out to be necessary to have a + new record we can still allocate real memory. */ +- bool alloca_used = false; ++ bool dataset_in_stack_or_freed = false; + dataset = NULL; + +- if (he == NULL) ++ if (he == NULL || ! __libc_use_alloca (alloca_used + total + n)) + dataset = (struct dataset *) mempool_alloc (db, total + n, 1); + + if (dataset == NULL) +@@ -216,10 +218,10 @@ cache_addgr (struct database_dyn *db, in + /* We cannot permanently add the result in the moment. But + we can provide the result as is. Store the data in some + temporary memory. */ +- dataset = (struct dataset *) alloca (total + n); ++ dataset = (struct dataset *) alloca_account (total + n, alloca_used); + + /* We cannot add this record to the permanent database. */ +- alloca_used = true; ++ dataset_in_stack_or_freed = true; + } + + dataset->head.allocsize = total + n; +@@ -273,6 +275,14 @@ cache_addgr (struct database_dyn *db, in + allocated on the stack and need not be freed. */ + dh->timeout = dataset->head.timeout; + ++dh->nreloads; ++ ++ /* If the new record was not allocated on the stack, then it must ++ be freed. Note that it can no longer be used. */ ++ if (! dataset_in_stack_or_freed) ++ { ++ free (dataset); ++ dataset_in_stack_or_freed = true; ++ } + } + else + { +@@ -288,7 +298,7 @@ cache_addgr (struct database_dyn *db, in + key_copy = (char *) newp + (key_copy - (char *) dataset); + + dataset = memcpy (newp, dataset, total + n); +- alloca_used = false; ++ dataset_in_stack_or_freed = false; + } + + /* Mark the old record as obsolete. */ +@@ -303,7 +313,7 @@ cache_addgr (struct database_dyn *db, in + assert (fd != -1); + + #ifdef HAVE_SENDFILE +- if (__builtin_expect (db->mmap_used, 1) && !alloca_used) ++ if (__builtin_expect (db->mmap_used, 1) && !dataset_in_stack_or_freed) + { + assert (db->wr_fd != -1); + assert ((char *) &dataset->resp > (char *) db->data); +@@ -330,7 +340,7 @@ cache_addgr (struct database_dyn *db, in + + /* Add the record to the database. But only if it has not been + stored on the stack. */ +- if (! alloca_used) ++ if (! dataset_in_stack_or_freed) + { + /* If necessary, we also propagate the data to disk. */ + if (db->persistent) diff --git a/src/patches/glibc/glibc-rh834386-2.patch b/src/patches/glibc/glibc-rh834386-2.patch new file mode 100644 index 0000000..ad895c7 --- /dev/null +++ b/src/patches/glibc/glibc-rh834386-2.patch @@ -0,0 +1,107 @@ +2013-05-03 Carlos O'Donell <carlos at redhat.com> + + * intl/dcigettext.c (DCIGETTEXT): Skip translating if _nl_find_msg returns -1. + (_nl_find_msg): Return -1 if recursive call returned -1. If newmem is null + return -1. + * intl/loadmsgcat.c (_nl_load_domain): If _nl_find_msg returns -1 abort + loading the domain. + +diff -Nrup a/intl/dcigettext.c b/intl/dcigettext.c +--- a/intl/dcigettext.c 2010-05-04 07:27:23.000000000 -0400 ++++ b/intl/dcigettext.c 2013-08-01 00:11:54.616363264 -0400 +@@ -640,6 +640,11 @@ DCIGETTEXT (domainname, msgid1, msgid2, + retval = _nl_find_msg (domain->successor[cnt], binding, + msgid1, 1, &retlen); + ++ /* Resource problems are not fatal, instead we return no ++ translation. */ ++ if (__builtin_expect (retval == (char *) -1, 0)) ++ goto no_translation; ++ + if (retval != NULL) + { + domain = domain->successor[cnt]; +@@ -943,6 +948,11 @@ _nl_find_msg (domain_file, domainbinding + nullentry = + _nl_find_msg (domain_file, domainbinding, "", 0, &nullentrylen); + ++ /* Resource problems are fatal. If we continue onwards we will ++ only attempt to calloc a new conv_tab and fail later. */ ++ if (__builtin_expect (nullentry == (char *) -1, 0)) ++ return (char *) -1; ++ + if (nullentry != NULL) + { + const char *charsetstr; +@@ -1156,7 +1166,7 @@ _nl_find_msg (domain_file, domainbinding + freemem_size); + # ifdef _LIBC + if (newmem != NULL) +- transmem_list = transmem_list->next; ++ transmem_list = newmem; + else + { + struct transmem_list *old = transmem_list; +@@ -1171,6 +1181,16 @@ _nl_find_msg (domain_file, domainbinding + malloc_count = 1; + freemem_size = INITIAL_BLOCK_SIZE; + newmem = (transmem_block_t *) malloc (freemem_size); ++# ifdef _LIBC ++ if (newmem != NULL) ++ { ++ /* Add the block to the list of blocks we have to free ++ at some point. */ ++ newmem->next = transmem_list; ++ transmem_list = newmem; ++ } ++ /* Fall through and return -1. */ ++# endif + } + if (__builtin_expect (newmem == NULL, 0)) + { +@@ -1181,11 +1201,6 @@ _nl_find_msg (domain_file, domainbinding + } + + # ifdef _LIBC +- /* Add the block to the list of blocks we have to free +- at some point. */ +- newmem->next = transmem_list; +- transmem_list = newmem; +- + freemem = (unsigned char *) newmem->data; + freemem_size -= offsetof (struct transmem_list, data); + # else +@@ -1402,7 +1417,7 @@ get_output_charset (domainbinding) + return _NL_CURRENT (LC_CTYPE, CODESET); + # else + # if HAVE_ICONV +- extern const char *locale_charset PARAMS ((void); ++ extern const char *locale_charset PARAMS ((void)); + return locale_charset (); + # endif + # endif +diff -Nrup a/intl/loadmsgcat.c b/intl/loadmsgcat.c +--- a/intl/loadmsgcat.c 2010-05-04 07:27:23.000000000 -0400 ++++ b/intl/loadmsgcat.c 2013-08-01 00:12:48.448237849 -0400 +@@ -1235,7 +1235,7 @@ _nl_load_domain (domain_file, domainbind + default: + /* This is an invalid revision. */ + invalid: +- /* This is an invalid .mo file. */ ++ /* This is an invalid .mo file or we ran out of resources. */ + free (domain->malloced); + #ifdef HAVE_MMAP + if (use_mmap) +@@ -1255,6 +1255,12 @@ _nl_load_domain (domain_file, domainbind + + /* Get the header entry and look for a plural specification. */ + nullentry = _nl_find_msg (domain_file, domainbinding, "", 0, &nullentrylen); ++ if (__builtin_expect (nullentry == (char *) -1, 0)) ++ { ++ __libc_rwlock_fini (domain->conversions_lock); ++ goto invalid; ++ } ++ + EXTRACT_PLURAL_EXPRESSION (nullentry, &domain->plural, &domain->nplurals); + + out: diff --git a/src/patches/glibc/glibc-rh834386.patch b/src/patches/glibc/glibc-rh834386.patch new file mode 100644 index 0000000..61ddbe8 --- /dev/null +++ b/src/patches/glibc/glibc-rh834386.patch @@ -0,0 +1,181 @@ +# +# Red Hat BZ: +# https://bugzilla.redhat.com/show_bug.cgi?id=816647 +# +# ChangeLog +# +#2013-04-30 Patsy Franklin pfrankli@redhat.com +# +# * iconv/gconv_cache.c (find_module): Demangle init_fct before +# checking for NULL. Mangle __btowc_fct if init_fct is non-NULL. +# * iconv/gconv_db.c (free_derivation): Check that __shlib_handle +# is non-NULL before demangling the end_fct. Check for NULL +# end_fct after demangling. +# (__gconv_release_step): Demangle the end_fct before checking +# it for NULL. Remove assert on __shlibc_handle != NULL. +# (gen_steps): Don't check btowc_fct for NULL before mangling. +# Demangle init_fct before checking for NULL. +# (increment_counter): Likewise +# * gconv_dl.c (__gconv_find_shlib): Don't check init_fct or +# end_fct for NULL before mangling. +# * wcsmbs/btowc.c (__btowc): Demangle btowc_fct before checking +# for NULL. +# +diff -Nrup a/iconv/gconv_cache.c b/iconv/gconv_cache.c +--- a/iconv/gconv_cache.c 2012-12-24 22:02:13.000000000 -0500 ++++ b/iconv/gconv_cache.c 2013-04-30 11:34:20.112389987 -0400 +@@ -207,17 +207,16 @@ find_module (const char *directory, cons + result->__data = NULL; + + /* Call the init function. */ +- if (result->__init_fct != NULL) +- { +- __gconv_init_fct init_fct = result->__init_fct; ++ __gconv_init_fct init_fct = result->__init_fct; + #ifdef PTR_DEMANGLE +- PTR_DEMANGLE (init_fct); ++ PTR_DEMANGLE (init_fct); + #endif ++ if (init_fct != NULL) ++ { + status = DL_CALL_FCT (init_fct, (result)); + + #ifdef PTR_MANGLE +- if (result->__btowc_fct != NULL) +- PTR_MANGLE (result->__btowc_fct); ++ PTR_MANGLE (result->__btowc_fct); + #endif + } + } +diff -Nrup a/iconv/gconv_db.c b/iconv/gconv_db.c +--- a/iconv/gconv_db.c 2012-12-24 22:02:13.000000000 -0500 ++++ b/iconv/gconv_db.c 2013-04-30 11:32:42.700592914 -0400 +@@ -179,16 +179,15 @@ free_derivation (void *p) + size_t cnt; + + for (cnt = 0; cnt < deriv->nsteps; ++cnt) +- if (deriv->steps[cnt].__counter > 0 +- && deriv->steps[cnt].__end_fct != NULL) ++ if ((deriv->steps[cnt].__counter > 0) ++ && (deriv->steps[cnt].__shlib_handle != NULL)) + { +- assert (deriv->steps[cnt].__shlib_handle != NULL); +- + __gconv_end_fct end_fct = deriv->steps[cnt].__end_fct; + #ifdef PTR_DEMANGLE + PTR_DEMANGLE (end_fct); + #endif +- DL_CALL_FCT (end_fct, (&deriv->steps[cnt])); ++ if (end_fct != NULL) ++ DL_CALL_FCT (end_fct, (&deriv->steps[cnt])); + } + + /* Free the name strings. */ +@@ -212,16 +211,12 @@ __gconv_release_step (struct __gconv_ste + if (step->__shlib_handle != NULL && --step->__counter == 0) + { + /* Call the destructor. */ +- if (step->__end_fct != NULL) +- { +- assert (step->__shlib_handle != NULL); +- +- __gconv_end_fct end_fct = step->__end_fct; ++ __gconv_end_fct end_fct = step->__end_fct; + #ifdef PTR_DEMANGLE +- PTR_DEMANGLE (end_fct); ++ PTR_DEMANGLE (end_fct); + #endif +- DL_CALL_FCT (end_fct, (step)); +- } ++ if (end_fct != NULL) ++ DL_CALL_FCT (end_fct, (step)); + + #ifndef STATIC_GCONV + /* Release the loaded module. */ +@@ -293,13 +288,11 @@ gen_steps (struct derivation_step *best, + + /* Call the init function. */ + __gconv_init_fct init_fct = result[step_cnt].__init_fct; +- if (init_fct != NULL) +- { +- assert (result[step_cnt].__shlib_handle != NULL); +- + # ifdef PTR_DEMANGLE +- PTR_DEMANGLE (init_fct); ++ PTR_DEMANGLE (init_fct); + # endif ++ if (init_fct != NULL) ++ { + status = DL_CALL_FCT (init_fct, (&result[step_cnt])); + + if (__builtin_expect (status, __GCONV_OK) != __GCONV_OK) +@@ -312,8 +305,7 @@ gen_steps (struct derivation_step *best, + } + + # ifdef PTR_MANGLE +- if (result[step_cnt].__btowc_fct != NULL) +- PTR_MANGLE (result[step_cnt].__btowc_fct); ++ PTR_MANGLE (result[step_cnt].__btowc_fct); + # endif + } + } +@@ -393,16 +385,15 @@ increment_counter (struct __gconv_step * + + /* Call the init function. */ + __gconv_init_fct init_fct = step->__init_fct; +- if (init_fct != NULL) +- { + #ifdef PTR_DEMANGLE +- PTR_DEMANGLE (init_fct); ++ PTR_DEMANGLE (init_fct); + #endif ++ if (init_fct != NULL) ++ { + DL_CALL_FCT (init_fct, (step)); + + #ifdef PTR_MANGLE +- if (step->__btowc_fct != NULL) +- PTR_MANGLE (step->__btowc_fct); ++ PTR_MANGLE (step->__btowc_fct); + #endif + } + } +diff -Nrup a/iconv/gconv_dl.c b/iconv/gconv_dl.c +--- a/iconv/gconv_dl.c 2012-12-24 22:02:13.000000000 -0500 ++++ b/iconv/gconv_dl.c 2013-04-30 11:32:42.701592922 -0400 +@@ -132,10 +132,8 @@ __gconv_find_shlib (const char *name) + + #ifdef PTR_MANGLE + PTR_MANGLE (found->fct); +- if (found->init_fct != NULL) +- PTR_MANGLE (found->init_fct); +- if (found->end_fct != NULL) +- PTR_MANGLE (found->end_fct); ++ PTR_MANGLE (found->init_fct); ++ PTR_MANGLE (found->end_fct); + #endif + + /* We have succeeded in loading the shared object. */ +diff -Nrup a/wcsmbs/btowc.c b/wcsmbs/btowc.c +--- a/wcsmbs/btowc.c 2012-12-24 22:02:13.000000000 -0500 ++++ b/wcsmbs/btowc.c 2013-04-30 11:32:42.701592922 -0400 +@@ -47,15 +47,15 @@ __btowc (c) + /* Get the conversion functions. */ + fcts = get_gconv_fcts (_NL_CURRENT_DATA (LC_CTYPE)); + __gconv_btowc_fct btowc_fct = fcts->towc->__btowc_fct; ++#ifdef PTR_DEMANGLE ++ if (fcts->towc->__shlib_handle != NULL) ++ PTR_DEMANGLE (btowc_fct); ++#endif + + if (__builtin_expect (fcts->towc_nsteps == 1, 1) + && __builtin_expect (btowc_fct != NULL, 1)) + { + /* Use the shortcut function. */ +-#ifdef PTR_DEMANGLE +- if (fcts->towc->__shlib_handle != NULL) +- PTR_DEMANGLE (btowc_fct); +-#endif + return DL_CALL_FCT (btowc_fct, (fcts->towc, (unsigned char) c)); + } + else diff --git a/src/patches/glibc/glibc-rh845218.patch b/src/patches/glibc/glibc-rh845218.patch new file mode 100644 index 0000000..47f909c --- /dev/null +++ b/src/patches/glibc/glibc-rh845218.patch @@ -0,0 +1,218 @@ +commit 16b293a7a6f65d8ff348a603d19e8fd4372fa3a9 +Author: Siddhesh Poyarekar siddhesh@redhat.com +Date: Wed Apr 30 11:48:43 2014 +0530 + + Do not fail if one of the two responses to AF_UNSPEC fails (BZ #14308) + + [Fixes BZ #14308, #12994, #13651] + + AF_UNSPEC results in sending two queries in parallel, one for the A + record and the other for the AAAA record. If one of these is a + referral, then the query fails, which is wrong. It should return at + least the one successful response. + + The fix has two parts. The first part makes the referral fall back to + the SERVFAIL path, which results in using the successful response. + There is a bug in that path however, due to which the second part is + necessary. The bug here is that if the first response is a failure + and the second succeeds, __libc_res_nsearch does not detect that and + assumes a failure. The case where the first response is a success and + the second fails, works correctly. + + This condition is produced by buggy routers, so here's a crude + interposable library that can simulate such a condition. The library + overrides the recvfrom syscall and modifies the header of the packet + received to reproduce this scenario. It has two key variables: + mod_packet and first_error. + + The mod_packet variable when set to 0, results in odd packets being + modified to be a referral. When set to 1, even packets are modified + to be a referral. + + The first_error causes the first response to be a failure so that a + domain-appended search is performed to test the second part of the + __libc_nsearch fix. + + The driver for this fix is a simple getaddrinfo program that does an + AF_UNSPEC query. I have omitted this since it should be easy to + implement. + + I have tested this on x86_64. + + The interceptor library source: + + /* Override recvfrom and modify the header of the first DNS response to make it + a referral and reproduce bz #845218. We have to resort to this ugly hack + because we cannot make bind return the buggy response of a referral for the + AAAA record and an authoritative response for the A record. */ + #define _GNU_SOURCE + #include <sys/types.h> + #include <sys/socket.h> + #include <netinet/in.h> + #include <arpa/inet.h> + #include <stdio.h> + #include <stdbool.h> + #include <endian.h> + #include <dlfcn.h> + #include <stdlib.h> + + /* Lifted from resolv/arpa/nameser_compat.h. */ + typedef struct { + unsigned id :16; /*%< query identification number */ + #if BYTE_ORDER == BIG_ENDIAN + /* fields in third byte */ + unsigned qr: 1; /*%< response flag */ + unsigned opcode: 4; /*%< purpose of message */ + unsigned aa: 1; /*%< authoritive answer */ + unsigned tc: 1; /*%< truncated message */ + unsigned rd: 1; /*%< recursion desired */ + /* fields + * in + * fourth + * byte + * */ + unsigned ra: 1; /*%< recursion available */ + unsigned unused :1; /*%< unused bits (MBZ as of 4.9.3a3) */ + unsigned ad: 1; /*%< authentic data from named */ + unsigned cd: 1; /*%< checking disabled by resolver */ + unsigned rcode :4; /*%< response code */ + #endif + #if BYTE_ORDER == LITTLE_ENDIAN || BYTE_ORDER == PDP_ENDIAN + /* fields + * in + * third + * byte + * */ + unsigned rd :1; /*%< recursion desired */ + unsigned tc :1; /*%< truncated message */ + unsigned aa :1; /*%< authoritive answer */ + unsigned opcode :4; /*%< purpose of message */ + unsigned qr :1; /*%< response flag */ + /* fields + * in + * fourth + * byte + * */ + unsigned rcode :4; /*%< response code */ + unsigned cd: 1; /*%< checking disabled by resolver */ + unsigned ad: 1; /*%< authentic data from named */ + unsigned unused :1; /*%< unused bits (MBZ as of 4.9.3a3) */ + unsigned ra :1; /*%< recursion available */ + #endif + /* remaining + * bytes + * */ + unsigned qdcount :16; /*%< number of question entries */ + unsigned ancount :16; /*%< number of answer entries */ + unsigned nscount :16; /*%< number of authority entries */ + unsigned arcount :16; /*%< number of resource entries */ + } HEADER; + + static int done = 0; + + /* Packets to modify. 0 for the odd packets and 1 for even packets. */ + static const int mod_packet = 0; + + /* Set to true if the first request should result in an error, resulting in a + search query. */ + static bool first_error = true; + + static ssize_t (*real_recvfrom) (int sockfd, void *buf, size_t len, int flags, + struct sockaddr *src_addr, socklen_t *addrlen); + + void + __attribute__ ((constructor)) + init (void) + { + real_recvfrom = dlsym (RTLD_NEXT, "recvfrom"); + + if (real_recvfrom == NULL) + { + printf ("Failed to get reference to recvfrom: %s\n", dlerror ()); + printf ("Cannot simulate test\n"); + abort (); + } + } + + /* Modify the second packet that we receive to set the header in a manner as to + reproduce BZ #845218. */ + static void + mod_buf (HEADER *h, int port) + { + if (done % 2 == mod_packet || (first_error && done == 1)) + { + printf ("(Modifying header)"); + + if (first_error && done == 1) + h->rcode = 3; + else + h->rcode = 0; /* NOERROR == 0. */ + h->ancount = 0; + h->aa = 0; + h->ra = 0; + h->arcount = 0; + } + done++; + } + + ssize_t + recvfrom (int sockfd, void *buf, size_t len, int flags, + struct sockaddr *src_addr, socklen_t *addrlen) + { + ssize_t ret = real_recvfrom (sockfd, buf, len, flags, src_addr, addrlen); + int port = htons (((struct sockaddr_in *) src_addr)->sin_port); + struct in_addr addr = ((struct sockaddr_in *) src_addr)->sin_addr; + const char *host = inet_ntoa (addr); + printf ("\n*** From %s:%d: ", host, port); + + mod_buf (buf, port); + + printf ("returned %zd\n", ret); + return ret; + } + +diff --git a/resolv/res_query.c b/resolv/res_query.c +index a9db837..4e6612c 100644 +--- a/resolv/res_query.c ++++ b/resolv/res_query.c +@@ -382,7 +382,9 @@ __libc_res_nsearch(res_state statp, + ret = __libc_res_nquerydomain(statp, name, NULL, class, type, + answer, anslen, answerp, + answerp2, nanswerp2, resplen2); +- if (ret > 0 || trailing_dot) ++ if (ret > 0 || trailing_dot ++ /* If the second response is valid then we use that. */ ++ || (ret == 0 && answerp2 != NULL && resplen2 > 0)) + return (ret); + saved_herrno = h_errno; + tried_as_is++; +@@ -422,7 +424,8 @@ __libc_res_nsearch(res_state statp, + answer, anslen, answerp, + answerp2, nanswerp2, + resplen2); +- if (ret > 0) ++ if (ret > 0 || (ret == 0 && answerp2 != NULL ++ && resplen2 > 0)) + return (ret); + + if (answerp && *answerp != answer) { +diff --git a/resolv/res_send.c b/resolv/res_send.c +index 60743df..3273d55 100644 +--- a/resolv/res_send.c ++++ b/resolv/res_send.c +@@ -1351,6 +1351,7 @@ send_dg(res_state statp, + (*thisresplenp > *thisanssizp) + ? *thisanssizp : *thisresplenp); + ++ next_ns: + if (recvresp1 || (buf2 != NULL && recvresp2)) { + *resplen2 = 0; + return resplen; +@@ -1368,7 +1369,6 @@ send_dg(res_state statp, + goto wait; + } + +- next_ns: + __res_iclose(statp, false); + /* don't retry if called from dig */ + if (!statp->pfcode) diff --git a/src/patches/glibc/glibc-rh848748.patch b/src/patches/glibc/glibc-rh848748.patch new file mode 100644 index 0000000..b75a368 --- /dev/null +++ b/src/patches/glibc/glibc-rh848748.patch @@ -0,0 +1,70 @@ +2013-04-30 Patsy Franklin pfrankli@redhat.com + + * nis/yp_xdr.c: Defined XDRMAXNAME and XDRMAXRECORD. + (xdr_domainname): Use XDRMAXNAME as maxsize. + (xdr_mapname): Use XDRMAXNAME as maxsize. + (xdr_peername): Use XDRMAXNAME as maxsize. + (xdr_keydat): Use XDRMAXRECORD as maxsize. + (xdr_valdat): Use XDRMAXRECORD as maxsize. + +diff -Nrup a/nis/yp_xdr.c b/nis/yp_xdr.c +--- a/nis/yp_xdr.c 2012-06-30 15:12:34.000000000 -0400 ++++ b/nis/yp_xdr.c 2013-04-30 05:36:02.492835503 -0400 +@@ -32,6 +32,14 @@ + #include <rpcsvc/yp.h> + #include <rpcsvc/ypclnt.h> + ++/* The specification suggests 1024 as a maximum length of all fields, ++ but current linux systems usually don't use any limits. So, to stay ++ as much compatible as possible with recent linux systems we choose ++ limits large enough to avoid problems. */ ++ ++#define XDRMAXNAME 1024 ++#define XDRMAXRECORD 16 * 1024 * 1024 ++ + bool_t + xdr_ypstat (XDR *xdrs, ypstat *objp) + { +@@ -49,21 +57,21 @@ libnsl_hidden_def (xdr_ypxfrstat) + bool_t + xdr_domainname (XDR *xdrs, domainname *objp) + { +- return xdr_string (xdrs, objp, ~0); ++ return xdr_string (xdrs, objp, XDRMAXNAME); + } + libnsl_hidden_def (xdr_domainname) + + bool_t + xdr_mapname (XDR *xdrs, mapname *objp) + { +- return xdr_string (xdrs, objp, ~0); ++ return xdr_string (xdrs, objp, XDRMAXNAME); + } + libnsl_hidden_def (xdr_mapname) + + bool_t + xdr_peername (XDR *xdrs, peername *objp) + { +- return xdr_string (xdrs, objp, ~0); ++ return xdr_string (xdrs, objp, XDRMAXNAME); + } + libnsl_hidden_def (xdr_peername) + +@@ -71,7 +79,7 @@ bool_t + xdr_keydat (XDR *xdrs, keydat *objp) + { + return xdr_bytes (xdrs, (char **) &objp->keydat_val, +- (u_int *) &objp->keydat_len, ~0); ++ (u_int *) &objp->keydat_len, XDRMAXRECORD); + } + libnsl_hidden_def (xdr_keydat) + +@@ -79,7 +87,7 @@ bool_t + xdr_valdat (XDR *xdrs, valdat *objp) + { + return xdr_bytes (xdrs, (char **) &objp->valdat_val, +- (u_int *) &objp->valdat_len, ~0); ++ (u_int *) &objp->valdat_len, XDRMAXRECORD); + } + libnsl_hidden_def (xdr_valdat) + diff --git a/src/patches/glibc/glibc-rh851470.patch b/src/patches/glibc/glibc-rh851470.patch new file mode 100644 index 0000000..94915da --- /dev/null +++ b/src/patches/glibc/glibc-rh851470.patch @@ -0,0 +1,52 @@ +commit 050af9c4e86eeecd484ed44b7765e750523276eb +Author: Siddhesh Poyarekar siddhesh@redhat.com +Date: Wed Aug 29 10:03:39 2012 +0530 + + Don't make ttyname* fail if proc filesystem is not available + + The ttyname and ttyname_r functions on Linux now fall back to + searching for the tty file descriptor in /dev/pts or /dev if /proc is + not available. This allows creation of chroots without the procfs + mounted on /proc. + + Fixes BZ #14516. + + 2012-08-29 Siddhesh Poyarekar siddhesh@redhat.com + + [BZ #14516] + * sysdeps/unix/sysv/linux/ttyname.c (ttyname): Don't return + failure if reading from procfs failed. + * sysdeps/unix/sysv/linux/ttyname_r.c (ttyname_r): Likewise. + +diff -rup a/sysdeps/unix/sysv/linux/ttyname.c b/sysdeps/unix/sysv/linux/ttyname.c +--- a/sysdeps/unix/sysv/linux/ttyname.c 2010-05-04 05:27:23.000000000 -0600 ++++ b/sysdeps/unix/sysv/linux/ttyname.c 2012-08-27 10:53:29.326671475 -0600 +@@ -146,12 +146,6 @@ ttyname (int fd) + } + + ssize_t len = __readlink (procname, ttyname_buf, buflen); +- if (__builtin_expect (len == -1 && errno == ENOENT, 0)) +- { +- __set_errno (EBADF); +- return NULL; +- } +- + if (__builtin_expect (len != -1 + #ifndef __ASSUME_PROC_SELF_FD_SYMLINK + /* This is for Linux 2.0. */ +diff -rup a/sysdeps/unix/sysv/linux/ttyname_r.c b/sysdeps/unix/sysv/linux/ttyname_r.c +--- a/sysdeps/unix/sysv/linux/ttyname_r.c 2010-05-04 05:27:23.000000000 -0600 ++++ b/sysdeps/unix/sysv/linux/ttyname_r.c 2012-08-27 10:54:05.406528501 -0600 +@@ -126,12 +126,6 @@ __ttyname_r (int fd, char *buf, size_t b + *_fitoa_word (fd, __stpcpy (procname, "/proc/self/fd/"), 10, 0) = '\0'; + + ssize_t ret = __readlink (procname, buf, buflen - 1); +- if (__builtin_expect (ret == -1 && errno == ENOENT, 0)) +- { +- __set_errno (EBADF); +- return EBADF; +- } +- + if (__builtin_expect (ret == -1 && errno == ENAMETOOLONG, 0)) + { + __set_errno (ERANGE); diff --git a/src/patches/glibc/glibc-rh859965.patch b/src/patches/glibc/glibc-rh859965.patch new file mode 100644 index 0000000..8fcbcd4 --- /dev/null +++ b/src/patches/glibc/glibc-rh859965.patch @@ -0,0 +1,854 @@ +# +# Based on the following patch: +# +# Upstream bug: https://sourceware.org/bugzilla/show_bug.cgi?id=14906 +# URL: https://sourceware.org/ml/libc-alpha/2015-02/msg00504.html +# +# 2015-02-17 Carlos O'Donell carlos@redhat.com +# +# [BZ #14906] +# * nscd/cache.c (prune_cache): Use TRACED_FILE. Compare and update +# traced file mtime. Use consistent log message. +# * nscd/connections.c [HAVE_INOTIFY] (install_watches): New function. +# (register_traced_file): Call install_watches. Always set mtime. +# (invalidate_cache): Iterate over all trace files. Call install_watches. +# (inotify_check_files): Don't inline. Handle watching parent +# directories and configuration file movement in and out. +# (handle_inotify_events): New function. +# (main_loop_poll): Call handle_inotify_events. +# (main_loop_epoll): Likewise. +# * nscd/nscd.h: Define TRACED_FILE, TRACED_DIR, and PATH_MAX. +# (struct traced_file): Use array of inotify fds. Add parent directory, +# and basename. +# (struct database_dyn): Remove unused file_mtime. +# (init_traced_file): New inline function. +# (define_traced_file): New macro. +# * nss/nss_db/db-init.c: Use define_traced_file. +# (_nss_db_init): Use init_traced_file. +# * nss/nss_files/files-init.c: Use define_traced_file. +# (_nss_files_init): Use init_traced_file. +# +diff -urN glibc-2.12-2-gc4ccff1.orig/misc/sys/cdefs.h glibc-2.12-2-gc4ccff1.mod1/misc/sys/cdefs.h +--- glibc-2.12-2-gc4ccff1.orig/misc/sys/cdefs.h 2015-02-18 04:42:12.115187116 -0500 ++++ glibc-2.12-2-gc4ccff1.mod1/misc/sys/cdefs.h 2015-02-18 04:02:03.635159090 -0500 +@@ -362,6 +362,14 @@ + # endif + #endif + ++#if __GNUC__ >= 3 ++# define __glibc_unlikely(cond) __builtin_expect ((cond), 0) ++# define __glibc_likely(cond) __builtin_expect ((cond), 1) ++#else ++# define __glibc_unlikely(cond) (cond) ++# define __glibc_likely(cond) (cond) ++#endif ++ + #include <bits/wordsize.h> + + #if defined __LONG_DOUBLE_MATH_OPTIONAL && defined __NO_LONG_DOUBLE_MATH +diff -urN glibc-2.12-2-gc4ccff1.orig/nscd/cache.c glibc-2.12-2-gc4ccff1.mod1/nscd/cache.c +--- glibc-2.12-2-gc4ccff1.orig/nscd/cache.c 2015-02-18 04:42:12.329180362 -0500 ++++ glibc-2.12-2-gc4ccff1.mod1/nscd/cache.c 2015-02-18 04:02:03.635159090 -0500 +@@ -266,29 +266,52 @@ + + /* If we check for the modification of the underlying file we invalidate + the entries also in this case. */ +- if (table->inotify_descr < 0 && table->check_file && now != LONG_MAX) ++ if (table->check_file && now != LONG_MAX) + { +- struct stat64 st; ++ struct traced_file *runp = table->traced_files; + +- if (stat64 (table->filename, &st) < 0) ++ while (runp != NULL) + { +- char buf[128]; +- /* We cannot stat() the file, disable file checking if the +- file does not exist. */ +- dbg_log (_("cannot stat() file `%s': %s"), +- table->filename, strerror_r (errno, buf, sizeof (buf))); +- if (errno == ENOENT) +- table->check_file = 0; +- } +- else +- { +- if (st.st_mtime != table->file_mtime) ++#ifdef HAVE_INOTIFY ++ if (runp->inotify_descr[TRACED_FILE] == -1) ++#endif + { +- /* The file changed. Invalidate all entries. */ +- now = LONG_MAX; +- table->file_mtime = st.st_mtime; ++ struct stat64 st; ++ ++ if (stat64 (runp->fname, &st) < 0) ++ { ++ /* Print a diagnostic that the traced file was missing. ++ We must not disable tracing since the file might return ++ shortly and we want to reload it at the next pruning. ++ Disabling tracing here would go against the configuration ++ as specified by the user via check-files. */ ++ char buf[128]; ++ dbg_log (_("checking for monitored file `%s': %s"), ++ runp->fname, strerror_r (errno, buf, sizeof (buf))); ++ } ++ else ++ { ++ /* This must be `!=` to catch cases where users turn the ++ clocks back and we still want to detect any time difference ++ in mtime. */ ++ if (st.st_mtime != runp->mtime) ++ { ++ dbg_log (_("monitored file `%s` changed (mtime)"), ++ runp->fname); ++ /* The file changed. Invalidate all entries. */ ++ now = LONG_MAX; ++ runp->mtime = st.st_mtime; ++#ifdef HAVE_INOTIFY ++ /* Attempt to install a watch on the file. */ ++ install_watches (runp); ++#endif ++ } ++ } + } ++ ++ runp = runp->next; + } ++ + } + + /* We run through the table and find values which are not valid anymore. +diff -urN glibc-2.12-2-gc4ccff1.orig/nscd/connections.c glibc-2.12-2-gc4ccff1.mod1/nscd/connections.c +--- glibc-2.12-2-gc4ccff1.orig/nscd/connections.c 2015-02-18 04:42:12.333180236 -0500 ++++ glibc-2.12-2-gc4ccff1.mod1/nscd/connections.c 2015-02-18 04:40:51.674726008 -0500 +@@ -74,6 +74,25 @@ + static void begin_drop_privileges (void); + static void finish_drop_privileges (void); + ++/* Define the traced files. */ ++#define PWD_FILENAME "/etc/passwd" ++define_traced_file (pwd, PWD_FILENAME); ++ ++#define GRP_FILENAME "/etc/group" ++define_traced_file (grp, GRP_FILENAME); ++ ++#define HST_FILENAME "/etc/hosts" ++define_traced_file (hst, HST_FILENAME); ++ ++#define RESOLV_FILENAME "/etc/resolv.conf" ++define_traced_file (resolv, RESOLV_FILENAME); ++ ++#define SERV_FILENAME "/etc/services" ++define_traced_file (serv, SERV_FILENAME); ++ ++#define NETGR_FILENAME "/etc/netgroup" ++define_traced_file (netgr, NETGR_FILENAME); ++ + /* Map request type to a string. */ + const char *const serv2str[LASTREQ] = + { +@@ -115,8 +134,6 @@ + .shared = 0, + .max_db_size = DEFAULT_MAX_DB_SIZE, + .suggested_module = DEFAULT_SUGGESTED_MODULE, +- .reset_res = 0, +- .filename = "/etc/passwd", + .db_filename = _PATH_NSCD_PASSWD_DB, + .disabled_iov = &pwd_iov_disabled, + .postimeout = 3600, +@@ -136,8 +153,6 @@ + .shared = 0, + .max_db_size = DEFAULT_MAX_DB_SIZE, + .suggested_module = DEFAULT_SUGGESTED_MODULE, +- .reset_res = 0, +- .filename = "/etc/group", + .db_filename = _PATH_NSCD_GROUP_DB, + .disabled_iov = &grp_iov_disabled, + .postimeout = 3600, +@@ -157,8 +172,6 @@ + .shared = 0, + .max_db_size = DEFAULT_MAX_DB_SIZE, + .suggested_module = DEFAULT_SUGGESTED_MODULE, +- .reset_res = 1, +- .filename = "/etc/hosts", + .db_filename = _PATH_NSCD_HOSTS_DB, + .disabled_iov = &hst_iov_disabled, + .postimeout = 3600, +@@ -178,8 +191,6 @@ + .shared = 0, + .max_db_size = DEFAULT_MAX_DB_SIZE, + .suggested_module = DEFAULT_SUGGESTED_MODULE, +- .reset_res = 0, +- .filename = "/etc/services", + .db_filename = _PATH_NSCD_SERVICES_DB, + .disabled_iov = &serv_iov_disabled, + .postimeout = 28800, +@@ -199,8 +210,6 @@ + .shared = 0, + .max_db_size = DEFAULT_MAX_DB_SIZE, + .suggested_module = DEFAULT_SUGGESTED_MODULE, +- .reset_res = 0, +- .filename = "/etc/netgroup", + .db_filename = _PATH_NSCD_NETGROUP_DB, + .disabled_iov = &netgroup_iov_disabled, + .postimeout = 28800, +@@ -863,41 +872,26 @@ + dbs[cnt].shared = 0; + assert (dbs[cnt].ro_fd == -1); + } ++ } + +- dbs[cnt].inotify_descr = -1; +- if (dbs[cnt].check_file) +- { +-#ifdef HAVE_INOTIFY +- if (inotify_fd < 0 +- || (dbs[cnt].inotify_descr +- = inotify_add_watch (inotify_fd, dbs[cnt].filename, +- IN_DELETE_SELF | IN_MODIFY)) < 0) +- /* We cannot notice changes in the main thread. */ +-#endif +- { +- /* We need the modification date of the file. */ +- struct stat64 st; ++ /* Initialize and register the traced files. */ ++ init_traced_file (&pwd_traced_file.file, PWD_FILENAME, 0); ++ register_traced_file (pwddb, &pwd_traced_file.file); + +- if (stat64 (dbs[cnt].filename, &st) < 0) +- { +- /* We cannot stat() the file, disable file checking. */ +- dbg_log (_("cannot stat() file `%s': %s"), +- dbs[cnt].filename, strerror (errno)); +- dbs[cnt].check_file = 0; +- } +- else +- dbs[cnt].file_mtime = st.st_mtime; +- } +- } ++ init_traced_file (&grp_traced_file.file, GRP_FILENAME, 0); ++ register_traced_file (grpdb, &grp_traced_file.file); + +-#ifdef HAVE_INOTIFY +- if (cnt == hstdb && inotify_fd >= -1) +- /* We also monitor the resolver configuration file. */ +- resolv_conf_descr = inotify_add_watch (inotify_fd, +- _PATH_RESCONF, +- IN_DELETE_SELF | IN_MODIFY); +-#endif +- } ++ init_traced_file (&hst_traced_file.file, HST_FILENAME, 0); ++ register_traced_file (hstdb, &hst_traced_file.file); ++ ++ init_traced_file (&resolv_traced_file.file, RESOLV_FILENAME, 1); ++ register_traced_file (hstdb, &resolv_traced_file.file); ++ ++ init_traced_file (&serv_traced_file.file, SERV_FILENAME, 0); ++ register_traced_file (servdb, &serv_traced_file.file); ++ ++ init_traced_file (&netgr_traced_file.file, NETGR_FILENAME, 0); ++ register_traced_file (netgrdb, &netgr_traced_file.file); + + /* Create the socket. */ + #ifndef __ASSUME_SOCK_CLOEXEC +@@ -968,6 +962,92 @@ + finish_drop_privileges (); + } + ++#ifdef HAVE_INOTIFY ++#define TRACED_FILE_MASK (IN_DELETE_SELF | IN_CLOSE_WRITE | IN_MOVE_SELF) ++#define TRACED_DIR_MASK (IN_DELETE_SELF | IN_CREATE | IN_MOVED_TO | IN_MOVE_SELF) ++void ++install_watches (struct traced_file *finfo) ++{ ++ /* If we have inotify support use it exclusively with no fallback ++ to stat. This is a design decision to make the implementation ++ sipmler. Either we use fstat for the file name or we use inotify ++ for both the file and parent directory. */ ++ if (finfo->inotify_descr[TRACED_FILE] < 0) ++ finfo->inotify_descr[TRACED_FILE] = inotify_add_watch (inotify_fd, ++ finfo->fname, ++ TRACED_FILE_MASK); ++ if (finfo->inotify_descr[TRACED_FILE] < 0) ++ { ++ dbg_log (_("disabled inotify-based monitoring for file `%s': %s"), ++ finfo->fname, strerror (errno)); ++ return; ++ } ++ dbg_log (_("monitoring file `%s` (%d)"), ++ finfo->fname, finfo->inotify_descr[TRACED_FILE]); ++ /* Additionally listen for IN_CREATE events in the files parent ++ directory. We do this because the file to be watched might be ++ deleted and then added back again. When it is added back again ++ we must re-add the watch. We must also cover IN_MOVED_TO to ++ detect a file being moved into the directory. */ ++ if (finfo->inotify_descr[TRACED_DIR] < 0) ++ finfo->inotify_descr[TRACED_DIR] = inotify_add_watch (inotify_fd, ++ finfo->dname, ++ TRACED_DIR_MASK); ++ if (finfo->inotify_descr[TRACED_DIR] < 0) ++ { ++ dbg_log (_("disabled inotify-based monitoring for directory `%s': %s"), ++ finfo->fname, strerror (errno)); ++ return; ++ } ++ dbg_log (_("monitoring directory `%s` (%d)"), ++ finfo->dname, finfo->inotify_descr[TRACED_DIR]); ++} ++#endif ++ ++/* Register the file in FINFO as a traced file for the database DBS[DBIX]. ++ ++ We support registering multiple files per database. Each call to ++ register_traced_file adds to the list of registered files. ++ ++ When we prune the database, either through timeout or a request to ++ invalidate, we will check to see if any of the registered files has changed. ++ When we accept new connections to handle a cache request we will also ++ check to see if any of the registered files has changed. ++ ++ If we have inotify support then we install an inotify fd to notify us of ++ file deletion or modification, both of which will require we invalidate ++ the cache for the database. Without inotify support we stat the file and ++ store st_mtime to determine if the file has been modified. */ ++void ++register_traced_file (size_t dbidx, struct traced_file *finfo) ++{ ++ /* If the database is disabled or file checking is disabled ++ then ignore the registration. */ ++ if (! dbs[dbidx].enabled || ! dbs[dbidx].check_file) ++ return; ++ ++ if (__glibc_unlikely (debug_level > 0)) ++ dbg_log (_("monitoring file %s for database %s"), ++ finfo->fname, dbnames[dbidx]); ++ ++#ifdef HAVE_INOTIFY ++ install_watches (finfo); ++#endif ++ struct stat64 st; ++ if (stat64 (finfo->fname, &st) < 0) ++ { ++ /* We cannot stat() the file, disable file checking. */ ++ dbg_log (_("disabled monitoring for file `%s': %s"), ++ finfo->fname, strerror (errno)); ++ finfo->mtime = 0; ++ } ++ else ++ finfo->mtime = st.st_mtime; ++ ++ /* Queue up the file name. */ ++ finfo->next = dbs[dbidx].traced_files; ++ dbs[dbidx].traced_files = finfo; ++} + + /* Close the connections. */ + void +@@ -986,9 +1066,25 @@ + for (number = pwddb; number < lastdb; ++number) + if (strcmp (key, dbnames[number]) == 0) + { +- if (dbs[number].reset_res) +- res_init (); +- ++ struct traced_file *runp = dbs[number].traced_files; ++ while (runp != NULL) ++ { ++ /* Make sure we reload from file when checking mtime. */ ++ runp->mtime = 0; ++#ifdef HAVE_INOTIFY ++ /* During an invalidation we try to reload the traced ++ file watches. This allows the user to re-sync if ++ inotify events were lost. Similar to what we do during ++ pruning. */ ++ install_watches (runp); ++#endif ++ if (runp->call_res_init) ++ { ++ res_init (); ++ break; ++ } ++ runp = runp->next; ++ } + break; + } + +@@ -1817,6 +1913,231 @@ + /* Array for times a connection was accepted. */ + static time_t *starttime; + ++#ifdef HAVE_INOTIFY ++/* Inotify event for changed file. */ ++union __inev ++{ ++ struct inotify_event i; ++# ifndef PATH_MAX ++# define PATH_MAX 1024 ++# endif ++ char buf[sizeof (struct inotify_event) + PATH_MAX]; ++}; ++ ++/* Returns 0 if the file is there and matches the last mtime ++ on record, otherwise -1. */ ++int ++check_file (struct traced_file *finfo) ++{ ++ struct stat64 st; ++ if (stat64 (finfo->fname, &st) < 0) ++ return -1; ++ return 0; ++} ++ ++/* Process the inotify event in INEV. If the event matches any of the files ++ registered with a database then mark that database as requiring its cache ++ to be cleared. We indicate the cache needs clearing by setting ++ TO_CLEAR[DBCNT] to true for the matching database. */ ++static void ++inotify_check_files (bool *to_clear, union __inev *inev) ++{ ++ /* Check which of the files changed. */ ++ for (size_t dbcnt = 0; dbcnt < lastdb; ++dbcnt) ++ { ++ struct traced_file *finfo = dbs[dbcnt].traced_files; ++ ++ while (finfo != NULL) ++ { ++ /* The configuration file was moved or deleted. ++ We stop watching it at that point, and reinitialize. */ ++ if (finfo->inotify_descr[TRACED_FILE] == inev->i.wd ++ && ((inev->i.mask & IN_MOVE_SELF) ++ || (inev->i.mask & IN_DELETE_SELF) ++ || (inev->i.mask & IN_IGNORED))) ++ { ++ int ret; ++ bool moved = (inev->i.mask & IN_MOVE_SELF) != 0; ++ ++ if (check_file (finfo) == 0) ++ { ++ dbg_log (_("ignored out of order inotify event for `%s`"), ++ finfo->fname); ++ return; ++ } ++ ++ dbg_log (_("monitored file `%s` was %s, removing watch"), ++ finfo->fname, moved ? "moved" : "deleted"); ++ /* File was moved out, remove the watch. Watches are ++ automatically removed when the file is deleted. */ ++ if (moved) ++ { ++ ret = inotify_rm_watch (inotify_fd, inev->i.wd); ++ if (ret < 0) ++ dbg_log (_("failed to remove file watch `%s`: %s"), ++ finfo->fname, strerror (errno)); ++ } ++ finfo->inotify_descr[TRACED_FILE] = -1; ++ to_clear[dbcnt] = true; ++ if (finfo->call_res_init) ++ res_init (); ++ return; ++ } ++ /* The configuration file was open for writing and has just closed. ++ We reset the cache and reinitialize. */ ++ if (finfo->inotify_descr[TRACED_FILE] == inev->i.wd ++ && inev->i.mask & IN_CLOSE_WRITE) ++ { ++ /* Mark cache as needing to be cleared and reinitialize. */ ++ dbg_log (_("monitored file `%s` was written to"), finfo->fname); ++ to_clear[dbcnt] = true; ++ if (finfo->call_res_init) ++ res_init (); ++ return; ++ } ++ /* The parent directory was moved or deleted. There is no coming ++ back from this. We do not track the parent of the parent, and ++ once this happens we trigger one last invalidation. You must ++ restart nscd to track subsequent changes. We track this to ++ do one last robust re-initialization and then we're done. */ ++ if (finfo->inotify_descr[TRACED_DIR] == inev->i.wd ++ && ((inev->i.mask & IN_DELETE_SELF) ++ || (inev->i.mask & IN_MOVE_SELF) ++ || (inev->i.mask & IN_IGNORED))) ++ { ++ bool moved = (inev->i.mask & IN_MOVE_SELF) != 0; ++ /* The directory watch may have already been removed ++ but we don't know so we just remove it again and ++ ignore the error. Then we remove the file watch. ++ Note: watches are automatically removed for deleted ++ files. */ ++ if (moved) ++ inotify_rm_watch (inotify_fd, inev->i.wd); ++ if (finfo->inotify_descr[TRACED_FILE] != -1) ++ { ++ dbg_log (_("monitored parent directory `%s` was %s, removing watch on `%s`"), ++ finfo->dname, moved ? "moved" : "deleted", finfo->fname); ++ if (inotify_rm_watch (inotify_fd, finfo->inotify_descr[TRACED_FILE]) < 0) ++ dbg_log (_("failed to remove file watch `%s`: %s"), ++ finfo->dname, strerror (errno)); ++ } ++ finfo->inotify_descr[TRACED_FILE] = -1; ++ finfo->inotify_descr[TRACED_DIR] = -1; ++ to_clear[dbcnt] = true; ++ if (finfo->call_res_init) ++ res_init (); ++ /* Continue to the next entry since this might be the ++ parent directory for multiple registered files and ++ we want to remove watches for all registered files. */ ++ continue; ++ } ++ /* The parent directory had a create or moved to event. */ ++ if (finfo->inotify_descr[TRACED_DIR] == inev->i.wd ++ && ((inev->i.mask & IN_MOVED_TO) ++ || (inev->i.mask & IN_CREATE)) ++ && strcmp (inev->i.name, finfo->sfname) == 0) ++ { ++ /* We detected a directory change. We look for the creation ++ of the file we are tracking or the move of the same file ++ into the directory. */ ++ int ret; ++ dbg_log (_("monitored file `%s` was %s, adding watch"), ++ finfo->fname, ++ inev->i.mask & IN_CREATE ? "created" : "moved into place"); ++ /* File was moved in or created. Regenerate the watch. */ ++ if (finfo->inotify_descr[TRACED_FILE] != -1) ++ inotify_rm_watch (inotify_fd, ++ finfo->inotify_descr[TRACED_FILE]); ++ ++ ret = inotify_add_watch (inotify_fd, ++ finfo->fname, ++ TRACED_FILE_MASK); ++ if (ret < 0) ++ dbg_log (_("failed to add file watch `%s`: %s"), ++ finfo->fname, strerror (errno)); ++ ++ finfo->inotify_descr[TRACED_FILE] = ret; ++ ++ /* The file is new or moved so mark cache as needing to ++ be cleared and reinitialize. */ ++ to_clear[dbcnt] = true; ++ if (finfo->call_res_init) ++ res_init (); ++ ++ /* Done re-adding the watch. Don't return, we may still ++ have other files in this same directory, same watch ++ descriptor, and need to process them. */ ++ } ++ /* Other events are ignored, and we move on to the next file. */ ++ finfo = finfo->next; ++ } ++ } ++} ++ ++/* If an entry in the array of booleans TO_CLEAR is TRUE then clear the cache ++ for the associated database, otherwise do nothing. The TO_CLEAR array must ++ have LASTDB entries. */ ++static inline void ++clear_db_cache (bool *to_clear) ++{ ++ for (size_t dbcnt = 0; dbcnt < lastdb; ++dbcnt) ++ if (to_clear[dbcnt]) ++ { ++ pthread_mutex_lock (&dbs[dbcnt].prune_lock); ++ dbs[dbcnt].clear_cache = 1; ++ pthread_mutex_unlock (&dbs[dbcnt].prune_lock); ++ pthread_cond_signal (&dbs[dbcnt].prune_cond); ++ } ++} ++ ++int ++handle_inotify_events (void) ++{ ++ bool to_clear[lastdb] = { false, }; ++ union __inev inev; ++ ++ /* Read all inotify events for files registered via ++ register_traced_file(). */ ++ while (1) ++ { ++ /* Potentially read multiple events into buf. */ ++ ssize_t nb = TEMP_FAILURE_RETRY (read (inotify_fd, ++ &inev.buf, ++ sizeof (inev))); ++ if (nb < (ssize_t) sizeof (struct inotify_event)) ++ { ++ /* Not even 1 event. */ ++ if (__glibc_unlikely (nb == -1 && errno != EAGAIN)) ++ return -1; ++ /* Done reading events that are ready. */ ++ break; ++ } ++ /* Process all events. The normal inotify interface delivers ++ complete events on a read and never a partial event. */ ++ char *eptr = &inev.buf[0]; ++ ssize_t count; ++ while (1) ++ { ++ /* Check which of the files changed. */ ++ inotify_check_files (to_clear, &inev); ++ count = sizeof (struct inotify_event) + inev.i.len; ++ eptr += count; ++ nb -= count; ++ if (nb >= (ssize_t) sizeof (struct inotify_event)) ++ memcpy (&inev, eptr, nb); ++ else ++ break; ++ } ++ continue; ++ } ++ /* Actually perform the cache clearing. */ ++ clear_db_cache (to_clear); ++ return 0; ++} ++ ++ ++#endif ++ + + static void + __attribute__ ((__noreturn__)) +@@ -1910,66 +2231,21 @@ + { + if (conns[1].revents != 0) + { +- bool to_clear[lastdb] = { false, }; +- union +- { +-# ifndef PATH_MAX +-# define PATH_MAX 1024 +-# endif +- struct inotify_event i; +- char buf[sizeof (struct inotify_event) + PATH_MAX]; +- } inev; ++ int ret; ++ ret = handle_inotify_events (); + +- while (1) ++ if (ret == -1) + { +- ssize_t nb = TEMP_FAILURE_RETRY (read (inotify_fd, &inev, +- sizeof (inev))); +- if (nb < (ssize_t) sizeof (struct inotify_event)) +- { +- if (__builtin_expect (nb == -1 && errno != EAGAIN, +- 0)) +- { +- /* Something went wrong when reading the inotify +- data. Better disable inotify. */ +- dbg_log (_("\ +-disabled inotify after read error %d"), +- errno); +- conns[1].fd = -1; +- firstfree = 1; +- if (nused == 2) +- nused = 1; +- close (inotify_fd); +- inotify_fd = -1; +- } +- break; +- } +- +- /* Check which of the files changed. */ +- for (size_t dbcnt = 0; dbcnt < lastdb; ++dbcnt) +- if (inev.i.wd == dbs[dbcnt].inotify_descr) +- { +- to_clear[dbcnt] = true; +- goto next; +- } +- +- if (inev.i.wd == resolv_conf_descr) +- { +- res_init (); +- to_clear[hstdb] = true; +- } +- next:; ++ /* Something went wrong when reading the inotify ++ data. Better disable inotify. */ ++ dbg_log (_("disabled inotify-based monitoring after read error %d"), errno); ++ conns[1].fd = -1; ++ firstfree = 1; ++ if (nused == 2) ++ nused = 1; ++ close (inotify_fd); ++ inotify_fd = -1; + } +- +- /* Actually perform the cache clearing. */ +- for (size_t dbcnt = 0; dbcnt < lastdb; ++dbcnt) +- if (to_clear[dbcnt]) +- { +- pthread_mutex_lock (&dbs[dbcnt].prune_lock); +- dbs[dbcnt].clear_cache = 1; +- pthread_mutex_unlock (&dbs[dbcnt].prune_lock); +- pthread_cond_signal (&dbs[dbcnt].prune_cond); +- } +- + --n; + } + +@@ -2112,58 +2388,18 @@ + # ifdef HAVE_INOTIFY + else if (revs[cnt].data.fd == inotify_fd) + { +- bool to_clear[lastdb] = { false, }; +- union +- { +- struct inotify_event i; +- char buf[sizeof (struct inotify_event) + PATH_MAX]; +- } inev; +- +- while (1) ++ int ret; ++ ret = handle_inotify_events (); ++ if (ret == -1) + { +- ssize_t nb = TEMP_FAILURE_RETRY (read (inotify_fd, &inev, +- sizeof (inev))); +- if (nb < (ssize_t) sizeof (struct inotify_event)) +- { +- if (__builtin_expect (nb == -1 && errno != EAGAIN, 0)) +- { +- /* Something went wrong when reading the inotify +- data. Better disable inotify. */ +- dbg_log (_("disabled inotify after read error %d"), +- errno); +- (void) epoll_ctl (efd, EPOLL_CTL_DEL, inotify_fd, +- NULL); +- close (inotify_fd); +- inotify_fd = -1; +- } +- break; +- } +- +- /* Check which of the files changed. */ +- for (size_t dbcnt = 0; dbcnt < lastdb; ++dbcnt) +- if (inev.i.wd == dbs[dbcnt].inotify_descr) +- { +- to_clear[dbcnt] = true; +- goto next; +- } +- +- if (inev.i.wd == resolv_conf_descr) +- { +- res_init (); +- to_clear[hstdb] = true; +- } +- next:; ++ /* Something went wrong when reading the inotify ++ data. Better disable inotify. */ ++ dbg_log (_("disabled inotify-based monitoring after read error %d"), errno); ++ (void) epoll_ctl (efd, EPOLL_CTL_DEL, inotify_fd, NULL); ++ close (inotify_fd); ++ inotify_fd = -1; ++ break; + } +- +- /* Actually perform the cache clearing. */ +- for (size_t dbcnt = 0; dbcnt < lastdb; ++dbcnt) +- if (to_clear[dbcnt]) +- { +- pthread_mutex_lock (&dbs[dbcnt].prune_lock); +- dbs[dbcnt].clear_cache = 1; +- pthread_mutex_unlock (&dbs[dbcnt].prune_lock); +- pthread_cond_signal (&dbs[dbcnt].prune_cond); +- } + } + # endif + else +diff -urN glibc-2.12-2-gc4ccff1.orig/nscd/nscd.h glibc-2.12-2-gc4ccff1.mod1/nscd/nscd.h +--- glibc-2.12-2-gc4ccff1.orig/nscd/nscd.h 2015-02-18 04:42:12.329180362 -0500 ++++ glibc-2.12-2-gc4ccff1.mod1/nscd/nscd.h 2015-02-18 04:02:03.636159059 -0500 +@@ -62,6 +62,67 @@ + 80% of the thread stack size. */ + #define MAX_STACK_USE ((8 * NSCD_THREAD_STACKSIZE) / 10) + ++/* Records the file registered per database that when changed ++ or modified requires invalidating the database. */ ++struct traced_file ++{ ++ /* Tracks the last modified time of the traced file. */ ++ time_t mtime; ++ /* Support multiple registered files per database. */ ++ struct traced_file *next; ++ int call_res_init; ++ /* Requires Inotify support to do anything useful. */ ++#define TRACED_FILE 0 ++#define TRACED_DIR 1 ++ int inotify_descr[2]; ++# ifndef PATH_MAX ++# define PATH_MAX 1024 ++# endif ++ /* The parent directory is used to scan for creation/deletion. */ ++ char dname[PATH_MAX]; ++ /* Just the name of the file with no directory component. */ ++ char *sfname; ++ /* The full-path name of the registered file. */ ++ char fname[]; ++}; ++ ++/* Initialize a `struct traced_file`. As input we need the name ++ of the file, and if invalidation requires calling res_init. ++ If CRINIT is 1 then res_init will be called after invalidation ++ or if the traced file is changed in any way, otherwise it will ++ not. */ ++static inline void ++init_traced_file(struct traced_file *file, const char *fname, int crinit) ++{ ++ char *dname; ++ file->mtime = 0; ++ file->inotify_descr[TRACED_FILE] = -1; ++ file->inotify_descr[TRACED_DIR] = -1; ++ strcpy (file->fname, fname); ++ /* Compute the parent directory name and store a copy. The copy makes ++ it much faster to add/remove watches while nscd is running instead ++ of computing this over and over again in a temp buffer. */ ++ file->dname[0] = '\0'; ++ dname = strrchr (fname, '/'); ++ if (dname != NULL) ++ { ++ size_t len = (size_t)(dname - fname); ++ if (len > sizeof (file->dname)) ++ abort (); ++ strncpy (file->dname, file->fname, len); ++ file->dname[len] = '\0'; ++ } ++ /* The basename is the name just after the last forward slash. */ ++ file->sfname = &dname[1]; ++ file->call_res_init = crinit; ++} ++ ++#define define_traced_file(id, filename) \ ++static union \ ++{ \ ++ struct traced_file file; \ ++ char buf[sizeof (struct traced_file) + sizeof (filename)]; \ ++} id##_traced_file; + + /* Structure describing dynamic part of one database. */ + struct database_dyn +@@ -74,15 +135,12 @@ + + int enabled; + int check_file; +- int inotify_descr; + int clear_cache; + int persistent; + int shared; + int propagate; +- int reset_res; +- const char filename[16]; ++ struct traced_file *traced_files; + const char *db_filename; +- time_t file_mtime; + size_t suggested_module; + size_t max_db_size; + +@@ -199,6 +257,10 @@ + + /* connections.c */ + extern void nscd_init (void); ++extern void register_traced_file (size_t dbidx, struct traced_file *finfo); ++#ifdef HAVE_INOTIFY ++extern void install_watches (struct traced_file *finfo); ++#endif + extern void close_sockets (void); + extern void start_threads (void) __attribute__ ((__noreturn__)); diff --git a/src/patches/glibc/glibc-rh862094.patch b/src/patches/glibc/glibc-rh862094.patch new file mode 100644 index 0000000..6e7fe0a --- /dev/null +++ b/src/patches/glibc/glibc-rh862094.patch @@ -0,0 +1,68 @@ +From bc5fb0374c3ce6eca92f44d13a55b066e707c4a0 Mon Sep 17 00:00:00 2001 +From: Andreas Schwab schwab@redhat.com +Date: Wed, 15 Sep 2010 07:20:57 -0700 +Subject: [PATCH] Don't try to free rpath strings allocated during startup + +--- + ChangeLog | 10 ++++++++++ + elf/dl-load.c | 3 --- + elf/dl-support.c | 3 +++ + elf/rtld.c | 4 ++++ + 4 files changed, 17 insertions(+), 3 deletions(-) + + 2010-09-13 Andreas Schwab schwab@redhat.com + Ulrich Drepper drepper@redhat.com + + * elf/rtld.c (dl_main): Set GLRO(dl_init_all_dirs) just before + re-relocationg ld.so. + * elf/dl-support.c (_dl_non_dynamic_init): And here after the + _dl_init_paths call. + * elf/dl-load.c (_dl_init_paths). Don't set GLRO(dl_init_all_dirs) + here anymore. + +diff --git a/elf/dl-load.c b/elf/dl-load.c +index 0adddf5..a7162eb 100644 +--- a/elf/dl-load.c ++++ b/elf/dl-load.c +@@ -787,9 +787,6 @@ _dl_init_paths (const char *llp) + } + else + env_path_list.dirs = (void *) -1; +- +- /* Remember the last search directory added at startup. */ +- GLRO(dl_init_all_dirs) = GL(dl_all_dirs); + } + + +diff --git a/elf/dl-support.c b/elf/dl-support.c +index f94d2c4..5897b32 100644 +--- a/elf/dl-support.c ++++ b/elf/dl-support.c +@@ -264,6 +264,9 @@ _dl_non_dynamic_init (void) + objects. */ + _dl_init_paths (getenv ("LD_LIBRARY_PATH")); + ++ /* Remember the last search directory added at startup. */ ++ _dl_init_all_dirs = GL(dl_all_dirs); ++ + _dl_lazy = *(getenv ("LD_BIND_NOW") ?: "") == '\0'; + + _dl_bind_not = *(getenv ("LD_BIND_NOT") ?: "") != '\0'; +diff --git a/elf/rtld.c b/elf/rtld.c +index 90f3ff1..5ecc4fe 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -2291,6 +2291,10 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n", + lossage); + } + ++ /* Remember the last search directory added at startup, now that ++ malloc will no longer be the one from dl-minimal.c. */ ++ GLRO(dl_init_all_dirs) = GL(dl_all_dirs); ++ + if (! prelinked && rtld_multiple_ref) + { + /* There was an explicit ref to the dynamic linker as a shared lib. +-- +1.7.1 + diff --git a/src/patches/glibc/glibc-rh863384.patch b/src/patches/glibc/glibc-rh863384.patch new file mode 100644 index 0000000..7644a4e --- /dev/null +++ b/src/patches/glibc/glibc-rh863384.patch @@ -0,0 +1,14 @@ +diff -pruN glibc-2.12-2-gc4ccff1/sysdeps/posix/getaddrinfo.c glibc-2.12-2-gc4ccff1.fixed/sysdeps/posix/getaddrinfo.c +--- glibc-2.12-2-gc4ccff1/sysdeps/posix/getaddrinfo.c 2013-07-23 15:23:42.011941780 +0530 ++++ glibc-2.12-2-gc4ccff1.fixed/sysdeps/posix/getaddrinfo.c 2013-07-23 15:24:54.032938976 +0530 +@@ -562,8 +562,8 @@ gaih_inet (const char *name, const struc + + /* If we do not have to look for IPv6 addresses, use + the simple, old functions, which do not support +- IPv6 scope ids. */ +- if (req->ai_family == AF_INET) ++ IPv6 scope ids, nor retrieving the canonical name. */ ++ if (req->ai_family == AF_INET && (req->ai_flags & AI_CANONNAME) == 0) + { + /* Add room for struct host_data in resolv/nss_dns/dns-host.c */ + size_t tmpbuflen = 512 + (MAX_NR_ALIASES+MAX_NR_ADDRS+1)*sizeof(char*) diff --git a/src/patches/glibc/glibc-rh867679.patch b/src/patches/glibc/glibc-rh867679.patch new file mode 100644 index 0000000..3e823c8 --- /dev/null +++ b/src/patches/glibc/glibc-rh867679.patch @@ -0,0 +1,139 @@ +commit 9fab36eb583c0e585e83a01253299afed9ea9a11 +Author: Siddhesh Poyarekar siddhesh@redhat.com +Date: Tue Sep 25 14:10:29 2012 +0530 + + Shrink heap on linux when overcommit_memory == 2 + + Using madvise with MADV_DONTNEED to release memory back to the kernel + is not sufficient to change the commit charge accounted against the + process on Linux. It is OK however, when overcommit is enabled or is + heuristic. However, when overcommit is restricted to a percentage of + memory setting the contents of /proc/sys/vm/overcommit_memory as 2, it + makes a difference since memory requests will fail. Hence, we do what + we do with secure exec binaries, which is to call mmap on the region + to be dropped with MAP_FIXED. This internally unmaps the pages in + question and reduces the amount of memory accounted against the + process. + +diff --git a/malloc/arena.c b/malloc/arena.c +index f24e76c..b209e3b 100644 +--- a/malloc/arena.c ++++ b/malloc/arena.c +@@ -19,6 +19,9 @@ + + #include <stdbool.h> + ++/* Get the implementation for check_may_shrink_heap. */ ++#include <malloc-sysdep.h> ++ + /* Compile-time constants. */ + + #define HEAP_MIN_SIZE (32*1024) +@@ -621,10 +624,10 @@ shrink_heap(heap_info *h, long diff) + new_size = (long)h->size - diff; + if(new_size < (long)sizeof(*h)) + return -1; +- /* Try to re-map the extra heap space freshly to save memory, and +- make it inaccessible. */ + #ifdef _LIBC +- if (__builtin_expect (__libc_enable_secure, 0)) ++ /* Try to re-map the extra heap space freshly to save memory, and make it ++ inaccessible. See malloc-sysdep.h to know when this is true. */ ++ if (__builtin_expect (check_may_shrink_heap (), 0)) + #else + if (1) + #endif +diff --git a/sysdeps/generic/malloc-sysdep.h b/sysdeps/generic/malloc-sysdep.h +new file mode 100644 +index 0000000..bbc48c0 +--- /dev/null ++++ b/sysdeps/generic/malloc-sysdep.h +@@ -0,0 +1,25 @@ ++/* System-specific malloc support functions. Generic version. ++ Copyright (C) 2012 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/. */ ++ ++/* Force an unmap when the heap shrinks in a secure exec. This ensures that ++ the old data pages immediately cease to be accessible. */ ++static inline bool ++check_may_shrink_heap (void) ++{ ++ return __libc_enable_secure; ++} +diff --git a/sysdeps/unix/sysv/linux/malloc-sysdep.h b/sysdeps/unix/sysv/linux/malloc-sysdep.h +new file mode 100644 +index 0000000..f926aea +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/malloc-sysdep.h +@@ -0,0 +1,57 @@ ++/* System-specific malloc support functions. Linux version. ++ Copyright (C) 2012 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 <fcntl.h> ++#include <not-cancel.h> ++ ++/* The Linux kernel overcommits address space by default and if there is not ++ enough memory available, it uses various parameters to decide the process to ++ kill. It is however possible to disable or curb this overcommit behavior ++ by setting the proc sysctl vm.overcommit_memory to the value '2' and with ++ that, a process is only allowed to use the maximum of a pre-determined ++ fraction of the total address space. In such a case, we want to make sure ++ that we are judicious with our heap usage as well, and explicitly give away ++ the freed top of the heap to reduce our commit charge. See the proc(5) man ++ page to know more about overcommit behavior. ++ ++ Other than that, we also force an unmap in a secure exec. */ ++static inline bool ++check_may_shrink_heap (void) ++{ ++ static int may_shrink_heap = -1; ++ ++ if (__builtin_expect (may_shrink_heap >= 0, 1)) ++ return may_shrink_heap; ++ ++ may_shrink_heap = __libc_enable_secure; ++ ++ if (__builtin_expect (may_shrink_heap == 0, 1)) ++ { ++ int fd = open_not_cancel_2 ("/proc/sys/vm/overcommit_memory", ++ O_RDONLY | O_CLOEXEC); ++ if (fd >= 0) ++ { ++ char val; ++ ssize_t n = read_not_cancel (fd, &val, 1); ++ may_shrink_heap = n > 0 && val == '2'; ++ close_not_cancel_no_status (fd); ++ } ++ } ++ ++ return may_shrink_heap; ++} diff --git a/src/patches/glibc/glibc-rh868808.patch b/src/patches/glibc/glibc-rh868808.patch new file mode 100644 index 0000000..27a10b2 --- /dev/null +++ b/src/patches/glibc/glibc-rh868808.patch @@ -0,0 +1,99 @@ +From d6f67f7d833b4e2039f832355fb0edd65522c9f4 Mon Sep 17 00:00:00 2001 +From: Ulrich Drepper drepper@gmail.com +Date: Sat, 14 May 2011 10:46:17 -0400 +Subject: [PATCH] Handle recursive calls in backtrace better + +--- + ChangeLog | 7 +++++++ + NEWS | 12 ++++++------ + sysdeps/ia64/backtrace.c | 27 +++++++++++++++++++++++---- + 3 files changed, 36 insertions(+), 10 deletions(-) + + 2011-05-14 Ulrich Drepper drepper@gmail.com + + [BZ #12432] + * sysdeps/ia64/backtrace.c (struct trace_reg): Add cfa element. + (dummy_getcfa): New function. + (init): Get _Unwind_GetCFA address, use dummy if not found. + (backtrace_helper): In recursion check, also check whether CFA changes. + (__backtrace): Completely initialize arg. + +diff --git a/sysdeps/ia64/backtrace.c b/sysdeps/ia64/backtrace.c +index 5cefb86..d4ff291 100644 +--- a/sysdeps/ia64/backtrace.c ++++ b/sysdeps/ia64/backtrace.c +@@ -1,5 +1,5 @@ + /* Return backtrace of current program state. +- Copyright (C) 2003, 2004, 2005, 2007, 2009 Free Software Foundation, Inc. ++ Copyright (C) 2003-2005, 2007, 2009, 2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek jakub@redhat.com, 2003. + +@@ -27,14 +27,26 @@ + struct trace_arg + { + void **array; +- int cnt, size; ++ _Unwind_Word cfa; ++ int cnt; ++ int size; + }; + + #ifdef SHARED + static _Unwind_Reason_Code (*unwind_backtrace) (_Unwind_Trace_Fn, void *); + static _Unwind_Ptr (*unwind_getip) (struct _Unwind_Context *); ++static _Unwind_Word (*unwind_getcfa) (struct _Unwind_Context *); + static void *libgcc_handle; + ++ ++/* Dummy version in case libgcc_s does not contain the real code. */ ++static _Unwind_Word ++dummy_getcfa (struct _Unwind_Context *ctx __attribute__ ((unused))) ++{ ++ return 0; ++} ++ ++ + static void + init (void) + { +@@ -47,10 +59,13 @@ init (void) + unwind_getip = __libc_dlsym (libgcc_handle, "_Unwind_GetIP"); + if (unwind_getip == NULL) + unwind_backtrace = NULL; ++ unwind_getcfa = (__libc_dlsym (libgcc_handle, "_Unwind_GetCFA") ++ ?: dummy_getcfa); + } + #else + # define unwind_backtrace _Unwind_Backtrace + # define unwind_getip _Unwind_GetIP ++# define unwind_getcfa _Unwind_GetCFA + #endif + + static _Unwind_Reason_Code +@@ -65,8 +80,12 @@ backtrace_helper (struct _Unwind_Context *ctx, void *a) + arg->array[arg->cnt] = (void *) unwind_getip (ctx); + + /* Check whether we make any progress. */ +- if (arg->cnt > 0 && arg->array[arg->cnt - 1] == arg->array[arg->cnt]) ++ _Unwind_Word cfa = unwind_getcfa (ctx); ++ ++ if (arg->cnt > 0 && arg->array[arg->cnt - 1] == arg->array[arg->cnt] ++ && cfa == arg->cfa) + return _URC_END_OF_STACK; ++ arg->cfa = cfa; + } + if (++arg->cnt == arg->size) + return _URC_END_OF_STACK; +@@ -78,7 +97,7 @@ __backtrace (array, size) + void **array; + int size; + { +- struct trace_arg arg = { .array = array, .size = size, .cnt = -1 }; ++ struct trace_arg arg = { .array = array, .cfa = 0, .size = size, .cnt = -1 }; + #ifdef SHARED + __libc_once_define (static, once); + +-- +1.7.1 + diff --git a/src/patches/glibc/glibc-rh905941.patch b/src/patches/glibc/glibc-rh905941.patch new file mode 100644 index 0000000..d5d50f2 --- /dev/null +++ b/src/patches/glibc/glibc-rh905941.patch @@ -0,0 +1,146 @@ +diff -pruN a/nptl/sysdeps/pthread/unwind-forcedunwind.c b/nptl/sysdeps/pthread/unwind-forcedunwind.c +--- a/nptl/sysdeps/pthread/unwind-forcedunwind.c 2010-05-04 16:57:23.000000000 +0530 ++++ b/nptl/sysdeps/pthread/unwind-forcedunwind.c 2014-06-02 23:00:02.901013275 +0530 +@@ -45,8 +45,10 @@ pthread_cancel_init (void) + + if (__builtin_expect (libgcc_s_handle != NULL, 1)) + { +- /* Force gcc to reload all values. */ +- asm volatile ("" ::: "memory"); ++ /* Order reads so as to prevent speculation of loads ++ of libgcc_s_{resume,personality,forcedunwind,getcfa} ++ to points prior to the write barrier. */ ++ atomic_read_barrier (); + return; + } + +@@ -72,9 +74,14 @@ pthread_cancel_init (void) + libgcc_s_forcedunwind = forcedunwind; + PTR_MANGLE (getcfa); + libgcc_s_getcfa = getcfa; +- /* Make sure libgcc_s_handle is written last. Otherwise, +- pthread_cancel_init might return early even when the pointer the +- caller is interested in is not initialized yet. */ ++ /* At the point at which any thread writes the handle ++ to libgcc_s_handle, the initialization is complete. ++ The writing of libgcc_s_handle is atomic. All other ++ threads reading libgcc_s_handle do so atomically. Any ++ thread that does not execute this function must issue ++ a read barrier to ensure that all of the above has ++ actually completed and that the values of the ++ function pointers are correct. */ + atomic_write_barrier (); + libgcc_s_handle = handle; + } +@@ -91,11 +98,19 @@ __unwind_freeres (void) + } + } + +-void +-_Unwind_Resume (struct _Unwind_Exception *exc) ++static __always_inline void ++_maybe_pthread_cancel_init (void) + { + if (__builtin_expect (libgcc_s_handle == NULL, 0)) + pthread_cancel_init (); ++ else ++ atomic_read_barrier (); ++} ++ ++void ++_Unwind_Resume (struct _Unwind_Exception *exc) ++{ ++ _maybe_pthread_cancel_init (); + + void (*resume) (struct _Unwind_Exception *exc) = libgcc_s_resume; + PTR_DEMANGLE (resume); +@@ -108,8 +123,7 @@ __gcc_personality_v0 (int version, _Unwi + struct _Unwind_Exception *ue_header, + struct _Unwind_Context *context) + { +- if (__builtin_expect (libgcc_s_handle == NULL, 0)) +- pthread_cancel_init (); ++ _maybe_pthread_cancel_init (); + + _Unwind_Reason_Code (*personality) + (int, _Unwind_Action, _Unwind_Exception_Class, struct _Unwind_Exception *, +@@ -122,8 +136,7 @@ _Unwind_Reason_Code + _Unwind_ForcedUnwind (struct _Unwind_Exception *exc, _Unwind_Stop_Fn stop, + void *stop_argument) + { +- if (__builtin_expect (libgcc_s_handle == NULL, 0)) +- pthread_cancel_init (); ++ _maybe_pthread_cancel_init (); + + _Unwind_Reason_Code (*forcedunwind) + (struct _Unwind_Exception *, _Unwind_Stop_Fn, void *) +@@ -135,8 +148,7 @@ _Unwind_ForcedUnwind (struct _Unwind_Exc + _Unwind_Word + _Unwind_GetCFA (struct _Unwind_Context *context) + { +- if (__builtin_expect (libgcc_s_handle == NULL, 0)) +- pthread_cancel_init (); ++ _maybe_pthread_cancel_init (); + + _Unwind_Word (*getcfa) (struct _Unwind_Context *) = libgcc_s_getcfa; + PTR_DEMANGLE (getcfa); +diff -pruN a/sysdeps/gnu/unwind-resume.c b/sysdeps/gnu/unwind-resume.c +--- a/sysdeps/gnu/unwind-resume.c 2010-05-04 16:57:23.000000000 +0530 ++++ b/sysdeps/gnu/unwind-resume.c 2014-06-02 23:02:26.812007078 +0530 +@@ -20,8 +20,11 @@ + #include <dlfcn.h> + #include <stdio.h> + #include <unwind.h> ++#include <pthreadP.h> ++#include <sysdep.h> + #include <libgcc_s.h> + ++static void *libgcc_s_handle; + static void (*libgcc_s_resume) (struct _Unwind_Exception *exc); + static _Unwind_Reason_Code (*libgcc_s_personality) + (int, _Unwind_Action, _Unwind_Exception_Class, struct _Unwind_Exception *, +@@ -42,13 +45,32 @@ init (void) + + libgcc_s_resume = resume; + libgcc_s_personality = personality; ++ atomic_write_barrier (); ++ /* At the point at which any thread writes the handle ++ to libgcc_s_handle, the initialization is complete. ++ The writing of libgcc_s_handle is atomic. All other ++ threads reading libgcc_s_handle do so atomically. Any ++ thread that does not execute this function must issue ++ a read barrier to ensure that all of the above has ++ actually completed and that the values of the ++ function pointers are correct. */ ++ libgcc_s_handle = handle; + } + ++static __always_inline void ++_maybe_init (void) ++{ ++ if (__builtin_expect (libgcc_s_handle == NULL, 0)) ++ init (); ++ else ++ atomic_read_barrier (); ++} ++ ++ + void + _Unwind_Resume (struct _Unwind_Exception *exc) + { +- if (__builtin_expect (libgcc_s_resume == NULL, 0)) +- init (); ++ _maybe_init (); + libgcc_s_resume (exc); + } + +@@ -58,8 +80,7 @@ __gcc_personality_v0 (int version, _Unwi + struct _Unwind_Exception *ue_header, + struct _Unwind_Context *context) + { +- if (__builtin_expect (libgcc_s_personality == NULL, 0)) +- init (); ++ _maybe_init (); + return libgcc_s_personality (version, actions, exception_class, + ue_header, context); + } diff --git a/src/patches/glibc/glibc-rh919562.patch b/src/patches/glibc/glibc-rh919562.patch new file mode 100644 index 0000000..42aa819 --- /dev/null +++ b/src/patches/glibc/glibc-rh919562.patch @@ -0,0 +1,190 @@ +# +# Patch provided by Ulrich Drepper in BZ#919562. +# +# Patch has not been sent upstream. +# +# 2013-03-08 Ulrich Drepper drepper@gmail.com +# +# * elf/rtld.c (dl_main): Correctly determine when the application +# required DSOs with TLS and bump the generation counter in that +# case. The current condition does not account for an audit +# module using TLS. +# * elf/dl-tls.c (_dl_count_modids): New function. +# (_dl_allocate_tls_init): Add assertion to check TLS +# generation. +# * sysdeps/generic/ldsodefs.h: Declare _dl_count_modids. +# * elf/Makefile: Add rules to build and run tst-audit9. +# * elf/tst-audit9.c: New file. +# * elf/tst-auditmod9a.c: New file. +# * elf/tst-auditmod9b.c: New file. +# +diff -urN glibc-2.12-2-gc4ccff1.orig/elf/dl-tls.c glibc-2.12-2-gc4ccff1/elf/dl-tls.c +--- glibc-2.12-2-gc4ccff1.orig/elf/dl-tls.c 2013-04-24 16:06:10.410756438 -0400 ++++ glibc-2.12-2-gc4ccff1/elf/dl-tls.c 2013-04-24 16:06:49.092604707 -0400 +@@ -109,6 +109,28 @@ + } + + ++size_t ++internal_function ++_dl_count_modids (void) ++{ ++ if (! __builtin_expect (GL(dl_tls_dtv_gaps), true)) ++ return GL(dl_tls_max_dtv_idx); ++ ++ size_t n = 0; ++ struct dtv_slotinfo_list *runp = GL(dl_tls_dtv_slotinfo_list); ++ while (runp != NULL) ++ { ++ for (size_t i = 0; i < runp->len; ++i) ++ if (runp->slotinfo[i].map != NULL) ++ ++n; ++ ++ runp = runp->next; ++ } ++ ++ return n; ++} ++ ++ + #ifdef SHARED + void + internal_function +@@ -411,6 +433,7 @@ + + /* Keep track of the maximum generation number. This might + not be the generation counter. */ ++ assert (listp->slotinfo[cnt].gen <= GL(dl_tls_generation)); + maxgen = MAX (maxgen, listp->slotinfo[cnt].gen); + + if (map->l_tls_offset == NO_TLS_OFFSET +diff -urN glibc-2.12-2-gc4ccff1.orig/elf/Makefile glibc-2.12-2-gc4ccff1/elf/Makefile +--- glibc-2.12-2-gc4ccff1.orig/elf/Makefile 2013-04-24 16:06:10.408756448 -0400 ++++ glibc-2.12-2-gc4ccff1/elf/Makefile 2013-04-24 16:07:29.475457962 -0400 +@@ -97,6 +97,8 @@ + tst-audit6.c tst-auditmod6a.c tst-auditmod6b.c \ + tst-auditmod6c.c \ + tst-audit7.c tst-auditmod7a.c tst-auditmod7b.c \ ++ tst-audit9.c \ ++ tst-auditmod9a.c tst-auditmod9b.c \ + order2mod1.c order2mod2.c order2mod3.c order2mod4.c \ + tst-stackguard1.c tst-stackguard1-static.c \ + tst-array5.c tst-array5-static.c tst-array5dep.c \ +@@ -198,7 +200,7 @@ + tst-dlmodcount tst-dlopenrpath tst-deep1 \ + tst-dlmopen1 tst-dlmopen2 tst-dlmopen3 \ + unload3 unload4 unload5 unload6 unload7 unload8 tst-global1 order2 \ +- tst-audit1 tst-audit2 \ ++ tst-audit1 tst-audit2 tst-audit9 \ + tst-stackguard1 tst-addr1 tst-thrlock \ + tst-unique1 tst-unique2 + # reldep9 +@@ -251,7 +253,8 @@ + unload8mod1 unload8mod1x unload8mod2 unload8mod3 \ + order2mod1 order2mod2 order2mod3 order2mod4 \ + tst-unique1mod1 tst-unique1mod2 \ +- tst-unique2mod1 tst-unique2mod2 ++ tst-unique2mod1 tst-unique2mod2 \ ++ tst-auditmod9a tst-auditmod9b + ifeq (yes,$(have-initfini-array)) + modules-names += tst-array2dep tst-array5dep + endif +@@ -574,6 +577,8 @@ + ifuncmod1.so-no-z-defs = yes + ifuncmod5.so-no-z-defs = yes + ifuncmod6.so-no-z-defs = yes ++tst-auditmod9a.so-no-z-defs = yes ++tst-auditmod9b.so-no-z-defs = yes + + ifeq ($(build-shared),yes) + # Build all the modules even when not actually running test programs. +@@ -1015,6 +1020,10 @@ + $(objpfx)tst-audit7.out: $(objpfx)tst-auditmod7b.so + tst-audit7-ENV = LD_AUDIT=$(objpfx)tst-auditmod7b.so + ++$(objpfx)tst-audit9: $(libdl) ++$(objpfx)tst-audit9.out: $(objpfx)tst-auditmod9a.so $(objpfx)tst-auditmod9b.so ++tst-audit9-ENV = LD_AUDIT=$(objpfx)tst-auditmod9a.so ++ + $(objpfx)tst-global1: $(libdl) + $(objpfx)tst-global1.out: $(objpfx)testobj6.so $(objpfx)testobj2.so + +diff -urN glibc-2.12-2-gc4ccff1.orig/elf/rtld.c glibc-2.12-2-gc4ccff1/elf/rtld.c +--- glibc-2.12-2-gc4ccff1.orig/elf/rtld.c 2013-04-24 16:06:10.410756438 -0400 ++++ glibc-2.12-2-gc4ccff1/elf/rtld.c 2013-04-24 16:06:49.096604693 -0400 +@@ -1637,6 +1637,10 @@ + } + } + ++ /* Keep track of the currently loaded modules to count how many ++ non-audit modules which use TLS are loaded. */ ++ size_t count_modids = _dl_count_modids (); ++ + /* Set up debugging before the debugger is notified for the first time. */ + #ifdef ELF_MACHINE_DEBUG_SETUP + /* Some machines (e.g. MIPS) don't use DT_DEBUG in this way. */ +@@ -2281,7 +2285,8 @@ + # define NONTLS_INIT_TP do { } while (0) + #endif + +- if (!was_tls_init_tp_called && GL(dl_tls_max_dtv_idx) > 0) ++ if ((!was_tls_init_tp_called && GL(dl_tls_max_dtv_idx) > 0) ++ || count_modids != _dl_count_modids ()) + ++GL(dl_tls_generation); + + /* Now that we have completed relocation, the initializer data +diff -urN glibc-2.12-2-gc4ccff1.orig/elf/tst-audit9.c glibc-2.12-2-gc4ccff1/elf/tst-audit9.c +--- glibc-2.12-2-gc4ccff1.orig/elf/tst-audit9.c 1969-12-31 19:00:00.000000000 -0500 ++++ glibc-2.12-2-gc4ccff1/elf/tst-audit9.c 2013-04-24 16:06:49.096604693 -0400 +@@ -0,0 +1,8 @@ ++#include <dlfcn.h> ++ ++int main(void) ++{ ++ void *h = dlopen("$ORIGIN/tst-auditmod9b.so", RTLD_LAZY); ++ int (*fp)(void) = dlsym(h, "f"); ++ return fp() - 1; ++} +diff -urN glibc-2.12-2-gc4ccff1.orig/elf/tst-auditmod9a.c glibc-2.12-2-gc4ccff1/elf/tst-auditmod9a.c +--- glibc-2.12-2-gc4ccff1.orig/elf/tst-auditmod9a.c 1969-12-31 19:00:00.000000000 -0500 ++++ glibc-2.12-2-gc4ccff1/elf/tst-auditmod9a.c 2013-04-24 16:06:49.097604689 -0400 +@@ -0,0 +1,16 @@ ++#include <stdint.h> ++ ++__thread int var; ++ ++unsigned int ++la_version (unsigned int v) ++{ ++ return v; ++} ++ ++void ++la_activity (uintptr_t *cookie, unsigned int flag) ++{ ++ ++var; ++} ++ +diff -urN glibc-2.12-2-gc4ccff1.orig/elf/tst-auditmod9b.c glibc-2.12-2-gc4ccff1/elf/tst-auditmod9b.c +--- glibc-2.12-2-gc4ccff1.orig/elf/tst-auditmod9b.c 1969-12-31 19:00:00.000000000 -0500 ++++ glibc-2.12-2-gc4ccff1/elf/tst-auditmod9b.c 2013-04-24 16:06:49.097604689 -0400 +@@ -0,0 +1,6 @@ ++__thread int a; ++ ++int f(void) ++{ ++ return ++a; ++} +diff -urN glibc-2.12-2-gc4ccff1.orig/sysdeps/generic/ldsodefs.h glibc-2.12-2-gc4ccff1/sysdeps/generic/ldsodefs.h +--- glibc-2.12-2-gc4ccff1.orig/sysdeps/generic/ldsodefs.h 2013-04-24 16:06:10.545755798 -0400 ++++ glibc-2.12-2-gc4ccff1/sysdeps/generic/ldsodefs.h 2013-04-24 16:06:49.098604686 -0400 +@@ -1031,6 +1031,9 @@ + /* Determine next available module ID. */ + extern size_t _dl_next_tls_modid (void) internal_function attribute_hidden; + ++/* Count the modules with TLS segments. */ ++extern size_t _dl_count_modids (void) internal_function attribute_hidden; ++ + /* Calculate offset of the TLS blocks in the static TLS block. */ + extern void _dl_determine_tlsoffset (void) internal_function attribute_hidden; + diff --git a/src/patches/glibc/glibc-rh929302.patch b/src/patches/glibc/glibc-rh929302.patch new file mode 100644 index 0000000..305b339 --- /dev/null +++ b/src/patches/glibc/glibc-rh929302.patch @@ -0,0 +1,98 @@ +From decadad73858bc108828eed5540c7955dc2a977b Mon Sep 17 00:00:00 2001 +From: Adhemerval Zanella azanella@linux.vnet.ibm.com +Date: Fri, 7 Jun 2013 14:44:58 -0500 +Subject: [PATCH 1/2] PowerPC: Change sched_getcpu to use vDSO getcpu instead of syscall. + +Backport of d5e0b9bd6e296f3ec5263fa296d39f3fed9b8fa2 from master. +--- + sysdeps/unix/sysv/linux/powerpc/Versions | 1 + + sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h | 2 + + sysdeps/unix/sysv/linux/powerpc/init-first.c | 3 ++ + sysdeps/unix/sysv/linux/powerpc/sched_getcpu.c | 30 ++++++++++++++++++++++ + 4 files changed, 36 insertions(+), 0 deletions(-) + create mode 100644 sysdeps/unix/sysv/linux/powerpc/sched_getcpu.c + +diff --git a/sysdeps/unix/sysv/linux/powerpc/Versions b/sysdeps/unix/sysv/linux/powerpc/Versions +index 1ef53b9..396a423 100644 +--- a/sysdeps/unix/sysv/linux/powerpc/Versions ++++ b/sysdeps/unix/sysv/linux/powerpc/Versions +@@ -3,5 +3,6 @@ libc { + __vdso_get_tbfreq; + __vdso_clock_gettime; + __vdso_clock_getres; ++ __vdso_getcpu; + } + } +diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h b/sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h +index 746d9ce..c3026d5 100644 +--- a/sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h ++++ b/sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h +@@ -31,6 +31,8 @@ extern void *__vdso_clock_getres; + + extern void *__vdso_get_tbfreq; + ++extern void *__vdso_getcpu; ++ + #endif + + #endif /* _LIBC_VDSO_H */ +diff --git a/sysdeps/unix/sysv/linux/powerpc/init-first.c b/sysdeps/unix/sysv/linux/powerpc/init-first.c +index 92dacc7..cfed655 100644 +--- a/sysdeps/unix/sysv/linux/powerpc/init-first.c ++++ b/sysdeps/unix/sysv/linux/powerpc/init-first.c +@@ -27,6 +27,7 @@ void *__vdso_gettimeofday attribute_hidden; + void *__vdso_clock_gettime; + void *__vdso_clock_getres; + void *__vdso_get_tbfreq; ++void *__vdso_getcpu; + + + static inline void +@@ -41,6 +42,8 @@ _libc_vdso_platform_setup (void) + __vdso_clock_getres = _dl_vdso_vsym ("__kernel_clock_getres", &linux2615); + + __vdso_get_tbfreq = _dl_vdso_vsym ("__kernel_vdso_get_tbfreq", &linux2615); ++ ++ __vdso_getcpu = _dl_vdso_vsym ("__kernel_getcpu", &linux2615); + } + + # define VDSO_SETUP _libc_vdso_platform_setup +diff --git a/sysdeps/unix/sysv/linux/powerpc/sched_getcpu.c b/sysdeps/unix/sysv/linux/powerpc/sched_getcpu.c +new file mode 100644 +index 0000000..617e6f1 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/powerpc/sched_getcpu.c +@@ -0,0 +1,30 @@ ++/* 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 ++ http://www.gnu.org/licenses/. */ ++ ++#include <sched.h> ++#include <sysdep.h> ++#include <bits/libc-vdso.h> ++ ++ ++int ++sched_getcpu (void) ++{ ++ unsigned int cpu; ++ int r = INLINE_VSYSCALL (getcpu, 3, &cpu, NULL, NULL); ++ ++ return r == -1 ? r : cpu; ++} +-- +1.7.1 + diff --git a/src/patches/glibc/glibc-rh970776.patch b/src/patches/glibc/glibc-rh970776.patch new file mode 100644 index 0000000..ec2f2a6 --- /dev/null +++ b/src/patches/glibc/glibc-rh970776.patch @@ -0,0 +1,279 @@ +Patch attached to bugzilla by Ankit Patel, from Red Hat translation team. + +Index: glibc-2.12-2-gc4ccff1/po/de.po +=================================================================== +--- glibc-2.12-2-gc4ccff1.orig/po/de.po 2010-05-04 08:27:23.000000000 -0300 ++++ glibc-2.12-2-gc4ccff1/po/de.po 2013-07-23 20:35:03.213177408 -0300 +@@ -2396,14 +2396,14 @@ msgstr "Zu viele Benutzer" + msgid "Disk quota exceeded" + msgstr "Der zugewiesene Plattenplatz (Quota) ist ÃŒberschritten" + +-#. TRANS Stale NFS file handle. This indicates an internal confusion in the NFS +-#. TRANS system which is due to file system rearrangements on the server host. +-#. TRANS Repairing this condition usually requires unmounting and remounting +-#. TRANS the NFS file system on the local host. +-#: stdio-common/../sysdeps/gnu/errlist.c:779 +-#: stdio-common/../sysdeps/unix/sysv/sysv4/solaris2/sparc/errlist.c:181 +-msgid "Stale NFS file handle" +-msgstr "Veraltete NFS-Dateizugriffsnummer" ++#. TRANS Stale file handle. This indicates an internal confusion in the ++#. TRANS file system which is due to file system rearrangements on the server host ++#. TRANS for NFS filesystems or corruption in other filesystems. ++#. TRANS Repairing this condition usually requires unmounting, possibly ++#. TRANS repairing and remounting the file system. ++#: sysdeps/gnu/errlist.c:787 ++msgid "Stale file handle" ++msgstr "Veraltetes Datei-Handle" + + #. TRANS An attempt was made to NFS-mount a remote file system with a file name that + #. TRANS already specifies an NFS-mounted file. +Index: glibc-2.12-2-gc4ccff1/po/es.po +=================================================================== +--- glibc-2.12-2-gc4ccff1.orig/po/es.po 2010-05-04 08:27:23.000000000 -0300 ++++ glibc-2.12-2-gc4ccff1/po/es.po 2013-07-23 20:35:03.243175029 -0300 +@@ -2533,14 +2533,14 @@ msgstr "Se ha excedido la cuota de disco + # Muy bien, he buscado "stale" y por lo que parece es algo que "caduca" + # o que "vence", como las letras comerciales. Me he decidido por "en desuso". + # +-#. TRANS Stale NFS file handle. This indicates an internal confusion in the NFS +-#. TRANS system which is due to file system rearrangements on the server host. +-#. TRANS Repairing this condition usually requires unmounting and remounting +-#. TRANS the NFS file system on the local host. +-#: stdio-common/../sysdeps/gnu/errlist.c:779 +-#: stdio-common/../sysdeps/unix/sysv/sysv4/solaris2/sparc/errlist.c:181 +-msgid "Stale NFS file handle" +-msgstr "`handle' de fichero NFS en desuso" ++#. TRANS Stale file handle. This indicates an internal confusion in the ++#. TRANS file system which is due to file system rearrangements on the server host ++#. TRANS for NFS filesystems or corruption in other filesystems. ++#. TRANS Repairing this condition usually requires unmounting, possibly ++#. TRANS repairing and remounting the file system. ++#: sysdeps/gnu/errlist.c:787 ++msgid "Stale file handle" ++msgstr "Identificador de archivos obsoletos" + + #. TRANS An attempt was made to NFS-mount a remote file system with a file name that + #. TRANS already specifies an NFS-mounted file. +Index: glibc-2.12-2-gc4ccff1/po/fr.po +=================================================================== +--- glibc-2.12-2-gc4ccff1.orig/po/fr.po 2010-05-04 08:27:23.000000000 -0300 ++++ glibc-2.12-2-gc4ccff1/po/fr.po 2013-07-23 20:35:03.250174474 -0300 +@@ -5802,13 +5802,14 @@ msgstr "Trop d'usagers" + msgid "Disk quota exceeded" + msgstr "Débordement du quota d'espace disque" + +-#. TRANS Stale NFS file handle. This indicates an internal confusion in the NFS +-#. TRANS system which is due to file system rearrangements on the server host. +-#. TRANS Repairing this condition usually requires unmounting and remounting +-#. TRANS the NFS file system on the local host. ++#. TRANS Stale file handle. This indicates an internal confusion in the ++#. TRANS file system which is due to file system rearrangements on the server host ++#. TRANS for NFS filesystems or corruption in other filesystems. ++#. TRANS Repairing this condition usually requires unmounting, possibly ++#. TRANS repairing and remounting the file system. + #: sysdeps/gnu/errlist.c:787 +-msgid "Stale NFS file handle" +-msgstr "Panne d'accÚs au fichier NFS" ++msgid "Stale file handle" ++msgstr "Gestionnaire de fichiers périmés" + + #. TRANS An attempt was made to NFS-mount a remote file system with a file name that + #. TRANS already specifies an NFS-mounted file. +Index: glibc-2.12-2-gc4ccff1/po/it.po +=================================================================== +--- glibc-2.12-2-gc4ccff1.orig/po/it.po 2010-05-04 08:27:23.000000000 -0300 ++++ glibc-2.12-2-gc4ccff1/po/it.po 2013-07-23 20:35:03.253174237 -0300 +@@ -1662,6 +1662,15 @@ msgstr "Superata la quota di disco" + msgid "Disk quota exceeded" + msgstr "Superata la quota di disco" + ++#. TRANS Stale file handle. This indicates an internal confusion in the ++#. TRANS file system which is due to file system rearrangements on the server host ++#. TRANS for NFS filesystems or corruption in other filesystems. ++#. TRANS Repairing this condition usually requires unmounting, possibly ++#. TRANS repairing and remounting the file system. ++#: sysdeps/gnu/errlist.c:787 ++msgid "Stale file handle" ++msgstr "Gestione file obsoleti" ++ + #: nscd/nscd.c:86 + msgid "Do not fork and display messages on the current tty" + msgstr "Non fa fork e stampa i messaggi sul tty corrente" +Index: glibc-2.12-2-gc4ccff1/po/ja.po +=================================================================== +--- glibc-2.12-2-gc4ccff1.orig/po/ja.po 2013-07-23 04:01:34.628665260 -0300 ++++ glibc-2.12-2-gc4ccff1/po/ja.po 2013-07-23 20:35:03.304170193 -0300 +@@ -2333,14 +2333,14 @@ msgstr "¥æ¡Œ¥¶€¬Â¿€¹€®€Þ€¹" + msgid "Disk quota exceeded" + msgstr "¥Ç¥£¥¹¥¯»ÈÍÑÎÌÀ©žÂ€òĶ²á€·€Þ€·€¿" + +-#. TRANS Stale NFS file handle. This indicates an internal confusion in the NFS +-#. TRANS system which is due to file system rearrangements on the server host. +-#. TRANS Repairing this condition usually requires unmounting and remounting +-#. TRANS the NFS file system on the local host. +-#: stdio-common/../sysdeps/gnu/errlist.c:779 +-#: stdio-common/../sysdeps/unix/sysv/sysv4/solaris2/sparc/errlist.c:181 +-msgid "Stale NFS file handle" +-msgstr "ŒÂžúÀ€Î€Ê€€NFS¥Õ¥¡¥€¥ë¥Ï¥ó¥É¥ë€Ç€¹" ++#. TRANS Stale file handle. This indicates an internal confusion in the ++#. TRANS file system which is due to file system rearrangements on the server host ++#. TRANS for NFS filesystems or corruption in other filesystems. ++#. TRANS Repairing this condition usually requires unmounting, possibly ++#. TRANS repairing and remounting the file system. ++#: sysdeps/gnu/errlist.c:787 ++msgid "Stale file handle" ++msgstr "žÅ€€¥Õ¥¡¥€¥ë¥Ï¥ó¥É¥ë€Ç€¹" + + #. TRANS An attempt was made to NFS-mount a remote file system with a file name that + #. TRANS already specifies an NFS-mounted file. +Index: glibc-2.12-2-gc4ccff1/po/ko.po +=================================================================== +--- glibc-2.12-2-gc4ccff1.orig/po/ko.po 2010-05-04 08:27:23.000000000 -0300 ++++ glibc-2.12-2-gc4ccff1/po/ko.po 2013-07-23 20:35:03.311169638 -0300 +@@ -5803,13 +5803,14 @@ msgstr "ì¬ì©ìê° ë묎 ë§ì" + msgid "Disk quota exceeded" + msgstr "ëì€í¬ í ë¹ëìŽ ìŽê³Œëš" + +-#. TRANS Stale NFS file handle. This indicates an internal confusion in the NFS +-#. TRANS system which is due to file system rearrangements on the server host. +-#. TRANS Repairing this condition usually requires unmounting and remounting +-#. TRANS the NFS file system on the local host. ++#. TRANS Stale file handle. This indicates an internal confusion in the ++#. TRANS file system which is due to file system rearrangements on the server host ++#. TRANS for NFS filesystems or corruption in other filesystems. ++#. TRANS Repairing this condition usually requires unmounting, possibly ++#. TRANS repairing and remounting the file system. + #: sysdeps/gnu/errlist.c:787 +-msgid "Stale NFS file handle" +-msgstr "ëìŽì§ NFS íìŒ ížë€" ++msgid "Stale file handle" ++msgstr "ì€ëë íìŒ ì²ëŠ¬" + + #. TRANS An attempt was made to NFS-mount a remote file system with a file name that + #. TRANS already specifies an NFS-mounted file. +Index: glibc-2.12-2-gc4ccff1/po/libc.pot +=================================================================== +--- glibc-2.12-2-gc4ccff1.orig/po/libc.pot 2010-05-04 08:27:23.000000000 -0300 ++++ glibc-2.12-2-gc4ccff1/po/libc.pot 2013-07-23 20:35:03.326168449 -0300 +@@ -5696,12 +5696,13 @@ msgstr "" + msgid "Disk quota exceeded" + msgstr "" + +-#. TRANS Stale NFS file handle. This indicates an internal confusion in the NFS +-#. TRANS system which is due to file system rearrangements on the server host. +-#. TRANS Repairing this condition usually requires unmounting and remounting +-#. TRANS the NFS file system on the local host. ++#. TRANS Stale file handle. This indicates an internal confusion in the ++#. TRANS file system which is due to file system rearrangements on the server host ++#. TRANS for NFS filesystems or corruption in other filesystems. ++#. TRANS Repairing this condition usually requires unmounting, possibly ++#. TRANS repairing and remounting the file system. + #: sysdeps/gnu/errlist.c:787 +-msgid "Stale NFS file handle" ++msgid "Stale file handle" + msgstr "" + + #. TRANS An attempt was made to NFS-mount a remote file system with a file name that +Index: glibc-2.12-2-gc4ccff1/po/pt_BR.po +=================================================================== +--- glibc-2.12-2-gc4ccff1.orig/po/pt_BR.po 2010-05-04 08:27:23.000000000 -0300 ++++ glibc-2.12-2-gc4ccff1/po/pt_BR.po 2013-07-23 20:35:03.331168053 -0300 +@@ -2287,13 +2287,14 @@ msgstr "Erro de Srmount" + msgid "Stack fault" + msgstr "Falha de pilha" + +-#. TRANS Stale NFS file handle. This indicates an internal confusion in the NFS +-#. TRANS system which is due to file system rearrangements on the server host. +-#. TRANS Repairing this condition usually requires unmounting and remounting +-#. TRANS the NFS file system on the local host. +-#: stdio-common/../sysdeps/gnu/errlist.c:506 +-msgid "Stale NFS file handle" +-msgstr "Manipulador de arquivo NFS corrompido" ++#. TRANS Stale file handle. This indicates an internal confusion in the ++#. TRANS file system which is due to file system rearrangements on the server host ++#. TRANS for NFS filesystems or corruption in other filesystems. ++#. TRANS Repairing this condition usually requires unmounting, possibly ++#. TRANS repairing and remounting the file system. ++#: sysdeps/gnu/errlist.c:787 ++msgid "Stale file handle" ++msgstr "Manipulador de arquivo obsoleto" + + #: nscd/nscd.c:81 + msgid "Start NUMBER threads" +Index: glibc-2.12-2-gc4ccff1/po/ru.po +=================================================================== +--- glibc-2.12-2-gc4ccff1.orig/po/ru.po 2010-05-04 08:27:23.000000000 -0300 ++++ glibc-2.12-2-gc4ccff1/po/ru.po 2013-07-23 20:35:03.338167498 -0300 +@@ -5798,13 +5798,14 @@ msgstr "СлОÑкПЌ ЌМПгП пПл + msgid "Disk quota exceeded" + msgstr "ÐÑевÑÑеМа ЎОÑÐºÐŸÐ²Ð°Ñ ÐºÐ²ÐŸÑа" + +-#. TRANS Stale NFS file handle. This indicates an internal confusion in the NFS +-#. TRANS system which is due to file system rearrangements on the server host. +-#. TRANS Repairing this condition usually requires unmounting and remounting +-#. TRANS the NFS file system on the local host. ++#. TRANS Stale file handle. This indicates an internal confusion in the ++#. TRANS file system which is due to file system rearrangements on the server host ++#. TRANS for NFS filesystems or corruption in other filesystems. ++#. TRANS Repairing this condition usually requires unmounting, possibly ++#. TRANS repairing and remounting the file system. + #: sysdeps/gnu/errlist.c:787 +-msgid "Stale NFS file handle" +-msgstr "УÑÑаÑевÑОй Ñ ÑМЎл Ñайла NFS" ++msgid "Stale file handle" ++msgstr "УÑÑаÑевÑОй ЎеÑкÑОпÑÐŸÑ Ñайла" + + #. TRANS An attempt was made to NFS-mount a remote file system with a file name that + #. TRANS already specifies an NFS-mounted file. +Index: glibc-2.12-2-gc4ccff1/po/zh_CN.po +=================================================================== +--- glibc-2.12-2-gc4ccff1.orig/po/zh_CN.po 2010-05-04 08:27:23.000000000 -0300 ++++ glibc-2.12-2-gc4ccff1/po/zh_CN.po 2013-07-23 20:35:03.344167022 -0300 +@@ -5519,13 +5519,14 @@ msgstr "çšæ·è¿å€" + msgid "Disk quota exceeded" + msgstr "è¶ åºç£çéé¢" + +-#. TRANS Stale NFS file handle. This indicates an internal confusion in the NFS +-#. TRANS system which is due to file system rearrangements on the server host. +-#. TRANS Repairing this condition usually requires unmounting and remounting +-#. TRANS the NFS file system on the local host. ++#. TRANS Stale file handle. This indicates an internal confusion in the ++#. TRANS file system which is due to file system rearrangements on the server host ++#. TRANS for NFS filesystems or corruption in other filesystems. ++#. TRANS Repairing this condition usually requires unmounting, possibly ++#. TRANS repairing and remounting the file system. + #: sysdeps/gnu/errlist.c:787 +-msgid "Stale NFS file handle" +-msgstr "" ++msgid "Stale file handle" ++msgstr "倱ææ件å¥æ" + + #. TRANS An attempt was made to NFS-mount a remote file system with a file name that + #. TRANS already specifies an NFS-mounted file. +Index: glibc-2.12-2-gc4ccff1/po/zh_TW.po +=================================================================== +--- glibc-2.12-2-gc4ccff1.orig/po/zh_TW.po 2010-05-04 08:27:23.000000000 -0300 ++++ glibc-2.12-2-gc4ccff1/po/zh_TW.po 2013-07-23 20:35:03.349166626 -0300 +@@ -2333,14 +2333,14 @@ msgstr "倪å€äœ¿çšè " + msgid "Disk quota exceeded" + msgstr "ç¡¬ç¢ quota 滿äº" + +-#. TRANS Stale NFS file handle. This indicates an internal confusion in the NFS +-#. TRANS system which is due to file system rearrangements on the server host. +-#. TRANS Repairing this condition usually requires unmounting and remounting +-#. TRANS the NFS file system on the local host. +-#: stdio-common/../sysdeps/gnu/errlist.c:779 +-#: stdio-common/../sysdeps/unix/sysv/sysv4/solaris2/sparc/errlist.c:181 +-msgid "Stale NFS file handle" +-msgstr "éèç NFS æªæ¡æ§å¶ç¢Œ" ++#. TRANS Stale file handle. This indicates an internal confusion in the ++#. TRANS file system which is due to file system rearrangements on the server host ++#. TRANS for NFS filesystems or corruption in other filesystems. ++#. TRANS Repairing this condition usually requires unmounting, possibly ++#. TRANS repairing and remounting the file system. ++#: sysdeps/gnu/errlist.c:787 ++msgid "Stale file handle" ++msgstr "éèçæªæ¡èç" + + #. TRANS An attempt was made to NFS-mount a remote file system with a file name that + #. TRANS already specifies an NFS-mounted file. diff --git a/src/patches/glibc/glibc-rh970992.patch b/src/patches/glibc/glibc-rh970992.patch deleted file mode 100644 index 42aa819..0000000 --- a/src/patches/glibc/glibc-rh970992.patch +++ /dev/null @@ -1,190 +0,0 @@ -# -# Patch provided by Ulrich Drepper in BZ#919562. -# -# Patch has not been sent upstream. -# -# 2013-03-08 Ulrich Drepper drepper@gmail.com -# -# * elf/rtld.c (dl_main): Correctly determine when the application -# required DSOs with TLS and bump the generation counter in that -# case. The current condition does not account for an audit -# module using TLS. -# * elf/dl-tls.c (_dl_count_modids): New function. -# (_dl_allocate_tls_init): Add assertion to check TLS -# generation. -# * sysdeps/generic/ldsodefs.h: Declare _dl_count_modids. -# * elf/Makefile: Add rules to build and run tst-audit9. -# * elf/tst-audit9.c: New file. -# * elf/tst-auditmod9a.c: New file. -# * elf/tst-auditmod9b.c: New file. -# -diff -urN glibc-2.12-2-gc4ccff1.orig/elf/dl-tls.c glibc-2.12-2-gc4ccff1/elf/dl-tls.c ---- glibc-2.12-2-gc4ccff1.orig/elf/dl-tls.c 2013-04-24 16:06:10.410756438 -0400 -+++ glibc-2.12-2-gc4ccff1/elf/dl-tls.c 2013-04-24 16:06:49.092604707 -0400 -@@ -109,6 +109,28 @@ - } - - -+size_t -+internal_function -+_dl_count_modids (void) -+{ -+ if (! __builtin_expect (GL(dl_tls_dtv_gaps), true)) -+ return GL(dl_tls_max_dtv_idx); -+ -+ size_t n = 0; -+ struct dtv_slotinfo_list *runp = GL(dl_tls_dtv_slotinfo_list); -+ while (runp != NULL) -+ { -+ for (size_t i = 0; i < runp->len; ++i) -+ if (runp->slotinfo[i].map != NULL) -+ ++n; -+ -+ runp = runp->next; -+ } -+ -+ return n; -+} -+ -+ - #ifdef SHARED - void - internal_function -@@ -411,6 +433,7 @@ - - /* Keep track of the maximum generation number. This might - not be the generation counter. */ -+ assert (listp->slotinfo[cnt].gen <= GL(dl_tls_generation)); - maxgen = MAX (maxgen, listp->slotinfo[cnt].gen); - - if (map->l_tls_offset == NO_TLS_OFFSET -diff -urN glibc-2.12-2-gc4ccff1.orig/elf/Makefile glibc-2.12-2-gc4ccff1/elf/Makefile ---- glibc-2.12-2-gc4ccff1.orig/elf/Makefile 2013-04-24 16:06:10.408756448 -0400 -+++ glibc-2.12-2-gc4ccff1/elf/Makefile 2013-04-24 16:07:29.475457962 -0400 -@@ -97,6 +97,8 @@ - tst-audit6.c tst-auditmod6a.c tst-auditmod6b.c \ - tst-auditmod6c.c \ - tst-audit7.c tst-auditmod7a.c tst-auditmod7b.c \ -+ tst-audit9.c \ -+ tst-auditmod9a.c tst-auditmod9b.c \ - order2mod1.c order2mod2.c order2mod3.c order2mod4.c \ - tst-stackguard1.c tst-stackguard1-static.c \ - tst-array5.c tst-array5-static.c tst-array5dep.c \ -@@ -198,7 +200,7 @@ - tst-dlmodcount tst-dlopenrpath tst-deep1 \ - tst-dlmopen1 tst-dlmopen2 tst-dlmopen3 \ - unload3 unload4 unload5 unload6 unload7 unload8 tst-global1 order2 \ -- tst-audit1 tst-audit2 \ -+ tst-audit1 tst-audit2 tst-audit9 \ - tst-stackguard1 tst-addr1 tst-thrlock \ - tst-unique1 tst-unique2 - # reldep9 -@@ -251,7 +253,8 @@ - unload8mod1 unload8mod1x unload8mod2 unload8mod3 \ - order2mod1 order2mod2 order2mod3 order2mod4 \ - tst-unique1mod1 tst-unique1mod2 \ -- tst-unique2mod1 tst-unique2mod2 -+ tst-unique2mod1 tst-unique2mod2 \ -+ tst-auditmod9a tst-auditmod9b - ifeq (yes,$(have-initfini-array)) - modules-names += tst-array2dep tst-array5dep - endif -@@ -574,6 +577,8 @@ - ifuncmod1.so-no-z-defs = yes - ifuncmod5.so-no-z-defs = yes - ifuncmod6.so-no-z-defs = yes -+tst-auditmod9a.so-no-z-defs = yes -+tst-auditmod9b.so-no-z-defs = yes - - ifeq ($(build-shared),yes) - # Build all the modules even when not actually running test programs. -@@ -1015,6 +1020,10 @@ - $(objpfx)tst-audit7.out: $(objpfx)tst-auditmod7b.so - tst-audit7-ENV = LD_AUDIT=$(objpfx)tst-auditmod7b.so - -+$(objpfx)tst-audit9: $(libdl) -+$(objpfx)tst-audit9.out: $(objpfx)tst-auditmod9a.so $(objpfx)tst-auditmod9b.so -+tst-audit9-ENV = LD_AUDIT=$(objpfx)tst-auditmod9a.so -+ - $(objpfx)tst-global1: $(libdl) - $(objpfx)tst-global1.out: $(objpfx)testobj6.so $(objpfx)testobj2.so - -diff -urN glibc-2.12-2-gc4ccff1.orig/elf/rtld.c glibc-2.12-2-gc4ccff1/elf/rtld.c ---- glibc-2.12-2-gc4ccff1.orig/elf/rtld.c 2013-04-24 16:06:10.410756438 -0400 -+++ glibc-2.12-2-gc4ccff1/elf/rtld.c 2013-04-24 16:06:49.096604693 -0400 -@@ -1637,6 +1637,10 @@ - } - } - -+ /* Keep track of the currently loaded modules to count how many -+ non-audit modules which use TLS are loaded. */ -+ size_t count_modids = _dl_count_modids (); -+ - /* Set up debugging before the debugger is notified for the first time. */ - #ifdef ELF_MACHINE_DEBUG_SETUP - /* Some machines (e.g. MIPS) don't use DT_DEBUG in this way. */ -@@ -2281,7 +2285,8 @@ - # define NONTLS_INIT_TP do { } while (0) - #endif - -- if (!was_tls_init_tp_called && GL(dl_tls_max_dtv_idx) > 0) -+ if ((!was_tls_init_tp_called && GL(dl_tls_max_dtv_idx) > 0) -+ || count_modids != _dl_count_modids ()) - ++GL(dl_tls_generation); - - /* Now that we have completed relocation, the initializer data -diff -urN glibc-2.12-2-gc4ccff1.orig/elf/tst-audit9.c glibc-2.12-2-gc4ccff1/elf/tst-audit9.c ---- glibc-2.12-2-gc4ccff1.orig/elf/tst-audit9.c 1969-12-31 19:00:00.000000000 -0500 -+++ glibc-2.12-2-gc4ccff1/elf/tst-audit9.c 2013-04-24 16:06:49.096604693 -0400 -@@ -0,0 +1,8 @@ -+#include <dlfcn.h> -+ -+int main(void) -+{ -+ void *h = dlopen("$ORIGIN/tst-auditmod9b.so", RTLD_LAZY); -+ int (*fp)(void) = dlsym(h, "f"); -+ return fp() - 1; -+} -diff -urN glibc-2.12-2-gc4ccff1.orig/elf/tst-auditmod9a.c glibc-2.12-2-gc4ccff1/elf/tst-auditmod9a.c ---- glibc-2.12-2-gc4ccff1.orig/elf/tst-auditmod9a.c 1969-12-31 19:00:00.000000000 -0500 -+++ glibc-2.12-2-gc4ccff1/elf/tst-auditmod9a.c 2013-04-24 16:06:49.097604689 -0400 -@@ -0,0 +1,16 @@ -+#include <stdint.h> -+ -+__thread int var; -+ -+unsigned int -+la_version (unsigned int v) -+{ -+ return v; -+} -+ -+void -+la_activity (uintptr_t *cookie, unsigned int flag) -+{ -+ ++var; -+} -+ -diff -urN glibc-2.12-2-gc4ccff1.orig/elf/tst-auditmod9b.c glibc-2.12-2-gc4ccff1/elf/tst-auditmod9b.c ---- glibc-2.12-2-gc4ccff1.orig/elf/tst-auditmod9b.c 1969-12-31 19:00:00.000000000 -0500 -+++ glibc-2.12-2-gc4ccff1/elf/tst-auditmod9b.c 2013-04-24 16:06:49.097604689 -0400 -@@ -0,0 +1,6 @@ -+__thread int a; -+ -+int f(void) -+{ -+ return ++a; -+} -diff -urN glibc-2.12-2-gc4ccff1.orig/sysdeps/generic/ldsodefs.h glibc-2.12-2-gc4ccff1/sysdeps/generic/ldsodefs.h ---- glibc-2.12-2-gc4ccff1.orig/sysdeps/generic/ldsodefs.h 2013-04-24 16:06:10.545755798 -0400 -+++ glibc-2.12-2-gc4ccff1/sysdeps/generic/ldsodefs.h 2013-04-24 16:06:49.098604686 -0400 -@@ -1031,6 +1031,9 @@ - /* Determine next available module ID. */ - extern size_t _dl_next_tls_modid (void) internal_function attribute_hidden; - -+/* Count the modules with TLS segments. */ -+extern size_t _dl_count_modids (void) internal_function attribute_hidden; -+ - /* Calculate offset of the TLS blocks in the static TLS block. */ - extern void _dl_determine_tlsoffset (void) internal_function attribute_hidden; - diff --git a/src/patches/glibc/glibc-rh978098.patch b/src/patches/glibc/glibc-rh978098.patch new file mode 100644 index 0000000..0b53dcc --- /dev/null +++ b/src/patches/glibc/glibc-rh978098.patch @@ -0,0 +1,124 @@ +# +# Based on commit e6c61494125126d2ba77e5d99f83887a2ed49783. +# +# 2011-04-10 Ulrich Drepper drepper@gmail.com +# +# [BZ #12650] +# * sysdeps/i386/dl-tls.h: Define TLS_DTV_UNALLOCATED. +# * sysdeps/ia64/dl-tls.h: Likewise. +# * sysdeps/powerpc/dl-tls.h: Likewise. +# * sysdeps/s390/dl-tls.h: Likewise. +# * sysdeps/sh/dl-tls.h: Likewise. +# * sysdeps/sparc/dl-tls.h: Likewise. +# * sysdeps/x86_64/dl-tls.h: Likewise. +# * elf/dl-tls.c: Don't define TLS_DTV_UNALLOCATED here. +# +diff -urN glibc-2.12-2-gc4ccff1/elf/dl-tls.c glibc-2.12-2-gc4ccff1.mod/elf/dl-tls.c +--- glibc-2.12-2-gc4ccff1/elf/dl-tls.c 2015-02-18 05:16:56.087096028 -0500 ++++ glibc-2.12-2-gc4ccff1.mod/elf/dl-tls.c 2015-02-18 05:21:04.018424445 -0500 +@@ -33,9 +33,6 @@ + to allow dynamic loading of modules defining IE-model TLS data. */ + #define TLS_STATIC_SURPLUS 64 + DL_NNS * 100 + +-/* Value used for dtv entries for which the allocation is delayed. */ +-#define TLS_DTV_UNALLOCATED ((void *) -1l) +- + + /* Out-of-memory handler. */ + #ifdef SHARED +diff -urN glibc-2.12-2-gc4ccff1/nptl/allocatestack.c glibc-2.12-2-gc4ccff1.mod/nptl/allocatestack.c +--- glibc-2.12-2-gc4ccff1/nptl/allocatestack.c 2015-02-18 05:16:56.101095594 -0500 ++++ glibc-2.12-2-gc4ccff1.mod/nptl/allocatestack.c 2015-02-18 05:21:04.019424414 -0500 +@@ -26,6 +26,7 @@ + #include <sys/mman.h> + #include <sys/param.h> + #include <dl-sysdep.h> ++#include <dl-tls.h> + #include <tls.h> + #include <list.h> + #include <lowlevellock.h> +@@ -242,6 +243,10 @@ + + /* Clear the DTV. */ + dtv_t *dtv = GET_DTV (TLS_TPADJ (result)); ++ for (size_t cnt = 0; cnt < dtv[-1].counter; ++cnt) ++ if (! dtv[1 + cnt].pointer.is_static ++ && dtv[1 + cnt].pointer.val != TLS_DTV_UNALLOCATED) ++ free (dtv[1 + cnt].pointer.val); + memset (dtv, '\0', (dtv[-1].counter + 1) * sizeof (dtv_t)); + + /* Re-initialize the TLS. */ +diff -urN glibc-2.12-2-gc4ccff1/sysdeps/i386/dl-tls.h glibc-2.12-2-gc4ccff1.mod/sysdeps/i386/dl-tls.h +--- glibc-2.12-2-gc4ccff1/sysdeps/i386/dl-tls.h 2010-05-04 07:27:23.000000000 -0400 ++++ glibc-2.12-2-gc4ccff1.mod/sysdeps/i386/dl-tls.h 2015-02-18 05:21:04.019424414 -0500 +@@ -58,3 +58,6 @@ + + # endif + #endif ++ ++/* Value used for dtv entries for which the allocation is delayed. */ ++#define TLS_DTV_UNALLOCATED ((void *) -1l) +diff -urN glibc-2.12-2-gc4ccff1/sysdeps/ia64/dl-tls.h glibc-2.12-2-gc4ccff1.mod/sysdeps/ia64/dl-tls.h +--- glibc-2.12-2-gc4ccff1/sysdeps/ia64/dl-tls.h 2010-05-04 07:27:23.000000000 -0400 ++++ glibc-2.12-2-gc4ccff1.mod/sysdeps/ia64/dl-tls.h 2015-02-18 05:21:04.019424414 -0500 +@@ -28,3 +28,6 @@ + #define DONT_USE_TLS_INDEX 1 + + extern void *__tls_get_addr (size_t m, size_t offset); ++ ++/* Value used for dtv entries for which the allocation is delayed. */ ++#define TLS_DTV_UNALLOCATED ((void *) -1l) +diff -urN glibc-2.12-2-gc4ccff1/sysdeps/powerpc/dl-tls.h glibc-2.12-2-gc4ccff1.mod/sysdeps/powerpc/dl-tls.h +--- glibc-2.12-2-gc4ccff1/sysdeps/powerpc/dl-tls.h 2010-05-04 07:27:23.000000000 -0400 ++++ glibc-2.12-2-gc4ccff1.mod/sysdeps/powerpc/dl-tls.h 2015-02-18 05:21:04.019424414 -0500 +@@ -47,3 +47,6 @@ + # define GET_ADDR_OFFSET (ti->ti_offset + TLS_DTV_OFFSET) + # define __TLS_GET_ADDR(__ti) (__tls_get_addr (__ti) - TLS_DTV_OFFSET) + #endif ++ ++/* Value used for dtv entries for which the allocation is delayed. */ ++#define TLS_DTV_UNALLOCATED ((void *) -1l) +diff -urN glibc-2.12-2-gc4ccff1/sysdeps/s390/dl-tls.h glibc-2.12-2-gc4ccff1.mod/sysdeps/s390/dl-tls.h +--- glibc-2.12-2-gc4ccff1/sysdeps/s390/dl-tls.h 2010-05-04 07:27:23.000000000 -0400 ++++ glibc-2.12-2-gc4ccff1.mod/sysdeps/s390/dl-tls.h 2015-02-18 05:21:04.019424414 -0500 +@@ -72,6 +72,9 @@ + # define __TLS_GET_ADDR(__ti) \ + ({ extern char _GLOBAL_OFFSET_TABLE_[] attribute_hidden; \ + (void *) __tls_get_offset ((char *) (__ti) - _GLOBAL_OFFSET_TABLE_) \ +- + (unsigned long) __builtin_thread_pointer (); }) ++ + (unsigned long) __builtin_thread_pointer (); }) + + #endif ++ ++/* Value used for dtv entries for which the allocation is delayed. */ ++#define TLS_DTV_UNALLOCATED ((void *) -1l) +diff -urN glibc-2.12-2-gc4ccff1/sysdeps/sh/dl-tls.h glibc-2.12-2-gc4ccff1.mod/sysdeps/sh/dl-tls.h +--- glibc-2.12-2-gc4ccff1/sysdeps/sh/dl-tls.h 2010-05-04 07:27:23.000000000 -0400 ++++ glibc-2.12-2-gc4ccff1.mod/sysdeps/sh/dl-tls.h 2015-02-18 05:21:04.019424414 -0500 +@@ -27,3 +27,6 @@ + + + extern void *__tls_get_addr (tls_index *ti); ++ ++/* Value used for dtv entries for which the allocation is delayed. */ ++#define TLS_DTV_UNALLOCATED ((void *) -1l) +diff -urN glibc-2.12-2-gc4ccff1/sysdeps/sparc/dl-tls.h glibc-2.12-2-gc4ccff1.mod/sysdeps/sparc/dl-tls.h +--- glibc-2.12-2-gc4ccff1/sysdeps/sparc/dl-tls.h 2010-05-04 07:27:23.000000000 -0400 ++++ glibc-2.12-2-gc4ccff1.mod/sysdeps/sparc/dl-tls.h 2015-02-18 05:21:04.019424414 -0500 +@@ -27,3 +27,6 @@ + + + extern void *__tls_get_addr (tls_index *ti); ++ ++/* Value used for dtv entries for which the allocation is delayed. */ ++#define TLS_DTV_UNALLOCATED ((void *) -1l) +diff -urN glibc-2.12-2-gc4ccff1/sysdeps/x86_64/dl-tls.h glibc-2.12-2-gc4ccff1.mod/sysdeps/x86_64/dl-tls.h +--- glibc-2.12-2-gc4ccff1/sysdeps/x86_64/dl-tls.h 2010-05-04 07:27:23.000000000 -0400 ++++ glibc-2.12-2-gc4ccff1.mod/sysdeps/x86_64/dl-tls.h 2015-02-18 05:21:04.019424414 -0500 +@@ -27,3 +27,6 @@ + + + extern void *__tls_get_addr (tls_index *ti); ++ ++/* Value used for dtv entries for which the allocation is delayed. */ ++#define TLS_DTV_UNALLOCATED ((void *) -1l) diff --git a/src/patches/glibc/glibc-rh981942.patch b/src/patches/glibc/glibc-rh981942.patch new file mode 100644 index 0000000..cbe1ab8 --- /dev/null +++ b/src/patches/glibc/glibc-rh981942.patch @@ -0,0 +1,22 @@ +commit 2e96f1c73b06e81da59ef7fffa426dc201875f31 +Author: Andreas Schwab schwab@redhat.com +Date: Thu Aug 4 15:42:10 2011 -0400 + + Fix encoding name for IDN in getaddrinfo + +diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c +index 6d574c5..a5aafe9 100644 +--- a/sysdeps/posix/getaddrinfo.c ++++ b/sysdeps/posix/getaddrinfo.c +@@ -432,7 +432,10 @@ gaih_inet (const char *name, const struct gaih_service *service, + /* In case the output string is the same as the input string + no new string has been allocated. */ + if (p != name) +- malloc_name = true; ++ { ++ name = p; ++ malloc_name = true; ++ } + } + #endif + diff --git a/src/patches/glibc/glibc-rh988931.patch b/src/patches/glibc/glibc-rh988931.patch new file mode 100644 index 0000000..38594a4 --- /dev/null +++ b/src/patches/glibc/glibc-rh988931.patch @@ -0,0 +1,33 @@ +commit e23fe25b33324a9ea992276c1a4f04127bf9ba4b +Author: Andreas Schwab schwab@redhat.com +Date: Sun Feb 20 07:24:56 2011 -0500 + + Move setting variable in relro data earlier in ld.so. + +diff --git a/elf/rtld.c b/elf/rtld.c +index 8510380..174954b 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -2179,6 +2179,10 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n", + we need it in the memory handling later. */ + GLRO(dl_initial_searchlist) = *GL(dl_ns)[LM_ID_BASE]._ns_main_searchlist; + ++ /* Remember the last search directory added at startup, now that ++ malloc will no longer be the one from dl-minimal.c. */ ++ GLRO(dl_init_all_dirs) = GL(dl_all_dirs); ++ + if (prelinked) + { + if (main_map->l_info [ADDRIDX (DT_GNU_CONFLICT)] != NULL) +@@ -2298,9 +2302,8 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n", + lossage); + } + +- /* Remember the last search directory added at startup, now that +- malloc will no longer be the one from dl-minimal.c. */ +- GLRO(dl_init_all_dirs) = GL(dl_all_dirs); ++ /* Make sure no new search directories have been added. */ ++ assert (GLRO(dl_init_all_dirs) == GL(dl_all_dirs)); + + if (! prelinked && rtld_multiple_ref) + { diff --git a/src/patches/glibc/glibc-rh989558-2.patch b/src/patches/glibc/glibc-rh989558-2.patch deleted file mode 100644 index ad895c7..0000000 --- a/src/patches/glibc/glibc-rh989558-2.patch +++ /dev/null @@ -1,107 +0,0 @@ -2013-05-03 Carlos O'Donell <carlos at redhat.com> - - * intl/dcigettext.c (DCIGETTEXT): Skip translating if _nl_find_msg returns -1. - (_nl_find_msg): Return -1 if recursive call returned -1. If newmem is null - return -1. - * intl/loadmsgcat.c (_nl_load_domain): If _nl_find_msg returns -1 abort - loading the domain. - -diff -Nrup a/intl/dcigettext.c b/intl/dcigettext.c ---- a/intl/dcigettext.c 2010-05-04 07:27:23.000000000 -0400 -+++ b/intl/dcigettext.c 2013-08-01 00:11:54.616363264 -0400 -@@ -640,6 +640,11 @@ DCIGETTEXT (domainname, msgid1, msgid2, - retval = _nl_find_msg (domain->successor[cnt], binding, - msgid1, 1, &retlen); - -+ /* Resource problems are not fatal, instead we return no -+ translation. */ -+ if (__builtin_expect (retval == (char *) -1, 0)) -+ goto no_translation; -+ - if (retval != NULL) - { - domain = domain->successor[cnt]; -@@ -943,6 +948,11 @@ _nl_find_msg (domain_file, domainbinding - nullentry = - _nl_find_msg (domain_file, domainbinding, "", 0, &nullentrylen); - -+ /* Resource problems are fatal. If we continue onwards we will -+ only attempt to calloc a new conv_tab and fail later. */ -+ if (__builtin_expect (nullentry == (char *) -1, 0)) -+ return (char *) -1; -+ - if (nullentry != NULL) - { - const char *charsetstr; -@@ -1156,7 +1166,7 @@ _nl_find_msg (domain_file, domainbinding - freemem_size); - # ifdef _LIBC - if (newmem != NULL) -- transmem_list = transmem_list->next; -+ transmem_list = newmem; - else - { - struct transmem_list *old = transmem_list; -@@ -1171,6 +1181,16 @@ _nl_find_msg (domain_file, domainbinding - malloc_count = 1; - freemem_size = INITIAL_BLOCK_SIZE; - newmem = (transmem_block_t *) malloc (freemem_size); -+# ifdef _LIBC -+ if (newmem != NULL) -+ { -+ /* Add the block to the list of blocks we have to free -+ at some point. */ -+ newmem->next = transmem_list; -+ transmem_list = newmem; -+ } -+ /* Fall through and return -1. */ -+# endif - } - if (__builtin_expect (newmem == NULL, 0)) - { -@@ -1181,11 +1201,6 @@ _nl_find_msg (domain_file, domainbinding - } - - # ifdef _LIBC -- /* Add the block to the list of blocks we have to free -- at some point. */ -- newmem->next = transmem_list; -- transmem_list = newmem; -- - freemem = (unsigned char *) newmem->data; - freemem_size -= offsetof (struct transmem_list, data); - # else -@@ -1402,7 +1417,7 @@ get_output_charset (domainbinding) - return _NL_CURRENT (LC_CTYPE, CODESET); - # else - # if HAVE_ICONV -- extern const char *locale_charset PARAMS ((void); -+ extern const char *locale_charset PARAMS ((void)); - return locale_charset (); - # endif - # endif -diff -Nrup a/intl/loadmsgcat.c b/intl/loadmsgcat.c ---- a/intl/loadmsgcat.c 2010-05-04 07:27:23.000000000 -0400 -+++ b/intl/loadmsgcat.c 2013-08-01 00:12:48.448237849 -0400 -@@ -1235,7 +1235,7 @@ _nl_load_domain (domain_file, domainbind - default: - /* This is an invalid revision. */ - invalid: -- /* This is an invalid .mo file. */ -+ /* This is an invalid .mo file or we ran out of resources. */ - free (domain->malloced); - #ifdef HAVE_MMAP - if (use_mmap) -@@ -1255,6 +1255,12 @@ _nl_load_domain (domain_file, domainbind - - /* Get the header entry and look for a plural specification. */ - nullentry = _nl_find_msg (domain_file, domainbinding, "", 0, &nullentrylen); -+ if (__builtin_expect (nullentry == (char *) -1, 0)) -+ { -+ __libc_rwlock_fini (domain->conversions_lock); -+ goto invalid; -+ } -+ - EXTRACT_PLURAL_EXPRESSION (nullentry, &domain->plural, &domain->nplurals); - - out: diff --git a/src/patches/glibc/glibc-rh989558.patch b/src/patches/glibc/glibc-rh989558.patch deleted file mode 100644 index 61ddbe8..0000000 --- a/src/patches/glibc/glibc-rh989558.patch +++ /dev/null @@ -1,181 +0,0 @@ -# -# Red Hat BZ: -# https://bugzilla.redhat.com/show_bug.cgi?id=816647 -# -# ChangeLog -# -#2013-04-30 Patsy Franklin pfrankli@redhat.com -# -# * iconv/gconv_cache.c (find_module): Demangle init_fct before -# checking for NULL. Mangle __btowc_fct if init_fct is non-NULL. -# * iconv/gconv_db.c (free_derivation): Check that __shlib_handle -# is non-NULL before demangling the end_fct. Check for NULL -# end_fct after demangling. -# (__gconv_release_step): Demangle the end_fct before checking -# it for NULL. Remove assert on __shlibc_handle != NULL. -# (gen_steps): Don't check btowc_fct for NULL before mangling. -# Demangle init_fct before checking for NULL. -# (increment_counter): Likewise -# * gconv_dl.c (__gconv_find_shlib): Don't check init_fct or -# end_fct for NULL before mangling. -# * wcsmbs/btowc.c (__btowc): Demangle btowc_fct before checking -# for NULL. -# -diff -Nrup a/iconv/gconv_cache.c b/iconv/gconv_cache.c ---- a/iconv/gconv_cache.c 2012-12-24 22:02:13.000000000 -0500 -+++ b/iconv/gconv_cache.c 2013-04-30 11:34:20.112389987 -0400 -@@ -207,17 +207,16 @@ find_module (const char *directory, cons - result->__data = NULL; - - /* Call the init function. */ -- if (result->__init_fct != NULL) -- { -- __gconv_init_fct init_fct = result->__init_fct; -+ __gconv_init_fct init_fct = result->__init_fct; - #ifdef PTR_DEMANGLE -- PTR_DEMANGLE (init_fct); -+ PTR_DEMANGLE (init_fct); - #endif -+ if (init_fct != NULL) -+ { - status = DL_CALL_FCT (init_fct, (result)); - - #ifdef PTR_MANGLE -- if (result->__btowc_fct != NULL) -- PTR_MANGLE (result->__btowc_fct); -+ PTR_MANGLE (result->__btowc_fct); - #endif - } - } -diff -Nrup a/iconv/gconv_db.c b/iconv/gconv_db.c ---- a/iconv/gconv_db.c 2012-12-24 22:02:13.000000000 -0500 -+++ b/iconv/gconv_db.c 2013-04-30 11:32:42.700592914 -0400 -@@ -179,16 +179,15 @@ free_derivation (void *p) - size_t cnt; - - for (cnt = 0; cnt < deriv->nsteps; ++cnt) -- if (deriv->steps[cnt].__counter > 0 -- && deriv->steps[cnt].__end_fct != NULL) -+ if ((deriv->steps[cnt].__counter > 0) -+ && (deriv->steps[cnt].__shlib_handle != NULL)) - { -- assert (deriv->steps[cnt].__shlib_handle != NULL); -- - __gconv_end_fct end_fct = deriv->steps[cnt].__end_fct; - #ifdef PTR_DEMANGLE - PTR_DEMANGLE (end_fct); - #endif -- DL_CALL_FCT (end_fct, (&deriv->steps[cnt])); -+ if (end_fct != NULL) -+ DL_CALL_FCT (end_fct, (&deriv->steps[cnt])); - } - - /* Free the name strings. */ -@@ -212,16 +211,12 @@ __gconv_release_step (struct __gconv_ste - if (step->__shlib_handle != NULL && --step->__counter == 0) - { - /* Call the destructor. */ -- if (step->__end_fct != NULL) -- { -- assert (step->__shlib_handle != NULL); -- -- __gconv_end_fct end_fct = step->__end_fct; -+ __gconv_end_fct end_fct = step->__end_fct; - #ifdef PTR_DEMANGLE -- PTR_DEMANGLE (end_fct); -+ PTR_DEMANGLE (end_fct); - #endif -- DL_CALL_FCT (end_fct, (step)); -- } -+ if (end_fct != NULL) -+ DL_CALL_FCT (end_fct, (step)); - - #ifndef STATIC_GCONV - /* Release the loaded module. */ -@@ -293,13 +288,11 @@ gen_steps (struct derivation_step *best, - - /* Call the init function. */ - __gconv_init_fct init_fct = result[step_cnt].__init_fct; -- if (init_fct != NULL) -- { -- assert (result[step_cnt].__shlib_handle != NULL); -- - # ifdef PTR_DEMANGLE -- PTR_DEMANGLE (init_fct); -+ PTR_DEMANGLE (init_fct); - # endif -+ if (init_fct != NULL) -+ { - status = DL_CALL_FCT (init_fct, (&result[step_cnt])); - - if (__builtin_expect (status, __GCONV_OK) != __GCONV_OK) -@@ -312,8 +305,7 @@ gen_steps (struct derivation_step *best, - } - - # ifdef PTR_MANGLE -- if (result[step_cnt].__btowc_fct != NULL) -- PTR_MANGLE (result[step_cnt].__btowc_fct); -+ PTR_MANGLE (result[step_cnt].__btowc_fct); - # endif - } - } -@@ -393,16 +385,15 @@ increment_counter (struct __gconv_step * - - /* Call the init function. */ - __gconv_init_fct init_fct = step->__init_fct; -- if (init_fct != NULL) -- { - #ifdef PTR_DEMANGLE -- PTR_DEMANGLE (init_fct); -+ PTR_DEMANGLE (init_fct); - #endif -+ if (init_fct != NULL) -+ { - DL_CALL_FCT (init_fct, (step)); - - #ifdef PTR_MANGLE -- if (step->__btowc_fct != NULL) -- PTR_MANGLE (step->__btowc_fct); -+ PTR_MANGLE (step->__btowc_fct); - #endif - } - } -diff -Nrup a/iconv/gconv_dl.c b/iconv/gconv_dl.c ---- a/iconv/gconv_dl.c 2012-12-24 22:02:13.000000000 -0500 -+++ b/iconv/gconv_dl.c 2013-04-30 11:32:42.701592922 -0400 -@@ -132,10 +132,8 @@ __gconv_find_shlib (const char *name) - - #ifdef PTR_MANGLE - PTR_MANGLE (found->fct); -- if (found->init_fct != NULL) -- PTR_MANGLE (found->init_fct); -- if (found->end_fct != NULL) -- PTR_MANGLE (found->end_fct); -+ PTR_MANGLE (found->init_fct); -+ PTR_MANGLE (found->end_fct); - #endif - - /* We have succeeded in loading the shared object. */ -diff -Nrup a/wcsmbs/btowc.c b/wcsmbs/btowc.c ---- a/wcsmbs/btowc.c 2012-12-24 22:02:13.000000000 -0500 -+++ b/wcsmbs/btowc.c 2013-04-30 11:32:42.701592922 -0400 -@@ -47,15 +47,15 @@ __btowc (c) - /* Get the conversion functions. */ - fcts = get_gconv_fcts (_NL_CURRENT_DATA (LC_CTYPE)); - __gconv_btowc_fct btowc_fct = fcts->towc->__btowc_fct; -+#ifdef PTR_DEMANGLE -+ if (fcts->towc->__shlib_handle != NULL) -+ PTR_DEMANGLE (btowc_fct); -+#endif - - if (__builtin_expect (fcts->towc_nsteps == 1, 1) - && __builtin_expect (btowc_fct != NULL, 1)) - { - /* Use the shortcut function. */ --#ifdef PTR_DEMANGLE -- if (fcts->towc->__shlib_handle != NULL) -- PTR_DEMANGLE (btowc_fct); --#endif - return DL_CALL_FCT (btowc_fct, (fcts->towc, (unsigned char) c)); - } - else
hooks/post-receive -- IPFire 2.x development tree