From: Arne Fitzenreiter Date: Wed, 17 Feb 2016 11:46:11 +0000 (+0100) Subject: glibc: new RHEL6 patches / fix CVE-2015-7547 and more X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=bb330e25e98f445493f63631c461bec1d7eb211b;p=people%2Fdweismueller%2Fipfire-2.x.git glibc: new RHEL6 patches / fix CVE-2015-7547 and more Signed-off-by: Arne Fitzenreiter --- diff --git a/lfs/glibc b/lfs/glibc index d7d51cf8c..e4c003028 100644 --- a/lfs/glibc +++ b/lfs/glibc @@ -1,7 +1,7 @@ ############################################################################### # # # IPFire.org - A linux based firewall # -# Copyright (C) 2007-2011 IPFire Team # +# Copyright (C) 2007-2016 IPFire Team # # # # 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 # @@ -140,156 +140,218 @@ 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 + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh978098.patch + 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 + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh867679.patch + 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 diff --git a/src/patches/glibc-test-installation.pl-libgcc_s.patch b/src/patches/glibc-test-installation.pl-libgcc_s.patch index a63d5d826..222135339 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 -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 #include #include @@ -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 () { +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 () { # - 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 , 2001. -@@ -23,7 +23,7 @@ +@@ -24,7 +24,7 @@ #define __frame_state_for fallback_frame_state_for #include #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 . -@@ -19,7 +19,7 @@ - #include - #include +@@ -22,7 +22,7 @@ #include + #include + #include -#include +#include + 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 000000000..738052d8e --- /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 000000000..9dc98b99b --- /dev/null +++ b/src/patches/glibc/glibc-rh1025933.patch @@ -0,0 +1,287 @@ +commit 0699f766b10c86912b75f35bef697106b70c1cf6 +Author: Carlos O'Donell +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 +-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 ], +- [#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 + #include + #include +-#include + #include + #include + #include +@@ -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 000000000..3bf8c4f06 --- /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 +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 +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 +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 +-#include +-#include + #include +-#include +-#include + +-#undef __gettimeofday +-#include ++#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 ++# include ++# include ++ ++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 ++# include ++ ++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 000000000..253b31133 --- /dev/null +++ b/src/patches/glibc/glibc-rh1039988.patch @@ -0,0 +1,141 @@ +commit 9a3c6a6ff602c88d7155139a7d7d0000b7b7e946 +Author: Siddhesh Poyarekar +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 000000000..affbe964c --- /dev/null +++ b/src/patches/glibc/glibc-rh1043557.patch @@ -0,0 +1,145 @@ +commit af37a8a3496327a6e5617a2c76f17aa1e8db835e +Author: Siddhesh Poyarekar +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 +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 +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 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 000000000..a662cfe46 --- /dev/null +++ b/src/patches/glibc/glibc-rh1053178.patch @@ -0,0 +1,214 @@ +# +# Based on the commit: +# +# commit 6c82a2f8d7c8e21e39237225c819f182ae438db3 +# Author: Carlos O'Donell +# 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 +# Cong Wang +# +# * 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 ++ + /* 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 +- + /* 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 directly; include 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 000000000..50b41096f --- /dev/null +++ b/src/patches/glibc/glibc-rh1054846.patch @@ -0,0 +1,57 @@ +commit fbd6b5a4052316f7eb03c4617eebfaafc59dcc06 +Author: Siddhesh Poyarekar +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 000000000..a03f1d10a --- /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 ++ . */ ++ ++ ++#include ++ ++#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 000000000..121127e6e --- /dev/null +++ b/src/patches/glibc/glibc-rh1074342.patch @@ -0,0 +1,26 @@ +commit c44496df2f090a56d3bf75df930592dac6bba46f +Author: Siddhesh Poyarekar +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 000000000..c8aa8b0d6 --- /dev/null +++ b/src/patches/glibc/glibc-rh1074353.patch @@ -0,0 +1,398 @@ +commit bc8f194c8c29e46e8ee4034f06e46988dfff38f7 +Author: Siddhesh Poyarekar +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 +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 000000000..60a0ece0d --- /dev/null +++ b/src/patches/glibc/glibc-rh1082379.patch @@ -0,0 +1,63 @@ +commit ea7d8b95e2fcb81f68b04ed7787a3dbda023991a +Author: Siddhesh Poyarekar +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 000000000..ee0f2898e --- /dev/null +++ b/src/patches/glibc/glibc-rh1085273.patch @@ -0,0 +1,31 @@ +commit d41242129ba693cdbc8db85b846fcaccf9f0b7c4 +Author: Siddhesh Poyarekar +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 000000000..9bd284ebf --- /dev/null +++ b/src/patches/glibc/glibc-rh1085289.patch @@ -0,0 +1,60 @@ +commit dd3022d75e6fb8957843d6d84257a5d8457822d5 +Author: Siddhesh Poyarekar +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 000000000..bafb30338 --- /dev/null +++ b/src/patches/glibc/glibc-rh1085312.patch @@ -0,0 +1,34 @@ +commit 58b930ae216bfa98cd60212b954b07b9963d6d04 +Author: Siddhesh Poyarekar +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 000000000..ca8f1f047 --- /dev/null +++ b/src/patches/glibc/glibc-rh1087833.patch @@ -0,0 +1,65 @@ +commit c3ec475c5dd16499aa040908e11d382c3ded9692 +Author: Siddhesh Poyarekar +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 000000000..d26eb14ec --- /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 000000000..d1af874dc --- /dev/null +++ b/src/patches/glibc/glibc-rh1091915.patch @@ -0,0 +1,40 @@ +commit 3cb26316b45b23dc5cfecbafdc489b28c3a52029 +Author: Siddhesh Poyarekar +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 000000000..58fe121aa --- /dev/null +++ b/src/patches/glibc/glibc-rh1099025-2.patch @@ -0,0 +1,159 @@ +commit d6c33fda03457ca8ca87a562fa2681af16ca4ea5 +Author: Roland McGrath +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 + #include + +-#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 + #include + +-#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 + #include + +-#undef __gettimeofday + #include + + /* 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 + #include + +-#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 +--- 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 000000000..d075be86e --- /dev/null +++ b/src/patches/glibc/glibc-rh1099025.patch @@ -0,0 +1,47 @@ +commit 736c304a1ab4cee36a2f3343f1698bc0abae4608 +Author: Adhemerval Zanella +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 000000000..439cf6d0c --- /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 000000000..7631312d5 --- /dev/null +++ b/src/patches/glibc/glibc-rh1116050.patch @@ -0,0 +1,407 @@ +# +# Based on this upstream commit: +# +# commit d8dd00805b8f3a011735d7a407097fb1c408d867 +# Author: H.J. Lu +# 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 . +# (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 + #include + #include ++#include + + #include + #include +@@ -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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++/* 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 ++ . */ ++ ++/* 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 000000000..f14c4cb24 --- /dev/null +++ b/src/patches/glibc/glibc-rh1124204.patch @@ -0,0 +1,47 @@ +# +# Derived from this upstream commit: +# +# commit 58a1335e76a553e1cf4edeebc27f16fc9b53d6e6 +# Author: Petr Baudis +# Date: Thu Mar 14 01:16:53 2013 +0100 +# +# Fix __times() handling of EFAULT when buf is NULL +# +# 2013-03-14 Petr Baudis +# +# * sysdeps/unix/sysv/linux/times.c (__times): On EFAULT, test +# for non-NULL pointer before the memory validity test. Pointed +# out by Holger Brunck . +# +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 000000000..72ba01db2 --- /dev/null +++ b/src/patches/glibc/glibc-rh1125307.patch @@ -0,0 +1,19 @@ +commit a11892631d92f594c690d0d50a642b0d1aba58b8 +Author: Ondřej Bílka +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-rh1133810-1.patch similarity index 100% rename from src/patches/glibc/glibc-rh1133809-1.patch rename to src/patches/glibc/glibc-rh1133810-1.patch diff --git a/src/patches/glibc/glibc-rh1133809-2.patch b/src/patches/glibc/glibc-rh1133810-2.patch similarity index 100% rename from src/patches/glibc/glibc-rh1133809-2.patch rename to src/patches/glibc/glibc-rh1133810-2.patch diff --git a/src/patches/glibc/glibc-rh1138769.patch b/src/patches/glibc/glibc-rh1138769.patch new file mode 100644 index 000000000..94a7d2a62 --- /dev/null +++ b/src/patches/glibc/glibc-rh1138769.patch @@ -0,0 +1,45 @@ +commit e35c53e397e7abbd41fedacdedcfa5af7b5c2c52 +Author: Siddhesh Poyarekar +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-rh1207995.patch b/src/patches/glibc/glibc-rh1144019.patch similarity index 100% rename from src/patches/glibc/glibc-rh1207995.patch rename to src/patches/glibc/glibc-rh1144019.patch diff --git a/src/patches/glibc/glibc-rh1144132.patch b/src/patches/glibc/glibc-rh1144132.patch new file mode 100644 index 000000000..4114b5897 --- /dev/null +++ b/src/patches/glibc/glibc-rh1144132.patch @@ -0,0 +1,58 @@ +# +# Based on this commit: +# +# commit 62058ce612ed3459501b4c4332e268edfe977f59 +# Author: Carlos O'Donell +# 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 000000000..59f4a6f41 --- /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-rh1171296.patch similarity index 100% rename from src/patches/glibc/glibc-rh1170121.patch rename to src/patches/glibc/glibc-rh1171296.patch diff --git a/src/patches/glibc/glibc-rh1139571.patch b/src/patches/glibc/glibc-rh1172044.patch similarity index 100% rename from src/patches/glibc/glibc-rh1139571.patch rename to src/patches/glibc/glibc-rh1172044.patch diff --git a/src/patches/glibc/glibc-rh1176907.patch b/src/patches/glibc/glibc-rh1176907.patch new file mode 100644 index 000000000..29cdacfc0 --- /dev/null +++ b/src/patches/glibc/glibc-rh1176907.patch @@ -0,0 +1,22 @@ +commit 7d81e8d6db95c112c297930a8f2f9617c305529a +Author: Florian Weimer +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-rh1183534.patch similarity index 94% rename from src/patches/glibc/glibc-rh1183533.patch rename to src/patches/glibc/glibc-rh1183534.patch index 9263cd5b6..eab7a3fa4 100644 --- a/src/patches/glibc/glibc-rh1183533.patch +++ b/src/patches/glibc/glibc-rh1183534.patch @@ -4,6 +4,19 @@ 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 diff --git a/src/patches/glibc/glibc-rh1195453-avx512.patch b/src/patches/glibc/glibc-rh1195453-avx512.patch new file mode 100644 index 000000000..4c70e5e1e --- /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 +# 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 +# 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 +# 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 000000000..5671fd87d --- /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-rh1209375.patch b/src/patches/glibc/glibc-rh1209376.patch similarity index 100% rename from src/patches/glibc/glibc-rh1209375.patch rename to src/patches/glibc/glibc-rh1209376.patch diff --git a/src/patches/glibc/glibc-rh1256812-2.patch b/src/patches/glibc/glibc-rh1256812-2.patch new file mode 100644 index 000000000..5596de7bd --- /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 000000000..e8fbb1b34 --- /dev/null +++ b/src/patches/glibc/glibc-rh1256812-3.patch @@ -0,0 +1,138 @@ +commit fdc0f374bcd2d0513569aa8d600f960e43e8af1d +Author: Ulrich Drepper +Date: Sun Oct 24 22:37:00 2010 -0400 + + Fix perturbing in malloc on free. + +commit e8349efd466cfedc0aa98be61d88ca8795c9e565 +Author: Ondřej Bílka +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 000000000..1e497f327 --- /dev/null +++ b/src/patches/glibc/glibc-rh1256812-4.patch @@ -0,0 +1,45 @@ +commit 55765a349a96482207fbf927d3666a51878f973b +Author: Josef Bacik +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 000000000..1eafcc17b --- /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 000000000..4683dc40c --- /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 000000000..5364dba0a --- /dev/null +++ b/src/patches/glibc/glibc-rh1256891.patch @@ -0,0 +1,26 @@ +commit 5c44738353ecaa1c81efca063ee8b55e092d7a43 +Author: Alexandre Oliva +Date: Wed Sep 5 15:43:04 2012 -0300 + + Don't change no_dyn_threshold on mallopt failure + + * malloc/malloc.c (__libc_mallopt) : 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 000000000..8d12d95e7 --- /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 +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 000000000..d44e4911a --- /dev/null +++ b/src/patches/glibc/glibc-rh1296031-0.patch @@ -0,0 +1,465 @@ +Sourceware bug 16574 + +commit d668061994a7486a3ba9c7d5e7882d85a2883707 +Author: Andreas Schwab +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 +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 +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 000000000..c430abba1 --- /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 ++ . */ ++ + /* + * 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 000000000..f27eccd67 --- /dev/null +++ b/src/patches/glibc/glibc-rh1299319-0.patch @@ -0,0 +1,61 @@ +commit 2c1094bd700e63a8d7f547b3f5495bedb55c0a08 +Author: Ulrich Drepper +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 000000000..e6288a24c --- /dev/null +++ b/src/patches/glibc/glibc-rh1299319-1.patch @@ -0,0 +1,19 @@ +commit 232872379ee82cd040a52a48cbbae65a249b5765 +Author: Adhemerval Zanella +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 000000000..41eccb7d4 --- /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 + #include + #include ++#include + + #include + +@@ -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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++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 000000000..d3e4f45f4 --- /dev/null +++ b/src/patches/glibc/glibc-rh629823-2.patch @@ -0,0 +1,95 @@ +commit 50fd745b4dec07e8e213cf2703b5cabcfa128225 +Author: Andreas Schwab +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 000000000..6315246f2 --- /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 ++#include + + + /* 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 , 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 ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "../inet/netgroup.h" ++#include "nscd.h" ++#include "dbg_log.h" ++#ifdef HAVE_SENDFILE ++# include ++#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 , 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 ++#include ++#include ++#include ++#include ++ ++#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 , 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 , 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 , 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 ++#include ++#include ++#include ++ ++ ++#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 ++ ++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 , 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 + #include + #include ++#include + + /* 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 ++#include ++#include ++#include ++#include ++ ++ ++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 000000000..13c1bee4d --- /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 + #ifndef SHARED + # include +-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 + #include + #include ++#include + + + /* 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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 000000000..182fe99a6 --- /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 000000000..e1ca4f1a4 --- /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 + + +-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 + #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 + + +-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 + #include + +-/* 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 1064640af..1147af686 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-rh989558-2.patch b/src/patches/glibc/glibc-rh834386-2.patch similarity index 100% rename from src/patches/glibc/glibc-rh989558-2.patch rename to src/patches/glibc/glibc-rh834386-2.patch diff --git a/src/patches/glibc/glibc-rh989558.patch b/src/patches/glibc/glibc-rh834386.patch similarity index 100% rename from src/patches/glibc/glibc-rh989558.patch rename to src/patches/glibc/glibc-rh834386.patch diff --git a/src/patches/glibc/glibc-rh845218.patch b/src/patches/glibc/glibc-rh845218.patch new file mode 100644 index 000000000..47f909c10 --- /dev/null +++ b/src/patches/glibc/glibc-rh845218.patch @@ -0,0 +1,218 @@ +commit 16b293a7a6f65d8ff348a603d19e8fd4372fa3a9 +Author: Siddhesh Poyarekar +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 + #include + #include + #include + #include + #include + #include + #include + #include + + /* 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 000000000..b75a36884 --- /dev/null +++ b/src/patches/glibc/glibc-rh848748.patch @@ -0,0 +1,70 @@ +2013-04-30 Patsy Franklin + + * 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 + #include + ++/* 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 000000000..94915da4f --- /dev/null +++ b/src/patches/glibc/glibc-rh851470.patch @@ -0,0 +1,52 @@ +commit 050af9c4e86eeecd484ed44b7765e750523276eb +Author: Siddhesh Poyarekar +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 + + [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 000000000..8fcbcd49b --- /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 +# +# [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 + + #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 000000000..6e7fe0af1 --- /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 +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 + Ulrich Drepper + + * 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 000000000..7644a4ed1 --- /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 000000000..3e823c86e --- /dev/null +++ b/src/patches/glibc/glibc-rh867679.patch @@ -0,0 +1,139 @@ +commit 9fab36eb583c0e585e83a01253299afed9ea9a11 +Author: Siddhesh Poyarekar +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 + ++/* Get the implementation for check_may_shrink_heap. */ ++#include ++ + /* 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 ++ . */ ++ ++/* 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 ++ . */ ++ ++#include ++#include ++ ++/* 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 000000000..27a10b23b --- /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 +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 + + [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 , 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 000000000..d5d50f25b --- /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 + #include + #include ++#include ++#include + #include + ++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-rh970992.patch b/src/patches/glibc/glibc-rh919562.patch similarity index 100% rename from src/patches/glibc/glibc-rh970992.patch rename to src/patches/glibc/glibc-rh919562.patch diff --git a/src/patches/glibc/glibc-rh929302.patch b/src/patches/glibc/glibc-rh929302.patch new file mode 100644 index 000000000..305b339c0 --- /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 +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 ++ . */ ++ ++#include ++#include ++#include ++ ++ ++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 000000000..ec2f2a6f9 --- /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-rh978098.patch b/src/patches/glibc/glibc-rh978098.patch new file mode 100644 index 000000000..0b53dcc25 --- /dev/null +++ b/src/patches/glibc/glibc-rh978098.patch @@ -0,0 +1,124 @@ +# +# Based on commit e6c61494125126d2ba77e5d99f83887a2ed49783. +# +# 2011-04-10 Ulrich Drepper +# +# [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 + #include + #include ++#include + #include + #include + #include +@@ -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 000000000..cbe1ab8db --- /dev/null +++ b/src/patches/glibc/glibc-rh981942.patch @@ -0,0 +1,22 @@ +commit 2e96f1c73b06e81da59ef7fffa426dc201875f31 +Author: Andreas Schwab +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 000000000..38594a47b --- /dev/null +++ b/src/patches/glibc/glibc-rh988931.patch @@ -0,0 +1,33 @@ +commit e23fe25b33324a9ea992276c1a4f04127bf9ba4b +Author: Andreas Schwab +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) + {