forked from rpms/glibc
import glibc-2.28-66.el8
This commit is contained in:
commit
0d6119401b
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
SOURCES/glibc-2.28.tar.xz
|
1
.glibc.metadata
Normal file
1
.glibc.metadata
Normal file
@ -0,0 +1 @@
|
||||
ccb5dc9e51a9884df8488f86982439d47b283b2a SOURCES/glibc-2.28.tar.xz
|
6058
SOURCES/ChangeLog.old
Normal file
6058
SOURCES/ChangeLog.old
Normal file
File diff suppressed because it is too large
Load Diff
494
SOURCES/SUPPORTED
Normal file
494
SOURCES/SUPPORTED
Normal file
@ -0,0 +1,494 @@
|
||||
# This file names the currently supported and somewhat tested locales.
|
||||
# If you have any additions please file a glibc bug report.
|
||||
SUPPORTED-LOCALES=\
|
||||
C.UTF-8/UTF-8 \
|
||||
aa_DJ.UTF-8/UTF-8 \
|
||||
aa_DJ/ISO-8859-1 \
|
||||
aa_ER/UTF-8 \
|
||||
aa_ER@saaho/UTF-8 \
|
||||
aa_ET/UTF-8 \
|
||||
af_ZA.UTF-8/UTF-8 \
|
||||
af_ZA/ISO-8859-1 \
|
||||
agr_PE/UTF-8 \
|
||||
ak_GH/UTF-8 \
|
||||
am_ET/UTF-8 \
|
||||
an_ES.UTF-8/UTF-8 \
|
||||
an_ES/ISO-8859-15 \
|
||||
anp_IN/UTF-8 \
|
||||
ar_AE.UTF-8/UTF-8 \
|
||||
ar_AE/ISO-8859-6 \
|
||||
ar_BH.UTF-8/UTF-8 \
|
||||
ar_BH/ISO-8859-6 \
|
||||
ar_DZ.UTF-8/UTF-8 \
|
||||
ar_DZ/ISO-8859-6 \
|
||||
ar_EG.UTF-8/UTF-8 \
|
||||
ar_EG/ISO-8859-6 \
|
||||
ar_IN/UTF-8 \
|
||||
ar_IQ.UTF-8/UTF-8 \
|
||||
ar_IQ/ISO-8859-6 \
|
||||
ar_JO.UTF-8/UTF-8 \
|
||||
ar_JO/ISO-8859-6 \
|
||||
ar_KW.UTF-8/UTF-8 \
|
||||
ar_KW/ISO-8859-6 \
|
||||
ar_LB.UTF-8/UTF-8 \
|
||||
ar_LB/ISO-8859-6 \
|
||||
ar_LY.UTF-8/UTF-8 \
|
||||
ar_LY/ISO-8859-6 \
|
||||
ar_MA.UTF-8/UTF-8 \
|
||||
ar_MA/ISO-8859-6 \
|
||||
ar_OM.UTF-8/UTF-8 \
|
||||
ar_OM/ISO-8859-6 \
|
||||
ar_QA.UTF-8/UTF-8 \
|
||||
ar_QA/ISO-8859-6 \
|
||||
ar_SA.UTF-8/UTF-8 \
|
||||
ar_SA/ISO-8859-6 \
|
||||
ar_SD.UTF-8/UTF-8 \
|
||||
ar_SD/ISO-8859-6 \
|
||||
ar_SS/UTF-8 \
|
||||
ar_SY.UTF-8/UTF-8 \
|
||||
ar_SY/ISO-8859-6 \
|
||||
ar_TN.UTF-8/UTF-8 \
|
||||
ar_TN/ISO-8859-6 \
|
||||
ar_YE.UTF-8/UTF-8 \
|
||||
ar_YE/ISO-8859-6 \
|
||||
ayc_PE/UTF-8 \
|
||||
az_AZ/UTF-8 \
|
||||
az_IR/UTF-8 \
|
||||
as_IN/UTF-8 \
|
||||
ast_ES.UTF-8/UTF-8 \
|
||||
ast_ES/ISO-8859-15 \
|
||||
be_BY.UTF-8/UTF-8 \
|
||||
be_BY/CP1251 \
|
||||
be_BY@latin/UTF-8 \
|
||||
bem_ZM/UTF-8 \
|
||||
ber_DZ/UTF-8 \
|
||||
ber_MA/UTF-8 \
|
||||
bg_BG.UTF-8/UTF-8 \
|
||||
bg_BG/CP1251 \
|
||||
bhb_IN.UTF-8/UTF-8 \
|
||||
bho_IN/UTF-8 \
|
||||
bho_NP/UTF-8 \
|
||||
bi_VU/UTF-8 \
|
||||
bn_BD/UTF-8 \
|
||||
bn_IN/UTF-8 \
|
||||
bo_CN/UTF-8 \
|
||||
bo_IN/UTF-8 \
|
||||
br_FR.UTF-8/UTF-8 \
|
||||
br_FR/ISO-8859-1 \
|
||||
br_FR@euro/ISO-8859-15 \
|
||||
brx_IN/UTF-8 \
|
||||
bs_BA.UTF-8/UTF-8 \
|
||||
bs_BA/ISO-8859-2 \
|
||||
byn_ER/UTF-8 \
|
||||
ca_AD.UTF-8/UTF-8 \
|
||||
ca_AD/ISO-8859-15 \
|
||||
ca_ES.UTF-8/UTF-8 \
|
||||
ca_ES/ISO-8859-1 \
|
||||
ca_ES@euro/ISO-8859-15 \
|
||||
ca_ES@valencia/UTF-8 \
|
||||
ca_FR.UTF-8/UTF-8 \
|
||||
ca_FR/ISO-8859-15 \
|
||||
ca_IT.UTF-8/UTF-8 \
|
||||
ca_IT/ISO-8859-15 \
|
||||
ce_RU/UTF-8 \
|
||||
chr_US/UTF-8 \
|
||||
cmn_TW/UTF-8 \
|
||||
crh_UA/UTF-8 \
|
||||
cs_CZ.UTF-8/UTF-8 \
|
||||
cs_CZ/ISO-8859-2 \
|
||||
csb_PL/UTF-8 \
|
||||
cv_RU/UTF-8 \
|
||||
cy_GB.UTF-8/UTF-8 \
|
||||
cy_GB/ISO-8859-14 \
|
||||
da_DK.UTF-8/UTF-8 \
|
||||
da_DK/ISO-8859-1 \
|
||||
da_DK.ISO-8859-15/ISO-8859-15 \
|
||||
de_AT.UTF-8/UTF-8 \
|
||||
de_AT/ISO-8859-1 \
|
||||
de_AT@euro/ISO-8859-15 \
|
||||
de_BE.UTF-8/UTF-8 \
|
||||
de_BE/ISO-8859-1 \
|
||||
de_BE@euro/ISO-8859-15 \
|
||||
de_CH.UTF-8/UTF-8 \
|
||||
de_CH/ISO-8859-1 \
|
||||
de_DE.UTF-8/UTF-8 \
|
||||
de_DE/ISO-8859-1 \
|
||||
de_DE@euro/ISO-8859-15 \
|
||||
de_IT.UTF-8/UTF-8 \
|
||||
de_IT/ISO-8859-1 \
|
||||
de_LI.UTF-8/UTF-8 \
|
||||
de_LU.UTF-8/UTF-8 \
|
||||
de_LU/ISO-8859-1 \
|
||||
de_LU@euro/ISO-8859-15 \
|
||||
doi_IN/UTF-8 \
|
||||
dsb_DE/UTF-8 \
|
||||
dv_MV/UTF-8 \
|
||||
dz_BT/UTF-8 \
|
||||
el_GR.UTF-8/UTF-8 \
|
||||
el_GR/ISO-8859-7 \
|
||||
el_GR@euro/ISO-8859-7 \
|
||||
el_CY.UTF-8/UTF-8 \
|
||||
el_CY/ISO-8859-7 \
|
||||
en_AG/UTF-8 \
|
||||
en_AU.UTF-8/UTF-8 \
|
||||
en_AU/ISO-8859-1 \
|
||||
en_BW.UTF-8/UTF-8 \
|
||||
en_BW/ISO-8859-1 \
|
||||
en_CA.UTF-8/UTF-8 \
|
||||
en_CA/ISO-8859-1 \
|
||||
en_DK.UTF-8/UTF-8 \
|
||||
en_DK/ISO-8859-1 \
|
||||
en_GB.UTF-8/UTF-8 \
|
||||
en_GB/ISO-8859-1 \
|
||||
en_GB.ISO-8859-15/ISO-8859-15 \
|
||||
en_HK.UTF-8/UTF-8 \
|
||||
en_HK/ISO-8859-1 \
|
||||
en_IE.UTF-8/UTF-8 \
|
||||
en_IE/ISO-8859-1 \
|
||||
en_IE@euro/ISO-8859-15 \
|
||||
en_IL/UTF-8 \
|
||||
en_IN/UTF-8 \
|
||||
en_NG/UTF-8 \
|
||||
en_NZ.UTF-8/UTF-8 \
|
||||
en_NZ/ISO-8859-1 \
|
||||
en_PH.UTF-8/UTF-8 \
|
||||
en_PH/ISO-8859-1 \
|
||||
en_SC.UTF-8/UTF-8 \
|
||||
en_SG.UTF-8/UTF-8 \
|
||||
en_SG/ISO-8859-1 \
|
||||
en_US.UTF-8/UTF-8 \
|
||||
en_US/ISO-8859-1 \
|
||||
en_US.ISO-8859-15/ISO-8859-15 \
|
||||
en_ZA.UTF-8/UTF-8 \
|
||||
en_ZA/ISO-8859-1 \
|
||||
en_ZM/UTF-8 \
|
||||
en_ZW.UTF-8/UTF-8 \
|
||||
en_ZW/ISO-8859-1 \
|
||||
eo/UTF-8 \
|
||||
es_AR.UTF-8/UTF-8 \
|
||||
es_AR/ISO-8859-1 \
|
||||
es_BO.UTF-8/UTF-8 \
|
||||
es_BO/ISO-8859-1 \
|
||||
es_CL.UTF-8/UTF-8 \
|
||||
es_CL/ISO-8859-1 \
|
||||
es_CO.UTF-8/UTF-8 \
|
||||
es_CO/ISO-8859-1 \
|
||||
es_CR.UTF-8/UTF-8 \
|
||||
es_CR/ISO-8859-1 \
|
||||
es_CU/UTF-8 \
|
||||
es_DO.UTF-8/UTF-8 \
|
||||
es_DO/ISO-8859-1 \
|
||||
es_EC.UTF-8/UTF-8 \
|
||||
es_EC/ISO-8859-1 \
|
||||
es_ES.UTF-8/UTF-8 \
|
||||
es_ES/ISO-8859-1 \
|
||||
es_ES@euro/ISO-8859-15 \
|
||||
es_GT.UTF-8/UTF-8 \
|
||||
es_GT/ISO-8859-1 \
|
||||
es_HN.UTF-8/UTF-8 \
|
||||
es_HN/ISO-8859-1 \
|
||||
es_MX.UTF-8/UTF-8 \
|
||||
es_MX/ISO-8859-1 \
|
||||
es_NI.UTF-8/UTF-8 \
|
||||
es_NI/ISO-8859-1 \
|
||||
es_PA.UTF-8/UTF-8 \
|
||||
es_PA/ISO-8859-1 \
|
||||
es_PE.UTF-8/UTF-8 \
|
||||
es_PE/ISO-8859-1 \
|
||||
es_PR.UTF-8/UTF-8 \
|
||||
es_PR/ISO-8859-1 \
|
||||
es_PY.UTF-8/UTF-8 \
|
||||
es_PY/ISO-8859-1 \
|
||||
es_SV.UTF-8/UTF-8 \
|
||||
es_SV/ISO-8859-1 \
|
||||
es_US.UTF-8/UTF-8 \
|
||||
es_US/ISO-8859-1 \
|
||||
es_UY.UTF-8/UTF-8 \
|
||||
es_UY/ISO-8859-1 \
|
||||
es_VE.UTF-8/UTF-8 \
|
||||
es_VE/ISO-8859-1 \
|
||||
et_EE.UTF-8/UTF-8 \
|
||||
et_EE/ISO-8859-1 \
|
||||
et_EE.ISO-8859-15/ISO-8859-15 \
|
||||
eu_ES.UTF-8/UTF-8 \
|
||||
eu_ES/ISO-8859-1 \
|
||||
eu_ES@euro/ISO-8859-15 \
|
||||
fa_IR/UTF-8 \
|
||||
ff_SN/UTF-8 \
|
||||
fi_FI.UTF-8/UTF-8 \
|
||||
fi_FI/ISO-8859-1 \
|
||||
fi_FI@euro/ISO-8859-15 \
|
||||
fil_PH/UTF-8 \
|
||||
fo_FO.UTF-8/UTF-8 \
|
||||
fo_FO/ISO-8859-1 \
|
||||
fr_BE.UTF-8/UTF-8 \
|
||||
fr_BE/ISO-8859-1 \
|
||||
fr_BE@euro/ISO-8859-15 \
|
||||
fr_CA.UTF-8/UTF-8 \
|
||||
fr_CA/ISO-8859-1 \
|
||||
fr_CH.UTF-8/UTF-8 \
|
||||
fr_CH/ISO-8859-1 \
|
||||
fr_FR.UTF-8/UTF-8 \
|
||||
fr_FR/ISO-8859-1 \
|
||||
fr_FR@euro/ISO-8859-15 \
|
||||
fr_LU.UTF-8/UTF-8 \
|
||||
fr_LU/ISO-8859-1 \
|
||||
fr_LU@euro/ISO-8859-15 \
|
||||
fur_IT/UTF-8 \
|
||||
fy_NL/UTF-8 \
|
||||
fy_DE/UTF-8 \
|
||||
ga_IE.UTF-8/UTF-8 \
|
||||
ga_IE/ISO-8859-1 \
|
||||
ga_IE@euro/ISO-8859-15 \
|
||||
gd_GB.UTF-8/UTF-8 \
|
||||
gd_GB/ISO-8859-15 \
|
||||
gez_ER/UTF-8 \
|
||||
gez_ER@abegede/UTF-8 \
|
||||
gez_ET/UTF-8 \
|
||||
gez_ET@abegede/UTF-8 \
|
||||
gl_ES.UTF-8/UTF-8 \
|
||||
gl_ES/ISO-8859-1 \
|
||||
gl_ES@euro/ISO-8859-15 \
|
||||
gu_IN/UTF-8 \
|
||||
gv_GB.UTF-8/UTF-8 \
|
||||
gv_GB/ISO-8859-1 \
|
||||
ha_NG/UTF-8 \
|
||||
hak_TW/UTF-8 \
|
||||
he_IL.UTF-8/UTF-8 \
|
||||
he_IL/ISO-8859-8 \
|
||||
hi_IN/UTF-8 \
|
||||
hif_FJ/UTF-8 \
|
||||
hne_IN/UTF-8 \
|
||||
hr_HR.UTF-8/UTF-8 \
|
||||
hr_HR/ISO-8859-2 \
|
||||
hsb_DE/ISO-8859-2 \
|
||||
hsb_DE.UTF-8/UTF-8 \
|
||||
ht_HT/UTF-8 \
|
||||
hu_HU.UTF-8/UTF-8 \
|
||||
hu_HU/ISO-8859-2 \
|
||||
hy_AM/UTF-8 \
|
||||
hy_AM.ARMSCII-8/ARMSCII-8 \
|
||||
ia_FR/UTF-8 \
|
||||
id_ID.UTF-8/UTF-8 \
|
||||
id_ID/ISO-8859-1 \
|
||||
ig_NG/UTF-8 \
|
||||
ik_CA/UTF-8 \
|
||||
is_IS.UTF-8/UTF-8 \
|
||||
is_IS/ISO-8859-1 \
|
||||
it_CH.UTF-8/UTF-8 \
|
||||
it_CH/ISO-8859-1 \
|
||||
it_IT.UTF-8/UTF-8 \
|
||||
it_IT/ISO-8859-1 \
|
||||
it_IT@euro/ISO-8859-15 \
|
||||
iu_CA/UTF-8 \
|
||||
ja_JP.EUC-JP/EUC-JP \
|
||||
ja_JP.UTF-8/UTF-8 \
|
||||
ka_GE.UTF-8/UTF-8 \
|
||||
ka_GE/GEORGIAN-PS \
|
||||
kab_DZ/UTF-8 \
|
||||
kk_KZ.UTF-8/UTF-8 \
|
||||
kk_KZ/PT154 \
|
||||
kl_GL.UTF-8/UTF-8 \
|
||||
kl_GL/ISO-8859-1 \
|
||||
km_KH/UTF-8 \
|
||||
kn_IN/UTF-8 \
|
||||
ko_KR.EUC-KR/EUC-KR \
|
||||
ko_KR.UTF-8/UTF-8 \
|
||||
kok_IN/UTF-8 \
|
||||
ks_IN/UTF-8 \
|
||||
ks_IN@devanagari/UTF-8 \
|
||||
ku_TR.UTF-8/UTF-8 \
|
||||
ku_TR/ISO-8859-9 \
|
||||
kw_GB.UTF-8/UTF-8 \
|
||||
kw_GB/ISO-8859-1 \
|
||||
ky_KG/UTF-8 \
|
||||
lb_LU/UTF-8 \
|
||||
lg_UG.UTF-8/UTF-8 \
|
||||
lg_UG/ISO-8859-10 \
|
||||
li_BE/UTF-8 \
|
||||
li_NL/UTF-8 \
|
||||
lij_IT/UTF-8 \
|
||||
ln_CD/UTF-8 \
|
||||
lo_LA/UTF-8 \
|
||||
lt_LT.UTF-8/UTF-8 \
|
||||
lt_LT/ISO-8859-13 \
|
||||
lv_LV.UTF-8/UTF-8 \
|
||||
lv_LV/ISO-8859-13 \
|
||||
lzh_TW/UTF-8 \
|
||||
mag_IN/UTF-8 \
|
||||
mai_IN/UTF-8 \
|
||||
mai_NP/UTF-8 \
|
||||
mfe_MU/UTF-8 \
|
||||
mg_MG.UTF-8/UTF-8 \
|
||||
mg_MG/ISO-8859-15 \
|
||||
mhr_RU/UTF-8 \
|
||||
mi_NZ.UTF-8/UTF-8 \
|
||||
mi_NZ/ISO-8859-13 \
|
||||
miq_NI/UTF-8 \
|
||||
mjw_IN/UTF-8 \
|
||||
mk_MK.UTF-8/UTF-8 \
|
||||
mk_MK/ISO-8859-5 \
|
||||
ml_IN/UTF-8 \
|
||||
mn_MN/UTF-8 \
|
||||
mni_IN/UTF-8 \
|
||||
mr_IN/UTF-8 \
|
||||
ms_MY.UTF-8/UTF-8 \
|
||||
ms_MY/ISO-8859-1 \
|
||||
mt_MT.UTF-8/UTF-8 \
|
||||
mt_MT/ISO-8859-3 \
|
||||
my_MM/UTF-8 \
|
||||
nan_TW/UTF-8 \
|
||||
nan_TW@latin/UTF-8 \
|
||||
nb_NO.UTF-8/UTF-8 \
|
||||
nb_NO/ISO-8859-1 \
|
||||
nds_DE/UTF-8 \
|
||||
nds_NL/UTF-8 \
|
||||
ne_NP/UTF-8 \
|
||||
nhn_MX/UTF-8 \
|
||||
niu_NU/UTF-8 \
|
||||
niu_NZ/UTF-8 \
|
||||
nl_AW/UTF-8 \
|
||||
nl_BE.UTF-8/UTF-8 \
|
||||
nl_BE/ISO-8859-1 \
|
||||
nl_BE@euro/ISO-8859-15 \
|
||||
nl_NL.UTF-8/UTF-8 \
|
||||
nl_NL/ISO-8859-1 \
|
||||
nl_NL@euro/ISO-8859-15 \
|
||||
nn_NO.UTF-8/UTF-8 \
|
||||
nn_NO/ISO-8859-1 \
|
||||
nr_ZA/UTF-8 \
|
||||
nso_ZA/UTF-8 \
|
||||
oc_FR.UTF-8/UTF-8 \
|
||||
oc_FR/ISO-8859-1 \
|
||||
om_ET/UTF-8 \
|
||||
om_KE.UTF-8/UTF-8 \
|
||||
om_KE/ISO-8859-1 \
|
||||
or_IN/UTF-8 \
|
||||
os_RU/UTF-8 \
|
||||
pa_IN/UTF-8 \
|
||||
pa_PK/UTF-8 \
|
||||
pap_AW/UTF-8 \
|
||||
pap_CW/UTF-8 \
|
||||
pl_PL.UTF-8/UTF-8 \
|
||||
pl_PL/ISO-8859-2 \
|
||||
ps_AF/UTF-8 \
|
||||
pt_BR.UTF-8/UTF-8 \
|
||||
pt_BR/ISO-8859-1 \
|
||||
pt_PT.UTF-8/UTF-8 \
|
||||
pt_PT/ISO-8859-1 \
|
||||
pt_PT@euro/ISO-8859-15 \
|
||||
quz_PE/UTF-8 \
|
||||
raj_IN/UTF-8 \
|
||||
ro_RO.UTF-8/UTF-8 \
|
||||
ro_RO/ISO-8859-2 \
|
||||
ru_RU.KOI8-R/KOI8-R \
|
||||
ru_RU.UTF-8/UTF-8 \
|
||||
ru_RU/ISO-8859-5 \
|
||||
ru_UA.UTF-8/UTF-8 \
|
||||
ru_UA/KOI8-U \
|
||||
rw_RW/UTF-8 \
|
||||
sa_IN/UTF-8 \
|
||||
sah_RU/UTF-8 \
|
||||
sat_IN/UTF-8 \
|
||||
sc_IT/UTF-8 \
|
||||
sd_IN/UTF-8 \
|
||||
sd_IN@devanagari/UTF-8 \
|
||||
se_NO/UTF-8 \
|
||||
sgs_LT/UTF-8 \
|
||||
shn_MM/UTF-8 \
|
||||
shs_CA/UTF-8 \
|
||||
si_LK/UTF-8 \
|
||||
sid_ET/UTF-8 \
|
||||
sk_SK.UTF-8/UTF-8 \
|
||||
sk_SK/ISO-8859-2 \
|
||||
sl_SI.UTF-8/UTF-8 \
|
||||
sl_SI/ISO-8859-2 \
|
||||
sm_WS/UTF-8 \
|
||||
so_DJ.UTF-8/UTF-8 \
|
||||
so_DJ/ISO-8859-1 \
|
||||
so_ET/UTF-8 \
|
||||
so_KE.UTF-8/UTF-8 \
|
||||
so_KE/ISO-8859-1 \
|
||||
so_SO.UTF-8/UTF-8 \
|
||||
so_SO/ISO-8859-1 \
|
||||
sq_AL.UTF-8/UTF-8 \
|
||||
sq_AL/ISO-8859-1 \
|
||||
sq_MK/UTF-8 \
|
||||
sr_ME/UTF-8 \
|
||||
sr_RS/UTF-8 \
|
||||
sr_RS@latin/UTF-8 \
|
||||
ss_ZA/UTF-8 \
|
||||
st_ZA.UTF-8/UTF-8 \
|
||||
st_ZA/ISO-8859-1 \
|
||||
sv_FI.UTF-8/UTF-8 \
|
||||
sv_FI/ISO-8859-1 \
|
||||
sv_FI@euro/ISO-8859-15 \
|
||||
sv_SE.UTF-8/UTF-8 \
|
||||
sv_SE/ISO-8859-1 \
|
||||
sv_SE.ISO-8859-15/ISO-8859-15 \
|
||||
sw_KE/UTF-8 \
|
||||
sw_TZ/UTF-8 \
|
||||
szl_PL/UTF-8 \
|
||||
ta_IN/UTF-8 \
|
||||
ta_LK/UTF-8 \
|
||||
tcy_IN.UTF-8/UTF-8 \
|
||||
te_IN/UTF-8 \
|
||||
tg_TJ.UTF-8/UTF-8 \
|
||||
tg_TJ/KOI8-T \
|
||||
th_TH.UTF-8/UTF-8 \
|
||||
th_TH/TIS-620 \
|
||||
the_NP/UTF-8 \
|
||||
ti_ER/UTF-8 \
|
||||
ti_ET/UTF-8 \
|
||||
tig_ER/UTF-8 \
|
||||
tk_TM/UTF-8 \
|
||||
tl_PH.UTF-8/UTF-8 \
|
||||
tl_PH/ISO-8859-1 \
|
||||
tn_ZA/UTF-8 \
|
||||
to_TO/UTF-8 \
|
||||
tpi_PG/UTF-8 \
|
||||
tr_CY.UTF-8/UTF-8 \
|
||||
tr_CY/ISO-8859-9 \
|
||||
tr_TR.UTF-8/UTF-8 \
|
||||
tr_TR/ISO-8859-9 \
|
||||
ts_ZA/UTF-8 \
|
||||
tt_RU/UTF-8 \
|
||||
tt_RU@iqtelif/UTF-8 \
|
||||
ug_CN/UTF-8 \
|
||||
uk_UA.UTF-8/UTF-8 \
|
||||
uk_UA/KOI8-U \
|
||||
unm_US/UTF-8 \
|
||||
ur_IN/UTF-8 \
|
||||
ur_PK/UTF-8 \
|
||||
uz_UZ.UTF-8/UTF-8 \
|
||||
uz_UZ/ISO-8859-1 \
|
||||
uz_UZ@cyrillic/UTF-8 \
|
||||
ve_ZA/UTF-8 \
|
||||
vi_VN/UTF-8 \
|
||||
wa_BE/ISO-8859-1 \
|
||||
wa_BE@euro/ISO-8859-15 \
|
||||
wa_BE.UTF-8/UTF-8 \
|
||||
wae_CH/UTF-8 \
|
||||
wal_ET/UTF-8 \
|
||||
wo_SN/UTF-8 \
|
||||
xh_ZA.UTF-8/UTF-8 \
|
||||
xh_ZA/ISO-8859-1 \
|
||||
yi_US.UTF-8/UTF-8 \
|
||||
yi_US/CP1255 \
|
||||
yo_NG/UTF-8 \
|
||||
yue_HK/UTF-8 \
|
||||
yuw_PG/UTF-8 \
|
||||
zh_CN.GB18030/GB18030 \
|
||||
zh_CN.GBK/GBK \
|
||||
zh_CN.UTF-8/UTF-8 \
|
||||
zh_CN/GB2312 \
|
||||
zh_HK.UTF-8/UTF-8 \
|
||||
zh_HK/BIG5-HKSCS \
|
||||
zh_SG.UTF-8/UTF-8 \
|
||||
zh_SG.GBK/GBK \
|
||||
zh_SG/GB2312 \
|
||||
zh_TW.EUC-TW/EUC-TW \
|
||||
zh_TW.UTF-8/UTF-8 \
|
||||
zh_TW/BIG5 \
|
||||
zu_ZA.UTF-8/UTF-8 \
|
||||
zu_ZA/ISO-8859-1 \
|
77
SOURCES/bench.mk
Normal file
77
SOURCES/bench.mk
Normal file
@ -0,0 +1,77 @@
|
||||
objpfx = $(prefix)/$(ver)/usr/libexec/glibc-benchtests/
|
||||
|
||||
bench-math := acos acosh asin asinh atan atanh cos cosh exp exp2 ffs ffsll \
|
||||
log log2 modf pow rint sin sincos sinh sqrt tan tanh
|
||||
|
||||
bench-pthread := pthread_once
|
||||
|
||||
bench := $(bench-math) $(bench-pthread)
|
||||
|
||||
run-bench := $(prefix)/$(ver)/lib64/ld-linux-x86-64.so.2 --library-path $(prefix)/$(ver)/lib64 $${run}
|
||||
|
||||
# String function benchmarks.
|
||||
string-bench := bcopy bzero memccpy memchr memcmp memcpy memmem memmove \
|
||||
mempcpy memset rawmemchr stpcpy stpncpy strcasecmp strcasestr \
|
||||
strcat strchr strchrnul strcmp strcpy strcspn strlen \
|
||||
strncasecmp strncat strncmp strncpy strnlen strpbrk strrchr \
|
||||
strspn strstr strcpy_chk stpcpy_chk memrchr strsep strtok
|
||||
string-bench-all := $(string-bench)
|
||||
|
||||
stdlib-bench := strtod
|
||||
|
||||
benchset := $(string-bench-all) $(stdlib-bench)
|
||||
|
||||
bench-malloc := malloc-thread
|
||||
|
||||
binaries-bench := $(addprefix $(objpfx)bench-,$(bench))
|
||||
binaries-benchset := $(addprefix $(objpfx)bench-,$(benchset))
|
||||
binaries-bench-malloc := $(addprefix $(objpfx)bench-,$(bench-malloc))
|
||||
|
||||
DETAILED_OPT :=
|
||||
|
||||
ifdef DETAILED
|
||||
DETAILED_OPT := -d
|
||||
endif
|
||||
|
||||
bench: bench-set bench-func bench-malloc
|
||||
|
||||
bench-set: $(binaries-benchset)
|
||||
for run in $^; do \
|
||||
outfile=$(prefix)/$$(basename $${run}.$(ver).out); \
|
||||
echo "Running $${run}"; \
|
||||
$(run-bench) > $${outfile}.tmp; \
|
||||
mv $${outfile}{.tmp,}; \
|
||||
done
|
||||
|
||||
bench-malloc: $(binaries-bench-malloc)
|
||||
run=$(objpfx)bench-malloc-thread; \
|
||||
outfile=$(prefix)/$$(basename $${run}.$(ver).out); \
|
||||
for thr in 1 8 16 32; do \
|
||||
echo "Running $${run} $${thr}"; \
|
||||
$(run-bench) $${thr} > $${outfile}.tmp; \
|
||||
mv $${outfile}{.tmp,}; \
|
||||
done
|
||||
|
||||
# Build and execute the benchmark functions. This target generates JSON
|
||||
# formatted bench.out. Each of the programs produce independent JSON output,
|
||||
# so one could even execute them individually and process it using any JSON
|
||||
# capable language or tool.
|
||||
bench-func: $(binaries-bench)
|
||||
{ echo "{\"timing_type\": \"hp-timing\","; \
|
||||
echo " \"functions\": {"; \
|
||||
for run in $^; do \
|
||||
if ! [ "x$${run}" = "x$<" ]; then \
|
||||
echo ","; \
|
||||
fi; \
|
||||
echo "Running $${run}" >&2; \
|
||||
$(run-bench) $(DETAILED_OPT); \
|
||||
done; \
|
||||
echo; \
|
||||
echo " }"; \
|
||||
echo "}"; } > $(prefix)/bench.$(ver).out-tmp; \
|
||||
if [ -f $(prefix)/bench.$(ver).out ]; then \
|
||||
mv -f $(prefix)/bench.$(ver).out{,.old}; \
|
||||
fi; \
|
||||
mv -f $(prefix)/bench.$(ver).out{-tmp,}
|
||||
# scripts/validate_benchout.py bench.out \
|
||||
# scripts/benchout.schema.json
|
862
SOURCES/build-locale-archive.c
Normal file
862
SOURCES/build-locale-archive.c
Normal file
@ -0,0 +1,862 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <assert.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <locale.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <getopt.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include "../locale/hashval.h"
|
||||
#define __LC_LAST 13
|
||||
#include "../locale/locarchive.h"
|
||||
#include "../crypt/md5.h"
|
||||
|
||||
const char *alias_file = DATADIR "/locale/locale.alias";
|
||||
const char *locar_file = PREFIX "/lib/locale/locale-archive";
|
||||
const char *tmpl_file = PREFIX "/lib/locale/locale-archive.tmpl";
|
||||
const char *loc_path = PREFIX "/lib/locale/";
|
||||
/* Flags set by `--verbose` option. */
|
||||
int be_quiet = 1;
|
||||
int verbose = 0;
|
||||
int max_locarchive_open_retry = 10;
|
||||
const char *output_prefix;
|
||||
|
||||
/* Endianness should have been taken care of by localedef. We don't need to do
|
||||
additional swapping. We need this variable exported however, since
|
||||
locarchive.c uses it to determine if it needs to swap endianness of a value
|
||||
before writing to or reading from the archive. */
|
||||
bool swap_endianness_p = false;
|
||||
|
||||
static const char *locnames[] =
|
||||
{
|
||||
#define DEFINE_CATEGORY(category, category_name, items, a) \
|
||||
[category] = category_name,
|
||||
#include "../locale/categories.def"
|
||||
#undef DEFINE_CATEGORY
|
||||
};
|
||||
|
||||
static int
|
||||
is_prime (unsigned long candidate)
|
||||
{
|
||||
/* No even number and none less than 10 will be passed here. */
|
||||
unsigned long int divn = 3;
|
||||
unsigned long int sq = divn * divn;
|
||||
|
||||
while (sq < candidate && candidate % divn != 0)
|
||||
{
|
||||
++divn;
|
||||
sq += 4 * divn;
|
||||
++divn;
|
||||
}
|
||||
|
||||
return candidate % divn != 0;
|
||||
}
|
||||
|
||||
unsigned long
|
||||
next_prime (unsigned long seed)
|
||||
{
|
||||
/* Make it definitely odd. */
|
||||
seed |= 1;
|
||||
|
||||
while (!is_prime (seed))
|
||||
seed += 2;
|
||||
|
||||
return seed;
|
||||
}
|
||||
|
||||
void
|
||||
error (int status, int errnum, const char *message, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start (args, message);
|
||||
fflush (stdout);
|
||||
fprintf (stderr, "%s: ", program_invocation_name);
|
||||
vfprintf (stderr, message, args);
|
||||
va_end (args);
|
||||
if (errnum)
|
||||
fprintf (stderr, ": %s", strerror (errnum));
|
||||
putc ('\n', stderr);
|
||||
fflush (stderr);
|
||||
if (status)
|
||||
exit (errnum == EROFS ? 0 : status);
|
||||
}
|
||||
|
||||
void *
|
||||
xmalloc (size_t size)
|
||||
{
|
||||
void *p = malloc (size);
|
||||
if (p == NULL)
|
||||
error (EXIT_FAILURE, errno, "could not allocate %zd bytes of memory", size);
|
||||
return p;
|
||||
}
|
||||
|
||||
static void
|
||||
open_tmpl_archive (struct locarhandle *ah)
|
||||
{
|
||||
struct stat64 st;
|
||||
int fd;
|
||||
struct locarhead head;
|
||||
const char *archivefname = ah->fname == NULL ? tmpl_file : ah->fname;
|
||||
|
||||
/* Open the archive. We must have exclusive write access. */
|
||||
fd = open64 (archivefname, O_RDONLY);
|
||||
if (fd == -1)
|
||||
error (EXIT_FAILURE, errno, "cannot open locale archive template file \"%s\"",
|
||||
archivefname);
|
||||
|
||||
if (fstat64 (fd, &st) < 0)
|
||||
error (EXIT_FAILURE, errno, "cannot stat locale archive template file \"%s\"",
|
||||
archivefname);
|
||||
|
||||
/* Read the header. */
|
||||
if (TEMP_FAILURE_RETRY (read (fd, &head, sizeof (head))) != sizeof (head))
|
||||
error (EXIT_FAILURE, errno, "cannot read archive header");
|
||||
|
||||
ah->fd = fd;
|
||||
ah->mmaped = (head.sumhash_offset
|
||||
+ head.sumhash_size * sizeof (struct sumhashent));
|
||||
if (ah->mmaped > (unsigned long) st.st_size)
|
||||
error (EXIT_FAILURE, 0, "locale archive template file truncated");
|
||||
ah->mmaped = st.st_size;
|
||||
ah->reserved = st.st_size;
|
||||
|
||||
/* Now we know how large the administrative information part is.
|
||||
Map all of it. */
|
||||
ah->addr = mmap64 (NULL, ah->mmaped, PROT_READ, MAP_SHARED, fd, 0);
|
||||
if (ah->addr == MAP_FAILED)
|
||||
error (EXIT_FAILURE, errno, "cannot map archive header");
|
||||
}
|
||||
|
||||
/* Open the locale archive. */
|
||||
extern void open_archive (struct locarhandle *ah, bool readonly);
|
||||
|
||||
/* Close the locale archive. */
|
||||
extern void close_archive (struct locarhandle *ah);
|
||||
|
||||
/* Add given locale data to the archive. */
|
||||
extern int add_locale_to_archive (struct locarhandle *ah, const char *name,
|
||||
locale_data_t data, bool replace);
|
||||
|
||||
extern void add_alias (struct locarhandle *ah, const char *alias,
|
||||
bool replace, const char *oldname,
|
||||
uint32_t *locrec_offset_p);
|
||||
|
||||
extern struct namehashent *
|
||||
insert_name (struct locarhandle *ah,
|
||||
const char *name, size_t name_len, bool replace);
|
||||
|
||||
struct nameent
|
||||
{
|
||||
char *name;
|
||||
struct locrecent *locrec;
|
||||
};
|
||||
|
||||
struct dataent
|
||||
{
|
||||
const unsigned char *sum;
|
||||
uint32_t file_offset;
|
||||
};
|
||||
|
||||
static int
|
||||
nameentcmp (const void *a, const void *b)
|
||||
{
|
||||
struct locrecent *la = ((const struct nameent *) a)->locrec;
|
||||
struct locrecent *lb = ((const struct nameent *) b)->locrec;
|
||||
uint32_t start_a = -1, end_a = 0;
|
||||
uint32_t start_b = -1, end_b = 0;
|
||||
int cnt;
|
||||
|
||||
for (cnt = 0; cnt < __LC_LAST; ++cnt)
|
||||
if (cnt != LC_ALL)
|
||||
{
|
||||
if (la->record[cnt].offset < start_a)
|
||||
start_a = la->record[cnt].offset;
|
||||
if (la->record[cnt].offset + la->record[cnt].len > end_a)
|
||||
end_a = la->record[cnt].offset + la->record[cnt].len;
|
||||
}
|
||||
assert (start_a != (uint32_t)-1);
|
||||
assert (end_a != 0);
|
||||
|
||||
for (cnt = 0; cnt < __LC_LAST; ++cnt)
|
||||
if (cnt != LC_ALL)
|
||||
{
|
||||
if (lb->record[cnt].offset < start_b)
|
||||
start_b = lb->record[cnt].offset;
|
||||
if (lb->record[cnt].offset + lb->record[cnt].len > end_b)
|
||||
end_b = lb->record[cnt].offset + lb->record[cnt].len;
|
||||
}
|
||||
assert (start_b != (uint32_t)-1);
|
||||
assert (end_b != 0);
|
||||
|
||||
if (start_a != start_b)
|
||||
return (int)start_a - (int)start_b;
|
||||
return (int)end_a - (int)end_b;
|
||||
}
|
||||
|
||||
static int
|
||||
dataentcmp (const void *a, const void *b)
|
||||
{
|
||||
if (((const struct dataent *) a)->file_offset
|
||||
< ((const struct dataent *) b)->file_offset)
|
||||
return -1;
|
||||
|
||||
if (((const struct dataent *) a)->file_offset
|
||||
> ((const struct dataent *) b)->file_offset)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sumsearchfn (const void *key, const void *ent)
|
||||
{
|
||||
uint32_t keyn = *(uint32_t *)key;
|
||||
uint32_t entn = ((struct dataent *)ent)->file_offset;
|
||||
|
||||
if (keyn < entn)
|
||||
return -1;
|
||||
if (keyn > entn)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
compute_data (struct locarhandle *ah, struct nameent *name, size_t sumused,
|
||||
struct dataent *files, locale_data_t data)
|
||||
{
|
||||
int cnt;
|
||||
struct locrecent *locrec = name->locrec;
|
||||
struct dataent *file;
|
||||
data[LC_ALL].addr = ((char *) ah->addr) + locrec->record[LC_ALL].offset;
|
||||
data[LC_ALL].size = locrec->record[LC_ALL].len;
|
||||
for (cnt = 0; cnt < __LC_LAST; ++cnt)
|
||||
if (cnt != LC_ALL)
|
||||
{
|
||||
data[cnt].addr = ((char *) ah->addr) + locrec->record[cnt].offset;
|
||||
data[cnt].size = locrec->record[cnt].len;
|
||||
if (data[cnt].addr >= data[LC_ALL].addr
|
||||
&& data[cnt].addr + data[cnt].size
|
||||
<= data[LC_ALL].addr + data[LC_ALL].size)
|
||||
__md5_buffer (data[cnt].addr, data[cnt].size, data[cnt].sum);
|
||||
else
|
||||
{
|
||||
file = bsearch (&locrec->record[cnt].offset, files, sumused,
|
||||
sizeof (*files), sumsearchfn);
|
||||
if (file == NULL)
|
||||
error (EXIT_FAILURE, 0, "inconsistent template file");
|
||||
memcpy (data[cnt].sum, file->sum, sizeof (data[cnt].sum));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
fill_archive (struct locarhandle *tmpl_ah,
|
||||
const char *fname,
|
||||
size_t install_langs_count, char *install_langs_list[],
|
||||
size_t nlist, char *list[],
|
||||
const char *primary)
|
||||
{
|
||||
struct locarhandle ah;
|
||||
struct locarhead *head;
|
||||
int result = 0;
|
||||
struct nameent *names;
|
||||
struct namehashent *namehashtab;
|
||||
size_t cnt, used;
|
||||
struct dataent *files;
|
||||
struct sumhashent *sumhashtab;
|
||||
size_t sumused;
|
||||
struct locrecent *primary_locrec = NULL;
|
||||
struct nameent *primary_nameent = NULL;
|
||||
|
||||
head = tmpl_ah->addr;
|
||||
names = (struct nameent *) malloc (head->namehash_used
|
||||
* sizeof (struct nameent));
|
||||
files = (struct dataent *) malloc (head->sumhash_used
|
||||
* sizeof (struct dataent));
|
||||
if (names == NULL || files == NULL)
|
||||
error (EXIT_FAILURE, errno, "could not allocate tables");
|
||||
|
||||
namehashtab = (struct namehashent *) ((char *) tmpl_ah->addr
|
||||
+ head->namehash_offset);
|
||||
sumhashtab = (struct sumhashent *) ((char *) tmpl_ah->addr
|
||||
+ head->sumhash_offset);
|
||||
|
||||
for (cnt = used = 0; cnt < head->namehash_size; ++cnt)
|
||||
if (namehashtab[cnt].locrec_offset != 0)
|
||||
{
|
||||
char * name;
|
||||
int i;
|
||||
assert (used < head->namehash_used);
|
||||
name = tmpl_ah->addr + namehashtab[cnt].name_offset;
|
||||
if (install_langs_count == 0)
|
||||
{
|
||||
/* Always intstall the entry. */
|
||||
names[used].name = name;
|
||||
names[used++].locrec
|
||||
= (struct locrecent *) ((char *) tmpl_ah->addr +
|
||||
namehashtab[cnt].locrec_offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Only install the entry if the user asked for it via
|
||||
--install-langs. */
|
||||
for (i = 0; i < install_langs_count; i++)
|
||||
{
|
||||
/* Add one for "_" and one for the null terminator. */
|
||||
size_t len = strlen (install_langs_list[i]) + 2;
|
||||
char *install_lang = (char *)xmalloc (len);
|
||||
strcpy (install_lang, install_langs_list[i]);
|
||||
if (strchr (install_lang, '_') == NULL)
|
||||
strcat (install_lang, "_");
|
||||
if (strncmp (name, install_lang, strlen (install_lang)) == 0)
|
||||
{
|
||||
names[used].name = name;
|
||||
names[used++].locrec
|
||||
= (struct locrecent *) ((char *)tmpl_ah->addr
|
||||
+ namehashtab[cnt].locrec_offset);
|
||||
}
|
||||
free (install_lang);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Sort the names. */
|
||||
qsort (names, used, sizeof (struct nameent), nameentcmp);
|
||||
|
||||
for (cnt = sumused = 0; cnt < head->sumhash_size; ++cnt)
|
||||
if (sumhashtab[cnt].file_offset != 0)
|
||||
{
|
||||
assert (sumused < head->sumhash_used);
|
||||
files[sumused].sum = (const unsigned char *) sumhashtab[cnt].sum;
|
||||
files[sumused++].file_offset = sumhashtab[cnt].file_offset;
|
||||
}
|
||||
|
||||
/* Sort by file locations. */
|
||||
qsort (files, sumused, sizeof (struct dataent), dataentcmp);
|
||||
|
||||
/* Open the archive. This call never returns if we cannot
|
||||
successfully open the archive. */
|
||||
ah.fname = NULL;
|
||||
if (fname != NULL)
|
||||
ah.fname = fname;
|
||||
open_archive (&ah, false);
|
||||
|
||||
if (primary != NULL)
|
||||
{
|
||||
for (cnt = 0; cnt < used; ++cnt)
|
||||
if (strcmp (names[cnt].name, primary) == 0)
|
||||
break;
|
||||
if (cnt < used)
|
||||
{
|
||||
locale_data_t data;
|
||||
|
||||
compute_data (tmpl_ah, &names[cnt], sumused, files, data);
|
||||
result |= add_locale_to_archive (&ah, primary, data, 0);
|
||||
primary_locrec = names[cnt].locrec;
|
||||
primary_nameent = &names[cnt];
|
||||
}
|
||||
}
|
||||
|
||||
for (cnt = 0; cnt < used; ++cnt)
|
||||
if (&names[cnt] == primary_nameent)
|
||||
continue;
|
||||
else if ((cnt > 0 && names[cnt - 1].locrec == names[cnt].locrec)
|
||||
|| names[cnt].locrec == primary_locrec)
|
||||
{
|
||||
const char *oldname;
|
||||
struct namehashent *namehashent;
|
||||
uint32_t locrec_offset;
|
||||
|
||||
if (names[cnt].locrec == primary_locrec)
|
||||
oldname = primary;
|
||||
else
|
||||
oldname = names[cnt - 1].name;
|
||||
namehashent = insert_name (&ah, oldname, strlen (oldname), true);
|
||||
assert (namehashent->name_offset != 0);
|
||||
assert (namehashent->locrec_offset != 0);
|
||||
locrec_offset = namehashent->locrec_offset;
|
||||
add_alias (&ah, names[cnt].name, 0, oldname, &locrec_offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
locale_data_t data;
|
||||
|
||||
compute_data (tmpl_ah, &names[cnt], sumused, files, data);
|
||||
result |= add_locale_to_archive (&ah, names[cnt].name, data, 0);
|
||||
}
|
||||
|
||||
while (nlist-- > 0)
|
||||
{
|
||||
const char *fname = *list++;
|
||||
size_t fnamelen = strlen (fname);
|
||||
struct stat64 st;
|
||||
DIR *dirp;
|
||||
struct dirent64 *d;
|
||||
int seen;
|
||||
locale_data_t data;
|
||||
int cnt;
|
||||
|
||||
/* First see whether this really is a directory and whether it
|
||||
contains all the require locale category files. */
|
||||
if (stat64 (fname, &st) < 0)
|
||||
{
|
||||
error (0, 0, "stat of \"%s\" failed: %s: ignored", fname,
|
||||
strerror (errno));
|
||||
continue;
|
||||
}
|
||||
if (!S_ISDIR (st.st_mode))
|
||||
{
|
||||
error (0, 0, "\"%s\" is no directory; ignored", fname);
|
||||
continue;
|
||||
}
|
||||
|
||||
dirp = opendir (fname);
|
||||
if (dirp == NULL)
|
||||
{
|
||||
error (0, 0, "cannot open directory \"%s\": %s: ignored",
|
||||
fname, strerror (errno));
|
||||
continue;
|
||||
}
|
||||
|
||||
seen = 0;
|
||||
while ((d = readdir64 (dirp)) != NULL)
|
||||
{
|
||||
for (cnt = 0; cnt < __LC_LAST; ++cnt)
|
||||
if (cnt != LC_ALL)
|
||||
if (strcmp (d->d_name, locnames[cnt]) == 0)
|
||||
{
|
||||
unsigned char d_type;
|
||||
|
||||
/* We have an object of the required name. If it's
|
||||
a directory we have to look at a file with the
|
||||
prefix "SYS_". Otherwise we have found what we
|
||||
are looking for. */
|
||||
#ifdef _DIRENT_HAVE_D_TYPE
|
||||
d_type = d->d_type;
|
||||
|
||||
if (d_type != DT_REG)
|
||||
#endif
|
||||
{
|
||||
char fullname[fnamelen + 2 * strlen (d->d_name) + 7];
|
||||
|
||||
#ifdef _DIRENT_HAVE_D_TYPE
|
||||
if (d_type == DT_UNKNOWN)
|
||||
#endif
|
||||
{
|
||||
strcpy (stpcpy (stpcpy (fullname, fname), "/"),
|
||||
d->d_name);
|
||||
|
||||
if (stat64 (fullname, &st) == -1)
|
||||
/* We cannot stat the file, ignore it. */
|
||||
break;
|
||||
|
||||
d_type = IFTODT (st.st_mode);
|
||||
}
|
||||
|
||||
if (d_type == DT_DIR)
|
||||
{
|
||||
/* We have to do more tests. The file is a
|
||||
directory and it therefore must contain a
|
||||
regular file with the same name except a
|
||||
"SYS_" prefix. */
|
||||
char *t = stpcpy (stpcpy (fullname, fname), "/");
|
||||
strcpy (stpcpy (stpcpy (t, d->d_name), "/SYS_"),
|
||||
d->d_name);
|
||||
|
||||
if (stat64 (fullname, &st) == -1)
|
||||
/* There is no SYS_* file or we cannot
|
||||
access it. */
|
||||
break;
|
||||
|
||||
d_type = IFTODT (st.st_mode);
|
||||
}
|
||||
}
|
||||
|
||||
/* If we found a regular file (eventually after
|
||||
following a symlink) we are successful. */
|
||||
if (d_type == DT_REG)
|
||||
++seen;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
closedir (dirp);
|
||||
|
||||
if (seen != __LC_LAST - 1)
|
||||
{
|
||||
/* We don't have all locale category files. Ignore the name. */
|
||||
error (0, 0, "incomplete set of locale files in \"%s\"",
|
||||
fname);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Add the files to the archive. To do this we first compute
|
||||
sizes and the MD5 sums of all the files. */
|
||||
for (cnt = 0; cnt < __LC_LAST; ++cnt)
|
||||
if (cnt != LC_ALL)
|
||||
{
|
||||
char fullname[fnamelen + 2 * strlen (locnames[cnt]) + 7];
|
||||
int fd;
|
||||
|
||||
strcpy (stpcpy (stpcpy (fullname, fname), "/"), locnames[cnt]);
|
||||
fd = open64 (fullname, O_RDONLY);
|
||||
if (fd == -1 || fstat64 (fd, &st) == -1)
|
||||
{
|
||||
/* Cannot read the file. */
|
||||
if (fd != -1)
|
||||
close (fd);
|
||||
break;
|
||||
}
|
||||
|
||||
if (S_ISDIR (st.st_mode))
|
||||
{
|
||||
char *t;
|
||||
close (fd);
|
||||
t = stpcpy (stpcpy (fullname, fname), "/");
|
||||
strcpy (stpcpy (stpcpy (t, locnames[cnt]), "/SYS_"),
|
||||
locnames[cnt]);
|
||||
|
||||
fd = open64 (fullname, O_RDONLY);
|
||||
if (fd == -1 || fstat64 (fd, &st) == -1
|
||||
|| !S_ISREG (st.st_mode))
|
||||
{
|
||||
if (fd != -1)
|
||||
close (fd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Map the file. */
|
||||
data[cnt].addr = mmap64 (NULL, st.st_size, PROT_READ, MAP_SHARED,
|
||||
fd, 0);
|
||||
if (data[cnt].addr == MAP_FAILED)
|
||||
{
|
||||
/* Cannot map it. */
|
||||
close (fd);
|
||||
break;
|
||||
}
|
||||
|
||||
data[cnt].size = st.st_size;
|
||||
__md5_buffer (data[cnt].addr, st.st_size, data[cnt].sum);
|
||||
|
||||
/* We don't need the file descriptor anymore. */
|
||||
close (fd);
|
||||
}
|
||||
|
||||
if (cnt != __LC_LAST)
|
||||
{
|
||||
while (cnt-- > 0)
|
||||
if (cnt != LC_ALL)
|
||||
munmap (data[cnt].addr, data[cnt].size);
|
||||
|
||||
error (0, 0, "cannot read all files in \"%s\": ignored", fname);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
result |= add_locale_to_archive (&ah, basename (fname), data, 0);
|
||||
|
||||
for (cnt = 0; cnt < __LC_LAST; ++cnt)
|
||||
if (cnt != LC_ALL)
|
||||
munmap (data[cnt].addr, data[cnt].size);
|
||||
}
|
||||
|
||||
/* We are done. */
|
||||
close_archive (&ah);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void usage()
|
||||
{
|
||||
printf ("\
|
||||
Usage: build-locale-archive [OPTION]... [TEMPLATE-FILE] [ARCHIVE-FILE]\n\
|
||||
Builds a locale archive from a template file.\n\
|
||||
Options:\n\
|
||||
-h, --help Print this usage message.\n\
|
||||
-v, --verbose Verbose execution.\n\
|
||||
-l, --install-langs=LIST Only include locales given in LIST into the \n\
|
||||
locale archive. LIST is a colon separated list\n\
|
||||
of locale prefixes, for example \"de:en:ja\".\n\
|
||||
The special argument \"all\" means to install\n\
|
||||
all languages and it must be present by itself.\n\
|
||||
If \"all\" is present with any other language it\n\
|
||||
will be treated as the name of a locale.\n\
|
||||
If the --install-langs option is missing, all\n\
|
||||
locales are installed. The colon separated list\n\
|
||||
can contain any strings matching the beginning of\n\
|
||||
locale names.\n\
|
||||
If a string does not contain a \"_\", it is added.\n\
|
||||
Examples:\n\
|
||||
--install-langs=\"en\"\n\
|
||||
installs en_US, en_US.iso88591,\n\
|
||||
en_US.iso885915, en_US.utf8,\n\
|
||||
en_GB ...\n\
|
||||
--install-langs=\"en_US.utf8\"\n\
|
||||
installs only en_US.utf8.\n\
|
||||
--install-langs=\"ko\"\n\
|
||||
installs ko_KR, ko_KR.euckr,\n\
|
||||
ko_KR.utf8 but *not* kok_IN\n\
|
||||
because \"ko\" does not contain\n\
|
||||
\"_\" and it is silently added\n\
|
||||
--install-langs\"ko:kok\"\n\
|
||||
installs ko_KR, ko_KR.euckr,\n\
|
||||
ko_KR.utf8, kok_IN, and\n\
|
||||
kok_IN.utf8.\n\
|
||||
--install-langs=\"POSIX\" will\n\
|
||||
installs *no* locales at all\n\
|
||||
because POSIX matches none of\n\
|
||||
the locales. Actually, any string\n\
|
||||
matching nothing will do that.\n\
|
||||
POSIX and C will always be\n\
|
||||
available because they are\n\
|
||||
builtin.\n\
|
||||
Aliases are installed as well,\n\
|
||||
i.e. --install-langs=\"de\"\n\
|
||||
will install not only every locale starting with\n\
|
||||
\"de\" but also the aliases \"deutsch\"\n\
|
||||
and and \"german\" although the latter does not\n\
|
||||
start with \"de\".\n\
|
||||
\n\
|
||||
If the arguments TEMPLATE-FILE and ARCHIVE-FILE are not given the locations\n\
|
||||
where the glibc used expects these files are used by default.\n\
|
||||
");
|
||||
}
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
char path[4096];
|
||||
DIR *dirp;
|
||||
struct dirent64 *d;
|
||||
struct stat64 st;
|
||||
char *list[16384], *primary;
|
||||
char *lang;
|
||||
int install_langs_count = 0;
|
||||
int i;
|
||||
char *install_langs_arg, *ila_start;
|
||||
char **install_langs_list = NULL;
|
||||
unsigned int cnt = 0;
|
||||
struct locarhandle tmpl_ah;
|
||||
char *new_locar_fname = NULL;
|
||||
size_t loc_path_len = strlen (loc_path);
|
||||
|
||||
while (1)
|
||||
{
|
||||
int c;
|
||||
|
||||
static struct option long_options[] =
|
||||
{
|
||||
{"help", no_argument, 0, 'h'},
|
||||
{"verbose", no_argument, 0, 'v'},
|
||||
{"install-langs", required_argument, 0, 'l'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
/* getopt_long stores the option index here. */
|
||||
int option_index = 0;
|
||||
|
||||
c = getopt_long (argc, argv, "vhl:",
|
||||
long_options, &option_index);
|
||||
|
||||
/* Detect the end of the options. */
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case 0:
|
||||
printf ("unknown option %s", long_options[option_index].name);
|
||||
if (optarg)
|
||||
printf (" with arg %s", optarg);
|
||||
printf ("\n");
|
||||
usage ();
|
||||
exit (1);
|
||||
|
||||
case 'v':
|
||||
verbose = 1;
|
||||
be_quiet = 0;
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
usage ();
|
||||
exit (0);
|
||||
|
||||
case 'l':
|
||||
install_langs_arg = ila_start = strdup (optarg);
|
||||
/* If the argument to --install-lang is "all", do
|
||||
not limit the list of languages to install and install
|
||||
them all. We do not support installing a single locale
|
||||
called "all". */
|
||||
#define MAGIC_INSTALL_ALL "all"
|
||||
if (install_langs_arg != NULL
|
||||
&& install_langs_arg[0] != '\0'
|
||||
&& !(strncmp(install_langs_arg, MAGIC_INSTALL_ALL,
|
||||
strlen(MAGIC_INSTALL_ALL)) == 0
|
||||
&& strlen (install_langs_arg) == 3))
|
||||
{
|
||||
/* Count the number of languages we will install. */
|
||||
while (true)
|
||||
{
|
||||
lang = strtok(install_langs_arg, ":;,");
|
||||
if (lang == NULL)
|
||||
break;
|
||||
install_langs_count++;
|
||||
install_langs_arg = NULL;
|
||||
}
|
||||
free (ila_start);
|
||||
|
||||
/* Reject an entire string made up of delimiters. */
|
||||
if (install_langs_count == 0)
|
||||
break;
|
||||
|
||||
/* Copy the list. */
|
||||
install_langs_list = (char **)xmalloc (sizeof(char *) * install_langs_count);
|
||||
install_langs_arg = ila_start = strdup (optarg);
|
||||
install_langs_count = 0;
|
||||
while (true)
|
||||
{
|
||||
lang = strtok(install_langs_arg, ":;,");
|
||||
if (lang == NULL)
|
||||
break;
|
||||
install_langs_list[install_langs_count] = lang;
|
||||
install_langs_count++;
|
||||
install_langs_arg = NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case '?':
|
||||
/* getopt_long already printed an error message. */
|
||||
usage ();
|
||||
exit (0);
|
||||
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
tmpl_ah.fname = NULL;
|
||||
if (optind < argc)
|
||||
tmpl_ah.fname = argv[optind];
|
||||
if (optind + 1 < argc)
|
||||
new_locar_fname = argv[optind + 1];
|
||||
if (verbose)
|
||||
{
|
||||
if (tmpl_ah.fname)
|
||||
printf("input archive file specified on command line: %s\n",
|
||||
tmpl_ah.fname);
|
||||
else
|
||||
printf("using default input archive file.\n");
|
||||
if (new_locar_fname)
|
||||
printf("output archive file specified on command line: %s\n",
|
||||
new_locar_fname);
|
||||
else
|
||||
printf("using default output archive file.\n");
|
||||
}
|
||||
|
||||
dirp = opendir (loc_path);
|
||||
if (dirp == NULL)
|
||||
error (EXIT_FAILURE, errno, "cannot open directory \"%s\"", loc_path);
|
||||
|
||||
open_tmpl_archive (&tmpl_ah);
|
||||
|
||||
if (new_locar_fname)
|
||||
unlink (new_locar_fname);
|
||||
else
|
||||
unlink (locar_file);
|
||||
primary = getenv ("LC_ALL");
|
||||
if (primary == NULL)
|
||||
primary = getenv ("LANG");
|
||||
if (primary != NULL)
|
||||
{
|
||||
if (strncmp (primary, "ja", 2) != 0
|
||||
&& strncmp (primary, "ko", 2) != 0
|
||||
&& strncmp (primary, "zh", 2) != 0)
|
||||
{
|
||||
char *ptr = malloc (strlen (primary) + strlen (".utf8") + 1), *p, *q;
|
||||
/* This leads to invalid locales sometimes:
|
||||
de_DE.iso885915@euro -> de_DE.utf8@euro */
|
||||
if (ptr != NULL)
|
||||
{
|
||||
p = ptr;
|
||||
q = primary;
|
||||
while (*q && *q != '.' && *q != '@')
|
||||
*p++ = *q++;
|
||||
if (*q == '.')
|
||||
while (*q && *q != '@')
|
||||
q++;
|
||||
p = stpcpy (p, ".utf8");
|
||||
strcpy (p, q);
|
||||
primary = ptr;
|
||||
}
|
||||
else
|
||||
primary = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy (path, loc_path, loc_path_len);
|
||||
|
||||
while ((d = readdir64 (dirp)) != NULL)
|
||||
{
|
||||
if (strcmp (d->d_name, ".") == 0 || strcmp (d->d_name, "..") == 0)
|
||||
continue;
|
||||
if (strchr (d->d_name, '_') == NULL)
|
||||
continue;
|
||||
|
||||
size_t d_name_len = strlen (d->d_name);
|
||||
if (loc_path_len + d_name_len + 1 > sizeof (path))
|
||||
{
|
||||
error (0, 0, "too long filename \"%s\"", d->d_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
memcpy (path + loc_path_len, d->d_name, d_name_len + 1);
|
||||
if (stat64 (path, &st) < 0)
|
||||
{
|
||||
error (0, errno, "cannot stat \"%s\"", path);
|
||||
continue;
|
||||
}
|
||||
if (! S_ISDIR (st.st_mode))
|
||||
continue;
|
||||
if (cnt == 16384)
|
||||
{
|
||||
error (0, 0, "too many directories in \"%s\"", loc_path);
|
||||
break;
|
||||
}
|
||||
list[cnt] = strdup (path);
|
||||
if (list[cnt] == NULL)
|
||||
{
|
||||
error (0, errno, "cannot add file to list \"%s\"", path);
|
||||
continue;
|
||||
}
|
||||
if (primary != NULL && cnt > 0 && strcmp (primary, d->d_name) == 0)
|
||||
{
|
||||
char *p = list[0];
|
||||
list[0] = list[cnt];
|
||||
list[cnt] = p;
|
||||
}
|
||||
cnt++;
|
||||
}
|
||||
closedir (dirp);
|
||||
/* Store the archive to the file specified as the second argument on the
|
||||
command line or the default locale archive. */
|
||||
fill_archive (&tmpl_ah, new_locar_fname,
|
||||
install_langs_count, install_langs_list,
|
||||
cnt, list, primary);
|
||||
close_archive (&tmpl_ah);
|
||||
truncate (tmpl_file, 0);
|
||||
if (install_langs_count > 0)
|
||||
{
|
||||
free (ila_start);
|
||||
free (install_langs_list);
|
||||
}
|
||||
char *tz_argv[] = { "/usr/sbin/tzdata-update", NULL };
|
||||
execve (tz_argv[0], (char *const *)tz_argv, (char *const *)&tz_argv[1]);
|
||||
exit (0);
|
||||
}
|
25
SOURCES/glibc-asflags.patch
Normal file
25
SOURCES/glibc-asflags.patch
Normal file
@ -0,0 +1,25 @@
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Wed Jul 4 16:16:57 2018 +0200
|
||||
|
||||
Makeconfig (ASFLAGS): Always append required assembler flags.
|
||||
|
||||
Submitted upstream here:
|
||||
|
||||
https://sourceware.org/ml/libc-alpha/2018-07/msg00077.html
|
||||
|
||||
Otherwise, we lose essential flags such as -Wa,--noexecstack due to
|
||||
the way += works in make due to the ASFLAGS command line override.
|
||||
|
||||
diff --git a/Makeconfig b/Makeconfig
|
||||
index b0b27f0113ac18b8..92e76d6200bbcd5b 100644
|
||||
--- a/Makeconfig
|
||||
+++ b/Makeconfig
|
||||
@@ -1047,7 +1047,7 @@ endif
|
||||
ifndef ASFLAGS
|
||||
ASFLAGS := $(filter -g% -fdebug-prefix-map=%,$(CFLAGS))
|
||||
endif
|
||||
-ASFLAGS += -Werror=undef $(ASFLAGS-config) $(asflags-cpu)
|
||||
+override ASFLAGS += -Werror=undef $(ASFLAGS-config) $(asflags-cpu)
|
||||
|
||||
ifndef BUILD_CC
|
||||
BUILD_CC = $(CC)
|
153
SOURCES/glibc-bench-compare
Executable file
153
SOURCES/glibc-bench-compare
Executable file
@ -0,0 +1,153 @@
|
||||
#!/usr/bin/bash
|
||||
# This script can be invoked as follows:
|
||||
#
|
||||
# glibc-bench-compare [options] <BUILD> [BUILD]
|
||||
#
|
||||
# Options may be one of the following:
|
||||
#
|
||||
# -t The BUILD arguments are task ids and not a version-release string
|
||||
# -a ARCH Do comparison for ARCH architecture
|
||||
#
|
||||
# If any of the above options are given, both BUILD arguments must be given.
|
||||
# Otherwise, if only one BUILD is specified, then it is compared against the
|
||||
# installed glibc.
|
||||
|
||||
# Silence the pushd/popd messages
|
||||
pushd() {
|
||||
command pushd "$@" > /dev/null 2>&1
|
||||
}
|
||||
|
||||
popd() {
|
||||
command popd "$@" > /dev/null 2>&1
|
||||
}
|
||||
|
||||
# Clean up any downloaded files before we exit
|
||||
trap "rm -rf /tmp/glibc-bench-compare.$BASHPID.*" EXIT
|
||||
|
||||
task=0
|
||||
arch=$(uname -i)
|
||||
options=0
|
||||
path=0
|
||||
installed=
|
||||
|
||||
# Look for any commandline options
|
||||
while getopts ":tpa:" opt; do
|
||||
case $opt in
|
||||
p)
|
||||
path=1
|
||||
;;
|
||||
t)
|
||||
task=1
|
||||
options=1
|
||||
echo "Not implemented."
|
||||
exit 1
|
||||
;;
|
||||
a)
|
||||
arch=$OPTARG
|
||||
options=1
|
||||
;;
|
||||
*)
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Done, now shift all option arguments out.
|
||||
shift $((OPTIND-1))
|
||||
|
||||
if [ $# -gt 2 ] || [ $# -eq 0 ] || [ $# -lt 2 -a $options -eq 1 ]; then
|
||||
echo "Usage: $0 [OPTIONS] <old> [new]"
|
||||
echo
|
||||
echo "OPTIONS:"
|
||||
echo -e "\t-t\tCompare two brew tasks"
|
||||
echo -e "\t-a ARCH\tGet rpms for the ARCH architecture"
|
||||
echo -e "\t-p\tCompare built rpms in two paths."
|
||||
echo -e "\t\tThis minimally needs glibc, glibc-common and glibc-benchtests"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z $2 ]; then
|
||||
new="$1"
|
||||
old=$(rpm --queryformat "%{VERSION}-%{RELEASE}\n" -q glibc | head -1)
|
||||
installed=$old
|
||||
else
|
||||
new="$2"
|
||||
old="$1"
|
||||
fi
|
||||
|
||||
decompress_rpms() {
|
||||
# We were given a path to the rpms. Figure out the version-release and
|
||||
# decompress the rpms.
|
||||
if [ -n $1 ]; then
|
||||
vr=$(rpm --queryformat="%{VERSION}-%{RELEASE}" -qp $1/glibc-2*.rpm | head -1)
|
||||
mkdir $vr && pushd $vr
|
||||
fi
|
||||
|
||||
for r in $1*.rpm; do
|
||||
( rpm2cpio $r | cpio -di ) > /dev/null
|
||||
done
|
||||
|
||||
if [ -n $1 ]; then
|
||||
popd
|
||||
echo $vr
|
||||
fi
|
||||
}
|
||||
|
||||
# Get rpms for a build and decompress them
|
||||
get_build() {
|
||||
echo "Processing build $1"
|
||||
mkdir $1 && pushd $1
|
||||
brew buildinfo "glibc-$1" |
|
||||
sed -n -e "s|/mnt/koji\(.\+$arch.\+\)|http://kojipkgs.fedoraproject.org\1|p" |
|
||||
while read url; do
|
||||
echo "Downloading $url"
|
||||
wget -q $url
|
||||
done
|
||||
decompress_rpms
|
||||
|
||||
echo "Removing rpms"
|
||||
rm -f $1/*.rpm
|
||||
|
||||
popd
|
||||
}
|
||||
|
||||
# Run benchmarks for a build
|
||||
run_bench() {
|
||||
if [ -z $1 ]; then
|
||||
make DETAILED=1 ver=$installed prefix= -f /usr/libexec/glibc-benchtests/bench.mk bench
|
||||
else
|
||||
make DETAILED=1 ver=$1 prefix=$PWD -f $1/usr/libexec/glibc-benchtests/bench.mk bench
|
||||
fi
|
||||
}
|
||||
|
||||
# Get absolute paths if needed, since we will change into the working directory
|
||||
# next.
|
||||
if [ $path -eq 1 ]; then
|
||||
old_path=$(realpath $old)/
|
||||
new_path=$(realpath $new)/
|
||||
fi
|
||||
|
||||
tmpdir=$(mktemp -p /tmp -d glibc-bench-compare.$$.XXXX)
|
||||
pushd $tmpdir
|
||||
|
||||
# Get both builds.
|
||||
if [ $path -eq 0 ]; then
|
||||
if [ -z $installed ]; then
|
||||
get_build $old
|
||||
fi
|
||||
get_build $new
|
||||
else
|
||||
old=$(decompress_rpms $old_path)
|
||||
new=$(decompress_rpms $new_path)
|
||||
fi
|
||||
|
||||
# make bench for each of those.
|
||||
if [ -z $installed ]; then
|
||||
run_bench $old
|
||||
else
|
||||
run_bench
|
||||
fi
|
||||
run_bench $new
|
||||
|
||||
# Now run the comparison script.
|
||||
$old/usr/libexec/glibc-benchtests/compare_bench.py $old/usr/libexec/glibc-benchtests/benchout.schema.json \
|
||||
bench.$old.out bench.$new.out
|
286
SOURCES/glibc-c-utf8-locale.patch
Normal file
286
SOURCES/glibc-c-utf8-locale.patch
Normal file
@ -0,0 +1,286 @@
|
||||
Short description: Add C.UTF-8 support.
|
||||
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
|
||||
Origin: PATCH
|
||||
Upstream status: not-submitted
|
||||
|
||||
This patch needs to upstream as part of Carlos O'Donell
|
||||
<carlos@redhat.com>'s work on enabling upstream C.UTF-8 support. This
|
||||
work is currently blocked on cleaning up the test results to prove that
|
||||
full code-point sorting is working as intended.
|
||||
|
||||
Note that this patch does not provide full code-point sorting as
|
||||
expected.
|
||||
|
||||
This patch needs to upstream as soon as possible since it would be nice
|
||||
to have this in F29 and fixed.
|
||||
|
||||
From 2eda7b462b415105f5a05c1323372d4e39d46439 Mon Sep 17 00:00:00 2001
|
||||
From: Mike FABIAN <mfabian@redhat.com>
|
||||
Date: Mon, 10 Aug 2015 15:58:12 +0200
|
||||
Subject: [PATCH] Add a C.UTF-8 locale
|
||||
|
||||
---
|
||||
localedata/SUPPORTED | 1 +
|
||||
localedata/locales/C | 238 +++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 239 insertions(+)
|
||||
create mode 100644 localedata/locales/C
|
||||
|
||||
diff --git a/localedata/SUPPORTED b/localedata/SUPPORTED
|
||||
index 8ca023e..2a78391 100644
|
||||
--- a/localedata/SUPPORTED
|
||||
+++ b/localedata/SUPPORTED
|
||||
@@ -1,6 +1,7 @@
|
||||
# This file names the currently supported and somewhat tested locales.
|
||||
# If you have any additions please file a glibc bug report.
|
||||
SUPPORTED-LOCALES=\
|
||||
+C.UTF-8/UTF-8 \
|
||||
aa_DJ.UTF-8/UTF-8 \
|
||||
aa_DJ/ISO-8859-1 \
|
||||
aa_ER/UTF-8 \
|
||||
diff --git a/localedata/locales/C b/localedata/locales/C
|
||||
new file mode 100644
|
||||
index 0000000..fdf460e
|
||||
--- /dev/null
|
||||
+++ b/localedata/locales/C
|
||||
@@ -0,0 +1,238 @@
|
||||
+escape_char /
|
||||
+comment_char %
|
||||
+% Locale for C locale in UTF-8
|
||||
+
|
||||
+LC_IDENTIFICATION
|
||||
+title "C locale"
|
||||
+source ""
|
||||
+address ""
|
||||
+contact ""
|
||||
+email "mfabian@redhat.com"
|
||||
+tel ""
|
||||
+fax ""
|
||||
+language "C"
|
||||
+territory ""
|
||||
+revision "1.0"
|
||||
+date "2015-08-10"
|
||||
+%
|
||||
+category "i18n:2012";LC_IDENTIFICATION
|
||||
+category "i18n:2012";LC_CTYPE
|
||||
+category "i18n:2012";LC_COLLATE
|
||||
+category "i18n:2012";LC_TIME
|
||||
+category "i18n:2012";LC_NUMERIC
|
||||
+category "i18n:2012";LC_MONETARY
|
||||
+category "i18n:2012";LC_MESSAGES
|
||||
+category "i18n:2012";LC_PAPER
|
||||
+category "i18n:2012";LC_NAME
|
||||
+category "i18n:2012";LC_ADDRESS
|
||||
+category "i18n:2012";LC_TELEPHONE
|
||||
+category "i18n:2012";LC_MEASUREMENT
|
||||
+END LC_IDENTIFICATION
|
||||
+
|
||||
+LC_CTYPE
|
||||
+copy "i18n"
|
||||
+
|
||||
+translit_start
|
||||
+include "translit_combining";""
|
||||
+translit_end
|
||||
+
|
||||
+END LC_CTYPE
|
||||
+
|
||||
+LC_COLLATE
|
||||
+order_start forward
|
||||
+<U0000>
|
||||
+..
|
||||
+<UFFFF>
|
||||
+<U10000>
|
||||
+..
|
||||
+<U1FFFF>
|
||||
+<U20000>
|
||||
+..
|
||||
+<U2FFFF>
|
||||
+<UE0000>
|
||||
+..
|
||||
+<UEFFFF>
|
||||
+<UF0000>
|
||||
+..
|
||||
+<UFFFFF>
|
||||
+<U100000>
|
||||
+..
|
||||
+<U10FFFF>
|
||||
+UNDEFINED
|
||||
+order_end
|
||||
+END LC_COLLATE
|
||||
+
|
||||
+LC_MONETARY
|
||||
+% This is the 14652 i18n fdcc-set definition for
|
||||
+% the LC_MONETARY category
|
||||
+% (except for the int_curr_symbol and currency_symbol, they are empty in
|
||||
+% the 14652 i18n fdcc-set definition and also empty in
|
||||
+% glibc/locale/C-monetary.c. But localedef complains in that case).
|
||||
+%
|
||||
+% Using "USD" for int_curr_symbol. But maybe "XXX" would be better?
|
||||
+% XXX is "No currency" (https://en.wikipedia.org/wiki/ISO_4217)
|
||||
+int_curr_symbol "<U0055><U0053><U0044><U0020>"
|
||||
+% Using "$" for currency_symbol. But maybe <U00A4> would be better?
|
||||
+% U+00A4 is the "generic currency symbol"
|
||||
+% (https://en.wikipedia.org/wiki/Currency_sign_%28typography%29)
|
||||
+currency_symbol "<U0024>"
|
||||
+mon_decimal_point "<U002E>"
|
||||
+mon_thousands_sep ""
|
||||
+mon_grouping -1
|
||||
+positive_sign ""
|
||||
+negative_sign "<U002D>"
|
||||
+int_frac_digits -1
|
||||
+frac_digits -1
|
||||
+p_cs_precedes -1
|
||||
+int_p_sep_by_space -1
|
||||
+p_sep_by_space -1
|
||||
+n_cs_precedes -1
|
||||
+int_n_sep_by_space -1
|
||||
+n_sep_by_space -1
|
||||
+p_sign_posn -1
|
||||
+n_sign_posn -1
|
||||
+%
|
||||
+END LC_MONETARY
|
||||
+
|
||||
+LC_NUMERIC
|
||||
+% This is the POSIX Locale definition for
|
||||
+% the LC_NUMERIC category.
|
||||
+%
|
||||
+decimal_point "<U002E>"
|
||||
+thousands_sep ""
|
||||
+grouping -1
|
||||
+END LC_NUMERIC
|
||||
+
|
||||
+LC_TIME
|
||||
+% This is the POSIX Locale definition for
|
||||
+% the LC_TIME category.
|
||||
+%
|
||||
+% Abbreviated weekday names (%a)
|
||||
+abday "<U0053><U0075><U006E>";"<U004D><U006F><U006E>";/
|
||||
+ "<U0054><U0075><U0065>";"<U0057><U0065><U0064>";/
|
||||
+ "<U0054><U0068><U0075>";"<U0046><U0072><U0069>";/
|
||||
+ "<U0053><U0061><U0074>"
|
||||
+
|
||||
+% Full weekday names (%A)
|
||||
+day "<U0053><U0075><U006E><U0064><U0061><U0079>";/
|
||||
+ "<U004D><U006F><U006E><U0064><U0061><U0079>";/
|
||||
+ "<U0054><U0075><U0065><U0073><U0064><U0061><U0079>";/
|
||||
+ "<U0057><U0065><U0064><U006E><U0065><U0073><U0064><U0061><U0079>";/
|
||||
+ "<U0054><U0068><U0075><U0072><U0073><U0064><U0061><U0079>";/
|
||||
+ "<U0046><U0072><U0069><U0064><U0061><U0079>";/
|
||||
+ "<U0053><U0061><U0074><U0075><U0072><U0064><U0061><U0079>"
|
||||
+
|
||||
+% Abbreviated month names (%b)
|
||||
+abmon "<U004A><U0061><U006E>";"<U0046><U0065><U0062>";/
|
||||
+ "<U004D><U0061><U0072>";"<U0041><U0070><U0072>";/
|
||||
+ "<U004D><U0061><U0079>";"<U004A><U0075><U006E>";/
|
||||
+ "<U004A><U0075><U006C>";"<U0041><U0075><U0067>";/
|
||||
+ "<U0053><U0065><U0070>";"<U004F><U0063><U0074>";/
|
||||
+ "<U004E><U006F><U0076>";"<U0044><U0065><U0063>"
|
||||
+
|
||||
+% Full month names (%B)
|
||||
+mon "<U004A><U0061><U006E><U0075><U0061><U0072><U0079>";/
|
||||
+ "<U0046><U0065><U0062><U0072><U0075><U0061><U0072><U0079>";/
|
||||
+ "<U004D><U0061><U0072><U0063><U0068>";/
|
||||
+ "<U0041><U0070><U0072><U0069><U006C>";/
|
||||
+ "<U004D><U0061><U0079>";/
|
||||
+ "<U004A><U0075><U006E><U0065>";/
|
||||
+ "<U004A><U0075><U006C><U0079>";/
|
||||
+ "<U0041><U0075><U0067><U0075><U0073><U0074>";/
|
||||
+ "<U0053><U0065><U0070><U0074><U0065><U006D><U0062><U0065><U0072>";/
|
||||
+ "<U004F><U0063><U0074><U006F><U0062><U0065><U0072>";/
|
||||
+ "<U004E><U006F><U0076><U0065><U006D><U0062><U0065><U0072>";/
|
||||
+ "<U0044><U0065><U0063><U0065><U006D><U0062><U0065><U0072>"
|
||||
+
|
||||
+% Week description, consists of three fields:
|
||||
+% 1. Number of days in a week.
|
||||
+% 2. Gregorian date that is a first weekday (19971130 for Sunday, 19971201 for Monday).
|
||||
+% 3. The weekday number to be contained in the first week of the year.
|
||||
+%
|
||||
+% ISO 8601 conforming applications should use the values 7, 19971201 (a
|
||||
+% Monday), and 4 (Thursday), respectively.
|
||||
+week 7;19971201;4
|
||||
+first_weekday 1
|
||||
+first_workday 1
|
||||
+
|
||||
+% Appropriate date and time representation (%c)
|
||||
+% "%a %b %e %H:%M:%S %Y"
|
||||
+d_t_fmt "<U0025><U0061><U0020><U0025><U0062><U0020><U0025><U0065><U0020><U0025><U0048><U003A><U0025><U004D><U003A><U0025><U0053><U0020><U0025><U0059>"
|
||||
+
|
||||
+% Appropriate date representation (%x)
|
||||
+% "%m/%d/%y"
|
||||
+d_fmt "<U0025><U006D><U002F><U0025><U0064><U002F><U0025><U0079>"
|
||||
+
|
||||
+% Appropriate time representation (%X)
|
||||
+% "%H:%M:%S"
|
||||
+t_fmt "<U0025><U0048><U003A><U0025><U004D><U003A><U0025><U0053>"
|
||||
+
|
||||
+% Appropriate AM/PM time representation (%r)
|
||||
+% "%I:%M:%S %p"
|
||||
+t_fmt_ampm "<U0025><U0049><U003A><U0025><U004D><U003A><U0025><U0053><U0020><U0025><U0070>"
|
||||
+
|
||||
+% Equivalent of AM/PM (%p) "AM"/"PM"
|
||||
+%
|
||||
+am_pm "<U0041><U004D>";"<U0050><U004D>"
|
||||
+
|
||||
+% Appropriate date representation (date(1)) "%a %b %e %H:%M:%S %Z %Y"
|
||||
+date_fmt "<U0025><U0061><U0020><U0025><U0062><U0020><U0025><U0065><U0020><U0025><U0048><U003A><U0025><U004D><U003A><U0025><U0053><U0020><U0025><U005A><U0020><U0025><U0059>"
|
||||
+END LC_TIME
|
||||
+
|
||||
+LC_MESSAGES
|
||||
+% This is the POSIX Locale definition for
|
||||
+% the LC_NUMERIC category.
|
||||
+%
|
||||
+yesexpr "<U005E><U005B><U0079><U0059><U005D>"
|
||||
+noexpr "<U005E><U005B><U006E><U004E><U005D>"
|
||||
+yesstr "<U0059><U0065><U0073>"
|
||||
+nostr "<U004E><U006F>"
|
||||
+END LC_MESSAGES
|
||||
+
|
||||
+LC_PAPER
|
||||
+% This is the ISO/IEC 14652 "i18n" definition for
|
||||
+% the LC_PAPER category.
|
||||
+% (A4 paper, this is also used in the built in C/POSIX
|
||||
+% locale in glibc/locale/C-paper.c)
|
||||
+height 297
|
||||
+width 210
|
||||
+END LC_PAPER
|
||||
+
|
||||
+LC_NAME
|
||||
+% This is the ISO/IEC 14652 "i18n" definition for
|
||||
+% the LC_NAME category.
|
||||
+% "%p%t%g%t%m%t%f"
|
||||
+% (also used in the built in C/POSIX locale in glibc/locale/C-name.c)
|
||||
+name_fmt "<U0025><U0070><U0025><U0074><U0025><U0067><U0025><U0074>/
|
||||
+<U0025><U006D><U0025><U0074><U0025><U0066>"
|
||||
+END LC_NAME
|
||||
+
|
||||
+LC_ADDRESS
|
||||
+% This is the ISO/IEC 14652 "i18n" definition for
|
||||
+% the LC_ADDRESS category.
|
||||
+% "%a%N%f%N%d%N%b%N%s %h %e %r%N%C-%z %T%N%c%N"
|
||||
+% (also used in the built in C/POSIX locale in glibc/locale/C-address.c)
|
||||
+postal_fmt "<U0025><U0061><U0025><U004E><U0025><U0066><U0025><U004E>/
|
||||
+<U0025><U0064><U0025><U004E><U0025><U0062><U0025><U004E><U0025><U0073>/
|
||||
+<U0020><U0025><U0068><U0020><U0025><U0065><U0020><U0025><U0072><U0025>/
|
||||
+<U004E><U0025><U0043><U002D><U0025><U007A><U0020><U0025><U0054><U0025>/
|
||||
+<U004E><U0025><U0063><U0025><U004E>"
|
||||
+END LC_ADDRESS
|
||||
+
|
||||
+LC_TELEPHONE
|
||||
+% This is the ISO/IEC 14652 "i18n" definition for
|
||||
+% the LC_TELEPHONE category.
|
||||
+% "+%c %a %l"
|
||||
+tel_int_fmt "<U002B><U0025><U0063><U0020><U0025><U0061><U0020><U0025>/
|
||||
+<U006C>"
|
||||
+% (also used in the built in C/POSIX locale in glibc/locale/C-telephone.c)
|
||||
+END LC_TELEPHONE
|
||||
+
|
||||
+LC_MEASUREMENT
|
||||
+% This is the ISO/IEC 14652 "i18n" definition for
|
||||
+% the LC_MEASUREMENT category.
|
||||
+% (same as in the built in C/POSIX locale in glibc/locale/C-measurement.c)
|
||||
+%metric
|
||||
+measurement 1
|
||||
+END LC_MEASUREMENT
|
||||
+
|
||||
--
|
||||
2.4.3
|
||||
|
15
SOURCES/glibc-cs-path.patch
Normal file
15
SOURCES/glibc-cs-path.patch
Normal file
@ -0,0 +1,15 @@
|
||||
Short description: Adjust CS_PATH return value.
|
||||
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
|
||||
Origin: PATCH
|
||||
Upstream status: not-needed
|
||||
|
||||
In Fedora we should return only /usr/bin because /bin is just a symlink
|
||||
to /usr/bin after MoveToUsr transition (which glibc has not really
|
||||
completed).
|
||||
|
||||
diff -pruN a/sysdeps/unix/confstr.h b/sysdeps/unix/confstr.h
|
||||
--- a/sysdeps/unix/confstr.h 2012-12-25 08:32:13.000000000 +0530
|
||||
+++ b/sysdeps/unix/confstr.h 2014-09-05 20:02:55.698275219 +0530
|
||||
@@ -1 +1 @@
|
||||
-#define CS_PATH "/bin:/usr/bin"
|
||||
+#define CS_PATH "/usr/bin"
|
91
SOURCES/glibc-fedora-__libc_multiple_libcs.patch
Normal file
91
SOURCES/glibc-fedora-__libc_multiple_libcs.patch
Normal file
@ -0,0 +1,91 @@
|
||||
Short description: Cleanup use of _dl_starting_up.
|
||||
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
|
||||
Origin: PATCH
|
||||
Upstream status: https://sourceware.org/ml/libc-alpha/2014-02/msg00589.html
|
||||
|
||||
Upstream discussions:
|
||||
https://sourceware.org/ml/libc-alpha/2014-02/msg00580.html
|
||||
|
||||
Based on the following commit:
|
||||
~~~
|
||||
From 16552c01a66633c9e412984d9d92616bd4e5303c Mon Sep 17 00:00:00 2001
|
||||
From: Andreas Schwab <schwab@redhat.com>
|
||||
Date: Fri, 11 Jun 2010 11:04:11 +0200
|
||||
Subject: [PATCH] Properly set __libc_multiple_libcs
|
||||
|
||||
* elf/rtld.c (_dl_starting_up): Always define.
|
||||
(dl_main): Always set _dl_starting_up.
|
||||
* elf/dl-support.c (_dl_starting_up): Always define.
|
||||
* elf/dl-init.c (_dl_init): Always clear _dl_starting_up.
|
||||
|
||||
---
|
||||
ChangeLog | 7 +++++++
|
||||
elf/dl-init.c | 4 ----
|
||||
elf/dl-support.c | 2 --
|
||||
elf/rtld.c | 4 ----
|
||||
4 files changed, 7 insertions(+), 10 deletions(-)
|
||||
~~~
|
||||
|
||||
This patch needs to go upstream to get cleaned up, but has always involed
|
||||
analysis of the GNU/Hurd parts of the change and that stalled out, but
|
||||
perhaps with build-many-glibcs we can now test these changes more easily.
|
||||
|
||||
Index: b/elf/dl-init.c
|
||||
===================================================================
|
||||
--- a/elf/dl-init.c
|
||||
+++ b/elf/dl-init.c
|
||||
@@ -119,8 +119,6 @@ _dl_init (struct link_map *main_map, int
|
||||
while (i-- > 0)
|
||||
call_init (main_map->l_initfini[i], argc, argv, env);
|
||||
|
||||
-#ifndef HAVE_INLINED_SYSCALLS
|
||||
/* Finished starting up. */
|
||||
_dl_starting_up = 0;
|
||||
-#endif
|
||||
}
|
||||
Index: b/elf/dl-support.c
|
||||
===================================================================
|
||||
--- a/elf/dl-support.c
|
||||
+++ b/elf/dl-support.c
|
||||
@@ -117,10 +117,8 @@ struct r_scope_elem _dl_initial_searchli
|
||||
.r_nlist = 1,
|
||||
};
|
||||
|
||||
-#ifndef HAVE_INLINED_SYSCALLS
|
||||
/* Nonzero during startup. */
|
||||
int _dl_starting_up = 1;
|
||||
-#endif
|
||||
|
||||
/* Random data provided by the kernel. */
|
||||
void *_dl_random;
|
||||
Index: b/elf/rtld.c
|
||||
===================================================================
|
||||
--- a/elf/rtld.c
|
||||
+++ b/elf/rtld.c
|
||||
@@ -214,7 +214,6 @@ audit_list_iter_next (struct audit_list_
|
||||
return iter->previous->name;
|
||||
}
|
||||
|
||||
-#ifndef HAVE_INLINED_SYSCALLS
|
||||
/* Set nonzero during loading and initialization of executable and
|
||||
libraries, cleared before the executable's entry point runs. This
|
||||
must not be initialized to nonzero, because the unused dynamic
|
||||
@@ -224,7 +223,6 @@ audit_list_iter_next (struct audit_list_
|
||||
never be called. */
|
||||
int _dl_starting_up = 0;
|
||||
rtld_hidden_def (_dl_starting_up)
|
||||
-#endif
|
||||
|
||||
/* This is the structure which defines all variables global to ld.so
|
||||
(except those which cannot be added for some reason). */
|
||||
@@ -898,10 +896,8 @@ dl_main (const ElfW(Phdr) *phdr,
|
||||
/* Process the environment variable which control the behaviour. */
|
||||
process_envvars (&mode);
|
||||
|
||||
-#ifndef HAVE_INLINED_SYSCALLS
|
||||
/* Set up a flag which tells we are just starting. */
|
||||
_dl_starting_up = 1;
|
||||
-#endif
|
||||
|
||||
if (*user_entry == (ElfW(Addr)) ENTRY_POINT)
|
||||
{
|
61
SOURCES/glibc-fedora-linux-tcsetattr.patch
Normal file
61
SOURCES/glibc-fedora-linux-tcsetattr.patch
Normal file
@ -0,0 +1,61 @@
|
||||
Short description: Fedora-specific workaround for kernel pty bug.
|
||||
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
|
||||
Origin: PATCH
|
||||
Upstream status: not-submitted
|
||||
|
||||
This is a Fedora-specific workaround for a kernel bug where calling
|
||||
ioctl on a pty will silently ignore the invalid c_cflag. The
|
||||
workaround is to use TCGETS to verify the setting matches. This is
|
||||
not upstream and needs to either be removed or submitted upstream
|
||||
after analysis.
|
||||
|
||||
Index: b/sysdeps/unix/sysv/linux/tcsetattr.c
|
||||
===================================================================
|
||||
--- a/sysdeps/unix/sysv/linux/tcsetattr.c
|
||||
+++ b/sysdeps/unix/sysv/linux/tcsetattr.c
|
||||
@@ -45,6 +45,7 @@ __tcsetattr (int fd, int optional_action
|
||||
{
|
||||
struct __kernel_termios k_termios;
|
||||
unsigned long int cmd;
|
||||
+ int retval;
|
||||
|
||||
switch (optional_actions)
|
||||
{
|
||||
@@ -75,7 +76,36 @@ __tcsetattr (int fd, int optional_action
|
||||
memcpy (&k_termios.c_cc[0], &termios_p->c_cc[0],
|
||||
__KERNEL_NCCS * sizeof (cc_t));
|
||||
|
||||
- return INLINE_SYSCALL (ioctl, 3, fd, cmd, &k_termios);
|
||||
+ retval = INLINE_SYSCALL (ioctl, 3, fd, cmd, &k_termios);
|
||||
+
|
||||
+ if (retval == 0 && cmd == TCSETS)
|
||||
+ {
|
||||
+ /* The Linux kernel has a bug which silently ignore the invalid
|
||||
+ c_cflag on pty. We have to check it here. */
|
||||
+ int save = errno;
|
||||
+ retval = INLINE_SYSCALL (ioctl, 3, fd, TCGETS, &k_termios);
|
||||
+ if (retval)
|
||||
+ {
|
||||
+ /* We cannot verify if the setting is ok. We don't return
|
||||
+ an error (?). */
|
||||
+ __set_errno (save);
|
||||
+ retval = 0;
|
||||
+ }
|
||||
+ else if ((termios_p->c_cflag & (PARENB | CREAD))
|
||||
+ != (k_termios.c_cflag & (PARENB | CREAD))
|
||||
+ || ((termios_p->c_cflag & CSIZE)
|
||||
+ && ((termios_p->c_cflag & CSIZE)
|
||||
+ != (k_termios.c_cflag & CSIZE))))
|
||||
+ {
|
||||
+ /* It looks like the Linux kernel silently changed the
|
||||
+ PARENB/CREAD/CSIZE bits in c_cflag. Report it as an
|
||||
+ error. */
|
||||
+ __set_errno (EINVAL);
|
||||
+ retval = -1;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return retval;
|
||||
}
|
||||
weak_alias (__tcsetattr, tcsetattr)
|
||||
libc_hidden_def (tcsetattr)
|
49
SOURCES/glibc-fedora-localedata-rh61908.patch
Normal file
49
SOURCES/glibc-fedora-localedata-rh61908.patch
Normal file
@ -0,0 +1,49 @@
|
||||
Short description: Add 4 ISO-8859-15 locales to SUPPORTED for Euro symbol.
|
||||
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
|
||||
Origin: PATCH
|
||||
Bug-RHEL: #61908
|
||||
Upstream status: not-needed
|
||||
|
||||
Very early RHL 7.3 requirement to add these locales so users can
|
||||
get access to Euro symbol. We should review this bug and decide if
|
||||
the UTF-8 locales are now serving the same purpose and drop the
|
||||
additional locales.
|
||||
|
||||
* Tue Mar 26 2002 Jakub Jelinek <jakub@redhat.com> 2.2.5-28
|
||||
- add a couple of .ISO-8859-15 locales (#61908)
|
||||
|
||||
diff -Nrup a/localedata/SUPPORTED b/localedata/SUPPORTED
|
||||
--- a/localedata/SUPPORTED 2012-11-25 12:59:31.000000000 -0700
|
||||
+++ b/localedata/SUPPORTED 2012-11-26 12:58:43.298223018 -0700
|
||||
@@ -89,6 +89,7 @@ cy_GB.UTF-8/UTF-8 \
|
||||
cy_GB/ISO-8859-14 \
|
||||
da_DK.UTF-8/UTF-8 \
|
||||
da_DK/ISO-8859-1 \
|
||||
+da_DK.ISO-8859-15/ISO-8859-15 \
|
||||
de_AT.UTF-8/UTF-8 \
|
||||
de_AT/ISO-8859-1 \
|
||||
de_AT@euro/ISO-8859-15 \
|
||||
@@ -121,6 +122,7 @@ en_DK.UTF-8/UTF-8 \
|
||||
en_DK/ISO-8859-1 \
|
||||
en_GB.UTF-8/UTF-8 \
|
||||
en_GB/ISO-8859-1 \
|
||||
+en_GB.ISO-8859-15/ISO-8859-15 \
|
||||
en_HK.UTF-8/UTF-8 \
|
||||
en_HK/ISO-8859-1 \
|
||||
en_IE.UTF-8/UTF-8 \
|
||||
@@ -136,6 +138,7 @@ en_SG.UTF-8/UTF-8 \
|
||||
en_SG/ISO-8859-1 \
|
||||
en_US.UTF-8/UTF-8 \
|
||||
en_US/ISO-8859-1 \
|
||||
+en_US.ISO-8859-15/ISO-8859-15 \
|
||||
en_ZA.UTF-8/UTF-8 \
|
||||
en_ZA/ISO-8859-1 \
|
||||
en_ZM/UTF-8 \
|
||||
@@ -385,6 +388,7 @@ sv_FI/ISO-8859-1 \
|
||||
sv_FI@euro/ISO-8859-15 \
|
||||
sv_SE.UTF-8/UTF-8 \
|
||||
sv_SE/ISO-8859-1 \
|
||||
+sv_SE.ISO-8859-15/ISO-8859-15 \
|
||||
sw_KE/UTF-8 \
|
||||
sw_TZ/UTF-8 \
|
||||
szl_PL/UTF-8 \
|
21
SOURCES/glibc-fedora-localedef.patch
Normal file
21
SOURCES/glibc-fedora-localedef.patch
Normal file
@ -0,0 +1,21 @@
|
||||
Short description: Fedora-specific glibc install locale changes.
|
||||
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
|
||||
Origin: PATCH
|
||||
Upstream status: not-needed
|
||||
|
||||
The Fedora glibc build and install does not need the normal install
|
||||
behaviour which updates the locale archive. The Fedora install phase
|
||||
in the spec file of the rpm will handle this manually.
|
||||
|
||||
diff --git a/localedata/Makefile b/localedata/Makefile
|
||||
index a5f3c92d58954dfc..56719c7c714aa0f1 100644
|
||||
--- a/localedata/Makefile
|
||||
+++ b/localedata/Makefile
|
||||
@@ -218,6 +218,7 @@ $(INSTALL-SUPPORTED-LOCALES): install-locales-dir
|
||||
echo -n '...'; \
|
||||
input=`echo $$locale | sed 's/\([^.]*\)[^@]*\(.*\)/\1\2/'`; \
|
||||
$(LOCALEDEF) $$flags --alias-file=../intl/locale.alias \
|
||||
+ --no-archive \
|
||||
-i locales/$$input -f charmaps/$$charset \
|
||||
$(addprefix --prefix=,$(install_root)) $$locale \
|
||||
&& echo ' done'; \
|
46
SOURCES/glibc-fedora-locarchive.patch
Normal file
46
SOURCES/glibc-fedora-locarchive.patch
Normal file
@ -0,0 +1,46 @@
|
||||
Short description: Allow access to internal locale archive functions.
|
||||
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
|
||||
Origin: PATCH
|
||||
Upstream status: not-needed
|
||||
|
||||
This is a part of commit glibc-2.3.3-1492-ga891c7b,
|
||||
needed for fedora/build-locale-archive.c only.
|
||||
|
||||
2007-04-16 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* locale/programs/locarchive.c (add_alias, insert_name): Remove static.
|
||||
|
||||
diff -Nrup a/locale/programs/locarchive.c b/locale/programs/locarchive.c
|
||||
--- a/locale/programs/locarchive.c 2012-06-05 07:42:49.000000000 -0600
|
||||
+++ b/locale/programs/locarchive.c 2012-06-07 12:15:21.585319540 -0600
|
||||
@@ -252,9 +252,9 @@ oldlocrecentcmp (const void *a, const vo
|
||||
/* forward decls for below */
|
||||
static uint32_t add_locale (struct locarhandle *ah, const char *name,
|
||||
locale_data_t data, bool replace);
|
||||
-static void add_alias (struct locarhandle *ah, const char *alias,
|
||||
- bool replace, const char *oldname,
|
||||
- uint32_t *locrec_offset_p);
|
||||
+void add_alias (struct locarhandle *ah, const char *alias,
|
||||
+ bool replace, const char *oldname,
|
||||
+ uint32_t *locrec_offset_p);
|
||||
|
||||
|
||||
static bool
|
||||
@@ -635,7 +635,7 @@ close_archive (struct locarhandle *ah)
|
||||
#include "../../intl/explodename.c"
|
||||
#include "../../intl/l10nflist.c"
|
||||
|
||||
-static struct namehashent *
|
||||
+struct namehashent *
|
||||
insert_name (struct locarhandle *ah,
|
||||
const char *name, size_t name_len, bool replace)
|
||||
{
|
||||
@@ -693,7 +693,7 @@ insert_name (struct locarhandle *ah,
|
||||
return &namehashtab[idx];
|
||||
}
|
||||
|
||||
-static void
|
||||
+void
|
||||
add_alias (struct locarhandle *ah, const char *alias, bool replace,
|
||||
const char *oldname, uint32_t *locrec_offset_p)
|
||||
{
|
31
SOURCES/glibc-fedora-manual-dircategory.patch
Normal file
31
SOURCES/glibc-fedora-manual-dircategory.patch
Normal file
@ -0,0 +1,31 @@
|
||||
Short description: Place glibc info into "Libraries" category.
|
||||
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
|
||||
Origin: PATCH
|
||||
Upstream status: not-needed
|
||||
|
||||
The category names for libraries is completely random including
|
||||
"Libraries", "GNU Libraries", "GNU libraries", and "Software libraries."
|
||||
In the GNU info manual the "Software libraries" category is given as an
|
||||
example, but really we need to standardize on a category for upstream.
|
||||
I suggest we drop this change after some upstream discussion.
|
||||
|
||||
From 4820b9175535e13df79ce816106016040014916e Mon Sep 17 00:00:00 2001
|
||||
From: Jakub Jelinek <jakub@redhat.com>
|
||||
Date: Fri, 3 Nov 2006 16:31:21 +0000
|
||||
Subject: [PATCH] Change @dircategory.
|
||||
|
||||
---
|
||||
manual/libc.texinfo | 2 +-
|
||||
1 files changed, 1 insertions(+), 1 deletions(-)
|
||||
|
||||
--- a/manual/libc.texinfo
|
||||
+++ b/manual/libc.texinfo
|
||||
@@ -7,7 +7,7 @@
|
||||
@include macros.texi
|
||||
|
||||
@comment Tell install-info what to do.
|
||||
-@dircategory Software libraries
|
||||
+@dircategory Libraries
|
||||
@direntry
|
||||
* Libc: (libc). C library.
|
||||
@end direntry
|
31
SOURCES/glibc-fedora-nis-rh188246.patch
Normal file
31
SOURCES/glibc-fedora-nis-rh188246.patch
Normal file
@ -0,0 +1,31 @@
|
||||
Short description: Fedora-specific enabling batch read in NSS.
|
||||
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
|
||||
Origin: PATCH
|
||||
Bug-RHEL: #188246
|
||||
Upstream status: not-submitted
|
||||
|
||||
Enable batch read in NSS. It's not clear if this is always a win or
|
||||
just a win for NIS+, this needs to be analyzed and sent upstream or
|
||||
removed.
|
||||
|
||||
From baba5d9461d4e8a581ac26fe4412ad783ffc73e7 Mon Sep 17 00:00:00 2001
|
||||
From: Jakub Jelinek <jakub@redhat.com>
|
||||
Date: Mon, 1 May 2006 08:02:53 +0000
|
||||
Subject: [PATCH] Enable SETENT_BATCH_READ nis/nss option by default
|
||||
|
||||
* Mon May 1 2006 Jakub Jelinek <jakub@redhat.com> 2.4.90-4
|
||||
- SETENT_BATCH_READ /etc/default/nss option for speeding up
|
||||
some usages of NIS+ (#188246)
|
||||
|
||||
diff --git a/nis/nss b/nis/nss
|
||||
--- a/nis/nss
|
||||
+++ b/nis/nss
|
||||
@@ -25,7 +25,7 @@
|
||||
# memory with every getXXent() call. Otherwise each getXXent() call
|
||||
# might result into a network communication with the server to get
|
||||
# the next entry.
|
||||
-#SETENT_BATCH_READ=TRUE
|
||||
+SETENT_BATCH_READ=TRUE
|
||||
#
|
||||
# ADJUNCT_AS_SHADOW
|
||||
# If set to TRUE, the passwd routines in the NIS NSS module will not
|
20
SOURCES/glibc-fedora-nscd.patch
Normal file
20
SOURCES/glibc-fedora-nscd.patch
Normal file
@ -0,0 +1,20 @@
|
||||
Short description: NSCD must use nscd user.
|
||||
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
|
||||
Origin: PATCH
|
||||
Upstream status: not-needed
|
||||
|
||||
Fedora-specific configuration adjustment to introduce the nscd user.
|
||||
(Upstream does not assume this user exists.)
|
||||
|
||||
diff -Nrup a/nscd/nscd.conf b/nscd/nscd.conf
|
||||
--- a/nscd/nscd.conf 2012-06-05 07:42:49.000000000 -0600
|
||||
+++ b/nscd/nscd.conf 2012-06-07 12:15:21.818318670 -0600
|
||||
@@ -33,7 +33,7 @@
|
||||
# logfile /var/log/nscd.log
|
||||
# threads 4
|
||||
# max-threads 32
|
||||
-# server-user nobody
|
||||
+ server-user nscd
|
||||
# stat-user somebody
|
||||
debug-level 0
|
||||
# reload-count 5
|
38
SOURCES/glibc-fedora-streams-rh436349.patch
Normal file
38
SOURCES/glibc-fedora-streams-rh436349.patch
Normal file
@ -0,0 +1,38 @@
|
||||
Short description: Do not define _XOPEN_STREAMS.
|
||||
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
|
||||
Origin: PATCH
|
||||
Bug-Fedora: #436349
|
||||
Upstream status: not-submitted
|
||||
|
||||
This patch should go upstream. Not defining _XOPEN_STREAMS is the
|
||||
same as setting it to -1 for POSIX conformance. The headers setting
|
||||
needs to be reviewed indepedently.
|
||||
|
||||
This is part of commit glibc-2.3.3-1564-gd0b6ac6
|
||||
|
||||
* Fri Mar 14 2008 Jakub Jelinek <jakub@redhat.com> 2.7.90-11
|
||||
- remove <stropts.h>, define _XOPEN_STREAMS -1 (#436349)
|
||||
|
||||
diff -Nrup a/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h b/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h
|
||||
--- a/sysdeps/unix/sysv/linux/bits/posix_opt.h 2012-06-05 07:42:49.000000000 -0600
|
||||
+++ b/sysdeps/unix/sysv/linux/bits/posix_opt.h 2012-06-07 12:15:21.817318674 -0600
|
||||
@@ -188,4 +188,7 @@
|
||||
/* Typed memory objects are not available. */
|
||||
#define _POSIX_TYPED_MEMORY_OBJECTS -1
|
||||
|
||||
+/* Streams are not available. */
|
||||
+#define _XOPEN_STREAMS -1
|
||||
+
|
||||
#endif /* bits/posix_opt.h */
|
||||
diff -Nrup a/streams/Makefile b/streams/Makefile
|
||||
--- a/streams/Makefile 2012-06-05 07:42:49.000000000 -0600
|
||||
+++ b/streams/Makefile 2012-06-07 12:15:21.824318649 -0600
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
include ../Makeconfig
|
||||
|
||||
-headers = stropts.h sys/stropts.h bits/stropts.h bits/xtitypes.h
|
||||
+#headers = stropts.h sys/stropts.h bits/stropts.h bits/xtitypes.h
|
||||
routines = isastream getmsg getpmsg putmsg putpmsg fattach fdetach
|
||||
|
||||
include ../Rules
|
21
SOURCES/glibc-nscd-sysconfig.patch
Normal file
21
SOURCES/glibc-nscd-sysconfig.patch
Normal file
@ -0,0 +1,21 @@
|
||||
Short description: Provide options to nscd startup.
|
||||
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
|
||||
Origin: PATCH
|
||||
Upstream status: not-needed
|
||||
|
||||
Fedora-specific nscd startup configuration file.
|
||||
|
||||
diff --git a/nscd/nscd.service b/nscd/nscd.service
|
||||
index b7428a3..19ba185 100644
|
||||
--- a/nscd/nscd.service
|
||||
+++ b/nscd/nscd.service
|
||||
@@ -5,7 +5,8 @@ Description=Name Service Cache Daemon
|
||||
|
||||
[Service]
|
||||
Type=forking
|
||||
-ExecStart=/usr/sbin/nscd
|
||||
+EnvironmentFile=-/etc/sysconfig/nscd
|
||||
+ExecStart=/usr/sbin/nscd $NSCD_OPTIONS
|
||||
ExecStop=/usr/sbin/nscd --shutdown
|
||||
ExecReload=/usr/sbin/nscd -i passwd
|
||||
ExecReload=/usr/sbin/nscd -i group
|
40
SOURCES/glibc-python3.patch
Normal file
40
SOURCES/glibc-python3.patch
Normal file
@ -0,0 +1,40 @@
|
||||
Use python3 for installed executable python scripts.
|
||||
|
||||
Fedora is a Python3-only distribution:
|
||||
https://fedoraproject.org/wiki/FinalizingFedoraSwitchtoPython3
|
||||
|
||||
This fixes build failures where builders may strictly enforce only
|
||||
python3 during a transitional phase.
|
||||
|
||||
Author: Carlos O'Donell <carlos@redhat.com>
|
||||
|
||||
diff --git a/benchtests/scripts/compare_bench.py b/benchtests/scripts/compare_bench.py
|
||||
index ea25f778c09bba9d..b53beb3c6e32c3cf 100755
|
||||
--- a/benchtests/scripts/compare_bench.py
|
||||
+++ b/benchtests/scripts/compare_bench.py
|
||||
@@ -1,4 +1,4 @@
|
||||
-#!/usr/bin/python
|
||||
+#!/usr/bin/python3
|
||||
# Copyright (C) 2015-2018 Free Software Foundation, Inc.
|
||||
# This file is part of the GNU C Library.
|
||||
#
|
||||
diff --git a/benchtests/scripts/import_bench.py b/benchtests/scripts/import_bench.py
|
||||
index 602b3f954d4801a6..76bf1528a5418748 100644
|
||||
--- a/benchtests/scripts/import_bench.py
|
||||
+++ b/benchtests/scripts/import_bench.py
|
||||
@@ -1,4 +1,4 @@
|
||||
-#!/usr/bin/python
|
||||
+#!/usr/bin/python3
|
||||
# Copyright (C) 2015-2018 Free Software Foundation, Inc.
|
||||
# This file is part of the GNU C Library.
|
||||
#
|
||||
diff --git a/benchtests/scripts/validate_benchout.py b/benchtests/scripts/validate_benchout.py
|
||||
index 6147f05bec3a4844..9a5c7947ee4ed7e9 100755
|
||||
--- a/benchtests/scripts/validate_benchout.py
|
||||
+++ b/benchtests/scripts/validate_benchout.py
|
||||
@@ -1,4 +1,4 @@
|
||||
-#!/usr/bin/python
|
||||
+#!/usr/bin/python3
|
||||
# Copyright (C) 2014-2018 Free Software Foundation, Inc.
|
||||
# This file is part of the GNU C Library.
|
||||
#
|
38
SOURCES/glibc-rh1070416.patch
Normal file
38
SOURCES/glibc-rh1070416.patch
Normal file
@ -0,0 +1,38 @@
|
||||
Short description: Add syslog.target dependency.
|
||||
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
|
||||
Origin: PATCH
|
||||
Bug-Fedora: #1070416
|
||||
Upstream status: not-needed
|
||||
|
||||
Fedora-specific changes to the nscd.service file.
|
||||
See also: glibc-nscd-sysconfig.patch.
|
||||
|
||||
--- a/nscd/nscd.service
|
||||
+++ b/nscd/nscd.service
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
[Unit]
|
||||
Description=Name Service Cache Daemon
|
||||
+After=syslog.target
|
||||
|
||||
[Service]
|
||||
Type=forking
|
||||
@@ -17,3 +18,4 @@
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
+Also=nscd.socket
|
||||
diff --git a/nscd/nscd.socket b/nscd/nscd.socket
|
||||
new file mode 100644
|
||||
index 0000000..7e512d5
|
||||
--- /dev/null
|
||||
+++ b/nscd/nscd.socket
|
||||
@@ -0,0 +1,8 @@
|
||||
+[Unit]
|
||||
+Description=Name Service Cache Daemon Socket
|
||||
+
|
||||
+[Socket]
|
||||
+ListenDatagram=/var/run/nscd/socket
|
||||
+
|
||||
+[Install]
|
||||
+WantedBy=sockets.target
|
22
SOURCES/glibc-rh1577365.patch
Normal file
22
SOURCES/glibc-rh1577365.patch
Normal file
@ -0,0 +1,22 @@
|
||||
Please see the following bug for a complete summary:
|
||||
https://bugzilla.redhat.com/show_bug.cgi?id=1615608
|
||||
|
||||
Index: glibc-2.28/manual/startup.texi
|
||||
===================================================================
|
||||
--- glibc-2.28.orig/manual/startup.texi
|
||||
+++ glibc-2.28/manual/startup.texi
|
||||
@@ -1005,14 +1005,6 @@ This function actually terminates the pr
|
||||
intercept this signal; see @ref{Signal Handling}.
|
||||
@end deftypefun
|
||||
|
||||
-@c Put in by rms. Don't remove.
|
||||
-@cartouche
|
||||
-@strong{Future Change Warning:} Proposed Federal censorship regulations
|
||||
-may prohibit us from giving you information about the possibility of
|
||||
-calling this function. We would be required to say that this is not an
|
||||
-acceptable way of terminating a program.
|
||||
-@end cartouche
|
||||
-
|
||||
@node Termination Internals
|
||||
@subsection Termination Internals
|
||||
|
24
SOURCES/glibc-rh1577438.patch
Normal file
24
SOURCES/glibc-rh1577438.patch
Normal file
@ -0,0 +1,24 @@
|
||||
Patch by Hanataka Shinya <hanataka.shinya@gmail.com> from
|
||||
<https://sourceware.org/bugzilla/show_bug.cgi?id=24405>. Confirmed by TAMUKI
|
||||
Shoichi's patch in
|
||||
<https://sourceware.org/ml/libc-alpha/2019-04/msg00005.html>.
|
||||
|
||||
The official announcement by the Japanese Prime Minister in
|
||||
<https://www.kantei.go.jp/jp/tyoukanpress/201904/1_a.html> uses U+4EE4 U+548C
|
||||
as well.
|
||||
|
||||
diff --git a/localedata/locales/ja_JP b/localedata/locales/ja_JP
|
||||
index 1fd2fee44b2879d9..30190b624856cc53 100644
|
||||
--- a/localedata/locales/ja_JP
|
||||
+++ b/localedata/locales/ja_JP
|
||||
@@ -14946,7 +14946,9 @@ am_pm "<U5348><U524D>";"<U5348><U5F8C>"
|
||||
|
||||
t_fmt_ampm "%p%I<U6642>%M<U5206>%S<U79D2>"
|
||||
|
||||
-era "+:2:1990//01//01:+*:<U5E73><U6210>:%EC%Ey<U5E74>";/
|
||||
+era "+:2:2020//01//01:+*:<U4EE4><U548C>:%EC%Ey<U5E74>";/
|
||||
+ "+:1:2019//05//01:2019//12//31:<U4EE4><U548C>:%EC<U5143><U5E74>";/
|
||||
+ "+:2:1990//01//01:2019//04//30:<U5E73><U6210>:%EC%Ey<U5E74>";/
|
||||
"+:1:1989//01//08:1989//12//31:<U5E73><U6210>:%EC<U5143><U5E74>";/
|
||||
"+:2:1927//01//01:1989//01//07:<U662D><U548C>:%EC%Ey<U5E74>";/
|
||||
"+:1:1926//12//25:1926//12//31:<U662D><U548C>:%EC<U5143><U5E74>";/
|
254
SOURCES/glibc-rh1614253.patch
Normal file
254
SOURCES/glibc-rh1614253.patch
Normal file
@ -0,0 +1,254 @@
|
||||
commit 4b25485f03158959cff45379eecc1d73c7dcdd11
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Fri Aug 10 11:19:26 2018 +0200
|
||||
|
||||
Linux: Rewrite __old_getdents64 [BZ #23497]
|
||||
|
||||
Commit 298d0e3129c0b5137f4989275b13fe30d0733c4d ("Consolidate Linux
|
||||
getdents{64} implementation") broke the implementation because it does
|
||||
not take into account struct offset differences.
|
||||
|
||||
The new implementation is close to the old one, before the
|
||||
consolidation, but has been cleaned up slightly.
|
||||
|
||||
(cherry picked from commit 690652882b499defb3d950dfeff8fe421d13cab5)
|
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
|
||||
index f71cc39c7e257a0a..773aaea0e980bdd6 100644
|
||||
--- a/sysdeps/unix/sysv/linux/Makefile
|
||||
+++ b/sysdeps/unix/sysv/linux/Makefile
|
||||
@@ -161,6 +161,7 @@ inhibit-glue = yes
|
||||
|
||||
ifeq ($(subdir),dirent)
|
||||
sysdep_routines += getdirentries getdirentries64
|
||||
+tests-internal += tst-readdir64-compat
|
||||
endif
|
||||
|
||||
ifeq ($(subdir),nis)
|
||||
diff --git a/sysdeps/unix/sysv/linux/getdents64.c b/sysdeps/unix/sysv/linux/getdents64.c
|
||||
index 3bde0cf4f0226f95..bc140b5a7fac3040 100644
|
||||
--- a/sysdeps/unix/sysv/linux/getdents64.c
|
||||
+++ b/sysdeps/unix/sysv/linux/getdents64.c
|
||||
@@ -33,41 +33,80 @@ strong_alias (__getdents64, __getdents)
|
||||
# include <shlib-compat.h>
|
||||
|
||||
# if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)
|
||||
-# include <olddirent.h>
|
||||
+# include <olddirent.h>
|
||||
+# include <unistd.h>
|
||||
|
||||
-/* kernel definition of as of 3.2. */
|
||||
-struct compat_linux_dirent
|
||||
+static ssize_t
|
||||
+handle_overflow (int fd, __off64_t offset, ssize_t count)
|
||||
{
|
||||
- /* Both d_ino and d_off are compat_ulong_t which are defined in all
|
||||
- architectures as 'u32'. */
|
||||
- uint32_t d_ino;
|
||||
- uint32_t d_off;
|
||||
- unsigned short d_reclen;
|
||||
- char d_name[1];
|
||||
-};
|
||||
+ /* If this is the first entry in the buffer, we can report the
|
||||
+ error. */
|
||||
+ if (count == 0)
|
||||
+ {
|
||||
+ __set_errno (EOVERFLOW);
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ /* Otherwise, seek to the overflowing entry, so that the next call
|
||||
+ will report the error, and return the data read so far.. */
|
||||
+ if (__lseek64 (fd, offset, SEEK_SET) != 0)
|
||||
+ return -1;
|
||||
+ return count;
|
||||
+}
|
||||
|
||||
ssize_t
|
||||
__old_getdents64 (int fd, char *buf, size_t nbytes)
|
||||
{
|
||||
- ssize_t retval = INLINE_SYSCALL_CALL (getdents, fd, buf, nbytes);
|
||||
+ /* We do not move the individual directory entries. This is only
|
||||
+ possible if the target type (struct __old_dirent64) is smaller
|
||||
+ than the source type. */
|
||||
+ _Static_assert (offsetof (struct __old_dirent64, d_name)
|
||||
+ <= offsetof (struct dirent64, d_name),
|
||||
+ "__old_dirent64 is larger than dirent64");
|
||||
+ _Static_assert (__alignof__ (struct __old_dirent64)
|
||||
+ <= __alignof__ (struct dirent64),
|
||||
+ "alignment of __old_dirent64 is larger than dirent64");
|
||||
|
||||
- /* The kernel added the d_type value after the name. Change this now. */
|
||||
- if (retval != -1)
|
||||
+ ssize_t retval = INLINE_SYSCALL_CALL (getdents64, fd, buf, nbytes);
|
||||
+ if (retval > 0)
|
||||
{
|
||||
- union
|
||||
- {
|
||||
- struct compat_linux_dirent k;
|
||||
- struct dirent u;
|
||||
- } *kbuf = (void *) buf;
|
||||
-
|
||||
- while ((char *) kbuf < buf + retval)
|
||||
+ char *p = buf;
|
||||
+ char *end = buf + retval;
|
||||
+ while (p < end)
|
||||
{
|
||||
- char d_type = *((char *) kbuf + kbuf->k.d_reclen - 1);
|
||||
- memmove (kbuf->u.d_name, kbuf->k.d_name,
|
||||
- strlen (kbuf->k.d_name) + 1);
|
||||
- kbuf->u.d_type = d_type;
|
||||
+ struct dirent64 *source = (struct dirent64 *) p;
|
||||
+
|
||||
+ /* Copy out the fixed-size data. */
|
||||
+ __ino_t ino = source->d_ino;
|
||||
+ __off64_t offset = source->d_off;
|
||||
+ unsigned int reclen = source->d_reclen;
|
||||
+ unsigned char type = source->d_type;
|
||||
+
|
||||
+ /* Check for ino_t overflow. */
|
||||
+ if (__glibc_unlikely (ino != source->d_ino))
|
||||
+ return handle_overflow (fd, offset, p - buf);
|
||||
+
|
||||
+ /* Convert to the target layout. Use a separate struct and
|
||||
+ memcpy to side-step aliasing issues. */
|
||||
+ struct __old_dirent64 result;
|
||||
+ result.d_ino = ino;
|
||||
+ result.d_off = offset;
|
||||
+ result.d_reclen = reclen;
|
||||
+ result.d_type = type;
|
||||
+
|
||||
+ /* Write the fixed-sized part of the result to the
|
||||
+ buffer. */
|
||||
+ size_t result_name_offset = offsetof (struct __old_dirent64, d_name);
|
||||
+ memcpy (p, &result, result_name_offset);
|
||||
+
|
||||
+ /* Adjust the position of the name if necessary. Copy
|
||||
+ everything until the end of the record, including the
|
||||
+ terminating NUL byte. */
|
||||
+ if (result_name_offset != offsetof (struct dirent64, d_name))
|
||||
+ memmove (p + result_name_offset, source->d_name,
|
||||
+ reclen - offsetof (struct dirent64, d_name));
|
||||
|
||||
- kbuf = (void *) ((char *) kbuf + kbuf->k.d_reclen);
|
||||
+ p += reclen;
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
diff --git a/sysdeps/unix/sysv/linux/tst-readdir64-compat.c b/sysdeps/unix/sysv/linux/tst-readdir64-compat.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..43c4a8477c7403c5
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/unix/sysv/linux/tst-readdir64-compat.c
|
||||
@@ -0,0 +1,111 @@
|
||||
+/* Test readdir64 compatibility symbol.
|
||||
+ Copyright (C) 2018 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <dirent.h>
|
||||
+#include <dlfcn.h>
|
||||
+#include <errno.h>
|
||||
+#include <shlib-compat.h>
|
||||
+#include <stdbool.h>
|
||||
+#include <stdio.h>
|
||||
+#include <string.h>
|
||||
+#include <support/check.h>
|
||||
+
|
||||
+/* Copied from <olddirent.h>. */
|
||||
+struct __old_dirent64
|
||||
+ {
|
||||
+ __ino_t d_ino;
|
||||
+ __off64_t d_off;
|
||||
+ unsigned short int d_reclen;
|
||||
+ unsigned char d_type;
|
||||
+ char d_name[256];
|
||||
+ };
|
||||
+
|
||||
+typedef struct __old_dirent64 *(*compat_readdir64_type) (DIR *);
|
||||
+
|
||||
+#if TEST_COMPAT (libc, GLIBC_2_1, GLIBC_2_2)
|
||||
+struct __old_dirent64 *compat_readdir64 (DIR *);
|
||||
+compat_symbol_reference (libc, compat_readdir64, readdir64, GLIBC_2_1);
|
||||
+#endif
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+#if TEST_COMPAT (libc, GLIBC_2_1, GLIBC_2_2)
|
||||
+
|
||||
+ /* Directory stream using the non-compat readdir64 symbol. The test
|
||||
+ checks against this. */
|
||||
+ DIR *dir_reference = opendir (".");
|
||||
+ TEST_VERIFY_EXIT (dir_reference != NULL);
|
||||
+ DIR *dir_test = opendir (".");
|
||||
+ TEST_VERIFY_EXIT (dir_test != NULL);
|
||||
+
|
||||
+ /* This loop assumes that the enumeration order is consistent for
|
||||
+ two different handles. Nothing should write to the current
|
||||
+ directory (in the source tree) while this test runs, so there
|
||||
+ should not be any difference due to races. */
|
||||
+ size_t count = 0;
|
||||
+ while (true)
|
||||
+ {
|
||||
+ errno = 0;
|
||||
+ struct dirent64 *entry_reference = readdir64 (dir_reference);
|
||||
+ if (entry_reference == NULL && errno != 0)
|
||||
+ FAIL_EXIT1 ("readdir64 entry %zu: %m\n", count);
|
||||
+ struct __old_dirent64 *entry_test = compat_readdir64 (dir_test);
|
||||
+ if (entry_reference == NULL)
|
||||
+ {
|
||||
+ if (errno == EOVERFLOW)
|
||||
+ {
|
||||
+ TEST_VERIFY (entry_reference->d_ino
|
||||
+ != (__ino_t) entry_reference->d_ino);
|
||||
+ printf ("info: inode number overflow at entry %zu\n", count);
|
||||
+ break;
|
||||
+ }
|
||||
+ if (errno != 0)
|
||||
+ FAIL_EXIT1 ("compat readdir64 entry %zu: %m\n", count);
|
||||
+ }
|
||||
+
|
||||
+ /* Check that both streams end at the same time. */
|
||||
+ if (entry_reference == NULL)
|
||||
+ {
|
||||
+ TEST_VERIFY (entry_test == NULL);
|
||||
+ break;
|
||||
+ }
|
||||
+ else
|
||||
+ TEST_VERIFY_EXIT (entry_test != NULL);
|
||||
+
|
||||
+ /* Check that the entries are the same. */
|
||||
+ TEST_COMPARE_BLOB (entry_reference->d_name,
|
||||
+ strlen (entry_reference->d_name),
|
||||
+ entry_test->d_name, strlen (entry_test->d_name));
|
||||
+ TEST_COMPARE (entry_reference->d_ino, entry_test->d_ino);
|
||||
+ TEST_COMPARE (entry_reference->d_off, entry_test->d_off);
|
||||
+ TEST_COMPARE (entry_reference->d_type, entry_test->d_type);
|
||||
+ TEST_COMPARE (entry_reference->d_reclen, entry_test->d_reclen);
|
||||
+
|
||||
+ ++count;
|
||||
+ }
|
||||
+ printf ("info: %zu directory entries found\n", count);
|
||||
+ TEST_VERIFY (count >= 3); /* ".", "..", and some source files. */
|
||||
+
|
||||
+ TEST_COMPARE (closedir (dir_test), 0);
|
||||
+ TEST_COMPARE (closedir (dir_reference), 0);
|
||||
+#endif
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
154
SOURCES/glibc-rh1614979.patch
Normal file
154
SOURCES/glibc-rh1614979.patch
Normal file
@ -0,0 +1,154 @@
|
||||
commit d524fa6c35e675eedbd8fe6cdf4db0b49c658026
|
||||
Author: H.J. Lu <hjl.tools@gmail.com>
|
||||
Date: Thu Nov 8 10:06:58 2018 -0800
|
||||
|
||||
Check multiple NT_GNU_PROPERTY_TYPE_0 notes [BZ #23509]
|
||||
|
||||
Linkers group input note sections with the same name into one output
|
||||
note section with the same name. One output note section is placed in
|
||||
one PT_NOTE segment. Since new linkers merge input .note.gnu.property
|
||||
sections into one output .note.gnu.property section, there is only
|
||||
one NT_GNU_PROPERTY_TYPE_0 note in one PT_NOTE segment with new linkers.
|
||||
Since older linkers treat input .note.gnu.property section as a generic
|
||||
note section and just concatenate all input .note.gnu.property sections
|
||||
into one output .note.gnu.property section without merging them, we may
|
||||
see multiple NT_GNU_PROPERTY_TYPE_0 notes in one PT_NOTE segment with
|
||||
older linkers.
|
||||
|
||||
When an older linker is used to created the program on CET-enabled OS,
|
||||
the linker output has a single .note.gnu.property section with multiple
|
||||
NT_GNU_PROPERTY_TYPE_0 notes, some of which have IBT and SHSTK enable
|
||||
bits set even if the program isn't CET enabled. Such programs will
|
||||
crash on CET-enabled machines. This patch updates the note parser:
|
||||
|
||||
1. Skip note parsing if a NT_GNU_PROPERTY_TYPE_0 note has been processed.
|
||||
2. Check multiple NT_GNU_PROPERTY_TYPE_0 notes.
|
||||
|
||||
[BZ #23509]
|
||||
* sysdeps/x86/dl-prop.h (_dl_process_cet_property_note): Skip
|
||||
note parsing if a NT_GNU_PROPERTY_TYPE_0 note has been processed.
|
||||
Update the l_cet field when processing NT_GNU_PROPERTY_TYPE_0 note.
|
||||
Check multiple NT_GNU_PROPERTY_TYPE_0 notes.
|
||||
* sysdeps/x86/link_map.h (l_cet): Expand to 3 bits, Add
|
||||
lc_unknown.
|
||||
|
||||
diff --git a/sysdeps/x86/dl-prop.h b/sysdeps/x86/dl-prop.h
|
||||
index 26c3131ac5e2d080..9ab890d12bb99133 100644
|
||||
--- a/sysdeps/x86/dl-prop.h
|
||||
+++ b/sysdeps/x86/dl-prop.h
|
||||
@@ -49,6 +49,10 @@ _dl_process_cet_property_note (struct link_map *l,
|
||||
const ElfW(Addr) align)
|
||||
{
|
||||
#if CET_ENABLED
|
||||
+ /* Skip if we have seen a NT_GNU_PROPERTY_TYPE_0 note before. */
|
||||
+ if (l->l_cet != lc_unknown)
|
||||
+ return;
|
||||
+
|
||||
/* The NT_GNU_PROPERTY_TYPE_0 note must be aliged to 4 bytes in
|
||||
32-bit objects and to 8 bytes in 64-bit objects. Skip notes
|
||||
with incorrect alignment. */
|
||||
@@ -57,6 +61,9 @@ _dl_process_cet_property_note (struct link_map *l,
|
||||
|
||||
const ElfW(Addr) start = (ElfW(Addr)) note;
|
||||
|
||||
+ unsigned int feature_1 = 0;
|
||||
+ unsigned int last_type = 0;
|
||||
+
|
||||
while ((ElfW(Addr)) (note + 1) - start < size)
|
||||
{
|
||||
/* Find the NT_GNU_PROPERTY_TYPE_0 note. */
|
||||
@@ -64,10 +71,18 @@ _dl_process_cet_property_note (struct link_map *l,
|
||||
&& note->n_type == NT_GNU_PROPERTY_TYPE_0
|
||||
&& memcmp (note + 1, "GNU", 4) == 0)
|
||||
{
|
||||
+ /* Stop if we see more than one GNU property note which may
|
||||
+ be generated by the older linker. */
|
||||
+ if (l->l_cet != lc_unknown)
|
||||
+ return;
|
||||
+
|
||||
+ /* Check CET status now. */
|
||||
+ l->l_cet = lc_none;
|
||||
+
|
||||
/* Check for invalid property. */
|
||||
if (note->n_descsz < 8
|
||||
|| (note->n_descsz % sizeof (ElfW(Addr))) != 0)
|
||||
- break;
|
||||
+ return;
|
||||
|
||||
/* Start and end of property array. */
|
||||
unsigned char *ptr = (unsigned char *) (note + 1) + 4;
|
||||
@@ -78,9 +93,15 @@ _dl_process_cet_property_note (struct link_map *l,
|
||||
unsigned int type = *(unsigned int *) ptr;
|
||||
unsigned int datasz = *(unsigned int *) (ptr + 4);
|
||||
|
||||
+ /* Property type must be in ascending order. */
|
||||
+ if (type < last_type)
|
||||
+ return;
|
||||
+
|
||||
ptr += 8;
|
||||
if ((ptr + datasz) > ptr_end)
|
||||
- break;
|
||||
+ return;
|
||||
+
|
||||
+ last_type = type;
|
||||
|
||||
if (type == GNU_PROPERTY_X86_FEATURE_1_AND)
|
||||
{
|
||||
@@ -89,14 +110,18 @@ _dl_process_cet_property_note (struct link_map *l,
|
||||
we stop the search regardless if its size is correct
|
||||
or not. There is no point to continue if this note
|
||||
is ill-formed. */
|
||||
- if (datasz == 4)
|
||||
- {
|
||||
- unsigned int feature_1 = *(unsigned int *) ptr;
|
||||
- if ((feature_1 & GNU_PROPERTY_X86_FEATURE_1_IBT))
|
||||
- l->l_cet |= lc_ibt;
|
||||
- if ((feature_1 & GNU_PROPERTY_X86_FEATURE_1_SHSTK))
|
||||
- l->l_cet |= lc_shstk;
|
||||
- }
|
||||
+ if (datasz != 4)
|
||||
+ return;
|
||||
+
|
||||
+ feature_1 = *(unsigned int *) ptr;
|
||||
+
|
||||
+ /* Keep searching for the next GNU property note
|
||||
+ generated by the older linker. */
|
||||
+ break;
|
||||
+ }
|
||||
+ else if (type > GNU_PROPERTY_X86_FEATURE_1_AND)
|
||||
+ {
|
||||
+ /* Stop since property type is in ascending order. */
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -112,6 +137,12 @@ _dl_process_cet_property_note (struct link_map *l,
|
||||
+ ELF_NOTE_NEXT_OFFSET (note->n_namesz, note->n_descsz,
|
||||
align));
|
||||
}
|
||||
+
|
||||
+ /* We get here only if there is one or no GNU property note. */
|
||||
+ if ((feature_1 & GNU_PROPERTY_X86_FEATURE_1_IBT))
|
||||
+ l->l_cet |= lc_ibt;
|
||||
+ if ((feature_1 & GNU_PROPERTY_X86_FEATURE_1_SHSTK))
|
||||
+ l->l_cet |= lc_shstk;
|
||||
#endif
|
||||
}
|
||||
|
||||
diff --git a/sysdeps/x86/link_map.h b/sysdeps/x86/link_map.h
|
||||
index ef1206a9d2396a6f..9367ed08896794a4 100644
|
||||
--- a/sysdeps/x86/link_map.h
|
||||
+++ b/sysdeps/x86/link_map.h
|
||||
@@ -19,8 +19,9 @@
|
||||
/* If this object is enabled with CET. */
|
||||
enum
|
||||
{
|
||||
- lc_none = 0, /* Not enabled with CET. */
|
||||
- lc_ibt = 1 << 0, /* Enabled with IBT. */
|
||||
- lc_shstk = 1 << 1, /* Enabled with STSHK. */
|
||||
+ lc_unknown = 0, /* Unknown CET status. */
|
||||
+ lc_none = 1 << 0, /* Not enabled with CET. */
|
||||
+ lc_ibt = 1 << 1, /* Enabled with IBT. */
|
||||
+ lc_shstk = 1 << 2, /* Enabled with STSHK. */
|
||||
lc_ibt_and_shstk = lc_ibt | lc_shstk /* Enabled with both. */
|
||||
- } l_cet:2;
|
||||
+ } l_cet:3;
|
28
SOURCES/glibc-rh1615781.patch
Normal file
28
SOURCES/glibc-rh1615781.patch
Normal file
@ -0,0 +1,28 @@
|
||||
commit d05b05d1570ba3ae354a2f5a3cfeefb373b09979
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Mon Aug 13 14:28:07 2018 +0200
|
||||
|
||||
error, error_at_line: Add missing va_end calls
|
||||
|
||||
(cherry picked from commit b7b52b9dec337a08a89bc67638773be652eba332)
|
||||
|
||||
diff --git a/misc/error.c b/misc/error.c
|
||||
index b4e8b6c93886b737..03378e2f2aa6251e 100644
|
||||
--- a/misc/error.c
|
||||
+++ b/misc/error.c
|
||||
@@ -319,6 +319,7 @@ error (int status, int errnum, const char *message, ...)
|
||||
|
||||
va_start (args, message);
|
||||
error_tail (status, errnum, message, args);
|
||||
+ va_end (args);
|
||||
|
||||
#ifdef _LIBC
|
||||
_IO_funlockfile (stderr);
|
||||
@@ -390,6 +391,7 @@ error_at_line (int status, int errnum, const char *file_name,
|
||||
|
||||
va_start (args, message);
|
||||
error_tail (status, errnum, message, args);
|
||||
+ va_end (args);
|
||||
|
||||
#ifdef _LIBC
|
||||
_IO_funlockfile (stderr);
|
35
SOURCES/glibc-rh1615784.patch
Normal file
35
SOURCES/glibc-rh1615784.patch
Normal file
@ -0,0 +1,35 @@
|
||||
commit bfcfa22589f2b4277a65e60c6b736b6bbfbd87d0
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Aug 14 10:51:07 2018 +0200
|
||||
|
||||
nscd: Deallocate existing user names in file parser
|
||||
|
||||
This avoids a theoretical memory leak (theoretical because it depends on
|
||||
multiple server-user/stat-user directives in the configuration file).
|
||||
|
||||
(cherry picked from commit 2d7acfac3ebf266dcbc82d0d6cc576f626953a03)
|
||||
|
||||
diff --git a/nscd/nscd_conf.c b/nscd/nscd_conf.c
|
||||
index 265a02434dd26c29..7293b795b6bcf71e 100644
|
||||
--- a/nscd/nscd_conf.c
|
||||
+++ b/nscd/nscd_conf.c
|
||||
@@ -190,7 +190,10 @@ nscd_parse_file (const char *fname, struct database_dyn dbs[lastdb])
|
||||
if (!arg1)
|
||||
error (0, 0, _("Must specify user name for server-user option"));
|
||||
else
|
||||
- server_user = xstrdup (arg1);
|
||||
+ {
|
||||
+ free ((char *) server_user);
|
||||
+ server_user = xstrdup (arg1);
|
||||
+ }
|
||||
}
|
||||
else if (strcmp (entry, "stat-user") == 0)
|
||||
{
|
||||
@@ -198,6 +201,7 @@ nscd_parse_file (const char *fname, struct database_dyn dbs[lastdb])
|
||||
error (0, 0, _("Must specify user name for stat-user option"));
|
||||
else
|
||||
{
|
||||
+ free ((char *) stat_user);
|
||||
stat_user = xstrdup (arg1);
|
||||
|
||||
struct passwd *pw = getpwnam (stat_user);
|
306
SOURCES/glibc-rh1615790.patch
Normal file
306
SOURCES/glibc-rh1615790.patch
Normal file
@ -0,0 +1,306 @@
|
||||
commit 2f498f3d140ab5152bd784df2be7af7d9c5e63ed
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Aug 14 10:57:48 2018 +0200
|
||||
|
||||
nss_files: Fix file stream leak in aliases lookup [BZ #23521]
|
||||
|
||||
In order to get a clean test case, it was necessary to fix partially
|
||||
fixed bug 23522 as well.
|
||||
|
||||
(cherry picked from commit e95c6f61920a0f9237cfb292fa44ad500e1df09b)
|
||||
|
||||
diff --git a/nss/Makefile b/nss/Makefile
|
||||
index 66fac7f5b8a4c0d8..5209fc0456dd6786 100644
|
||||
--- a/nss/Makefile
|
||||
+++ b/nss/Makefile
|
||||
@@ -65,6 +65,7 @@ ifeq (yes,$(build-shared))
|
||||
tests += tst-nss-files-hosts-erange
|
||||
tests += tst-nss-files-hosts-multi
|
||||
tests += tst-nss-files-hosts-getent
|
||||
+tests += tst-nss-files-alias-leak
|
||||
endif
|
||||
|
||||
# If we have a thread library then we can test cancellation against
|
||||
@@ -171,3 +172,5 @@ endif
|
||||
$(objpfx)tst-nss-files-hosts-erange: $(libdl)
|
||||
$(objpfx)tst-nss-files-hosts-multi: $(libdl)
|
||||
$(objpfx)tst-nss-files-hosts-getent: $(libdl)
|
||||
+$(objpfx)tst-nss-files-alias-leak: $(libdl)
|
||||
+$(objpfx)tst-nss-files-alias-leak.out: $(objpfx)/libnss_files.so
|
||||
diff --git a/nss/nss_files/files-alias.c b/nss/nss_files/files-alias.c
|
||||
index cfd34b66b921bbff..35b0bfc5d2479ab6 100644
|
||||
--- a/nss/nss_files/files-alias.c
|
||||
+++ b/nss/nss_files/files-alias.c
|
||||
@@ -221,6 +221,13 @@ get_next_alias (FILE *stream, const char *match, struct aliasent *result,
|
||||
{
|
||||
while (! feof_unlocked (listfile))
|
||||
{
|
||||
+ if (room_left < 2)
|
||||
+ {
|
||||
+ free (old_line);
|
||||
+ fclose (listfile);
|
||||
+ goto no_more_room;
|
||||
+ }
|
||||
+
|
||||
first_unused[room_left - 1] = '\xff';
|
||||
line = fgets_unlocked (first_unused, room_left,
|
||||
listfile);
|
||||
@@ -229,6 +236,7 @@ get_next_alias (FILE *stream, const char *match, struct aliasent *result,
|
||||
if (first_unused[room_left - 1] != '\xff')
|
||||
{
|
||||
free (old_line);
|
||||
+ fclose (listfile);
|
||||
goto no_more_room;
|
||||
}
|
||||
|
||||
@@ -256,6 +264,7 @@ get_next_alias (FILE *stream, const char *match, struct aliasent *result,
|
||||
+ __alignof__ (char *)))
|
||||
{
|
||||
free (old_line);
|
||||
+ fclose (listfile);
|
||||
goto no_more_room;
|
||||
}
|
||||
room_left -= ((first_unused - cp)
|
||||
diff --git a/nss/tst-nss-files-alias-leak.c b/nss/tst-nss-files-alias-leak.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..26d38e2dba1ddaf3
|
||||
--- /dev/null
|
||||
+++ b/nss/tst-nss-files-alias-leak.c
|
||||
@@ -0,0 +1,237 @@
|
||||
+/* Check for file descriptor leak in alias :include: processing (bug 23521).
|
||||
+ Copyright (C) 2018 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <aliases.h>
|
||||
+#include <array_length.h>
|
||||
+#include <dlfcn.h>
|
||||
+#include <errno.h>
|
||||
+#include <gnu/lib-names.h>
|
||||
+#include <nss.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
+#include <support/check.h>
|
||||
+#include <support/namespace.h>
|
||||
+#include <support/support.h>
|
||||
+#include <support/temp_file.h>
|
||||
+#include <support/test-driver.h>
|
||||
+#include <support/xstdio.h>
|
||||
+#include <support/xunistd.h>
|
||||
+
|
||||
+static struct support_chroot *chroot_env;
|
||||
+
|
||||
+/* Number of the aliases for the "many" user. This must be large
|
||||
+ enough to trigger reallocation for the pointer array, but result in
|
||||
+ answers below the maximum size tried in do_test. */
|
||||
+enum { many_aliases = 30 };
|
||||
+
|
||||
+static void
|
||||
+prepare (int argc, char **argv)
|
||||
+{
|
||||
+ chroot_env = support_chroot_create
|
||||
+ ((struct support_chroot_configuration) { } );
|
||||
+
|
||||
+ char *path = xasprintf ("%s/etc/aliases", chroot_env->path_chroot);
|
||||
+ add_temp_file (path);
|
||||
+ support_write_file_string
|
||||
+ (path,
|
||||
+ "user1: :include:/etc/aliases.user1\n"
|
||||
+ "user2: :include:/etc/aliases.user2\n"
|
||||
+ "comment: comment1, :include:/etc/aliases.comment\n"
|
||||
+ "many: :include:/etc/aliases.many\n");
|
||||
+ free (path);
|
||||
+
|
||||
+ path = xasprintf ("%s/etc/aliases.user1", chroot_env->path_chroot);
|
||||
+ add_temp_file (path);
|
||||
+ support_write_file_string (path, "alias1\n");
|
||||
+ free (path);
|
||||
+
|
||||
+ path = xasprintf ("%s/etc/aliases.user2", chroot_env->path_chroot);
|
||||
+ add_temp_file (path);
|
||||
+ support_write_file_string (path, "alias1a, alias2\n");
|
||||
+ free (path);
|
||||
+
|
||||
+ path = xasprintf ("%s/etc/aliases.comment", chroot_env->path_chroot);
|
||||
+ add_temp_file (path);
|
||||
+ support_write_file_string
|
||||
+ (path,
|
||||
+ /* The line must be longer than the line with the :include:
|
||||
+ directive in /etc/aliases. */
|
||||
+ "# Long line. ##############################################\n"
|
||||
+ "comment2\n");
|
||||
+ free (path);
|
||||
+
|
||||
+ path = xasprintf ("%s/etc/aliases.many", chroot_env->path_chroot);
|
||||
+ add_temp_file (path);
|
||||
+ FILE *fp = xfopen (path, "w");
|
||||
+ for (int i = 0; i < many_aliases; ++i)
|
||||
+ fprintf (fp, "a%d\n", i);
|
||||
+ TEST_VERIFY_EXIT (! ferror (fp));
|
||||
+ xfclose (fp);
|
||||
+ free (path);
|
||||
+}
|
||||
+
|
||||
+/* The names of the users to test. */
|
||||
+static const char *users[] = { "user1", "user2", "comment", "many" };
|
||||
+
|
||||
+static void
|
||||
+check_aliases (int id, const struct aliasent *e)
|
||||
+{
|
||||
+ TEST_VERIFY_EXIT (id >= 0 || id < array_length (users));
|
||||
+ const char *name = users[id];
|
||||
+ TEST_COMPARE_BLOB (e->alias_name, strlen (e->alias_name),
|
||||
+ name, strlen (name));
|
||||
+
|
||||
+ switch (id)
|
||||
+ {
|
||||
+ case 0:
|
||||
+ TEST_COMPARE (e->alias_members_len, 1);
|
||||
+ TEST_COMPARE_BLOB (e->alias_members[0], strlen (e->alias_members[0]),
|
||||
+ "alias1", strlen ("alias1"));
|
||||
+ break;
|
||||
+
|
||||
+ case 1:
|
||||
+ TEST_COMPARE (e->alias_members_len, 2);
|
||||
+ TEST_COMPARE_BLOB (e->alias_members[0], strlen (e->alias_members[0]),
|
||||
+ "alias1a", strlen ("alias1a"));
|
||||
+ TEST_COMPARE_BLOB (e->alias_members[1], strlen (e->alias_members[1]),
|
||||
+ "alias2", strlen ("alias2"));
|
||||
+ break;
|
||||
+
|
||||
+ case 2:
|
||||
+ TEST_COMPARE (e->alias_members_len, 2);
|
||||
+ TEST_COMPARE_BLOB (e->alias_members[0], strlen (e->alias_members[0]),
|
||||
+ "comment1", strlen ("comment1"));
|
||||
+ TEST_COMPARE_BLOB (e->alias_members[1], strlen (e->alias_members[1]),
|
||||
+ "comment2", strlen ("comment2"));
|
||||
+ break;
|
||||
+
|
||||
+ case 3:
|
||||
+ TEST_COMPARE (e->alias_members_len, many_aliases);
|
||||
+ for (int i = 0; i < e->alias_members_len; ++i)
|
||||
+ {
|
||||
+ char alias[30];
|
||||
+ int len = snprintf (alias, sizeof (alias), "a%d", i);
|
||||
+ TEST_VERIFY_EXIT (len > 0);
|
||||
+ TEST_COMPARE_BLOB (e->alias_members[i], strlen (e->alias_members[i]),
|
||||
+ alias, len);
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ /* Make sure we don't try to load the module in the chroot. */
|
||||
+ if (dlopen (LIBNSS_FILES_SO, RTLD_NOW) == NULL)
|
||||
+ FAIL_EXIT1 ("could not load " LIBNSS_FILES_SO ": %s", dlerror ());
|
||||
+
|
||||
+ /* Some of these descriptors will become unavailable if there is a
|
||||
+ file descriptor leak. 10 is chosen somewhat arbitrarily. The
|
||||
+ array must be longer than the number of files opened by nss_files
|
||||
+ at the same time (currently that number is 2). */
|
||||
+ int next_descriptors[10];
|
||||
+ for (size_t i = 0; i < array_length (next_descriptors); ++i)
|
||||
+ {
|
||||
+ next_descriptors[i] = dup (0);
|
||||
+ TEST_VERIFY_EXIT (next_descriptors[i] > 0);
|
||||
+ }
|
||||
+ for (size_t i = 0; i < array_length (next_descriptors); ++i)
|
||||
+ xclose (next_descriptors[i]);
|
||||
+
|
||||
+ support_become_root ();
|
||||
+ if (!support_can_chroot ())
|
||||
+ return EXIT_UNSUPPORTED;
|
||||
+
|
||||
+ __nss_configure_lookup ("aliases", "files");
|
||||
+
|
||||
+ xchroot (chroot_env->path_chroot);
|
||||
+
|
||||
+ /* Attempt various buffer sizes. If the operation succeeds, we
|
||||
+ expect correct data. */
|
||||
+ for (int id = 0; id < array_length (users); ++id)
|
||||
+ {
|
||||
+ bool found = false;
|
||||
+ for (size_t size = 1; size <= 1000; ++size)
|
||||
+ {
|
||||
+ void *buffer = malloc (size);
|
||||
+ struct aliasent result;
|
||||
+ struct aliasent *res;
|
||||
+ errno = EINVAL;
|
||||
+ int ret = getaliasbyname_r (users[id], &result, buffer, size, &res);
|
||||
+ if (ret == 0)
|
||||
+ {
|
||||
+ if (res != NULL)
|
||||
+ {
|
||||
+ found = true;
|
||||
+ check_aliases (id, res);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ support_record_failure ();
|
||||
+ printf ("error: failed lookup for user \"%s\", size %zu\n",
|
||||
+ users[id], size);
|
||||
+ }
|
||||
+ }
|
||||
+ else if (ret != ERANGE)
|
||||
+ {
|
||||
+ support_record_failure ();
|
||||
+ printf ("error: invalid return code %d (user \%s\", size %zu)\n",
|
||||
+ ret, users[id], size);
|
||||
+ }
|
||||
+ free (buffer);
|
||||
+
|
||||
+ /* Make sure that we did not have a file descriptor leak. */
|
||||
+ for (size_t i = 0; i < array_length (next_descriptors); ++i)
|
||||
+ {
|
||||
+ int new_fd = dup (0);
|
||||
+ if (new_fd != next_descriptors[i])
|
||||
+ {
|
||||
+ support_record_failure ();
|
||||
+ printf ("error: descriptor %d at index %zu leaked"
|
||||
+ " (user \"%s\", size %zu)\n",
|
||||
+ next_descriptors[i], i, users[id], size);
|
||||
+
|
||||
+ /* Close unexpected descriptor, the leak probing
|
||||
+ descriptors, and the leaked descriptor
|
||||
+ next_descriptors[i]. */
|
||||
+ xclose (new_fd);
|
||||
+ for (size_t j = 0; j <= i; ++j)
|
||||
+ xclose (next_descriptors[j]);
|
||||
+ goto next_size;
|
||||
+ }
|
||||
+ }
|
||||
+ for (size_t i = 0; i < array_length (next_descriptors); ++i)
|
||||
+ xclose (next_descriptors[i]);
|
||||
+
|
||||
+ next_size:
|
||||
+ ;
|
||||
+ }
|
||||
+ if (!found)
|
||||
+ {
|
||||
+ support_record_failure ();
|
||||
+ printf ("error: user %s not found\n", users[id]);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ support_chroot_free (chroot_env);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#define PREPARE prepare
|
||||
+#include <support/test-driver.c>
|
27
SOURCES/glibc-rh1622675.patch
Normal file
27
SOURCES/glibc-rh1622675.patch
Normal file
@ -0,0 +1,27 @@
|
||||
commit aa8a3e4cdef20c50cb20f008864fff05cbfbdf29
|
||||
Author: Martin Kuchta <martin.kuchta@netapp.com>
|
||||
Date: Mon Aug 27 18:54:46 2018 +0200
|
||||
|
||||
pthread_cond_broadcast: Fix waiters-after-spinning case [BZ #23538]
|
||||
|
||||
(cherry picked from commit 99ea93ca31795469d2a1f1570f17a5c39c2eb7e2)
|
||||
|
||||
diff --git a/nptl/pthread_cond_common.c b/nptl/pthread_cond_common.c
|
||||
index 8e425eb01eceabec..479e54febb417675 100644
|
||||
--- a/nptl/pthread_cond_common.c
|
||||
+++ b/nptl/pthread_cond_common.c
|
||||
@@ -405,8 +405,12 @@ __condvar_quiesce_and_switch_g1 (pthread_cond_t *cond, uint64_t wseq,
|
||||
{
|
||||
/* There is still a waiter after spinning. Set the wake-request
|
||||
flag and block. Relaxed MO is fine because this is just about
|
||||
- this futex word. */
|
||||
- r = atomic_fetch_or_relaxed (cond->__data.__g_refs + g1, 1);
|
||||
+ this futex word.
|
||||
+
|
||||
+ Update r to include the set wake-request flag so that the upcoming
|
||||
+ futex_wait only blocks if the flag is still set (otherwise, we'd
|
||||
+ violate the basic client-side futex protocol). */
|
||||
+ r = atomic_fetch_or_relaxed (cond->__data.__g_refs + g1, 1) | 1;
|
||||
|
||||
if ((r >> 1) > 0)
|
||||
futex_wait_simple (cond->__data.__g_refs + g1, r, private);
|
41
SOURCES/glibc-rh1622678-1.patch
Normal file
41
SOURCES/glibc-rh1622678-1.patch
Normal file
@ -0,0 +1,41 @@
|
||||
commit 58559f14437d2aa71753a29fed435efa06aa4576
|
||||
Author: Paul Eggert <eggert@cs.ucla.edu>
|
||||
Date: Tue Aug 28 21:54:28 2018 +0200
|
||||
|
||||
regex: fix uninitialized memory access
|
||||
|
||||
I introduced this bug into gnulib in commit
|
||||
8335a4d6c7b4448cd0bcb6d0bebf1d456bcfdb17 dated 2006-04-10;
|
||||
eventually it was merged into glibc. The bug was found by
|
||||
project-repo <bugs@feusi.co> and reported here:
|
||||
https://lists.gnu.org/r/sed-devel/2018-08/msg00017.html
|
||||
Diagnosis and draft fix reported by Assaf Gordon here:
|
||||
https://lists.gnu.org/r/bug-gnulib/2018-08/msg00071.html
|
||||
https://lists.gnu.org/r/bug-gnulib/2018-08/msg00142.html
|
||||
* posix/regex_internal.c (build_wcs_upper_buffer):
|
||||
Fix bug when mbrtowc returns 0.
|
||||
|
||||
(cherry picked from commit bc680b336971305cb39896b30d72dc7101b62242)
|
||||
|
||||
diff --git a/posix/regex_internal.c b/posix/regex_internal.c
|
||||
index 7f0083b918de6530..b10588f1ccbb1992 100644
|
||||
--- a/posix/regex_internal.c
|
||||
+++ b/posix/regex_internal.c
|
||||
@@ -317,7 +317,7 @@ build_wcs_upper_buffer (re_string_t *pstr)
|
||||
mbclen = __mbrtowc (&wc,
|
||||
((const char *) pstr->raw_mbs + pstr->raw_mbs_idx
|
||||
+ byte_idx), remain_len, &pstr->cur_state);
|
||||
- if (BE (mbclen < (size_t) -2, 1))
|
||||
+ if (BE (0 < mbclen && mbclen < (size_t) -2, 1))
|
||||
{
|
||||
wchar_t wcu = __towupper (wc);
|
||||
if (wcu != wc)
|
||||
@@ -386,7 +386,7 @@ build_wcs_upper_buffer (re_string_t *pstr)
|
||||
else
|
||||
p = (const char *) pstr->raw_mbs + pstr->raw_mbs_idx + src_idx;
|
||||
mbclen = __mbrtowc (&wc, p, remain_len, &pstr->cur_state);
|
||||
- if (BE (mbclen < (size_t) -2, 1))
|
||||
+ if (BE (0 < mbclen && mbclen < (size_t) -2, 1))
|
||||
{
|
||||
wchar_t wcu = __towupper (wc);
|
||||
if (wcu != wc)
|
226
SOURCES/glibc-rh1622678-2.patch
Normal file
226
SOURCES/glibc-rh1622678-2.patch
Normal file
@ -0,0 +1,226 @@
|
||||
commit 0b79004569e5ce1669136b8c41564c3809730f15
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Aug 28 12:57:46 2018 +0200
|
||||
|
||||
regex: Add test tst-regcomp-truncated [BZ #23578]
|
||||
|
||||
(cherry picked from commit 761404b74d9853ce1608195e24f25b78a910591a)
|
||||
|
||||
diff --git a/posix/Makefile b/posix/Makefile
|
||||
index 00c62841a282f15a..83162123f9c927a0 100644
|
||||
--- a/posix/Makefile
|
||||
+++ b/posix/Makefile
|
||||
@@ -96,7 +96,7 @@ tests := test-errno tstgetopt testfnm runtests runptests \
|
||||
tst-posix_fadvise tst-posix_fadvise64 \
|
||||
tst-sysconf-empty-chroot tst-glob_symlinks tst-fexecve \
|
||||
tst-glob-tilde test-ssize-max tst-spawn4 bug-regex37 \
|
||||
- bug-regex38
|
||||
+ bug-regex38 tst-regcomp-truncated
|
||||
tests-internal := bug-regex5 bug-regex20 bug-regex33 \
|
||||
tst-rfc3484 tst-rfc3484-2 tst-rfc3484-3 \
|
||||
tst-glob_lstat_compat tst-spawn4-compat
|
||||
@@ -194,6 +194,7 @@ $(objpfx)tst-regex2.out: $(gen-locales)
|
||||
$(objpfx)tst-regexloc.out: $(gen-locales)
|
||||
$(objpfx)tst-rxspencer.out: $(gen-locales)
|
||||
$(objpfx)tst-rxspencer-no-utf8.out: $(gen-locales)
|
||||
+$(objpfx)tst-regcomp-truncated.out: $(gen-locales)
|
||||
endif
|
||||
|
||||
# If we will use the generic uname implementation, we must figure out what
|
||||
diff --git a/posix/tst-regcomp-truncated.c b/posix/tst-regcomp-truncated.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..a4a1581bbc2b39eb
|
||||
--- /dev/null
|
||||
+++ b/posix/tst-regcomp-truncated.c
|
||||
@@ -0,0 +1,191 @@
|
||||
+/* Test compilation of truncated regular expressions.
|
||||
+ Copyright (C) 2018 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+/* This test constructs various patterns in an attempt to trigger
|
||||
+ over-reading the regular expression compiler, such as bug
|
||||
+ 23578. */
|
||||
+
|
||||
+#include <array_length.h>
|
||||
+#include <errno.h>
|
||||
+#include <locale.h>
|
||||
+#include <regex.h>
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
+#include <support/check.h>
|
||||
+#include <support/next_to_fault.h>
|
||||
+#include <support/support.h>
|
||||
+#include <support/test-driver.h>
|
||||
+#include <wchar.h>
|
||||
+
|
||||
+/* Locales to test. */
|
||||
+static const char locales[][17] =
|
||||
+ {
|
||||
+ "C",
|
||||
+ "en_US.UTF-8",
|
||||
+ "de_DE.ISO-8859-1",
|
||||
+ };
|
||||
+
|
||||
+/* Syntax options. Will be combined with other flags. */
|
||||
+static const reg_syntax_t syntaxes[] =
|
||||
+ {
|
||||
+ RE_SYNTAX_EMACS,
|
||||
+ RE_SYNTAX_AWK,
|
||||
+ RE_SYNTAX_GNU_AWK,
|
||||
+ RE_SYNTAX_POSIX_AWK,
|
||||
+ RE_SYNTAX_GREP,
|
||||
+ RE_SYNTAX_EGREP,
|
||||
+ RE_SYNTAX_POSIX_EGREP,
|
||||
+ RE_SYNTAX_POSIX_BASIC,
|
||||
+ RE_SYNTAX_POSIX_EXTENDED,
|
||||
+ RE_SYNTAX_POSIX_MINIMAL_EXTENDED,
|
||||
+ };
|
||||
+
|
||||
+/* Trailing characters placed after the initial character. */
|
||||
+static const char trailing_strings[][4] =
|
||||
+ {
|
||||
+ "",
|
||||
+ "[",
|
||||
+ "\\",
|
||||
+ "[\\",
|
||||
+ "(",
|
||||
+ "(\\",
|
||||
+ "\\(",
|
||||
+ };
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ /* Staging buffer for the constructed regular expression. */
|
||||
+ char buffer[16];
|
||||
+
|
||||
+ /* Allocation used to detect over-reading by the regular expression
|
||||
+ compiler. */
|
||||
+ struct support_next_to_fault ntf
|
||||
+ = support_next_to_fault_allocate (sizeof (buffer));
|
||||
+
|
||||
+ /* Arbitrary Unicode codepoint at which we stop generating
|
||||
+ characters. We do not probe the whole range because that would
|
||||
+ take too long due to combinatorical exploision as the result of
|
||||
+ combination with other flags. */
|
||||
+ static const wchar_t last_character = 0xfff;
|
||||
+
|
||||
+ for (size_t locale_idx = 0; locale_idx < array_length (locales);
|
||||
+ ++ locale_idx)
|
||||
+ {
|
||||
+ if (setlocale (LC_ALL, locales[locale_idx]) == NULL)
|
||||
+ {
|
||||
+ support_record_failure ();
|
||||
+ printf ("error: setlocale (\"%s\"): %m", locales[locale_idx]);
|
||||
+ continue;
|
||||
+ }
|
||||
+ if (test_verbose > 0)
|
||||
+ printf ("info: testing locale \"%s\"\n", locales[locale_idx]);
|
||||
+
|
||||
+ for (wchar_t wc = 0; wc <= last_character; ++wc)
|
||||
+ {
|
||||
+ char *after_wc;
|
||||
+ if (wc == 0)
|
||||
+ {
|
||||
+ /* wcrtomb treats L'\0' in a special way. */
|
||||
+ *buffer = '\0';
|
||||
+ after_wc = &buffer[1];
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ mbstate_t ps = { };
|
||||
+ size_t ret = wcrtomb (buffer, wc, &ps);
|
||||
+ if (ret == (size_t) -1)
|
||||
+ {
|
||||
+ /* EILSEQ means that the target character set
|
||||
+ cannot encode the character. */
|
||||
+ if (errno != EILSEQ)
|
||||
+ {
|
||||
+ support_record_failure ();
|
||||
+ printf ("error: wcrtomb (0x%x) failed: %m\n",
|
||||
+ (unsigned) wc);
|
||||
+ }
|
||||
+ continue;
|
||||
+ }
|
||||
+ TEST_VERIFY_EXIT (ret != 0);
|
||||
+ after_wc = &buffer[ret];
|
||||
+ }
|
||||
+
|
||||
+ for (size_t trailing_idx = 0;
|
||||
+ trailing_idx < array_length (trailing_strings);
|
||||
+ ++trailing_idx)
|
||||
+ {
|
||||
+ char *after_trailing
|
||||
+ = stpcpy (after_wc, trailing_strings[trailing_idx]);
|
||||
+
|
||||
+ for (int do_nul = 0; do_nul < 2; ++do_nul)
|
||||
+ {
|
||||
+ char *after_nul;
|
||||
+ if (do_nul)
|
||||
+ {
|
||||
+ *after_trailing = '\0';
|
||||
+ after_nul = &after_trailing[1];
|
||||
+ }
|
||||
+ else
|
||||
+ after_nul = after_trailing;
|
||||
+
|
||||
+ size_t length = after_nul - buffer;
|
||||
+
|
||||
+ /* Make sure that the faulting region starts
|
||||
+ after the used portion of the buffer. */
|
||||
+ char *ntf_start = ntf.buffer + sizeof (buffer) - length;
|
||||
+ memcpy (ntf_start, buffer, length);
|
||||
+
|
||||
+ for (const reg_syntax_t *psyntax = syntaxes;
|
||||
+ psyntax < array_end (syntaxes); ++psyntax)
|
||||
+ for (int do_icase = 0; do_icase < 2; ++do_icase)
|
||||
+ {
|
||||
+ re_syntax_options = *psyntax;
|
||||
+ if (do_icase)
|
||||
+ re_syntax_options |= RE_ICASE;
|
||||
+
|
||||
+ regex_t reg;
|
||||
+ memset (®, 0, sizeof (reg));
|
||||
+ const char *msg = re_compile_pattern
|
||||
+ (ntf_start, length, ®);
|
||||
+ if (msg != NULL)
|
||||
+ {
|
||||
+ if (test_verbose > 0)
|
||||
+ {
|
||||
+ char *quoted = support_quote_blob
|
||||
+ (buffer, length);
|
||||
+ printf ("info: compilation failed for pattern"
|
||||
+ " \"%s\", syntax 0x%lx: %s\n",
|
||||
+ quoted, re_syntax_options, msg);
|
||||
+ free (quoted);
|
||||
+ }
|
||||
+ }
|
||||
+ else
|
||||
+ regfree (®);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ support_next_to_fault_free (&ntf);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
34
SOURCES/glibc-rh1623536-2.patch
Normal file
34
SOURCES/glibc-rh1623536-2.patch
Normal file
@ -0,0 +1,34 @@
|
||||
commit 3a67c72c1512f778304a5644dea2fcf5bdece274
|
||||
Author: Andreas Schwab <schwab@suse.de>
|
||||
Date: Thu Sep 27 12:37:06 2018 +0200
|
||||
|
||||
Fix stack overflow in tst-setcontext9 (bug 23717)
|
||||
|
||||
The function f1a, executed on a stack of size 32k, allocates an object of
|
||||
size 32k on the stack. Make the stack variables static to reduce
|
||||
excessive stack usage.
|
||||
|
||||
(cherry picked from commit f841c97e515a1673485a2b12b3c280073d737890)
|
||||
|
||||
diff --git a/stdlib/tst-setcontext9.c b/stdlib/tst-setcontext9.c
|
||||
index db8355766ca7b906..009928235dd5987e 100644
|
||||
--- a/stdlib/tst-setcontext9.c
|
||||
+++ b/stdlib/tst-setcontext9.c
|
||||
@@ -58,7 +58,7 @@ f1b (void)
|
||||
static void
|
||||
f1a (void)
|
||||
{
|
||||
- char st2[32768];
|
||||
+ static char st2[32768];
|
||||
puts ("start f1a");
|
||||
if (getcontext (&ctx[2]) != 0)
|
||||
{
|
||||
@@ -93,7 +93,7 @@ f1a (void)
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
- char st1[32768];
|
||||
+ static char st1[32768];
|
||||
puts ("making contexts");
|
||||
if (getcontext (&ctx[0]) != 0)
|
||||
{
|
100
SOURCES/glibc-rh1623536.patch
Normal file
100
SOURCES/glibc-rh1623536.patch
Normal file
@ -0,0 +1,100 @@
|
||||
commit a55e109709af55e6ed67d3f9536cac5d929c982e
|
||||
Author: Carlos O'Donell <carlos@redhat.com>
|
||||
Date: Wed Sep 5 01:16:42 2018 -0400
|
||||
|
||||
Fix tst-setcontext9 for optimized small stacks.
|
||||
|
||||
If the compiler reduces the stack usage in function f1 before calling
|
||||
into function f2, then when we swapcontext back to f1 and continue
|
||||
execution we may overwrite registers that were spilled to the stack
|
||||
while f2 was executing. Later when we return to f2 the corrupt
|
||||
registers will be reloaded from the stack and the test will crash. This
|
||||
was most commonly observed on i686 with __x86.get_pc_thunk.dx and
|
||||
needing to save and restore $edx. Overall i686 has few registers and
|
||||
the spilling to the stack is bound to happen, therefore the solution to
|
||||
making this test robust is to split function f1 into two parts f1a and
|
||||
f1b, and allocate f1b it's own stack such that subsequent execution does
|
||||
not overwrite the stack in use by function f2.
|
||||
|
||||
Tested on i686 and x86_64.
|
||||
|
||||
Signed-off-by: Carlos O'Donell <carlos@redhat.com>
|
||||
(cherry picked from commit 791b350dc725545e3f9b5db0f97ebdbc60c9735f)
|
||||
|
||||
diff --git a/stdlib/tst-setcontext9.c b/stdlib/tst-setcontext9.c
|
||||
index 4636ce9030fa38a7..db8355766ca7b906 100644
|
||||
--- a/stdlib/tst-setcontext9.c
|
||||
+++ b/stdlib/tst-setcontext9.c
|
||||
@@ -41,26 +41,55 @@ f2 (void)
|
||||
}
|
||||
|
||||
static void
|
||||
-f1 (void)
|
||||
+f1b (void)
|
||||
{
|
||||
- puts ("start f1");
|
||||
- if (getcontext (&ctx[2]) != 0)
|
||||
- {
|
||||
- printf ("%s: getcontext: %m\n", __FUNCTION__);
|
||||
- exit (EXIT_FAILURE);
|
||||
- }
|
||||
if (done)
|
||||
{
|
||||
- puts ("set context in f1");
|
||||
+ puts ("set context in f1b");
|
||||
if (setcontext (&ctx[3]) != 0)
|
||||
{
|
||||
printf ("%s: setcontext: %m\n", __FUNCTION__);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
+ exit (EXIT_FAILURE);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+f1a (void)
|
||||
+{
|
||||
+ char st2[32768];
|
||||
+ puts ("start f1a");
|
||||
+ if (getcontext (&ctx[2]) != 0)
|
||||
+ {
|
||||
+ printf ("%s: getcontext: %m\n", __FUNCTION__);
|
||||
+ exit (EXIT_FAILURE);
|
||||
+ }
|
||||
+ ctx[2].uc_stack.ss_sp = st2;
|
||||
+ ctx[2].uc_stack.ss_size = sizeof st2;
|
||||
+ ctx[2].uc_link = &ctx[0];
|
||||
+ makecontext (&ctx[2], (void (*) (void)) f1b, 0);
|
||||
f2 ();
|
||||
}
|
||||
|
||||
+/* The execution path through the test looks like this:
|
||||
+ do_test (call)
|
||||
+ -> "making contexts"
|
||||
+ -> "swap contexts"
|
||||
+ f1a (via swapcontext to ctx[1], with alternate stack)
|
||||
+ -> "start f1a"
|
||||
+ f2 (call)
|
||||
+ -> "swap contexts in f2"
|
||||
+ f1b (via swapcontext to ctx[2], with alternate stack)
|
||||
+ -> "set context in f1b"
|
||||
+ do_test (via setcontext to ctx[3], main stack)
|
||||
+ -> "setcontext"
|
||||
+ f2 (via setcontext to ctx[4], with alternate stack)
|
||||
+ -> "end f2"
|
||||
+
|
||||
+ We must use an alternate stack for f1b, because if we don't then the
|
||||
+ result of executing an earlier caller may overwrite registers
|
||||
+ spilled to the stack in f2. */
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
@@ -79,7 +108,7 @@ do_test (void)
|
||||
ctx[1].uc_stack.ss_sp = st1;
|
||||
ctx[1].uc_stack.ss_size = sizeof st1;
|
||||
ctx[1].uc_link = &ctx[0];
|
||||
- makecontext (&ctx[1], (void (*) (void)) f1, 0);
|
||||
+ makecontext (&ctx[1], (void (*) (void)) f1a, 0);
|
||||
puts ("swap contexts");
|
||||
if (swapcontext (&ctx[3], &ctx[1]) != 0)
|
||||
{
|
61
SOURCES/glibc-rh1623537.patch
Normal file
61
SOURCES/glibc-rh1623537.patch
Normal file
@ -0,0 +1,61 @@
|
||||
commit b297581acb66f80b513996c1580158b0fb12d469
|
||||
Author: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com>
|
||||
Date: Mon Jan 14 17:54:44 2019 -0200
|
||||
|
||||
Add XFAIL_ROUNDING_IBM128_LIBGCC to more fma() tests
|
||||
|
||||
Ignore 16 errors in math/test-ldouble-fma and 4 errors in
|
||||
math/test-ildouble-fma when IBM 128-bit long double used.
|
||||
These errors are caused by spurious overflows from libgcc.
|
||||
|
||||
* math/libm-test-fma.inc (fma_test_data): Set
|
||||
XFAIL_ROUNDING_IBM128_LIBGCC to more tests.
|
||||
|
||||
Signed-off-by: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com>
|
||||
(cherry picked from commit ecdacd34a2ac3b6d5a529ff218b29261d9d98a7a)
|
||||
|
||||
diff --git a/math/libm-test-fma.inc b/math/libm-test-fma.inc
|
||||
index 5b29fb820194e055..a7ee40992420c1ab 100644
|
||||
--- a/math/libm-test-fma.inc
|
||||
+++ b/math/libm-test-fma.inc
|
||||
@@ -119,32 +119,32 @@ static const struct test_fff_f_data fma_test_data[] =
|
||||
TEST_fff_f (fma, plus_infty, plus_infty, -min_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
||||
TEST_fff_f (fma, plus_infty, plus_infty, min_subnorm_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
||||
TEST_fff_f (fma, plus_infty, plus_infty, -min_subnorm_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
||||
- TEST_fff_f (fma, plus_infty, plus_infty, max_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
||||
- TEST_fff_f (fma, plus_infty, plus_infty, -max_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
||||
+ TEST_fff_f (fma, plus_infty, plus_infty, max_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED|XFAIL_ROUNDING_IBM128_LIBGCC),
|
||||
+ TEST_fff_f (fma, plus_infty, plus_infty, -max_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED|XFAIL_ROUNDING_IBM128_LIBGCC),
|
||||
TEST_fff_f (fma, plus_infty, minus_infty, plus_zero, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
||||
TEST_fff_f (fma, plus_infty, minus_infty, minus_zero, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
||||
TEST_fff_f (fma, plus_infty, minus_infty, min_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
||||
TEST_fff_f (fma, plus_infty, minus_infty, -min_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
||||
TEST_fff_f (fma, plus_infty, minus_infty, min_subnorm_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
||||
TEST_fff_f (fma, plus_infty, minus_infty, -min_subnorm_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
||||
- TEST_fff_f (fma, plus_infty, minus_infty, max_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
||||
- TEST_fff_f (fma, plus_infty, minus_infty, -max_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
||||
+ TEST_fff_f (fma, plus_infty, minus_infty, max_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED|XFAIL_ROUNDING_IBM128_LIBGCC),
|
||||
+ TEST_fff_f (fma, plus_infty, minus_infty, -max_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED|XFAIL_ROUNDING_IBM128_LIBGCC),
|
||||
TEST_fff_f (fma, minus_infty, plus_infty, plus_zero, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
||||
TEST_fff_f (fma, minus_infty, plus_infty, minus_zero, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
||||
TEST_fff_f (fma, minus_infty, plus_infty, min_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
||||
TEST_fff_f (fma, minus_infty, plus_infty, -min_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
||||
TEST_fff_f (fma, minus_infty, plus_infty, min_subnorm_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
||||
TEST_fff_f (fma, minus_infty, plus_infty, -min_subnorm_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
||||
- TEST_fff_f (fma, minus_infty, plus_infty, max_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
||||
- TEST_fff_f (fma, minus_infty, plus_infty, -max_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
||||
+ TEST_fff_f (fma, minus_infty, plus_infty, max_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED|XFAIL_ROUNDING_IBM128_LIBGCC),
|
||||
+ TEST_fff_f (fma, minus_infty, plus_infty, -max_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED|XFAIL_ROUNDING_IBM128_LIBGCC),
|
||||
TEST_fff_f (fma, minus_infty, minus_infty, plus_zero, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
||||
TEST_fff_f (fma, minus_infty, minus_infty, minus_zero, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
||||
TEST_fff_f (fma, minus_infty, minus_infty, min_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
||||
TEST_fff_f (fma, minus_infty, minus_infty, -min_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
||||
TEST_fff_f (fma, minus_infty, minus_infty, min_subnorm_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
||||
TEST_fff_f (fma, minus_infty, minus_infty, -min_subnorm_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
||||
- TEST_fff_f (fma, minus_infty, minus_infty, max_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
||||
- TEST_fff_f (fma, minus_infty, minus_infty, -max_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
||||
+ TEST_fff_f (fma, minus_infty, minus_infty, max_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED|XFAIL_ROUNDING_IBM128_LIBGCC),
|
||||
+ TEST_fff_f (fma, minus_infty, minus_infty, -max_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED|XFAIL_ROUNDING_IBM128_LIBGCC),
|
||||
|
||||
AUTO_TESTS_fff_f (fma),
|
||||
};
|
29
SOURCES/glibc-rh1631293-1.patch
Normal file
29
SOURCES/glibc-rh1631293-1.patch
Normal file
@ -0,0 +1,29 @@
|
||||
commit e7d22db29cfdd2f1fb97a70a76fa53d151569945
|
||||
Author: Mingli Yu <Mingli.Yu@windriver.com>
|
||||
Date: Thu Sep 20 12:41:13 2018 +0200
|
||||
|
||||
Linux gethostid: Check for NULL value from gethostbyname_r [BZ #23679]
|
||||
|
||||
A NULL value can happen with certain gethostbyname_r failures.
|
||||
|
||||
(cherry picked from commit 1214ba06e6771acb953a190091b0f6055c64fd25)
|
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/gethostid.c b/sysdeps/unix/sysv/linux/gethostid.c
|
||||
index 2e20f034dc134cc7..ee0190e7f945db1f 100644
|
||||
--- a/sysdeps/unix/sysv/linux/gethostid.c
|
||||
+++ b/sysdeps/unix/sysv/linux/gethostid.c
|
||||
@@ -102,12 +102,12 @@ gethostid (void)
|
||||
{
|
||||
int ret = __gethostbyname_r (hostname, &hostbuf,
|
||||
tmpbuf.data, tmpbuf.length, &hp, &herr);
|
||||
- if (ret == 0)
|
||||
+ if (ret == 0 && hp != NULL)
|
||||
break;
|
||||
else
|
||||
{
|
||||
/* Enlarge the buffer on ERANGE. */
|
||||
- if (herr == NETDB_INTERNAL && errno == ERANGE)
|
||||
+ if (ret != 0 && herr == NETDB_INTERNAL && errno == ERANGE)
|
||||
{
|
||||
if (!scratch_buffer_grow (&tmpbuf))
|
||||
return 0;
|
146
SOURCES/glibc-rh1631293-2.patch
Normal file
146
SOURCES/glibc-rh1631293-2.patch
Normal file
@ -0,0 +1,146 @@
|
||||
commit 307d04334d516bb180f484a2b283f97310bfee66
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Thu Sep 20 12:03:01 2018 +0200
|
||||
|
||||
misc: New test misc/tst-gethostid
|
||||
|
||||
The empty /etc/hosts file used to trigger bug 23679.
|
||||
|
||||
(cherry picked from commit db9a8ad4ff3fc58e3773a9a4d0cabe3c1bc9c94c)
|
||||
|
||||
diff --git a/misc/Makefile b/misc/Makefile
|
||||
index b7be2bc19a6f7ed5..c9f81515ac9aef2c 100644
|
||||
--- a/misc/Makefile
|
||||
+++ b/misc/Makefile
|
||||
@@ -86,6 +86,11 @@ tests := tst-dirname tst-tsearch tst-fdset tst-efgcvt tst-mntent tst-hsearch \
|
||||
tst-preadvwritev tst-preadvwritev64 tst-makedev tst-empty \
|
||||
tst-preadvwritev2 tst-preadvwritev64v2
|
||||
|
||||
+# Tests which need libdl.
|
||||
+ifeq (yes,$(build-shared))
|
||||
+tests += tst-gethostid
|
||||
+endif
|
||||
+
|
||||
tests-internal := tst-atomic tst-atomic-long tst-allocate_once
|
||||
tests-static := tst-empty
|
||||
|
||||
@@ -145,3 +150,5 @@ tst-allocate_once-ENV = MALLOC_TRACE=$(objpfx)tst-allocate_once.mtrace
|
||||
$(objpfx)tst-allocate_once-mem.out: $(objpfx)tst-allocate_once.out
|
||||
$(common-objpfx)malloc/mtrace $(objpfx)tst-allocate_once.mtrace > $@; \
|
||||
$(evaluate-test)
|
||||
+
|
||||
+$(objpfx)tst-gethostid: $(libdl)
|
||||
diff --git a/misc/tst-gethostid.c b/misc/tst-gethostid.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..1490aaf3f517ff1d
|
||||
--- /dev/null
|
||||
+++ b/misc/tst-gethostid.c
|
||||
@@ -0,0 +1,108 @@
|
||||
+/* Basic test for gethostid.
|
||||
+ Copyright (C) 2018 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <gnu/lib-names.h>
|
||||
+#include <nss.h>
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
+#include <support/namespace.h>
|
||||
+#include <support/support.h>
|
||||
+#include <support/temp_file.h>
|
||||
+#include <support/xdlfcn.h>
|
||||
+#include <support/xstdio.h>
|
||||
+#include <support/xunistd.h>
|
||||
+#include <unistd.h>
|
||||
+
|
||||
+/* Initial test is run outside a chroot, to increase the likelihood of
|
||||
+ success. */
|
||||
+static void
|
||||
+outside_chroot (void *closure)
|
||||
+{
|
||||
+ long id = gethostid ();
|
||||
+ printf ("info: host ID outside chroot: 0x%lx\n", id);
|
||||
+}
|
||||
+
|
||||
+/* The same, but this time perform a chroot operation. */
|
||||
+static void
|
||||
+in_chroot (void *closure)
|
||||
+{
|
||||
+ const char *chroot_path = closure;
|
||||
+ xchroot (chroot_path);
|
||||
+ long id = gethostid ();
|
||||
+ printf ("info: host ID in chroot: 0x%lx\n", id);
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ support_isolate_in_subprocess (outside_chroot, NULL);
|
||||
+
|
||||
+ /* Now run the test inside a chroot. */
|
||||
+ support_become_root ();
|
||||
+ if (!support_can_chroot ())
|
||||
+ /* Cannot perform further tests. */
|
||||
+ return 0;
|
||||
+
|
||||
+ /* Only use nss_files. */
|
||||
+ __nss_configure_lookup ("hosts", "files");
|
||||
+
|
||||
+ /* Load the DSO outside of the chroot. */
|
||||
+ xdlopen (LIBNSS_FILES_SO, RTLD_LAZY);
|
||||
+
|
||||
+ char *chroot_dir = support_create_temp_directory ("tst-gethostid-");
|
||||
+ support_isolate_in_subprocess (in_chroot, chroot_dir);
|
||||
+
|
||||
+ /* Tests with /etc/hosts in the chroot. */
|
||||
+ {
|
||||
+ char *path = xasprintf ("%s/etc", chroot_dir);
|
||||
+ add_temp_file (path);
|
||||
+ xmkdir (path, 0777);
|
||||
+ free (path);
|
||||
+ path = xasprintf ("%s/etc/hosts", chroot_dir);
|
||||
+ add_temp_file (path);
|
||||
+
|
||||
+ FILE *fp = xfopen (path, "w");
|
||||
+ xfclose (fp);
|
||||
+ printf ("info: chroot test with an empty /etc/hosts file\n");
|
||||
+ support_isolate_in_subprocess (in_chroot, chroot_dir);
|
||||
+
|
||||
+ char hostname[1024];
|
||||
+ int ret = gethostname (hostname, sizeof (hostname));
|
||||
+ if (ret < 0)
|
||||
+ printf ("warning: invalid result from gethostname: %d\n", ret);
|
||||
+ else if (strlen (hostname) == 0)
|
||||
+ puts ("warning: gethostname returned empty string");
|
||||
+ else
|
||||
+ {
|
||||
+ printf ("info: chroot test with IPv6 address in /etc/hosts for: %s\n",
|
||||
+ hostname);
|
||||
+ fp = xfopen (path, "w");
|
||||
+ /* Use an IPv6 address to induce another lookup failure. */
|
||||
+ fprintf (fp, "2001:db8::1 %s\n", hostname);
|
||||
+ xfclose (fp);
|
||||
+ support_isolate_in_subprocess (in_chroot, chroot_dir);
|
||||
+ }
|
||||
+ free (path);
|
||||
+ }
|
||||
+ free (chroot_dir);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
108
SOURCES/glibc-rh1631722.patch
Normal file
108
SOURCES/glibc-rh1631722.patch
Normal file
@ -0,0 +1,108 @@
|
||||
commit 0ef2f4400c06927af34c515555f68840a70ba409
|
||||
Author: Wilco Dijkstra <wdijkstr@arm.com>
|
||||
Date: Wed Sep 19 16:50:18 2018 +0100
|
||||
|
||||
Fix strstr bug with huge needles (bug 23637)
|
||||
|
||||
The generic strstr in GLIBC 2.28 fails to match huge needles. The optimized
|
||||
AVAILABLE macro reads ahead a large fixed amount to reduce the overhead of
|
||||
repeatedly checking for the end of the string. However if the needle length
|
||||
is larger than this, two_way_long_needle may confuse this as meaning the end
|
||||
of the string and return NULL. This is fixed by adding the needle length to
|
||||
the amount to read ahead.
|
||||
|
||||
[BZ #23637]
|
||||
* string/test-strstr.c (pr23637): New function.
|
||||
(test_main): Add tests with longer needles.
|
||||
* string/strcasestr.c (AVAILABLE): Fix readahead distance.
|
||||
* string/strstr.c (AVAILABLE): Likewise.
|
||||
|
||||
(cherry picked from commit 83a552b0bb9fc2a5e80a0ab3723c0a80ce1db9f2)
|
||||
|
||||
diff --git a/string/strcasestr.c b/string/strcasestr.c
|
||||
index 5909fe3cdba88e47..421764bd1b0ff22e 100644
|
||||
--- a/string/strcasestr.c
|
||||
+++ b/string/strcasestr.c
|
||||
@@ -37,8 +37,9 @@
|
||||
/* Two-Way algorithm. */
|
||||
#define RETURN_TYPE char *
|
||||
#define AVAILABLE(h, h_l, j, n_l) \
|
||||
- (((j) + (n_l) <= (h_l)) || ((h_l) += __strnlen ((void*)((h) + (h_l)), 512), \
|
||||
- (j) + (n_l) <= (h_l)))
|
||||
+ (((j) + (n_l) <= (h_l)) \
|
||||
+ || ((h_l) += __strnlen ((void*)((h) + (h_l)), (n_l) + 512), \
|
||||
+ (j) + (n_l) <= (h_l)))
|
||||
#define CHECK_EOL (1)
|
||||
#define RET0_IF_0(a) if (!a) goto ret0
|
||||
#define CANON_ELEMENT(c) TOLOWER (c)
|
||||
diff --git a/string/strstr.c b/string/strstr.c
|
||||
index 265e9f310ce507ce..79ebcc75329d0b17 100644
|
||||
--- a/string/strstr.c
|
||||
+++ b/string/strstr.c
|
||||
@@ -33,8 +33,9 @@
|
||||
|
||||
#define RETURN_TYPE char *
|
||||
#define AVAILABLE(h, h_l, j, n_l) \
|
||||
- (((j) + (n_l) <= (h_l)) || ((h_l) += __strnlen ((void*)((h) + (h_l)), 512), \
|
||||
- (j) + (n_l) <= (h_l)))
|
||||
+ (((j) + (n_l) <= (h_l)) \
|
||||
+ || ((h_l) += __strnlen ((void*)((h) + (h_l)), (n_l) + 512), \
|
||||
+ (j) + (n_l) <= (h_l)))
|
||||
#define CHECK_EOL (1)
|
||||
#define RET0_IF_0(a) if (!a) goto ret0
|
||||
#define FASTSEARCH(S,C,N) (void*) strchr ((void*)(S), (C))
|
||||
diff --git a/string/test-strstr.c b/string/test-strstr.c
|
||||
index 8d99716ff39cc2c2..5861b01b73e4c315 100644
|
||||
--- a/string/test-strstr.c
|
||||
+++ b/string/test-strstr.c
|
||||
@@ -151,6 +151,32 @@ check2 (void)
|
||||
}
|
||||
}
|
||||
|
||||
+#define N 1024
|
||||
+
|
||||
+static void
|
||||
+pr23637 (void)
|
||||
+{
|
||||
+ char *h = (char*) buf1;
|
||||
+ char *n = (char*) buf2;
|
||||
+
|
||||
+ for (int i = 0; i < N; i++)
|
||||
+ {
|
||||
+ n[i] = 'x';
|
||||
+ h[i] = ' ';
|
||||
+ h[i + N] = 'x';
|
||||
+ }
|
||||
+
|
||||
+ n[N] = '\0';
|
||||
+ h[N * 2] = '\0';
|
||||
+
|
||||
+ /* Ensure we don't match at the first 'x'. */
|
||||
+ h[0] = 'x';
|
||||
+
|
||||
+ char *exp_result = stupid_strstr (h, n);
|
||||
+ FOR_EACH_IMPL (impl, 0)
|
||||
+ check_result (impl, h, n, exp_result);
|
||||
+}
|
||||
+
|
||||
static int
|
||||
test_main (void)
|
||||
{
|
||||
@@ -158,6 +184,7 @@ test_main (void)
|
||||
|
||||
check1 ();
|
||||
check2 ();
|
||||
+ pr23637 ();
|
||||
|
||||
printf ("%23s", "");
|
||||
FOR_EACH_IMPL (impl, 0)
|
||||
@@ -202,6 +229,9 @@ test_main (void)
|
||||
do_test (15, 9, hlen, klen, 1);
|
||||
do_test (15, 15, hlen, klen, 0);
|
||||
do_test (15, 15, hlen, klen, 1);
|
||||
+
|
||||
+ do_test (15, 15, hlen + klen * 4, klen * 4, 0);
|
||||
+ do_test (15, 15, hlen + klen * 4, klen * 4, 1);
|
||||
}
|
||||
|
||||
do_test (0, 0, page_size - 1, 16, 0);
|
82
SOURCES/glibc-rh1631730.patch
Normal file
82
SOURCES/glibc-rh1631730.patch
Normal file
@ -0,0 +1,82 @@
|
||||
commit 2339d6a55eb7a7e040ae888e906adc49eeb59eab
|
||||
Author: H.J. Lu <hjl.tools@gmail.com>
|
||||
Date: Wed Sep 12 08:40:59 2018 -0700
|
||||
|
||||
i386: Use ENTRY and END in start.S [BZ #23606]
|
||||
|
||||
Wrapping the _start function with ENTRY and END to insert ENDBR32 at
|
||||
function entry when CET is enabled. Since _start now includes CFI,
|
||||
without "cfi_undefined (eip)", unwinder may not terminate at _start
|
||||
and we will get
|
||||
|
||||
Program received signal SIGSEGV, Segmentation fault.
|
||||
0xf7dc661e in ?? () from /lib/libgcc_s.so.1
|
||||
Missing separate debuginfos, use: dnf debuginfo-install libgcc-8.2.1-3.0.fc28.i686
|
||||
(gdb) bt
|
||||
#0 0xf7dc661e in ?? () from /lib/libgcc_s.so.1
|
||||
#1 0xf7dc7c18 in _Unwind_Backtrace () from /lib/libgcc_s.so.1
|
||||
#2 0xf7f0d809 in __GI___backtrace (array=array@entry=0xffffc7d0,
|
||||
size=size@entry=20) at ../sysdeps/i386/backtrace.c:127
|
||||
#3 0x08049254 in compare (p1=p1@entry=0xffffcad0, p2=p2@entry=0xffffcad4)
|
||||
at backtrace-tst.c:12
|
||||
#4 0xf7e2a28c in msort_with_tmp (p=p@entry=0xffffca5c, b=b@entry=0xffffcad0,
|
||||
n=n@entry=2) at msort.c:65
|
||||
#5 0xf7e29f64 in msort_with_tmp (n=2, b=0xffffcad0, p=0xffffca5c)
|
||||
at msort.c:53
|
||||
#6 msort_with_tmp (p=p@entry=0xffffca5c, b=b@entry=0xffffcad0, n=n@entry=5)
|
||||
at msort.c:53
|
||||
#7 0xf7e29f64 in msort_with_tmp (n=5, b=0xffffcad0, p=0xffffca5c)
|
||||
at msort.c:53
|
||||
#8 msort_with_tmp (p=p@entry=0xffffca5c, b=b@entry=0xffffcad0, n=n@entry=10)
|
||||
at msort.c:53
|
||||
#9 0xf7e29f64 in msort_with_tmp (n=10, b=0xffffcad0, p=0xffffca5c)
|
||||
at msort.c:53
|
||||
#10 msort_with_tmp (p=p@entry=0xffffca5c, b=b@entry=0xffffcad0, n=n@entry=20)
|
||||
at msort.c:53
|
||||
#11 0xf7e2a5b6 in msort_with_tmp (n=20, b=0xffffcad0, p=0xffffca5c)
|
||||
at msort.c:297
|
||||
#12 __GI___qsort_r (b=b@entry=0xffffcad0, n=n@entry=20, s=s@entry=4,
|
||||
cmp=cmp@entry=0x8049230 <compare>, arg=arg@entry=0x0) at msort.c:297
|
||||
#13 0xf7e2a84d in __GI_qsort (b=b@entry=0xffffcad0, n=n@entry=20, s=s@entry=4,
|
||||
cmp=cmp@entry=0x8049230 <compare>) at msort.c:308
|
||||
#14 0x080490f6 in main (argc=2, argv=0xffffcbd4) at backtrace-tst.c:39
|
||||
|
||||
FAIL: debug/backtrace-tst
|
||||
|
||||
[BZ #23606]
|
||||
* sysdeps/i386/start.S: Include <sysdep.h>
|
||||
(_start): Use ENTRY/END to insert ENDBR32 at entry when CET is
|
||||
enabled. Add cfi_undefined (eip).
|
||||
|
||||
Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
|
||||
|
||||
(cherry picked from commit 5a274db4ea363d6b0b92933f085a92daaf1be2f2)
|
||||
|
||||
diff --git a/sysdeps/i386/start.S b/sysdeps/i386/start.S
|
||||
index 91035fa83fb7ee38..e35e9bd31b2cea30 100644
|
||||
--- a/sysdeps/i386/start.S
|
||||
+++ b/sysdeps/i386/start.S
|
||||
@@ -52,10 +52,11 @@
|
||||
NULL
|
||||
*/
|
||||
|
||||
- .text
|
||||
- .globl _start
|
||||
- .type _start,@function
|
||||
-_start:
|
||||
+#include <sysdep.h>
|
||||
+
|
||||
+ENTRY (_start)
|
||||
+ /* Clearing frame pointer is insufficient, use CFI. */
|
||||
+ cfi_undefined (eip)
|
||||
/* Clear the frame pointer. The ABI suggests this be done, to mark
|
||||
the outermost frame obviously. */
|
||||
xorl %ebp, %ebp
|
||||
@@ -131,6 +132,7 @@ _start:
|
||||
1: movl (%esp), %ebx
|
||||
ret
|
||||
#endif
|
||||
+END (_start)
|
||||
|
||||
/* To fulfill the System V/i386 ABI we need this symbol. Yuck, it's so
|
||||
meaningless since we don't support machines < 80386. */
|
483
SOURCES/glibc-rh1635779.patch
Normal file
483
SOURCES/glibc-rh1635779.patch
Normal file
@ -0,0 +1,483 @@
|
||||
commit e5d262effe3a87164308a3f37e61b32d0348692a
|
||||
Author: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com>
|
||||
Date: Fri Nov 30 18:05:32 2018 -0200
|
||||
|
||||
Fix _dl_profile_fixup data-dependency issue (Bug 23690)
|
||||
|
||||
There is a data-dependency between the fields of struct l_reloc_result
|
||||
and the field used as the initialization guard. Users of the guard
|
||||
expect writes to the structure to be observable when they also observe
|
||||
the guard initialized. The solution for this problem is to use an acquire
|
||||
and release load and store to ensure previous writes to the structure are
|
||||
observable if the guard is initialized.
|
||||
|
||||
The previous implementation used DL_FIXUP_VALUE_ADDR (l_reloc_result->addr)
|
||||
as the initialization guard, making it impossible for some architectures
|
||||
to load and store it atomically, i.e. hppa and ia64, due to its larger size.
|
||||
|
||||
This commit adds an unsigned int to l_reloc_result to be used as the new
|
||||
initialization guard of the struct, making it possible to load and store
|
||||
it atomically in all architectures. The fix ensures that the values
|
||||
observed in l_reloc_result are consistent and do not lead to crashes.
|
||||
The algorithm is documented in the code in elf/dl-runtime.c
|
||||
(_dl_profile_fixup). Not all data races have been eliminated.
|
||||
|
||||
Tested with build-many-glibcs and on powerpc, powerpc64, and powerpc64le.
|
||||
|
||||
[BZ #23690]
|
||||
* elf/dl-runtime.c (_dl_profile_fixup): Guarantee memory
|
||||
modification order when accessing reloc_result->addr.
|
||||
* include/link.h (reloc_result): Add field init.
|
||||
* nptl/Makefile (tests): Add tst-audit-threads.
|
||||
(modules-names): Add tst-audit-threads-mod1 and
|
||||
tst-audit-threads-mod2.
|
||||
Add rules to build tst-audit-threads.
|
||||
* nptl/tst-audit-threads-mod1.c: New file.
|
||||
* nptl/tst-audit-threads-mod2.c: Likewise.
|
||||
* nptl/tst-audit-threads.c: Likewise.
|
||||
* nptl/tst-audit-threads.h: Likewise.
|
||||
|
||||
Signed-off-by: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com>
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||
|
||||
diff --git a/elf/dl-runtime.c b/elf/dl-runtime.c
|
||||
index 63bbc89776..3d2f4a7a76 100644
|
||||
--- a/elf/dl-runtime.c
|
||||
+++ b/elf/dl-runtime.c
|
||||
@@ -183,10 +183,36 @@ _dl_profile_fixup (
|
||||
/* This is the address in the array where we store the result of previous
|
||||
relocations. */
|
||||
struct reloc_result *reloc_result = &l->l_reloc_result[reloc_index];
|
||||
- DL_FIXUP_VALUE_TYPE *resultp = &reloc_result->addr;
|
||||
|
||||
- DL_FIXUP_VALUE_TYPE value = *resultp;
|
||||
- if (DL_FIXUP_VALUE_CODE_ADDR (value) == 0)
|
||||
+ /* CONCURRENCY NOTES:
|
||||
+
|
||||
+ Multiple threads may be calling the same PLT sequence and with
|
||||
+ LD_AUDIT enabled they will be calling into _dl_profile_fixup to
|
||||
+ update the reloc_result with the result of the lazy resolution.
|
||||
+ The reloc_result guard variable is reloc_init, and we use
|
||||
+ acquire/release loads and store to it to ensure that the results of
|
||||
+ the structure are consistent with the loaded value of the guard.
|
||||
+ This does not fix all of the data races that occur when two or more
|
||||
+ threads read reloc_result->reloc_init with a value of zero and read
|
||||
+ and write to that reloc_result concurrently. The expectation is
|
||||
+ generally that while this is a data race it works because the
|
||||
+ threads write the same values. Until the data races are fixed
|
||||
+ there is a potential for problems to arise from these data races.
|
||||
+ The reloc result updates should happen in parallel but there should
|
||||
+ be an atomic RMW which does the final update to the real result
|
||||
+ entry (see bug 23790).
|
||||
+
|
||||
+ The following code uses reloc_result->init set to 0 to indicate if it is
|
||||
+ the first time this object is being relocated, otherwise 1 which
|
||||
+ indicates the object has already been relocated.
|
||||
+
|
||||
+ Reading/Writing from/to reloc_result->reloc_init must not happen
|
||||
+ before previous writes to reloc_result complete as they could
|
||||
+ end-up with an incomplete struct. */
|
||||
+ DL_FIXUP_VALUE_TYPE value;
|
||||
+ unsigned int init = atomic_load_acquire (&reloc_result->init);
|
||||
+
|
||||
+ if (init == 0)
|
||||
{
|
||||
/* This is the first time we have to relocate this object. */
|
||||
const ElfW(Sym) *const symtab
|
||||
@@ -346,19 +372,31 @@ _dl_profile_fixup (
|
||||
|
||||
/* Store the result for later runs. */
|
||||
if (__glibc_likely (! GLRO(dl_bind_not)))
|
||||
- *resultp = value;
|
||||
+ {
|
||||
+ reloc_result->addr = value;
|
||||
+ /* Guarantee all previous writes complete before
|
||||
+ init is updated. See CONCURRENCY NOTES earlier */
|
||||
+ atomic_store_release (&reloc_result->init, 1);
|
||||
+ }
|
||||
+ init = 1;
|
||||
}
|
||||
+ else
|
||||
+ value = reloc_result->addr;
|
||||
|
||||
/* By default we do not call the pltexit function. */
|
||||
long int framesize = -1;
|
||||
|
||||
+
|
||||
#ifdef SHARED
|
||||
/* Auditing checkpoint: report the PLT entering and allow the
|
||||
auditors to change the value. */
|
||||
- if (DL_FIXUP_VALUE_CODE_ADDR (value) != 0 && GLRO(dl_naudit) > 0
|
||||
+ if (GLRO(dl_naudit) > 0
|
||||
/* Don't do anything if no auditor wants to intercept this call. */
|
||||
&& (reloc_result->enterexit & LA_SYMB_NOPLTENTER) == 0)
|
||||
{
|
||||
+ /* Sanity check: DL_FIXUP_VALUE_CODE_ADDR (value) should have been
|
||||
+ initialized earlier in this function or in another thread. */
|
||||
+ assert (DL_FIXUP_VALUE_CODE_ADDR (value) != 0);
|
||||
ElfW(Sym) *defsym = ((ElfW(Sym) *) D_PTR (reloc_result->bound,
|
||||
l_info[DT_SYMTAB])
|
||||
+ reloc_result->boundndx);
|
||||
diff --git a/include/link.h b/include/link.h
|
||||
index 5924594548..83b1c34b7b 100644
|
||||
--- a/include/link.h
|
||||
+++ b/include/link.h
|
||||
@@ -216,6 +216,10 @@ struct link_map
|
||||
unsigned int boundndx;
|
||||
uint32_t enterexit;
|
||||
unsigned int flags;
|
||||
+ /* CONCURRENCY NOTE: This is used to guard the concurrent initialization
|
||||
+ of the relocation result across multiple threads. See the more
|
||||
+ detailed notes in elf/dl-runtime.c. */
|
||||
+ unsigned int init;
|
||||
} *l_reloc_result;
|
||||
|
||||
/* Pointer to the version information if available. */
|
||||
diff --git a/nptl/Makefile b/nptl/Makefile
|
||||
index 982e43adfa..98b0aa01c7 100644
|
||||
--- a/nptl/Makefile
|
||||
+++ b/nptl/Makefile
|
||||
@@ -382,7 +382,8 @@ tests += tst-cancelx2 tst-cancelx3 tst-cancelx4 tst-cancelx5 \
|
||||
tst-cleanupx0 tst-cleanupx1 tst-cleanupx2 tst-cleanupx3 tst-cleanupx4 \
|
||||
tst-oncex3 tst-oncex4
|
||||
ifeq ($(build-shared),yes)
|
||||
-tests += tst-atfork2 tst-tls4 tst-_res1 tst-fini1 tst-compat-forwarder
|
||||
+tests += tst-atfork2 tst-tls4 tst-_res1 tst-fini1 tst-compat-forwarder \
|
||||
+ tst-audit-threads
|
||||
tests-internal += tst-tls3 tst-tls3-malloc tst-tls5 tst-stackguard1
|
||||
tests-nolibpthread += tst-fini1
|
||||
ifeq ($(have-z-execstack),yes)
|
||||
@@ -394,7 +395,8 @@ 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-stack4mod \
|
||||
tst-_res1mod1 tst-_res1mod2 tst-execstack-mod tst-fini1mod \
|
||||
- tst-join7mod tst-compat-forwarder-mod
|
||||
+ tst-join7mod tst-compat-forwarder-mod tst-audit-threads-mod1 \
|
||||
+ tst-audit-threads-mod2
|
||||
extra-test-objs += $(addsuffix .os,$(strip $(modules-names))) \
|
||||
tst-cleanup4aux.o tst-cleanupx4aux.o
|
||||
test-extras += tst-cleanup4aux tst-cleanupx4aux
|
||||
@@ -712,6 +714,14 @@ $(objpfx)tst-compat-forwarder: $(objpfx)tst-compat-forwarder-mod.so
|
||||
|
||||
tst-mutex10-ENV = GLIBC_TUNABLES=glibc.elision.enable=1
|
||||
|
||||
+# Protect against a build using -Wl,-z,now.
|
||||
+LDFLAGS-tst-audit-threads-mod1.so = -Wl,-z,lazy
|
||||
+LDFLAGS-tst-audit-threads-mod2.so = -Wl,-z,lazy
|
||||
+LDFLAGS-tst-audit-threads = -Wl,-z,lazy
|
||||
+$(objpfx)tst-audit-threads: $(objpfx)tst-audit-threads-mod2.so
|
||||
+$(objpfx)tst-audit-threads.out: $(objpfx)tst-audit-threads-mod1.so
|
||||
+tst-audit-threads-ENV = LD_AUDIT=$(objpfx)tst-audit-threads-mod1.so
|
||||
+
|
||||
# The tests here better do not run in parallel
|
||||
ifneq ($(filter %tests,$(MAKECMDGOALS)),)
|
||||
.NOTPARALLEL:
|
||||
diff --git a/nptl/tst-audit-threads-mod1.c b/nptl/tst-audit-threads-mod1.c
|
||||
new file mode 100644
|
||||
index 0000000000..615d5ee512
|
||||
--- /dev/null
|
||||
+++ b/nptl/tst-audit-threads-mod1.c
|
||||
@@ -0,0 +1,74 @@
|
||||
+/* Dummy audit library for test-audit-threads.
|
||||
+
|
||||
+ Copyright (C) 2018 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <elf.h>
|
||||
+#include <link.h>
|
||||
+#include <stdio.h>
|
||||
+#include <assert.h>
|
||||
+#include <string.h>
|
||||
+
|
||||
+/* We must use a dummy LD_AUDIT module to force the dynamic loader to
|
||||
+ *not* update the real PLT, and instead use a cached value for the
|
||||
+ lazy resolution result. It is the update of that cached value that
|
||||
+ we are testing for correctness by doing this. */
|
||||
+
|
||||
+/* Library to be audited. */
|
||||
+#define LIB "tst-audit-threads-mod2.so"
|
||||
+/* CALLNUM is the number of retNum functions. */
|
||||
+#define CALLNUM 7999
|
||||
+
|
||||
+#define CONCATX(a, b) __CONCAT (a, b)
|
||||
+
|
||||
+static int previous = 0;
|
||||
+
|
||||
+unsigned int
|
||||
+la_version (unsigned int ver)
|
||||
+{
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+unsigned int
|
||||
+la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie)
|
||||
+{
|
||||
+ return LA_FLG_BINDTO | LA_FLG_BINDFROM;
|
||||
+}
|
||||
+
|
||||
+uintptr_t
|
||||
+CONCATX(la_symbind, __ELF_NATIVE_CLASS) (ElfW(Sym) *sym,
|
||||
+ unsigned int ndx,
|
||||
+ uintptr_t *refcook,
|
||||
+ uintptr_t *defcook,
|
||||
+ unsigned int *flags,
|
||||
+ const char *symname)
|
||||
+{
|
||||
+ const char * retnum = "retNum";
|
||||
+ char * num = strstr (symname, retnum);
|
||||
+ int n;
|
||||
+ /* Validate if the symbols are getting called in the correct order.
|
||||
+ This code is here to verify binutils does not optimize out the PLT
|
||||
+ entries that require the symbol binding. */
|
||||
+ if (num != NULL)
|
||||
+ {
|
||||
+ n = atoi (num);
|
||||
+ assert (n >= previous);
|
||||
+ assert (n <= CALLNUM);
|
||||
+ previous = n;
|
||||
+ }
|
||||
+ return sym->st_value;
|
||||
+}
|
||||
diff --git a/nptl/tst-audit-threads-mod2.c b/nptl/tst-audit-threads-mod2.c
|
||||
new file mode 100644
|
||||
index 0000000000..f9817dd3dc
|
||||
--- /dev/null
|
||||
+++ b/nptl/tst-audit-threads-mod2.c
|
||||
@@ -0,0 +1,22 @@
|
||||
+/* Shared object with a huge number of functions for test-audit-threads.
|
||||
+
|
||||
+ Copyright (C) 2018 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+/* Define all the retNumN functions in a library. */
|
||||
+#define definenum
|
||||
+#include "tst-audit-threads.h"
|
||||
diff --git a/nptl/tst-audit-threads.c b/nptl/tst-audit-threads.c
|
||||
new file mode 100644
|
||||
index 0000000000..e4bf433bd8
|
||||
--- /dev/null
|
||||
+++ b/nptl/tst-audit-threads.c
|
||||
@@ -0,0 +1,97 @@
|
||||
+/* Test multi-threading using LD_AUDIT.
|
||||
+
|
||||
+ Copyright (C) 2018 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+/* This test uses a dummy LD_AUDIT library (test-audit-threads-mod1) and a
|
||||
+ library with a huge number of functions in order to validate lazy symbol
|
||||
+ binding with an audit library. We use one thread per CPU to test that
|
||||
+ concurrent lazy resolution does not have any defects which would cause
|
||||
+ the process to fail. We use an LD_AUDIT library to force the testing of
|
||||
+ the relocation resolution caching code in the dynamic loader i.e.
|
||||
+ _dl_runtime_profile and _dl_profile_fixup. */
|
||||
+
|
||||
+#include <support/xthread.h>
|
||||
+#include <strings.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <sys/sysinfo.h>
|
||||
+
|
||||
+static int do_test (void);
|
||||
+
|
||||
+/* This test usually takes less than 3s to run. However, there are cases that
|
||||
+ take up to 30s. */
|
||||
+#define TIMEOUT 60
|
||||
+#define TEST_FUNCTION do_test ()
|
||||
+#include "../test-skeleton.c"
|
||||
+
|
||||
+/* Declare the functions we are going to call. */
|
||||
+#define externnum
|
||||
+#include "tst-audit-threads.h"
|
||||
+#undef externnum
|
||||
+
|
||||
+int num_threads;
|
||||
+pthread_barrier_t barrier;
|
||||
+
|
||||
+void
|
||||
+sync_all (int num)
|
||||
+{
|
||||
+ pthread_barrier_wait (&barrier);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+call_all_ret_nums (void)
|
||||
+{
|
||||
+ /* Call each function one at a time from all threads. */
|
||||
+#define callnum
|
||||
+#include "tst-audit-threads.h"
|
||||
+#undef callnum
|
||||
+}
|
||||
+
|
||||
+void *
|
||||
+thread_main (void *unused)
|
||||
+{
|
||||
+ call_all_ret_nums ();
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+#define STR2(X) #X
|
||||
+#define STR(X) STR2(X)
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ int i;
|
||||
+ pthread_t *threads;
|
||||
+
|
||||
+ num_threads = get_nprocs ();
|
||||
+ if (num_threads <= 1)
|
||||
+ num_threads = 2;
|
||||
+
|
||||
+ /* Used to synchronize all the threads after calling each retNumN. */
|
||||
+ xpthread_barrier_init (&barrier, NULL, num_threads);
|
||||
+
|
||||
+ threads = (pthread_t *) xcalloc (num_threads, sizeof(pthread_t));
|
||||
+ for (i = 0; i < num_threads; i++)
|
||||
+ threads[i] = xpthread_create(NULL, thread_main, NULL);
|
||||
+
|
||||
+ for (i = 0; i < num_threads; i++)
|
||||
+ xpthread_join(threads[i]);
|
||||
+
|
||||
+ free (threads);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
diff --git a/nptl/tst-audit-threads.h b/nptl/tst-audit-threads.h
|
||||
new file mode 100644
|
||||
index 0000000000..1c9ecc08df
|
||||
--- /dev/null
|
||||
+++ b/nptl/tst-audit-threads.h
|
||||
@@ -0,0 +1,92 @@
|
||||
+/* Helper header for test-audit-threads.
|
||||
+
|
||||
+ Copyright (C) 2018 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+/* We use this helper to create a large number of functions, all of
|
||||
+ which will be resolved lazily and thus have their PLT updated.
|
||||
+ This is done to provide enough functions that we can statistically
|
||||
+ observe a thread vs. PLT resolution failure if one exists. */
|
||||
+
|
||||
+#define CONCAT(a, b) a ## b
|
||||
+#define NUM(x, y) CONCAT (x, y)
|
||||
+
|
||||
+#define FUNC10(x) \
|
||||
+ FUNC (NUM (x, 0)); \
|
||||
+ FUNC (NUM (x, 1)); \
|
||||
+ FUNC (NUM (x, 2)); \
|
||||
+ FUNC (NUM (x, 3)); \
|
||||
+ FUNC (NUM (x, 4)); \
|
||||
+ FUNC (NUM (x, 5)); \
|
||||
+ FUNC (NUM (x, 6)); \
|
||||
+ FUNC (NUM (x, 7)); \
|
||||
+ FUNC (NUM (x, 8)); \
|
||||
+ FUNC (NUM (x, 9))
|
||||
+
|
||||
+#define FUNC100(x) \
|
||||
+ FUNC10 (NUM (x, 0)); \
|
||||
+ FUNC10 (NUM (x, 1)); \
|
||||
+ FUNC10 (NUM (x, 2)); \
|
||||
+ FUNC10 (NUM (x, 3)); \
|
||||
+ FUNC10 (NUM (x, 4)); \
|
||||
+ FUNC10 (NUM (x, 5)); \
|
||||
+ FUNC10 (NUM (x, 6)); \
|
||||
+ FUNC10 (NUM (x, 7)); \
|
||||
+ FUNC10 (NUM (x, 8)); \
|
||||
+ FUNC10 (NUM (x, 9))
|
||||
+
|
||||
+#define FUNC1000(x) \
|
||||
+ FUNC100 (NUM (x, 0)); \
|
||||
+ FUNC100 (NUM (x, 1)); \
|
||||
+ FUNC100 (NUM (x, 2)); \
|
||||
+ FUNC100 (NUM (x, 3)); \
|
||||
+ FUNC100 (NUM (x, 4)); \
|
||||
+ FUNC100 (NUM (x, 5)); \
|
||||
+ FUNC100 (NUM (x, 6)); \
|
||||
+ FUNC100 (NUM (x, 7)); \
|
||||
+ FUNC100 (NUM (x, 8)); \
|
||||
+ FUNC100 (NUM (x, 9))
|
||||
+
|
||||
+#define FUNC7000() \
|
||||
+ FUNC1000 (1); \
|
||||
+ FUNC1000 (2); \
|
||||
+ FUNC1000 (3); \
|
||||
+ FUNC1000 (4); \
|
||||
+ FUNC1000 (5); \
|
||||
+ FUNC1000 (6); \
|
||||
+ FUNC1000 (7);
|
||||
+
|
||||
+#ifdef FUNC
|
||||
+# undef FUNC
|
||||
+#endif
|
||||
+
|
||||
+#ifdef externnum
|
||||
+# define FUNC(x) extern int CONCAT (retNum, x) (void)
|
||||
+#endif
|
||||
+
|
||||
+#ifdef definenum
|
||||
+# define FUNC(x) int CONCAT (retNum, x) (void) { return x; }
|
||||
+#endif
|
||||
+
|
||||
+#ifdef callnum
|
||||
+# define FUNC(x) CONCAT (retNum, x) (); sync_all (x)
|
||||
+#endif
|
||||
+
|
||||
+/* A value of 7000 functions is chosen as an arbitrarily large
|
||||
+ number of functions that will allow us enough attempts to
|
||||
+ verify lazy resolution operation. */
|
||||
+FUNC7000 ();
|
35
SOURCES/glibc-rh1638520.patch
Normal file
35
SOURCES/glibc-rh1638520.patch
Normal file
@ -0,0 +1,35 @@
|
||||
commit ed643089cd3251038863d32e67ec47b94cd557f3
|
||||
Author: Szabolcs Nagy <szabolcs.nagy@arm.com>
|
||||
Date: Tue Oct 9 14:31:28 2018 +0100
|
||||
|
||||
Increase timeout of libio/tst-readline
|
||||
|
||||
Increase timeout from the default 20s to 100s. This test makes close to
|
||||
20 million syscalls with distribution:
|
||||
|
||||
12327675 read
|
||||
4143204 lseek
|
||||
929475 close
|
||||
929471 openat
|
||||
92817 fstat
|
||||
1431 write
|
||||
...
|
||||
|
||||
The default timeout assumes each can finish in 1us on average which
|
||||
is not true on slow machines.
|
||||
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||
|
||||
* libio/tst-readline.c (TIMEOUT): Define.
|
||||
|
||||
diff --git a/libio/tst-readline.c b/libio/tst-readline.c
|
||||
index 9322ef68da5e38a9..63f5227760d88c63 100644
|
||||
--- a/libio/tst-readline.c
|
||||
+++ b/libio/tst-readline.c
|
||||
@@ -232,5 +232,6 @@ do_test (void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+#define TIMEOUT 100
|
||||
#define PREPARE prepare
|
||||
#include <support/test-driver.c>
|
2823
SOURCES/glibc-rh1638523-1.patch
Normal file
2823
SOURCES/glibc-rh1638523-1.patch
Normal file
File diff suppressed because it is too large
Load Diff
80
SOURCES/glibc-rh1638523-2.patch
Normal file
80
SOURCES/glibc-rh1638523-2.patch
Normal file
@ -0,0 +1,80 @@
|
||||
commit 6c3a8a9d868a8deddf0d6dcc785b6d120de90523
|
||||
Author: Paul Pluzhnikov <ppluzhnikov@kazbek.mtv.corp.google.com>
|
||||
Date: Fri Aug 24 18:08:51 2018 -0700
|
||||
|
||||
Fix BZ#23400 (creating temporary files in source tree), and undefined behavior in test.
|
||||
|
||||
diff --git a/stdlib/test-bz22786.c b/stdlib/test-bz22786.c
|
||||
index e7837f98c19fc4bf..d1aa69106ccf6ac5 100644
|
||||
--- a/stdlib/test-bz22786.c
|
||||
+++ b/stdlib/test-bz22786.c
|
||||
@@ -26,28 +26,20 @@
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
+#include <support/check.h>
|
||||
+#include <support/support.h>
|
||||
+#include <support/temp_file.h>
|
||||
#include <support/test-driver.h>
|
||||
#include <libc-diag.h>
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
- const char dir[] = "bz22786";
|
||||
- const char lnk[] = "bz22786/symlink";
|
||||
+ const char *dir = support_create_temp_directory ("bz22786.");
|
||||
+ const char *lnk = xasprintf ("%s/symlink", dir);
|
||||
+ const size_t path_len = (size_t) INT_MAX + strlen (lnk) + 1;
|
||||
|
||||
- rmdir (dir);
|
||||
- if (mkdir (dir, 0755) != 0 && errno != EEXIST)
|
||||
- {
|
||||
- printf ("mkdir %s: %m\n", dir);
|
||||
- return EXIT_FAILURE;
|
||||
- }
|
||||
- if (symlink (".", lnk) != 0 && errno != EEXIST)
|
||||
- {
|
||||
- printf ("symlink (%s, %s): %m\n", dir, lnk);
|
||||
- return EXIT_FAILURE;
|
||||
- }
|
||||
-
|
||||
- const size_t path_len = (size_t) INT_MAX + 1;
|
||||
+ TEST_VERIFY_EXIT (symlink (".", lnk) == 0);
|
||||
|
||||
DIAG_PUSH_NEEDS_COMMENT;
|
||||
#if __GNUC_PREREQ (7, 0)
|
||||
@@ -55,20 +47,14 @@ do_test (void)
|
||||
allocation to succeed for the test to work. */
|
||||
DIAG_IGNORE_NEEDS_COMMENT (7, "-Walloc-size-larger-than=");
|
||||
#endif
|
||||
- char *path = malloc (path_len);
|
||||
+ char *path = xmalloc (path_len);
|
||||
DIAG_POP_NEEDS_COMMENT;
|
||||
|
||||
- if (path == NULL)
|
||||
- {
|
||||
- printf ("malloc (%zu): %m\n", path_len);
|
||||
- return EXIT_UNSUPPORTED;
|
||||
- }
|
||||
-
|
||||
- /* Construct very long path = "bz22786/symlink/aaaa....." */
|
||||
- char *p = mempcpy (path, lnk, sizeof (lnk) - 1);
|
||||
+ /* Construct very long path = "/tmp/bz22786.XXXX/symlink/aaaa....." */
|
||||
+ char *p = mempcpy (path, lnk, strlen (lnk));
|
||||
*(p++) = '/';
|
||||
- memset (p, 'a', path_len - (path - p) - 2);
|
||||
- p[path_len - (path - p) - 1] = '\0';
|
||||
+ memset (p, 'a', path_len - (p - path) - 2);
|
||||
+ p[path_len - (p - path) - 1] = '\0';
|
||||
|
||||
/* This call crashes before the fix for bz22786 on 32-bit platforms. */
|
||||
p = realpath (path, NULL);
|
||||
@@ -81,7 +67,6 @@ do_test (void)
|
||||
|
||||
/* Cleanup. */
|
||||
unlink (lnk);
|
||||
- rmdir (dir);
|
||||
|
||||
return 0;
|
||||
}
|
55
SOURCES/glibc-rh1638523-3.patch
Normal file
55
SOURCES/glibc-rh1638523-3.patch
Normal file
@ -0,0 +1,55 @@
|
||||
commit 3bad2358d67d371497079bba4f8eca9c0096f4e2
|
||||
Author: Stefan Liebler <stli@linux.ibm.com>
|
||||
Date: Thu Aug 30 08:44:32 2018 +0200
|
||||
|
||||
Test stdlib/test-bz22786 exits now with unsupported if malloc fails.
|
||||
|
||||
The test tries to allocate more than 2^31 bytes which will always fail on s390
|
||||
as it has maximum 2^31bit of memory.
|
||||
Before commit 6c3a8a9d868a8deddf0d6dcc785b6d120de90523, this test returned
|
||||
unsupported if malloc fails. This patch re enables this behaviour.
|
||||
|
||||
Furthermore support_delete_temp_files() failed to remove the temp directory
|
||||
in this case as it is not empty due to the created symlink.
|
||||
Thus the creation of the symlink is moved behind malloc.
|
||||
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||
|
||||
ChangeLog:
|
||||
|
||||
* stdlib/test-bz22786.c (do_test): Return EXIT_UNSUPPORTED
|
||||
if malloc fails.
|
||||
|
||||
diff --git a/stdlib/test-bz22786.c b/stdlib/test-bz22786.c
|
||||
index d1aa69106ccf6ac5..777bf9180f4b5022 100644
|
||||
--- a/stdlib/test-bz22786.c
|
||||
+++ b/stdlib/test-bz22786.c
|
||||
@@ -39,16 +39,25 @@ do_test (void)
|
||||
const char *lnk = xasprintf ("%s/symlink", dir);
|
||||
const size_t path_len = (size_t) INT_MAX + strlen (lnk) + 1;
|
||||
|
||||
- TEST_VERIFY_EXIT (symlink (".", lnk) == 0);
|
||||
-
|
||||
DIAG_PUSH_NEEDS_COMMENT;
|
||||
#if __GNUC_PREREQ (7, 0)
|
||||
/* GCC 7 warns about too-large allocations; here we need such
|
||||
allocation to succeed for the test to work. */
|
||||
DIAG_IGNORE_NEEDS_COMMENT (7, "-Walloc-size-larger-than=");
|
||||
#endif
|
||||
- char *path = xmalloc (path_len);
|
||||
+ char *path = malloc (path_len);
|
||||
DIAG_POP_NEEDS_COMMENT;
|
||||
+ if (path == NULL)
|
||||
+ {
|
||||
+ printf ("malloc (%zu): %m\n", path_len);
|
||||
+ /* On 31-bit s390 the malloc will always fail as we do not have
|
||||
+ so much memory, and we want to mark the test unsupported.
|
||||
+ Likewise on systems with little physical memory the test will
|
||||
+ fail and should be unsupported. */
|
||||
+ return EXIT_UNSUPPORTED;
|
||||
+ }
|
||||
+
|
||||
+ TEST_VERIFY_EXIT (symlink (".", lnk) == 0);
|
||||
|
||||
/* Construct very long path = "/tmp/bz22786.XXXX/symlink/aaaa....." */
|
||||
char *p = mempcpy (path, lnk, strlen (lnk));
|
65
SOURCES/glibc-rh1638523-4.patch
Normal file
65
SOURCES/glibc-rh1638523-4.patch
Normal file
@ -0,0 +1,65 @@
|
||||
commit f5e7e95921847bd83186bfe621fc2b48c4de5477
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Oct 30 13:11:47 2018 +0100
|
||||
|
||||
stdlib/test-bz22786: Avoid spurious test failures using alias mappings
|
||||
|
||||
On systems without enough random-access memory, stdlib/test-bz22786
|
||||
will go deeply into swap and time out, even with a substantial
|
||||
TIMEOUTFACTOR. This commit adds a facility to construct repeating
|
||||
strings with alias mappings, so that the requirement for physical
|
||||
memory, and uses it in stdlib/test-bz22786.
|
||||
|
||||
Adjusted here for conflicts due to the previous support/ backport in
|
||||
glibc-rh1638523-1.patch.
|
||||
|
||||
diff --git a/stdlib/test-bz22786.c b/stdlib/test-bz22786.c
|
||||
index 777bf9180f4b5022..bb1e04f2debe9042 100644
|
||||
--- a/stdlib/test-bz22786.c
|
||||
+++ b/stdlib/test-bz22786.c
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
+#include <support/blob_repeat.h>
|
||||
#include <support/check.h>
|
||||
#include <support/support.h>
|
||||
#include <support/temp_file.h>
|
||||
@@ -39,17 +40,12 @@ do_test (void)
|
||||
const char *lnk = xasprintf ("%s/symlink", dir);
|
||||
const size_t path_len = (size_t) INT_MAX + strlen (lnk) + 1;
|
||||
|
||||
- DIAG_PUSH_NEEDS_COMMENT;
|
||||
-#if __GNUC_PREREQ (7, 0)
|
||||
- /* GCC 7 warns about too-large allocations; here we need such
|
||||
- allocation to succeed for the test to work. */
|
||||
- DIAG_IGNORE_NEEDS_COMMENT (7, "-Walloc-size-larger-than=");
|
||||
-#endif
|
||||
- char *path = malloc (path_len);
|
||||
- DIAG_POP_NEEDS_COMMENT;
|
||||
+ struct support_blob_repeat repeat
|
||||
+ = support_blob_repeat_allocate ("a", 1, path_len);
|
||||
+ char *path = repeat.start;
|
||||
if (path == NULL)
|
||||
{
|
||||
- printf ("malloc (%zu): %m\n", path_len);
|
||||
+ printf ("Repeated allocation (%zu bytes): %m\n", path_len);
|
||||
/* On 31-bit s390 the malloc will always fail as we do not have
|
||||
so much memory, and we want to mark the test unsupported.
|
||||
Likewise on systems with little physical memory the test will
|
||||
@@ -62,7 +58,6 @@ do_test (void)
|
||||
/* Construct very long path = "/tmp/bz22786.XXXX/symlink/aaaa....." */
|
||||
char *p = mempcpy (path, lnk, strlen (lnk));
|
||||
*(p++) = '/';
|
||||
- memset (p, 'a', path_len - (p - path) - 2);
|
||||
p[path_len - (p - path) - 1] = '\0';
|
||||
|
||||
/* This call crashes before the fix for bz22786 on 32-bit platforms. */
|
||||
@@ -76,6 +71,7 @@ do_test (void)
|
||||
|
||||
/* Cleanup. */
|
||||
unlink (lnk);
|
||||
+ support_blob_repeat_free (&repeat);
|
||||
|
||||
return 0;
|
||||
}
|
51
SOURCES/glibc-rh1638523-5.patch
Normal file
51
SOURCES/glibc-rh1638523-5.patch
Normal file
@ -0,0 +1,51 @@
|
||||
commit 07da99aad93c9364acb7efdab47c27ba698f6313
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Oct 30 13:55:01 2018 +0100
|
||||
|
||||
stdlib/tst-strtod-overflow: Switch to support_blob_repeat
|
||||
|
||||
This is another test with an avoidable large memory allocation.
|
||||
|
||||
diff --git a/stdlib/tst-strtod-overflow.c b/stdlib/tst-strtod-overflow.c
|
||||
index d14638d68ef4f471..dc53c1e521443e1d 100644
|
||||
--- a/stdlib/tst-strtod-overflow.c
|
||||
+++ b/stdlib/tst-strtod-overflow.c
|
||||
@@ -19,6 +19,8 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
+#include <support/blob_repeat.h>
|
||||
+#include <support/test-driver.h>
|
||||
|
||||
#define EXPONENT "e-2147483649"
|
||||
#define SIZE 214748364
|
||||
@@ -26,21 +28,23 @@
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
- char *p = malloc (1 + SIZE + sizeof (EXPONENT));
|
||||
- if (p == NULL)
|
||||
+ struct support_blob_repeat repeat = support_blob_repeat_allocate
|
||||
+ ("0", 1, 1 + SIZE + sizeof (EXPONENT));
|
||||
+ if (repeat.size == 0)
|
||||
{
|
||||
- puts ("malloc failed, cannot test for overflow");
|
||||
- return 0;
|
||||
+ puts ("warning: memory allocation failed, cannot test for overflow");
|
||||
+ return EXIT_UNSUPPORTED;
|
||||
}
|
||||
+ char *p = repeat.start;
|
||||
p[0] = '1';
|
||||
- memset (p + 1, '0', SIZE);
|
||||
memcpy (p + 1 + SIZE, EXPONENT, sizeof (EXPONENT));
|
||||
double d = strtod (p, NULL);
|
||||
if (d != 0)
|
||||
{
|
||||
- printf ("strtod returned wrong value: %a\n", d);
|
||||
+ printf ("error: strtod returned wrong value: %a\n", d);
|
||||
return 1;
|
||||
}
|
||||
+ support_blob_repeat_free (&repeat);
|
||||
return 0;
|
||||
}
|
||||
|
30
SOURCES/glibc-rh1638523-6.patch
Normal file
30
SOURCES/glibc-rh1638523-6.patch
Normal file
@ -0,0 +1,30 @@
|
||||
commit 60708030536df82616c16aa2f14f533c4362b969
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Oct 30 13:56:40 2018 +0100
|
||||
|
||||
stdlib/test-bz22786: Avoid memory leaks in the test itself
|
||||
|
||||
diff --git a/stdlib/test-bz22786.c b/stdlib/test-bz22786.c
|
||||
index bb1e04f2debe9042..8035e8a394e7d034 100644
|
||||
--- a/stdlib/test-bz22786.c
|
||||
+++ b/stdlib/test-bz22786.c
|
||||
@@ -36,8 +36,8 @@
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
- const char *dir = support_create_temp_directory ("bz22786.");
|
||||
- const char *lnk = xasprintf ("%s/symlink", dir);
|
||||
+ char *dir = support_create_temp_directory ("bz22786.");
|
||||
+ char *lnk = xasprintf ("%s/symlink", dir);
|
||||
const size_t path_len = (size_t) INT_MAX + strlen (lnk) + 1;
|
||||
|
||||
struct support_blob_repeat repeat
|
||||
@@ -72,6 +72,8 @@ do_test (void)
|
||||
/* Cleanup. */
|
||||
unlink (lnk);
|
||||
support_blob_repeat_free (&repeat);
|
||||
+ free (lnk);
|
||||
+ free (dir);
|
||||
|
||||
return 0;
|
||||
}
|
35
SOURCES/glibc-rh1639343-1.patch
Normal file
35
SOURCES/glibc-rh1639343-1.patch
Normal file
@ -0,0 +1,35 @@
|
||||
commit f9b645b4b0a10c43753296ce3fa40053fa44606a
|
||||
Author: Mike Frysinger <vapier@gentoo.org>
|
||||
Date: Wed Apr 24 13:32:22 2019 +0200
|
||||
|
||||
memusagestat: use local glibc when linking [BZ #18465]
|
||||
|
||||
The memusagestat is the only binary that has its own link line which
|
||||
causes it to be linked against the existing installed C library. It
|
||||
has been this way since it was originally committed in 1999, but I
|
||||
don't see any reason as to why. Since we want all the programs we
|
||||
build locally to be against the new copy of glibc, change the build
|
||||
to be like all other programs.
|
||||
|
||||
diff --git a/malloc/Makefile b/malloc/Makefile
|
||||
index 388cf7e9ee3a2569..228a1279a5960d8c 100644
|
||||
--- a/malloc/Makefile
|
||||
+++ b/malloc/Makefile
|
||||
@@ -131,6 +131,7 @@ ifneq ($(cross-compiling),yes)
|
||||
# If the gd library is available we build the `memusagestat' program.
|
||||
ifneq ($(LIBGD),no)
|
||||
others: $(objpfx)memusage
|
||||
+others += memusagestat
|
||||
install-bin = memusagestat
|
||||
install-bin-script += memusage
|
||||
generated += memusagestat memusage
|
||||
@@ -154,8 +155,7 @@ cpp-srcs-left := $(memusagestat-modules)
|
||||
lib := memusagestat
|
||||
include $(patsubst %,$(..)libof-iterator.mk,$(cpp-srcs-left))
|
||||
|
||||
-$(objpfx)memusagestat: $(memusagestat-modules:%=$(objpfx)%.o)
|
||||
- $(LINK.o) -o $@ $^ $(libgd-LDFLAGS) -lgd -lpng -lz -lm
|
||||
+LDLIBS-memusagestat = $(libgd-LDFLAGS) -lgd -lpng -lz -lm
|
||||
|
||||
ifeq ($(run-built-tests),yes)
|
||||
ifeq (yes,$(build-shared))
|
90
SOURCES/glibc-rh1639343-2.patch
Normal file
90
SOURCES/glibc-rh1639343-2.patch
Normal file
@ -0,0 +1,90 @@
|
||||
commit 94a4e9e4f401ffe829a992820439977ead0a0ce7
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Thu Apr 25 10:41:43 2019 +0200
|
||||
|
||||
Extend BIND_NOW to installed programs with --enable-bind-now
|
||||
|
||||
Commit 2d6ab5df3b675e96ee587ae6a8c2ce004c6b1ba9 ("Document and fix
|
||||
--enable-bind-now [BZ #21015]") extended BIND_NOW to all installed
|
||||
shared objects. This change also covers installed programs.
|
||||
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||
|
||||
diff --git a/INSTALL b/INSTALL
|
||||
index d6c8e899fbb47dac..d56e102ec9ed3281 100644
|
||||
--- a/INSTALL
|
||||
+++ b/INSTALL
|
||||
@@ -169,10 +169,10 @@ if 'CFLAGS' is specified it must enable optimization. For example:
|
||||
protection.
|
||||
|
||||
'--enable-bind-now'
|
||||
- Disable lazy binding for installed shared objects. This provides
|
||||
- additional security hardening because it enables full RELRO and a
|
||||
- read-only global offset table (GOT), at the cost of slightly
|
||||
- increased program load times.
|
||||
+ Disable lazy binding for installed shared objects and programs.
|
||||
+ This provides additional security hardening because it enables full
|
||||
+ RELRO and a read-only global offset table (GOT), at the cost of
|
||||
+ slightly increased program load times.
|
||||
|
||||
'--enable-pt_chown'
|
||||
The file 'pt_chown' is a helper binary for 'grantpt' (*note
|
||||
diff --git a/Makeconfig b/Makeconfig
|
||||
index 8dc2fec9dc683416..742c0c0783a14bfa 100644
|
||||
--- a/Makeconfig
|
||||
+++ b/Makeconfig
|
||||
@@ -398,6 +398,8 @@ endif
|
||||
# test modules.
|
||||
ifeq ($(bind-now),yes)
|
||||
LDFLAGS-lib.so += -Wl,-z,now
|
||||
+# Extra flags for dynamically linked non-test main programs.
|
||||
+link-extra-flags += -Wl,-z,now
|
||||
endif
|
||||
|
||||
# Command to run after every final link (executable or shared object).
|
||||
@@ -426,7 +428,7 @@ ifndef +link-pie
|
||||
$(link-extra-libs)
|
||||
+link-pie-after-libc = $(+postctorS) $(+postinit)
|
||||
define +link-pie
|
||||
-$(+link-pie-before-libc) $(rtld-LDFLAGS) $(link-libc) $(+link-pie-after-libc)
|
||||
+$(+link-pie-before-libc) $(rtld-LDFLAGS) $(link-extra-flags) $(link-libc) $(+link-pie-after-libc)
|
||||
$(call after-link,$@)
|
||||
endef
|
||||
define +link-pie-tests
|
||||
@@ -454,7 +456,7 @@ ifndef +link-static
|
||||
$(link-extra-libs-static)
|
||||
+link-static-after-libc = $(+postctorT) $(+postinit)
|
||||
define +link-static
|
||||
-$(+link-static-before-libc) $(link-libc-static) $(+link-static-after-libc)
|
||||
+$(+link-static-before-libc) $(link-extra-flags) $(link-libc-static) $(+link-static-after-libc)
|
||||
$(call after-link,$@)
|
||||
endef
|
||||
define +link-static-tests
|
||||
@@ -485,7 +487,7 @@ else # not build-pie-default
|
||||
$(link-extra-libs)
|
||||
+link-after-libc = $(+postctor) $(+postinit)
|
||||
define +link
|
||||
-$(+link-before-libc) $(rtld-LDFLAGS) $(link-libc) $(+link-after-libc)
|
||||
+$(+link-before-libc) $(rtld-LDFLAGS) $(link-extra-flags) $(link-libc) $(+link-after-libc)
|
||||
$(call after-link,$@)
|
||||
endef
|
||||
define +link-tests
|
||||
diff --git a/manual/install.texi b/manual/install.texi
|
||||
index e757891dc2eebb2e..351d67c68b255f62 100644
|
||||
--- a/manual/install.texi
|
||||
+++ b/manual/install.texi
|
||||
@@ -199,10 +199,10 @@ number of routines called directly from assembler are excluded from this
|
||||
protection.
|
||||
|
||||
@item --enable-bind-now
|
||||
-Disable lazy binding for installed shared objects. This provides
|
||||
-additional security hardening because it enables full RELRO and a
|
||||
-read-only global offset table (GOT), at the cost of slightly increased
|
||||
-program load times.
|
||||
+Disable lazy binding for installed shared objects and programs. This
|
||||
+provides additional security hardening because it enables full RELRO
|
||||
+and a read-only global offset table (GOT), at the cost of slightly
|
||||
+increased program load times.
|
||||
|
||||
@pindex pt_chown
|
||||
@findex grantpt
|
43
SOURCES/glibc-rh1639343-3.patch
Normal file
43
SOURCES/glibc-rh1639343-3.patch
Normal file
@ -0,0 +1,43 @@
|
||||
commit b5ffdc48c20ae865b197b67e5a9068a528fbc198
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Thu Apr 25 10:41:52 2019 +0200
|
||||
|
||||
benchtests: Enable BIND_NOW if configured with --enable-bind-now
|
||||
|
||||
Benchmarks should reflect distribution build policies, so it makes
|
||||
sense to honor the BIND_NOW configuration for them.
|
||||
|
||||
This commit keeps using $(+link-tests), so that the benchmarks are
|
||||
linked according to the --enable-hardcoded-path-in-tests configure
|
||||
option.
|
||||
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||
|
||||
diff --git a/benchtests/Makefile b/benchtests/Makefile
|
||||
index bcd6a9c26d9a0005..28d6b0c43f5bd390 100644
|
||||
--- a/benchtests/Makefile
|
||||
+++ b/benchtests/Makefile
|
||||
@@ -235,13 +235,21 @@ bench-func: $(binaries-bench)
|
||||
scripts/benchout.schema.json; \
|
||||
fi
|
||||
|
||||
-$(timing-type) $(binaries-bench) $(binaries-benchset) \
|
||||
- $(binaries-bench-malloc): %: %.o $(objpfx)json-lib.o \
|
||||
+ifeq ($(bind-now),yes)
|
||||
+link-bench-bind-now = -Wl,-z,now
|
||||
+endif
|
||||
+
|
||||
+bench-link-targets = $(timing-type) $(binaries-bench) $(binaries-benchset) \
|
||||
+ $(binaries-bench-malloc)
|
||||
+
|
||||
+$(bench-link-targets): %: %.o $(objpfx)json-lib.o \
|
||||
$(link-extra-libs-tests) \
|
||||
$(sort $(filter $(common-objpfx)lib%,$(link-libc))) \
|
||||
$(addprefix $(csu-objpfx),start.o) $(+preinit) $(+postinit)
|
||||
$(+link-tests)
|
||||
|
||||
+$(bench-link-targets): LDFLAGS += $(link-bench-bind-now)
|
||||
+
|
||||
$(objpfx)bench-%.c: %-inputs $(bench-deps)
|
||||
{ if [ -n "$($*-INCLUDE)" ]; then \
|
||||
cat $($*-INCLUDE); \
|
100
SOURCES/glibc-rh1639343-4.patch
Normal file
100
SOURCES/glibc-rh1639343-4.patch
Normal file
@ -0,0 +1,100 @@
|
||||
commit e30fb31c0ad8d31babd1d0d0f05e37c6579a870b
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Fri Apr 26 07:16:47 2019 +0200
|
||||
|
||||
Makeconfig: Move $(CC) to +link command variables
|
||||
|
||||
This change is needed to add linker flags which come very early in the
|
||||
command linke (before LDFLAGS) and are not applied to test programs
|
||||
(only to installed programs).
|
||||
|
||||
diff --git a/Makeconfig b/Makeconfig
|
||||
index 742c0c0783a14bfa..1ad25fc5a7251aea 100644
|
||||
--- a/Makeconfig
|
||||
+++ b/Makeconfig
|
||||
@@ -415,7 +415,7 @@ link-extra-libs-tests = $(libsupport)
|
||||
|
||||
# Command for linking PIE programs with the C library.
|
||||
ifndef +link-pie
|
||||
-+link-pie-before-libc = $(CC) $(if $($(@F)-no-pie),$(no-pie-ldflag),-pie) \
|
||||
++link-pie-before-libc = $(if $($(@F)-no-pie),$(no-pie-ldflag),-pie) \
|
||||
-Wl,-O1 -nostdlib -nostartfiles -o $@ \
|
||||
$(sysdep-LDFLAGS) $(LDFLAGS) $(LDFLAGS-$(@F)) \
|
||||
$(combreloc-LDFLAGS) $(relro-LDFLAGS) $(hashstyle-LDFLAGS) \
|
||||
@@ -428,23 +428,24 @@ ifndef +link-pie
|
||||
$(link-extra-libs)
|
||||
+link-pie-after-libc = $(+postctorS) $(+postinit)
|
||||
define +link-pie
|
||||
-$(+link-pie-before-libc) $(rtld-LDFLAGS) $(link-extra-flags) $(link-libc) $(+link-pie-after-libc)
|
||||
+$(CC) $(+link-pie-before-libc) $(rtld-LDFLAGS) $(link-extra-flags) \
|
||||
+ $(link-libc) $(+link-pie-after-libc)
|
||||
$(call after-link,$@)
|
||||
endef
|
||||
define +link-pie-tests
|
||||
-$(+link-pie-before-libc) $(rtld-tests-LDFLAGS) $(link-libc-tests) \
|
||||
- $(+link-pie-after-libc)
|
||||
+$(CC) $(+link-pie-before-libc) $(rtld-tests-LDFLAGS) $(link-libc-tests) \
|
||||
+ $(+link-pie-after-libc)
|
||||
$(call after-link,$@)
|
||||
endef
|
||||
define +link-pie-printers-tests
|
||||
-$(+link-pie-before-libc) $(built-rtld-LDFLAGS) $(link-libc-printers-tests) \
|
||||
- $(+link-pie-after-libc)
|
||||
+$(CC) $(+link-pie-before-libc) $(built-rtld-LDFLAGS) \
|
||||
+ $(link-libc-printers-tests) $(+link-pie-after-libc)
|
||||
$(call after-link,$@)
|
||||
endef
|
||||
endif
|
||||
# Command for statically linking programs with the C library.
|
||||
ifndef +link-static
|
||||
-+link-static-before-libc = $(CC) -nostdlib -nostartfiles -static -o $@ \
|
||||
++link-static-before-libc = -nostdlib -nostartfiles -static -o $@ \
|
||||
$(if $($(@F)-no-pie),$(no-pie-ldflag),$(default-pie-ldflag)) \
|
||||
$(sysdep-LDFLAGS) $(LDFLAGS) $(LDFLAGS-$(@F)) \
|
||||
$(firstword $(CRT-$(@F)) $(csu-objpfx)$(real-static-start-installed-name)) \
|
||||
@@ -456,11 +457,13 @@ ifndef +link-static
|
||||
$(link-extra-libs-static)
|
||||
+link-static-after-libc = $(+postctorT) $(+postinit)
|
||||
define +link-static
|
||||
-$(+link-static-before-libc) $(link-extra-flags) $(link-libc-static) $(+link-static-after-libc)
|
||||
+$(CC) $(+link-static-before-libc) $(link-extra-flags) $(link-libc-static) \
|
||||
+ $(+link-static-after-libc)
|
||||
$(call after-link,$@)
|
||||
endef
|
||||
define +link-static-tests
|
||||
-$(+link-static-before-libc) $(link-libc-static-tests) $(+link-static-after-libc)
|
||||
+$(CC) $(+link-static-before-libc) $(link-libc-static-tests) \
|
||||
+ $(+link-static-after-libc)
|
||||
$(call after-link,$@)
|
||||
endef
|
||||
endif
|
||||
@@ -475,7 +478,7 @@ ifeq (yes,$(build-pie-default))
|
||||
+link-tests = $(+link-pie-tests)
|
||||
+link-printers-tests = $(+link-pie-printers-tests)
|
||||
else # not build-pie-default
|
||||
-+link-before-libc = $(CC) -nostdlib -nostartfiles -o $@ \
|
||||
++link-before-libc = -nostdlib -nostartfiles -o $@ \
|
||||
$(sysdep-LDFLAGS) $(LDFLAGS) $(LDFLAGS-$(@F)) \
|
||||
$(combreloc-LDFLAGS) $(relro-LDFLAGS) $(hashstyle-LDFLAGS) \
|
||||
$(firstword $(CRT-$(@F)) $(csu-objpfx)$(start-installed-name)) \
|
||||
@@ -487,16 +490,17 @@ else # not build-pie-default
|
||||
$(link-extra-libs)
|
||||
+link-after-libc = $(+postctor) $(+postinit)
|
||||
define +link
|
||||
-$(+link-before-libc) $(rtld-LDFLAGS) $(link-extra-flags) $(link-libc) $(+link-after-libc)
|
||||
+$(CC) $(+link-before-libc) $(rtld-LDFLAGS) $(link-extra-flags) $(link-libc) \
|
||||
+ $(+link-after-libc)
|
||||
$(call after-link,$@)
|
||||
endef
|
||||
define +link-tests
|
||||
-$(+link-before-libc) $(rtld-tests-LDFLAGS) $(link-libc-tests) \
|
||||
+$(CC) $(+link-before-libc) $(rtld-tests-LDFLAGS) $(link-libc-tests) \
|
||||
$(+link-after-libc)
|
||||
$(call after-link,$@)
|
||||
endef
|
||||
define +link-printers-tests
|
||||
-$(+link-before-libc) $(built-rtld-LDFLAGS) $(link-libc-printers-tests) \
|
||||
+$(CC) $(+link-before-libc) $(built-rtld-LDFLAGS) $(link-libc-printers-tests) \
|
||||
$(+link-after-libc)
|
||||
$(call after-link,$@)
|
||||
endef
|
74
SOURCES/glibc-rh1639343-5.patch
Normal file
74
SOURCES/glibc-rh1639343-5.patch
Normal file
@ -0,0 +1,74 @@
|
||||
commit a8ff215e56050a907189e713fd449bcafe99ff6b
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Fri Apr 26 07:16:30 2019 +0200
|
||||
|
||||
Makeconfig: Move -Wl,-rpath-link options before library references
|
||||
|
||||
Previously, the -Wl,-rpath-link options came after the libraries
|
||||
injected using LDLIBS-* variables on the link editor command line for
|
||||
main programs. As a result, it could happen that installed libraries
|
||||
that reference glibc libraries used the installed glibc from the system
|
||||
directories, instead of the glibc from the build tree. This can lead to
|
||||
link failures if the wrong version of libpthread.so.0 is used, for
|
||||
instance, due to differences in the internal GLIBC_PRIVATE interfaces,
|
||||
as seen with memusagestat and -lgd after commit
|
||||
f9b645b4b0a10c43753296ce3fa40053fa44606a ("memusagestat: use local glibc
|
||||
when linking [BZ #18465]").
|
||||
|
||||
The isolation is necessarily imperfect because these installed
|
||||
libraries are linked against the installed glibc in the system
|
||||
directories. However, in most cases, the built glibc will be newer
|
||||
than the installed glibc, and this link is permitted because of the
|
||||
ABI backwards compatibility glibc provides.
|
||||
|
||||
diff --git a/Makeconfig b/Makeconfig
|
||||
index 1ad25fc5a7251aea..e315fb8a75ca5063 100644
|
||||
--- a/Makeconfig
|
||||
+++ b/Makeconfig
|
||||
@@ -428,8 +428,8 @@ ifndef +link-pie
|
||||
$(link-extra-libs)
|
||||
+link-pie-after-libc = $(+postctorS) $(+postinit)
|
||||
define +link-pie
|
||||
-$(CC) $(+link-pie-before-libc) $(rtld-LDFLAGS) $(link-extra-flags) \
|
||||
- $(link-libc) $(+link-pie-after-libc)
|
||||
+$(CC) $(link-libc-rpath-link) $(+link-pie-before-libc) $(rtld-LDFLAGS) \
|
||||
+ $(link-extra-flags) $(link-libc) $(+link-pie-after-libc)
|
||||
$(call after-link,$@)
|
||||
endef
|
||||
define +link-pie-tests
|
||||
@@ -490,8 +490,8 @@ else # not build-pie-default
|
||||
$(link-extra-libs)
|
||||
+link-after-libc = $(+postctor) $(+postinit)
|
||||
define +link
|
||||
-$(CC) $(+link-before-libc) $(rtld-LDFLAGS) $(link-extra-flags) $(link-libc) \
|
||||
- $(+link-after-libc)
|
||||
+$(CC) $(link-libc-rpath-link) $(+link-before-libc) $(rtld-LDFLAGS) \
|
||||
+ $(link-extra-flags) $(link-libc) $(+link-after-libc)
|
||||
$(call after-link,$@)
|
||||
endef
|
||||
define +link-tests
|
||||
@@ -552,6 +552,15 @@ ifeq (yes,$(build-shared))
|
||||
link-libc-rpath = -Wl,-rpath=$(rpath-link)
|
||||
link-libc-rpath-link = -Wl,-rpath-link=$(rpath-link)
|
||||
|
||||
+# For programs which are not tests, $(link-libc-rpath-link) is added
|
||||
+# directly in $(+link), $(+link-pie) above, so that -Wl,-rpath-link
|
||||
+# comes before the expansion of LDLIBS-* and affects libraries added
|
||||
+# there. For shared objects, -Wl,-rpath-link is added via
|
||||
+# $(build-shlib-helper) and $(build-module-helper) in Makerules (also
|
||||
+# before the expansion of LDLIBS-* variables).
|
||||
+
|
||||
+# Tests use -Wl,-rpath instead of -Wl,-rpath-link for
|
||||
+# build-hardcoded-path-in-tests.
|
||||
ifeq (yes,$(build-hardcoded-path-in-tests))
|
||||
link-libc-tests-rpath-link = $(link-libc-rpath)
|
||||
else
|
||||
@@ -562,7 +571,7 @@ link-libc-before-gnulib = $(common-objpfx)libc.so$(libc.so-version) \
|
||||
$(common-objpfx)$(patsubst %,$(libtype.oS),c) \
|
||||
$(as-needed) $(elf-objpfx)ld.so \
|
||||
$(no-as-needed)
|
||||
-link-libc = $(link-libc-rpath-link) $(link-libc-before-gnulib) $(gnulib)
|
||||
+link-libc = $(link-libc-before-gnulib) $(gnulib)
|
||||
|
||||
link-libc-tests-after-rpath-link = $(link-libc-before-gnulib) $(gnulib-tests)
|
||||
link-libc-tests = $(link-libc-tests-rpath-link) \
|
25
SOURCES/glibc-rh1639343-6.patch
Normal file
25
SOURCES/glibc-rh1639343-6.patch
Normal file
@ -0,0 +1,25 @@
|
||||
commit c57afec0a9b318bb691e0f5fa4e9681cf30df7a4
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Fri Apr 26 07:16:56 2019 +0200
|
||||
|
||||
elf: Link sotruss-lib.so with BIND_NOW for --enable-bind-now
|
||||
|
||||
The audit module itself can be linked with BIND_NOW; it does not
|
||||
affect its functionality.
|
||||
|
||||
This should complete the leftovers from commit
|
||||
2d6ab5df3b675e96ee587ae6a8c2ce004c6b1ba9 ("Document and fix
|
||||
--enable-bind-now [BZ #21015]").
|
||||
|
||||
diff --git a/elf/Makefile b/elf/Makefile
|
||||
index f5285b99e22fe84d..9194339836900b9d 100644
|
||||
--- a/elf/Makefile
|
||||
+++ b/elf/Makefile
|
||||
@@ -133,6 +133,7 @@ install-others += $(inst_auditdir)/sotruss-lib.so
|
||||
install-bin-script += sotruss
|
||||
generated += sotruss
|
||||
libof-sotruss-lib = extramodules
|
||||
+LDFLAGS-sotruss-lib.so += $(z-now-$(bind-now))
|
||||
$(objpfx)sotruss-lib.so: $(objpfx)sotruss-lib.os
|
||||
$(build-module-asneeded)
|
||||
$(objpfx)sotruss-lib.so: $(common-objpfx)libc.so $(objpfx)ld.so \
|
41
SOURCES/glibc-rh1641982.patch
Normal file
41
SOURCES/glibc-rh1641982.patch
Normal file
@ -0,0 +1,41 @@
|
||||
commit c3d8dc45c9df199b8334599a6cbd98c9950dba62
|
||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
Date: Thu Oct 11 15:18:40 2018 -0300
|
||||
|
||||
x86: Fix Haswell strong flags (BZ#23709)
|
||||
|
||||
Th commit 'Disable TSX on some Haswell processors.' (2702856bf4) changed the
|
||||
default flags for Haswell models. Previously, new models were handled by the
|
||||
default switch path, which assumed a Core i3/i5/i7 if AVX is available. After
|
||||
the patch, Haswell models (0x3f, 0x3c, 0x45, 0x46) do not set the flags
|
||||
Fast_Rep_String, Fast_Unaligned_Load, Fast_Unaligned_Copy, and
|
||||
Prefer_PMINUB_for_stringop (only the TSX one).
|
||||
|
||||
This patch fixes it by disentangle the TSX flag handling from the memory
|
||||
optimization ones. The strstr case cited on patch now selects the
|
||||
__strstr_sse2_unaligned as expected for the Haswell cpu.
|
||||
|
||||
Checked on x86_64-linux-gnu.
|
||||
|
||||
[BZ #23709]
|
||||
* sysdeps/x86/cpu-features.c (init_cpu_features): Set TSX bits
|
||||
independently of other flags.
|
||||
|
||||
diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c
|
||||
index ea0b64fdb962a934..4695ac80d4148327 100644
|
||||
--- a/sysdeps/x86/cpu-features.c
|
||||
+++ b/sysdeps/x86/cpu-features.c
|
||||
@@ -316,7 +316,13 @@ init_cpu_features (struct cpu_features *cpu_features)
|
||||
| bit_arch_Fast_Unaligned_Copy
|
||||
| bit_arch_Prefer_PMINUB_for_stringop);
|
||||
break;
|
||||
+ }
|
||||
|
||||
+ /* Disable TSX on some Haswell processors to avoid TSX on kernels that
|
||||
+ weren't updated with the latest microcode package (which disables
|
||||
+ broken feature by default). */
|
||||
+ switch (model)
|
||||
+ {
|
||||
case 0x3f:
|
||||
/* Xeon E7 v3 with stepping >= 4 has working TSX. */
|
||||
if (stepping >= 4)
|
230
SOURCES/glibc-rh1642094-1.patch
Normal file
230
SOURCES/glibc-rh1642094-1.patch
Normal file
@ -0,0 +1,230 @@
|
||||
commit bcdaad21d4635931d1bd3b54a7894276925d081d
|
||||
Author: DJ Delorie <dj@delorie.com>
|
||||
Date: Tue Nov 20 13:24:09 2018 -0500
|
||||
|
||||
malloc: tcache double free check
|
||||
|
||||
* malloc/malloc.c (tcache_entry): Add key field.
|
||||
(tcache_put): Set it.
|
||||
(tcache_get): Likewise.
|
||||
(_int_free): Check for double free in tcache.
|
||||
* malloc/tst-tcfree1.c: New.
|
||||
* malloc/tst-tcfree2.c: New.
|
||||
* malloc/Makefile: Run the new tests.
|
||||
* manual/probes.texi: Document memory_tcache_double_free probe.
|
||||
|
||||
* dlfcn/dlerror.c (check_free): Prevent double frees.
|
||||
|
||||
diff --git a/dlfcn/dlerror.c b/dlfcn/dlerror.c
|
||||
index 33574faab65628ff..96bf92533335036b 100644
|
||||
--- a/dlfcn/dlerror.c
|
||||
+++ b/dlfcn/dlerror.c
|
||||
@@ -198,7 +198,10 @@ check_free (struct dl_action_result *rec)
|
||||
Dl_info info;
|
||||
if (_dl_addr (check_free, &info, &map, NULL) != 0 && map->l_ns == 0)
|
||||
#endif
|
||||
- free ((char *) rec->errstring);
|
||||
+ {
|
||||
+ free ((char *) rec->errstring);
|
||||
+ rec->errstring = NULL;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/malloc/Makefile b/malloc/Makefile
|
||||
index 7d54bad866f63cb8..e6dfbfc14cb3d140 100644
|
||||
--- a/malloc/Makefile
|
||||
+++ b/malloc/Makefile
|
||||
@@ -38,6 +38,7 @@ tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \
|
||||
tst-malloc_info \
|
||||
tst-malloc-too-large \
|
||||
tst-malloc-stats-cancellation \
|
||||
+ tst-tcfree1 tst-tcfree2 \
|
||||
|
||||
tests-static := \
|
||||
tst-interpose-static-nothread \
|
||||
diff --git a/malloc/malloc.c b/malloc/malloc.c
|
||||
index e247c77b7d4de26e..c6b0282e783eaeea 100644
|
||||
--- a/malloc/malloc.c
|
||||
+++ b/malloc/malloc.c
|
||||
@@ -2888,6 +2888,8 @@ mremap_chunk (mchunkptr p, size_t new_size)
|
||||
typedef struct tcache_entry
|
||||
{
|
||||
struct tcache_entry *next;
|
||||
+ /* This field exists to detect double frees. */
|
||||
+ struct tcache_perthread_struct *key;
|
||||
} tcache_entry;
|
||||
|
||||
/* There is one of these for each thread, which contains the
|
||||
@@ -2911,6 +2913,11 @@ tcache_put (mchunkptr chunk, size_t tc_idx)
|
||||
{
|
||||
tcache_entry *e = (tcache_entry *) chunk2mem (chunk);
|
||||
assert (tc_idx < TCACHE_MAX_BINS);
|
||||
+
|
||||
+ /* Mark this chunk as "in the tcache" so the test in _int_free will
|
||||
+ detect a double free. */
|
||||
+ e->key = tcache;
|
||||
+
|
||||
e->next = tcache->entries[tc_idx];
|
||||
tcache->entries[tc_idx] = e;
|
||||
++(tcache->counts[tc_idx]);
|
||||
@@ -2926,6 +2933,7 @@ tcache_get (size_t tc_idx)
|
||||
assert (tcache->entries[tc_idx] > 0);
|
||||
tcache->entries[tc_idx] = e->next;
|
||||
--(tcache->counts[tc_idx]);
|
||||
+ e->key = NULL;
|
||||
return (void *) e;
|
||||
}
|
||||
|
||||
@@ -4152,6 +4160,26 @@ _int_free (mstate av, mchunkptr p, int have_lock)
|
||||
{
|
||||
size_t tc_idx = csize2tidx (size);
|
||||
|
||||
+ /* Check to see if it's already in the tcache. */
|
||||
+ tcache_entry *e = (tcache_entry *) chunk2mem (p);
|
||||
+
|
||||
+ /* This test succeeds on double free. However, we don't 100%
|
||||
+ trust it (it also matches random payload data at a 1 in
|
||||
+ 2^<size_t> chance), so verify it's not an unlikely coincidence
|
||||
+ before aborting. */
|
||||
+ if (__glibc_unlikely (e->key == tcache && tcache))
|
||||
+ {
|
||||
+ tcache_entry *tmp;
|
||||
+ LIBC_PROBE (memory_tcache_double_free, 2, e, tc_idx);
|
||||
+ for (tmp = tcache->entries[tc_idx];
|
||||
+ tmp;
|
||||
+ tmp = tmp->next)
|
||||
+ if (tmp == e)
|
||||
+ malloc_printerr ("free(): double free detected in tcache 2");
|
||||
+ /* If we get here, it was a coincidence. We've wasted a few
|
||||
+ cycles, but don't abort. */
|
||||
+ }
|
||||
+
|
||||
if (tcache
|
||||
&& tc_idx < mp_.tcache_bins
|
||||
&& tcache->counts[tc_idx] < mp_.tcache_count)
|
||||
diff --git a/malloc/tst-tcfree1.c b/malloc/tst-tcfree1.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..bc29375ce77304ac
|
||||
--- /dev/null
|
||||
+++ b/malloc/tst-tcfree1.c
|
||||
@@ -0,0 +1,42 @@
|
||||
+/* Test that malloc tcache catches double free.
|
||||
+ Copyright (C) 2018 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <errno.h>
|
||||
+#include <error.h>
|
||||
+#include <limits.h>
|
||||
+#include <malloc.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <stdio.h>
|
||||
+#include <sys/signal.h>
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ /* Do one allocation of any size that fits in tcache. */
|
||||
+ char * volatile x = malloc (32);
|
||||
+
|
||||
+ free (x); // puts in tcache
|
||||
+ free (x); // should abort
|
||||
+
|
||||
+ printf("FAIL: tcache double free not detected\n");
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+#define TEST_FUNCTION do_test
|
||||
+#define EXPECTED_SIGNAL SIGABRT
|
||||
+#include <support/test-driver.c>
|
||||
diff --git a/malloc/tst-tcfree2.c b/malloc/tst-tcfree2.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..17f06bacd411c315
|
||||
--- /dev/null
|
||||
+++ b/malloc/tst-tcfree2.c
|
||||
@@ -0,0 +1,48 @@
|
||||
+/* Test that malloc tcache catches double free.
|
||||
+ Copyright (C) 2018 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <errno.h>
|
||||
+#include <error.h>
|
||||
+#include <limits.h>
|
||||
+#include <malloc.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <stdio.h>
|
||||
+#include <sys/signal.h>
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ char * volatile ptrs[20];
|
||||
+ int i;
|
||||
+
|
||||
+ /* Allocate enough small chunks so that when we free them all, the tcache
|
||||
+ is full, and the first one we freed is at the end of its linked list. */
|
||||
+#define COUNT 20
|
||||
+ for (i=0; i<COUNT; i++)
|
||||
+ ptrs[i] = malloc (20);
|
||||
+ for (i=0; i<COUNT; i++)
|
||||
+ free (ptrs[i]);
|
||||
+ free (ptrs[0]);
|
||||
+
|
||||
+ printf("FAIL: tcache double free\n");
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+#define TEST_FUNCTION do_test
|
||||
+#define EXPECTED_SIGNAL SIGABRT
|
||||
+#include <support/test-driver.c>
|
||||
diff --git a/manual/probes.texi b/manual/probes.texi
|
||||
index ab2a3102bb350ef4..0ea560ed78bcfd7e 100644
|
||||
--- a/manual/probes.texi
|
||||
+++ b/manual/probes.texi
|
||||
@@ -243,6 +243,18 @@ This probe is triggered when the
|
||||
value of this tunable.
|
||||
@end deftp
|
||||
|
||||
+@deftp Probe memory_tcache_double_free (void *@var{$arg1}, int @var{$arg2})
|
||||
+This probe is triggered when @code{free} determines that the memory
|
||||
+being freed has probably already been freed, and resides in the
|
||||
+per-thread cache. Note that there is an extremely unlikely chance
|
||||
+that this probe will trigger due to random payload data remaining in
|
||||
+the allocated memory matching the key used to detect double frees.
|
||||
+This probe actually indicates that an expensive linear search of the
|
||||
+tcache, looking for a double free, has happened. Argument @var{$arg1}
|
||||
+is the memory location as passed to @code{free}, Argument @var{$arg2}
|
||||
+is the tcache bin it resides in.
|
||||
+@end deftp
|
||||
+
|
||||
@node Mathematical Function Probes
|
||||
@section Mathematical Function Probes
|
||||
|
73
SOURCES/glibc-rh1642094-2.patch
Normal file
73
SOURCES/glibc-rh1642094-2.patch
Normal file
@ -0,0 +1,73 @@
|
||||
commit affec03b713c82c43a5b025dddc21bde3334f41e
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Mon Nov 26 20:06:37 2018 +0100
|
||||
|
||||
malloc: tcache: Validate tc_idx before checking for double-frees [BZ #23907]
|
||||
|
||||
The previous check could read beyond the end of the tcache entry
|
||||
array. If the e->key == tcache cookie check happened to pass, this
|
||||
would result in crashes.
|
||||
|
||||
diff --git a/malloc/malloc.c b/malloc/malloc.c
|
||||
index c6b0282e783eaeea..13c52f376859562d 100644
|
||||
--- a/malloc/malloc.c
|
||||
+++ b/malloc/malloc.c
|
||||
@@ -4159,33 +4159,33 @@ _int_free (mstate av, mchunkptr p, int have_lock)
|
||||
#if USE_TCACHE
|
||||
{
|
||||
size_t tc_idx = csize2tidx (size);
|
||||
-
|
||||
- /* Check to see if it's already in the tcache. */
|
||||
- tcache_entry *e = (tcache_entry *) chunk2mem (p);
|
||||
-
|
||||
- /* This test succeeds on double free. However, we don't 100%
|
||||
- trust it (it also matches random payload data at a 1 in
|
||||
- 2^<size_t> chance), so verify it's not an unlikely coincidence
|
||||
- before aborting. */
|
||||
- if (__glibc_unlikely (e->key == tcache && tcache))
|
||||
+ if (tcache != NULL && tc_idx < mp_.tcache_bins)
|
||||
{
|
||||
- tcache_entry *tmp;
|
||||
- LIBC_PROBE (memory_tcache_double_free, 2, e, tc_idx);
|
||||
- for (tmp = tcache->entries[tc_idx];
|
||||
- tmp;
|
||||
- tmp = tmp->next)
|
||||
- if (tmp == e)
|
||||
- malloc_printerr ("free(): double free detected in tcache 2");
|
||||
- /* If we get here, it was a coincidence. We've wasted a few
|
||||
- cycles, but don't abort. */
|
||||
- }
|
||||
+ /* Check to see if it's already in the tcache. */
|
||||
+ tcache_entry *e = (tcache_entry *) chunk2mem (p);
|
||||
+
|
||||
+ /* This test succeeds on double free. However, we don't 100%
|
||||
+ trust it (it also matches random payload data at a 1 in
|
||||
+ 2^<size_t> chance), so verify it's not an unlikely
|
||||
+ coincidence before aborting. */
|
||||
+ if (__glibc_unlikely (e->key == tcache))
|
||||
+ {
|
||||
+ tcache_entry *tmp;
|
||||
+ LIBC_PROBE (memory_tcache_double_free, 2, e, tc_idx);
|
||||
+ for (tmp = tcache->entries[tc_idx];
|
||||
+ tmp;
|
||||
+ tmp = tmp->next)
|
||||
+ if (tmp == e)
|
||||
+ malloc_printerr ("free(): double free detected in tcache 2");
|
||||
+ /* If we get here, it was a coincidence. We've wasted a
|
||||
+ few cycles, but don't abort. */
|
||||
+ }
|
||||
|
||||
- if (tcache
|
||||
- && tc_idx < mp_.tcache_bins
|
||||
- && tcache->counts[tc_idx] < mp_.tcache_count)
|
||||
- {
|
||||
- tcache_put (p, tc_idx);
|
||||
- return;
|
||||
+ if (tcache->counts[tc_idx] < mp_.tcache_count)
|
||||
+ {
|
||||
+ tcache_put (p, tc_idx);
|
||||
+ return;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
#endif
|
89
SOURCES/glibc-rh1642094-3.patch
Normal file
89
SOURCES/glibc-rh1642094-3.patch
Normal file
@ -0,0 +1,89 @@
|
||||
commit 7c9a7c68363051cfc5fa1ebb96b3b2c1f82dcb76
|
||||
Author: DJ Delorie <dj@redhat.com>
|
||||
Date: Fri Nov 30 22:13:09 2018 -0500
|
||||
|
||||
malloc: Add another test for tcache double free check.
|
||||
|
||||
This one tests for BZ#23907 where the double free
|
||||
test didn't check the tcache bin bounds before dereferencing
|
||||
the bin.
|
||||
|
||||
[BZ #23907]
|
||||
* malloc/tst-tcfree3.c: New.
|
||||
* malloc/Makefile: Add it.
|
||||
|
||||
diff --git a/malloc/Makefile b/malloc/Makefile
|
||||
index e6dfbfc14cb3d140..388cf7e9ee3a2569 100644
|
||||
--- a/malloc/Makefile
|
||||
+++ b/malloc/Makefile
|
||||
@@ -38,7 +38,7 @@ tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \
|
||||
tst-malloc_info \
|
||||
tst-malloc-too-large \
|
||||
tst-malloc-stats-cancellation \
|
||||
- tst-tcfree1 tst-tcfree2 \
|
||||
+ tst-tcfree1 tst-tcfree2 tst-tcfree3 \
|
||||
|
||||
tests-static := \
|
||||
tst-interpose-static-nothread \
|
||||
diff --git a/malloc/tst-tcfree3.c b/malloc/tst-tcfree3.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..016d30ddd8114082
|
||||
--- /dev/null
|
||||
+++ b/malloc/tst-tcfree3.c
|
||||
@@ -0,0 +1,56 @@
|
||||
+/* Test that malloc tcache catches double free.
|
||||
+ Copyright (C) 2018 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <malloc.h>
|
||||
+#include <string.h>
|
||||
+
|
||||
+/* Prevent GCC from optimizing away any malloc/free pairs. */
|
||||
+#pragma GCC optimize ("O0")
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ /* Do two allocation of any size that fit in tcache, and one that
|
||||
+ doesn't. */
|
||||
+ int ** volatile a = malloc (32);
|
||||
+ int ** volatile b = malloc (32);
|
||||
+ /* This is just under the mmap threshold. */
|
||||
+ int ** volatile c = malloc (127 * 1024);
|
||||
+
|
||||
+ /* The invalid "tcache bucket" we might dereference will likely end
|
||||
+ up somewhere within this memory block, so make all the accidental
|
||||
+ "next" pointers cause segfaults. BZ #23907. */
|
||||
+ memset (c, 0xff, 127 * 1024);
|
||||
+
|
||||
+ free (a); // puts in tcache
|
||||
+
|
||||
+ /* A is now free and contains the key we use to detect in-tcache.
|
||||
+ Copy the key to the other chunks. */
|
||||
+ memcpy (b, a, 32);
|
||||
+ memcpy (c, a, 32);
|
||||
+
|
||||
+ /* This free tests the "are we in the tcache already" loop with a
|
||||
+ VALID bin but "coincidental" matching key. */
|
||||
+ free (b); // should NOT abort
|
||||
+ /* This free tests the "is it a valid tcache bin" test. */
|
||||
+ free (c); // should NOT abort
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
34
SOURCES/glibc-rh1645593.patch
Normal file
34
SOURCES/glibc-rh1645593.patch
Normal file
@ -0,0 +1,34 @@
|
||||
commit 28669f86f6780a18daca264f32d66b1428c9c6f1
|
||||
Author: Stefan Liebler <stli@linux.ibm.com>
|
||||
Date: Thu Sep 6 14:27:03 2018 +0200
|
||||
|
||||
Fix segfault in maybe_script_execute.
|
||||
|
||||
If glibc is built with gcc 8 and -march=z900,
|
||||
the testcase posix/tst-spawn4-compat crashes with a segfault.
|
||||
|
||||
In function maybe_script_execute, the new_argv array is dynamically
|
||||
initialized on stack with (argc + 1) elements.
|
||||
The function wants to add _PATH_BSHELL as the first argument
|
||||
and writes out of bounds of new_argv.
|
||||
There is an off-by-one because maybe_script_execute fails to count
|
||||
the terminating NULL when sizing new_argv.
|
||||
|
||||
ChangeLog:
|
||||
|
||||
* sysdeps/unix/sysv/linux/spawni.c (maybe_script_execute):
|
||||
Increment size of new_argv by one.
|
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/spawni.c b/sysdeps/unix/sysv/linux/spawni.c
|
||||
index cf0213ece55c675d..85239cedbf2a5ab5 100644
|
||||
--- a/sysdeps/unix/sysv/linux/spawni.c
|
||||
+++ b/sysdeps/unix/sysv/linux/spawni.c
|
||||
@@ -101,7 +101,7 @@ maybe_script_execute (struct posix_spawn_args *args)
|
||||
ptrdiff_t argc = args->argc;
|
||||
|
||||
/* Construct an argument list for the shell. */
|
||||
- char *new_argv[argc + 1];
|
||||
+ char *new_argv[argc + 2];
|
||||
new_argv[0] = (char *) _PATH_BSHELL;
|
||||
new_argv[1] = (char *) args->file;
|
||||
if (argc > 1)
|
193
SOURCES/glibc-rh1645596.patch
Normal file
193
SOURCES/glibc-rh1645596.patch
Normal file
@ -0,0 +1,193 @@
|
||||
commit 7a16bdbb9ff4122af0a28dc20996c95352011fdd
|
||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
Date: Wed Aug 29 16:36:44 2018 -0300
|
||||
|
||||
Fix misreported errno on preadv2/pwritev2 (BZ#23579)
|
||||
|
||||
The fallback code of Linux wrapper for preadv2/pwritev2 executes
|
||||
regardless of the errno code for preadv2, instead of the case where
|
||||
the syscall is not supported.
|
||||
|
||||
This fixes it by calling the fallback code iff errno is ENOSYS. The
|
||||
patch also adds tests for both invalid file descriptor and invalid
|
||||
iov_len and vector count.
|
||||
|
||||
The only discrepancy between preadv2 and fallback code regarding
|
||||
error reporting is when an invalid flags are used. The fallback code
|
||||
bails out earlier with ENOTSUP instead of EINVAL/EBADF when the syscall
|
||||
is used.
|
||||
|
||||
Checked on x86_64-linux-gnu on a 4.4.0 and 4.15.0 kernel.
|
||||
|
||||
[BZ #23579]
|
||||
* misc/tst-preadvwritev2-common.c (do_test_with_invalid_fd): New
|
||||
test.
|
||||
* misc/tst-preadvwritev2.c, misc/tst-preadvwritev64v2.c (do_test):
|
||||
Call do_test_with_invalid_fd.
|
||||
* sysdeps/unix/sysv/linux/preadv2.c (preadv2): Use fallback code iff
|
||||
errno is ENOSYS.
|
||||
* sysdeps/unix/sysv/linux/preadv64v2.c (preadv64v2): Likewise.
|
||||
* sysdeps/unix/sysv/linux/pwritev2.c (pwritev2): Likewise.
|
||||
* sysdeps/unix/sysv/linux/pwritev64v2.c (pwritev64v2): Likewise.
|
||||
|
||||
diff --git a/misc/tst-preadvwritev2-common.c b/misc/tst-preadvwritev2-common.c
|
||||
index f889a21544947042..50b9da3fea56d288 100644
|
||||
--- a/misc/tst-preadvwritev2-common.c
|
||||
+++ b/misc/tst-preadvwritev2-common.c
|
||||
@@ -19,9 +19,6 @@
|
||||
#include <limits.h>
|
||||
#include <support/check.h>
|
||||
|
||||
-static void
|
||||
-do_test_with_invalid_flags (void)
|
||||
-{
|
||||
#ifndef RWF_HIPRI
|
||||
# define RWF_HIPRI 0
|
||||
#endif
|
||||
@@ -39,6 +36,68 @@ do_test_with_invalid_flags (void)
|
||||
#endif
|
||||
#define RWF_SUPPORTED (RWF_HIPRI | RWF_DSYNC | RWF_SYNC | RWF_NOWAIT \
|
||||
| RWF_APPEND)
|
||||
+
|
||||
+static void
|
||||
+do_test_with_invalid_fd (void)
|
||||
+{
|
||||
+ char buf[256];
|
||||
+ struct iovec iov = { buf, sizeof buf };
|
||||
+
|
||||
+ /* Check with flag being 0 to use the fallback code which calls pwritev
|
||||
+ or writev. */
|
||||
+ TEST_VERIFY (preadv2 (-1, &iov, 1, -1, 0) == -1);
|
||||
+ TEST_COMPARE (errno, EBADF);
|
||||
+ TEST_VERIFY (pwritev2 (-1, &iov, 1, -1, 0) == -1);
|
||||
+ TEST_COMPARE (errno, EBADF);
|
||||
+
|
||||
+ /* Same tests as before but with flags being different than 0. Since
|
||||
+ there is no emulation for any flag value, fallback code returns
|
||||
+ ENOTSUP. This is different running on a kernel with preadv2/pwritev2
|
||||
+ support, where EBADF is returned). */
|
||||
+ TEST_VERIFY (preadv2 (-1, &iov, 1, 0, RWF_HIPRI) == -1);
|
||||
+ TEST_VERIFY (errno == EBADF || errno == ENOTSUP);
|
||||
+ TEST_VERIFY (pwritev2 (-1, &iov, 1, 0, RWF_HIPRI) == -1);
|
||||
+ TEST_VERIFY (errno == EBADF || errno == ENOTSUP);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+do_test_with_invalid_iov (void)
|
||||
+{
|
||||
+ {
|
||||
+ char buf[256];
|
||||
+ struct iovec iov;
|
||||
+
|
||||
+ iov.iov_base = buf;
|
||||
+ iov.iov_len = (size_t)SSIZE_MAX + 1;
|
||||
+
|
||||
+ TEST_VERIFY (preadv2 (temp_fd, &iov, 1, 0, 0) == -1);
|
||||
+ TEST_COMPARE (errno, EINVAL);
|
||||
+ TEST_VERIFY (pwritev2 (temp_fd, &iov, 1, 0, 0) == -1);
|
||||
+ TEST_COMPARE (errno, EINVAL);
|
||||
+
|
||||
+ /* Same as for invalid file descriptor tests, emulation fallback
|
||||
+ first checks for flag value and return ENOTSUP. */
|
||||
+ TEST_VERIFY (preadv2 (temp_fd, &iov, 1, 0, RWF_HIPRI) == -1);
|
||||
+ TEST_VERIFY (errno == EINVAL || errno == ENOTSUP);
|
||||
+ TEST_VERIFY (pwritev2 (temp_fd, &iov, 1, 0, RWF_HIPRI) == -1);
|
||||
+ TEST_VERIFY (errno == EINVAL || errno == ENOTSUP);
|
||||
+ }
|
||||
+
|
||||
+ {
|
||||
+ /* An invalid iovec buffer should trigger an invalid memory access
|
||||
+ or an error (Linux for instance returns EFAULT). */
|
||||
+ struct iovec iov[IOV_MAX+1] = { 0 };
|
||||
+
|
||||
+ TEST_VERIFY (preadv2 (temp_fd, iov, IOV_MAX + 1, 0, RWF_HIPRI) == -1);
|
||||
+ TEST_VERIFY (errno == EINVAL || errno == ENOTSUP);
|
||||
+ TEST_VERIFY (pwritev2 (temp_fd, iov, IOV_MAX + 1, 0, RWF_HIPRI) == -1);
|
||||
+ TEST_VERIFY (errno == EINVAL || errno == ENOTSUP);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+do_test_with_invalid_flags (void)
|
||||
+{
|
||||
/* Set the next bit from the mask of all supported flags. */
|
||||
int invalid_flag = RWF_SUPPORTED != 0 ? __builtin_clz (RWF_SUPPORTED) : 2;
|
||||
invalid_flag = 0x1 << ((sizeof (int) * CHAR_BIT) - invalid_flag);
|
||||
diff --git a/misc/tst-preadvwritev2.c b/misc/tst-preadvwritev2.c
|
||||
index be22802dbe00317f..cb58cbe41ecc639d 100644
|
||||
--- a/misc/tst-preadvwritev2.c
|
||||
+++ b/misc/tst-preadvwritev2.c
|
||||
@@ -30,6 +30,8 @@ do_test (void)
|
||||
{
|
||||
do_test_with_invalid_flags ();
|
||||
do_test_without_offset ();
|
||||
+ do_test_with_invalid_fd ();
|
||||
+ do_test_with_invalid_iov ();
|
||||
|
||||
return do_test_with_offset (0);
|
||||
}
|
||||
diff --git a/misc/tst-preadvwritev64v2.c b/misc/tst-preadvwritev64v2.c
|
||||
index 8d3cc32b284dbf4c..6a9de54c786acc53 100644
|
||||
--- a/misc/tst-preadvwritev64v2.c
|
||||
+++ b/misc/tst-preadvwritev64v2.c
|
||||
@@ -32,6 +32,8 @@ do_test (void)
|
||||
{
|
||||
do_test_with_invalid_flags ();
|
||||
do_test_without_offset ();
|
||||
+ do_test_with_invalid_fd ();
|
||||
+ do_test_with_invalid_iov ();
|
||||
|
||||
return do_test_with_offset (0);
|
||||
}
|
||||
diff --git a/sysdeps/unix/sysv/linux/preadv2.c b/sysdeps/unix/sysv/linux/preadv2.c
|
||||
index c8bf0764ef2629fc..bb08cbc5fd96962e 100644
|
||||
--- a/sysdeps/unix/sysv/linux/preadv2.c
|
||||
+++ b/sysdeps/unix/sysv/linux/preadv2.c
|
||||
@@ -32,7 +32,7 @@ preadv2 (int fd, const struct iovec *vector, int count, off_t offset,
|
||||
# ifdef __NR_preadv2
|
||||
ssize_t result = SYSCALL_CANCEL (preadv2, fd, vector, count,
|
||||
LO_HI_LONG (offset), flags);
|
||||
- if (result >= 0)
|
||||
+ if (result >= 0 || errno != ENOSYS)
|
||||
return result;
|
||||
# endif
|
||||
/* Trying to emulate the preadv2 syscall flags is troublesome:
|
||||
diff --git a/sysdeps/unix/sysv/linux/preadv64v2.c b/sysdeps/unix/sysv/linux/preadv64v2.c
|
||||
index d7400a0252a8c6a1..b72a047347b1db0e 100644
|
||||
--- a/sysdeps/unix/sysv/linux/preadv64v2.c
|
||||
+++ b/sysdeps/unix/sysv/linux/preadv64v2.c
|
||||
@@ -30,7 +30,7 @@ preadv64v2 (int fd, const struct iovec *vector, int count, off64_t offset,
|
||||
#ifdef __NR_preadv64v2
|
||||
ssize_t result = SYSCALL_CANCEL (preadv64v2, fd, vector, count,
|
||||
LO_HI_LONG (offset), flags);
|
||||
- if (result >= 0)
|
||||
+ if (result >= 0 || errno != ENOSYS)
|
||||
return result;
|
||||
#endif
|
||||
/* Trying to emulate the preadv2 syscall flags is troublesome:
|
||||
diff --git a/sysdeps/unix/sysv/linux/pwritev2.c b/sysdeps/unix/sysv/linux/pwritev2.c
|
||||
index 29c2264c8f3d949a..26333ebd43c5f0af 100644
|
||||
--- a/sysdeps/unix/sysv/linux/pwritev2.c
|
||||
+++ b/sysdeps/unix/sysv/linux/pwritev2.c
|
||||
@@ -28,7 +28,7 @@ pwritev2 (int fd, const struct iovec *vector, int count, off_t offset,
|
||||
# ifdef __NR_pwritev2
|
||||
ssize_t result = SYSCALL_CANCEL (pwritev2, fd, vector, count,
|
||||
LO_HI_LONG (offset), flags);
|
||||
- if (result >= 0)
|
||||
+ if (result >= 0 || errno != ENOSYS)
|
||||
return result;
|
||||
# endif
|
||||
/* Trying to emulate the pwritev2 syscall flags is troublesome:
|
||||
diff --git a/sysdeps/unix/sysv/linux/pwritev64v2.c b/sysdeps/unix/sysv/linux/pwritev64v2.c
|
||||
index 42da321149bce40d..17ea905aa6a8db94 100644
|
||||
--- a/sysdeps/unix/sysv/linux/pwritev64v2.c
|
||||
+++ b/sysdeps/unix/sysv/linux/pwritev64v2.c
|
||||
@@ -30,7 +30,7 @@ pwritev64v2 (int fd, const struct iovec *vector, int count, off64_t offset,
|
||||
#ifdef __NR_pwritev64v2
|
||||
ssize_t result = SYSCALL_CANCEL (pwritev64v2, fd, vector, count,
|
||||
LO_HI_LONG (offset), flags);
|
||||
- if (result >= 0)
|
||||
+ if (result >= 0 || errno != ENOSYS)
|
||||
return result;
|
||||
#endif
|
||||
/* Trying to emulate the pwritev2 syscall flags is troublesome:
|
33
SOURCES/glibc-rh1645597.patch
Normal file
33
SOURCES/glibc-rh1645597.patch
Normal file
@ -0,0 +1,33 @@
|
||||
commit dae3ed958c3d0090838e49ff4f78c201262b1cf0
|
||||
Author: Rafal Luzynski <digitalfreak@lingonborough.com>
|
||||
Date: Tue Oct 2 23:34:18 2018 +0200
|
||||
|
||||
kl_GL: Fix spelling of Sunday, should be "sapaat" (bug 20209).
|
||||
|
||||
Although CLDR says otherwise, it is confirmed by Oqaasileriffik, the
|
||||
official Greenlandic language regulator, that this change is correct.
|
||||
|
||||
[BZ #20209]
|
||||
* localedata/locales/kl_GL: (abday): Fix spelling of Sun (Sunday),
|
||||
should be "sap" rather than "sab".
|
||||
(day): Fix spelling of Sunday, should be "sapaat" rather than
|
||||
"sabaat".
|
||||
|
||||
diff --git a/localedata/locales/kl_GL b/localedata/locales/kl_GL
|
||||
index 5ab14a31aade8644..5723ce7dcf9c5742 100644
|
||||
--- a/localedata/locales/kl_GL
|
||||
+++ b/localedata/locales/kl_GL
|
||||
@@ -70,11 +70,11 @@ copy "da_DK"
|
||||
END LC_NUMERIC
|
||||
|
||||
LC_TIME
|
||||
-abday "sab";"ata";/
|
||||
+abday "sap";"ata";/
|
||||
"mar";"pin";/
|
||||
"sis";"tal";/
|
||||
"arf"
|
||||
-day "sabaat";/
|
||||
+day "sapaat";/
|
||||
"ataasinngorneq";/
|
||||
"marlunngorneq";/
|
||||
"pingasunngorneq";/
|
134
SOURCES/glibc-rh1645601.patch
Normal file
134
SOURCES/glibc-rh1645601.patch
Normal file
@ -0,0 +1,134 @@
|
||||
commit 7b1f9406761331cf35fe521fbdb592beecf68a2c
|
||||
Author: H.J. Lu <hjl.tools@gmail.com>
|
||||
Date: Fri Sep 28 13:31:19 2018 -0700
|
||||
|
||||
i386: Use _dl_runtime_[resolve|profile]_shstk for SHSTK [BZ #23716]
|
||||
|
||||
When elf_machine_runtime_setup is called to set up resolver, it should
|
||||
use _dl_runtime_resolve_shstk or _dl_runtime_profile_shstk if SHSTK is
|
||||
enabled by kernel.
|
||||
|
||||
Tested on i686 with and without --enable-cet as well as on CET emulator
|
||||
with --enable-cet.
|
||||
|
||||
[BZ #23716]
|
||||
* sysdeps/i386/dl-cet.c: Removed.
|
||||
* sysdeps/i386/dl-machine.h (_dl_runtime_resolve_shstk): New
|
||||
prototype.
|
||||
(_dl_runtime_profile_shstk): Likewise.
|
||||
(elf_machine_runtime_setup): Use _dl_runtime_profile_shstk or
|
||||
_dl_runtime_resolve_shstk if SHSTK is enabled by kernel.
|
||||
|
||||
Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
|
||||
|
||||
diff --git a/sysdeps/i386/dl-cet.c b/sysdeps/i386/dl-cet.c
|
||||
deleted file mode 100644
|
||||
index 5d9a4e8d5179b572..0000000000000000
|
||||
--- a/sysdeps/i386/dl-cet.c
|
||||
+++ /dev/null
|
||||
@@ -1,67 +0,0 @@
|
||||
-/* Linux/i386 CET initializers function.
|
||||
- Copyright (C) 2018 Free Software Foundation, Inc.
|
||||
-
|
||||
- The GNU C Library is free software; you can redistribute it and/or
|
||||
- modify it under the terms of the GNU Lesser General Public
|
||||
- License as published by the Free Software Foundation; either
|
||||
- version 2.1 of the License, or (at your option) any later version.
|
||||
-
|
||||
- The GNU C Library is distributed in the hope that it will be useful,
|
||||
- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
- Lesser General Public License for more details.
|
||||
-
|
||||
- You should have received a copy of the GNU Lesser General Public
|
||||
- License along with the GNU C Library; if not, see
|
||||
- <http://www.gnu.org/licenses/>. */
|
||||
-
|
||||
-
|
||||
-#define LINKAGE static inline
|
||||
-#define _dl_cet_check cet_check
|
||||
-#include <sysdeps/x86/dl-cet.c>
|
||||
-#undef _dl_cet_check
|
||||
-
|
||||
-#ifdef SHARED
|
||||
-void
|
||||
-_dl_cet_check (struct link_map *main_map, const char *program)
|
||||
-{
|
||||
- cet_check (main_map, program);
|
||||
-
|
||||
- if ((GL(dl_x86_feature_1)[0] & GNU_PROPERTY_X86_FEATURE_1_SHSTK))
|
||||
- {
|
||||
- /* Replace _dl_runtime_resolve and _dl_runtime_profile with
|
||||
- _dl_runtime_resolve_shstk and _dl_runtime_profile_shstk,
|
||||
- respectively if SHSTK is enabled. */
|
||||
- extern void _dl_runtime_resolve (Elf32_Word) attribute_hidden;
|
||||
- extern void _dl_runtime_resolve_shstk (Elf32_Word) attribute_hidden;
|
||||
- extern void _dl_runtime_profile (Elf32_Word) attribute_hidden;
|
||||
- extern void _dl_runtime_profile_shstk (Elf32_Word) attribute_hidden;
|
||||
- unsigned int i;
|
||||
- struct link_map *l;
|
||||
- Elf32_Addr *got;
|
||||
-
|
||||
- if (main_map->l_info[DT_JMPREL])
|
||||
- {
|
||||
- got = (Elf32_Addr *) D_PTR (main_map, l_info[DT_PLTGOT]);
|
||||
- if (got[2] == (Elf32_Addr) &_dl_runtime_resolve)
|
||||
- got[2] = (Elf32_Addr) &_dl_runtime_resolve_shstk;
|
||||
- else if (got[2] == (Elf32_Addr) &_dl_runtime_profile)
|
||||
- got[2] = (Elf32_Addr) &_dl_runtime_profile_shstk;
|
||||
- }
|
||||
-
|
||||
- i = main_map->l_searchlist.r_nlist;
|
||||
- while (i-- > 0)
|
||||
- {
|
||||
- l = main_map->l_initfini[i];
|
||||
- if (l->l_info[DT_JMPREL])
|
||||
- {
|
||||
- got = (Elf32_Addr *) D_PTR (l, l_info[DT_PLTGOT]);
|
||||
- if (got[2] == (Elf32_Addr) &_dl_runtime_resolve)
|
||||
- got[2] = (Elf32_Addr) &_dl_runtime_resolve_shstk;
|
||||
- else if (got[2] == (Elf32_Addr) &_dl_runtime_profile)
|
||||
- got[2] = (Elf32_Addr) &_dl_runtime_profile_shstk;
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
-}
|
||||
-#endif
|
||||
diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h
|
||||
index 1afdcbd9ea2626e4..f6cfb90e21015250 100644
|
||||
--- a/sysdeps/i386/dl-machine.h
|
||||
+++ b/sysdeps/i386/dl-machine.h
|
||||
@@ -67,6 +67,11 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
|
||||
Elf32_Addr *got;
|
||||
extern void _dl_runtime_resolve (Elf32_Word) attribute_hidden;
|
||||
extern void _dl_runtime_profile (Elf32_Word) attribute_hidden;
|
||||
+ extern void _dl_runtime_resolve_shstk (Elf32_Word) attribute_hidden;
|
||||
+ extern void _dl_runtime_profile_shstk (Elf32_Word) attribute_hidden;
|
||||
+ /* Check if SHSTK is enabled by kernel. */
|
||||
+ bool shstk_enabled
|
||||
+ = (GL(dl_x86_feature_1)[0] & GNU_PROPERTY_X86_FEATURE_1_SHSTK) != 0;
|
||||
|
||||
if (l->l_info[DT_JMPREL] && lazy)
|
||||
{
|
||||
@@ -93,7 +98,9 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
|
||||
end in this function. */
|
||||
if (__glibc_unlikely (profile))
|
||||
{
|
||||
- got[2] = (Elf32_Addr) &_dl_runtime_profile;
|
||||
+ got[2] = (shstk_enabled
|
||||
+ ? (Elf32_Addr) &_dl_runtime_profile_shstk
|
||||
+ : (Elf32_Addr) &_dl_runtime_profile);
|
||||
|
||||
if (GLRO(dl_profile) != NULL
|
||||
&& _dl_name_match_p (GLRO(dl_profile), l))
|
||||
@@ -104,7 +111,9 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
|
||||
else
|
||||
/* This function will get called to fix up the GOT entry indicated by
|
||||
the offset on the stack, and then jump to the resolved address. */
|
||||
- got[2] = (Elf32_Addr) &_dl_runtime_resolve;
|
||||
+ got[2] = (shstk_enabled
|
||||
+ ? (Elf32_Addr) &_dl_runtime_resolve_shstk
|
||||
+ : (Elf32_Addr) &_dl_runtime_resolve);
|
||||
}
|
||||
|
||||
return lazy;
|
738
SOURCES/glibc-rh1645604.patch
Normal file
738
SOURCES/glibc-rh1645604.patch
Normal file
@ -0,0 +1,738 @@
|
||||
commit 403b4feb22dcbc85ace72a361d2a951380372471
|
||||
Author: Stefan Liebler <stli@linux.ibm.com>
|
||||
Date: Wed Oct 17 12:23:04 2018 +0200
|
||||
|
||||
Fix race in pthread_mutex_lock while promoting to PTHREAD_MUTEX_ELISION_NP [BZ #23275]
|
||||
|
||||
The race leads either to pthread_mutex_destroy returning EBUSY
|
||||
or triggering an assertion (See description in bugzilla).
|
||||
|
||||
This patch is fixing the race by ensuring that the elision path is
|
||||
used in all cases if elision is enabled by the GLIBC_TUNABLES framework.
|
||||
|
||||
The __kind variable in struct __pthread_mutex_s is accessed concurrently.
|
||||
Therefore we are now using the atomic macros.
|
||||
|
||||
The new testcase tst-mutex10 is triggering the race on s390x and intel.
|
||||
Presumably also on power, but I don't have access to a power machine
|
||||
with lock-elision. At least the code for power is the same as on the other
|
||||
two architectures.
|
||||
|
||||
ChangeLog:
|
||||
|
||||
[BZ #23275]
|
||||
* nptl/tst-mutex10.c: New File.
|
||||
* nptl/Makefile (tests): Add tst-mutex10.
|
||||
(tst-mutex10-ENV): New variable.
|
||||
* sysdeps/unix/sysv/linux/s390/force-elision.h: (FORCE_ELISION):
|
||||
Ensure that elision path is used if elision is available.
|
||||
* sysdeps/unix/sysv/linux/powerpc/force-elision.h (FORCE_ELISION):
|
||||
Likewise.
|
||||
* sysdeps/unix/sysv/linux/x86/force-elision.h: (FORCE_ELISION):
|
||||
Likewise.
|
||||
* nptl/pthreadP.h (PTHREAD_MUTEX_TYPE, PTHREAD_MUTEX_TYPE_ELISION)
|
||||
(PTHREAD_MUTEX_PSHARED): Use atomic_load_relaxed.
|
||||
* nptl/pthread_mutex_consistent.c (pthread_mutex_consistent): Likewise.
|
||||
* nptl/pthread_mutex_getprioceiling.c (pthread_mutex_getprioceiling):
|
||||
Likewise.
|
||||
* nptl/pthread_mutex_lock.c (__pthread_mutex_lock_full)
|
||||
(__pthread_mutex_cond_lock_adjust): Likewise.
|
||||
* nptl/pthread_mutex_setprioceiling.c (pthread_mutex_setprioceiling):
|
||||
Likewise.
|
||||
* nptl/pthread_mutex_timedlock.c (__pthread_mutex_timedlock): Likewise.
|
||||
* nptl/pthread_mutex_trylock.c (__pthread_mutex_trylock): Likewise.
|
||||
* nptl/pthread_mutex_unlock.c (__pthread_mutex_unlock_full): Likewise.
|
||||
* sysdeps/nptl/bits/thread-shared-types.h (struct __pthread_mutex_s):
|
||||
Add comments.
|
||||
* nptl/pthread_mutex_destroy.c (__pthread_mutex_destroy):
|
||||
Use atomic_load_relaxed and atomic_store_relaxed.
|
||||
* nptl/pthread_mutex_init.c (__pthread_mutex_init):
|
||||
Use atomic_store_relaxed.
|
||||
|
||||
diff --git a/nptl/Makefile b/nptl/Makefile
|
||||
index be8066524cdc57db..49b6faa330c492e0 100644
|
||||
--- a/nptl/Makefile
|
||||
+++ b/nptl/Makefile
|
||||
@@ -241,9 +241,9 @@ LDLIBS-tst-minstack-throw = -lstdc++
|
||||
|
||||
tests = tst-attr1 tst-attr2 tst-attr3 tst-default-attr \
|
||||
tst-mutex1 tst-mutex2 tst-mutex3 tst-mutex4 tst-mutex5 tst-mutex6 \
|
||||
- tst-mutex7 tst-mutex9 tst-mutex5a tst-mutex7a tst-mutex7robust \
|
||||
- tst-mutexpi1 tst-mutexpi2 tst-mutexpi3 tst-mutexpi4 tst-mutexpi5 \
|
||||
- tst-mutexpi5a tst-mutexpi6 tst-mutexpi7 tst-mutexpi7a \
|
||||
+ tst-mutex7 tst-mutex9 tst-mutex10 tst-mutex5a tst-mutex7a \
|
||||
+ tst-mutex7robust tst-mutexpi1 tst-mutexpi2 tst-mutexpi3 tst-mutexpi4 \
|
||||
+ tst-mutexpi5 tst-mutexpi5a tst-mutexpi6 tst-mutexpi7 tst-mutexpi7a \
|
||||
tst-mutexpi9 \
|
||||
tst-spin1 tst-spin2 tst-spin3 tst-spin4 \
|
||||
tst-cond1 tst-cond2 tst-cond3 tst-cond4 tst-cond5 tst-cond6 tst-cond7 \
|
||||
@@ -709,6 +709,8 @@ endif
|
||||
|
||||
$(objpfx)tst-compat-forwarder: $(objpfx)tst-compat-forwarder-mod.so
|
||||
|
||||
+tst-mutex10-ENV = GLIBC_TUNABLES=glibc.elision.enable=1
|
||||
+
|
||||
# The tests here better do not run in parallel
|
||||
ifneq ($(filter %tests,$(MAKECMDGOALS)),)
|
||||
.NOTPARALLEL:
|
||||
diff --git a/nptl/pthreadP.h b/nptl/pthreadP.h
|
||||
index 13bdb11133536195..19efe1e35feed5be 100644
|
||||
--- a/nptl/pthreadP.h
|
||||
+++ b/nptl/pthreadP.h
|
||||
@@ -110,19 +110,23 @@ enum
|
||||
};
|
||||
#define PTHREAD_MUTEX_PSHARED_BIT 128
|
||||
|
||||
+/* See concurrency notes regarding __kind in struct __pthread_mutex_s
|
||||
+ in sysdeps/nptl/bits/thread-shared-types.h. */
|
||||
#define PTHREAD_MUTEX_TYPE(m) \
|
||||
- ((m)->__data.__kind & 127)
|
||||
+ (atomic_load_relaxed (&((m)->__data.__kind)) & 127)
|
||||
/* Don't include NO_ELISION, as that type is always the same
|
||||
as the underlying lock type. */
|
||||
#define PTHREAD_MUTEX_TYPE_ELISION(m) \
|
||||
- ((m)->__data.__kind & (127|PTHREAD_MUTEX_ELISION_NP))
|
||||
+ (atomic_load_relaxed (&((m)->__data.__kind)) \
|
||||
+ & (127 | PTHREAD_MUTEX_ELISION_NP))
|
||||
|
||||
#if LLL_PRIVATE == 0 && LLL_SHARED == 128
|
||||
# define PTHREAD_MUTEX_PSHARED(m) \
|
||||
- ((m)->__data.__kind & 128)
|
||||
+ (atomic_load_relaxed (&((m)->__data.__kind)) & 128)
|
||||
#else
|
||||
# define PTHREAD_MUTEX_PSHARED(m) \
|
||||
- (((m)->__data.__kind & 128) ? LLL_SHARED : LLL_PRIVATE)
|
||||
+ ((atomic_load_relaxed (&((m)->__data.__kind)) & 128) \
|
||||
+ ? LLL_SHARED : LLL_PRIVATE)
|
||||
#endif
|
||||
|
||||
/* The kernel when waking robust mutexes on exit never uses
|
||||
diff --git a/nptl/pthread_mutex_consistent.c b/nptl/pthread_mutex_consistent.c
|
||||
index 85b8e1a6cb027e9b..4fbd875430439e4d 100644
|
||||
--- a/nptl/pthread_mutex_consistent.c
|
||||
+++ b/nptl/pthread_mutex_consistent.c
|
||||
@@ -23,8 +23,11 @@
|
||||
int
|
||||
pthread_mutex_consistent (pthread_mutex_t *mutex)
|
||||
{
|
||||
- /* Test whether this is a robust mutex with a dead owner. */
|
||||
- if ((mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) == 0
|
||||
+ /* Test whether this is a robust mutex with a dead owner.
|
||||
+ See concurrency notes regarding __kind in struct __pthread_mutex_s
|
||||
+ in sysdeps/nptl/bits/thread-shared-types.h. */
|
||||
+ if ((atomic_load_relaxed (&(mutex->__data.__kind))
|
||||
+ & PTHREAD_MUTEX_ROBUST_NORMAL_NP) == 0
|
||||
|| mutex->__data.__owner != PTHREAD_MUTEX_INCONSISTENT)
|
||||
return EINVAL;
|
||||
|
||||
diff --git a/nptl/pthread_mutex_destroy.c b/nptl/pthread_mutex_destroy.c
|
||||
index 5a22611541995778..713ea684962fefc1 100644
|
||||
--- a/nptl/pthread_mutex_destroy.c
|
||||
+++ b/nptl/pthread_mutex_destroy.c
|
||||
@@ -27,12 +27,17 @@ __pthread_mutex_destroy (pthread_mutex_t *mutex)
|
||||
{
|
||||
LIBC_PROBE (mutex_destroy, 1, mutex);
|
||||
|
||||
- if ((mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) == 0
|
||||
+ /* See concurrency notes regarding __kind in struct __pthread_mutex_s
|
||||
+ in sysdeps/nptl/bits/thread-shared-types.h. */
|
||||
+ if ((atomic_load_relaxed (&(mutex->__data.__kind))
|
||||
+ & PTHREAD_MUTEX_ROBUST_NORMAL_NP) == 0
|
||||
&& mutex->__data.__nusers != 0)
|
||||
return EBUSY;
|
||||
|
||||
- /* Set to an invalid value. */
|
||||
- mutex->__data.__kind = -1;
|
||||
+ /* Set to an invalid value. Relaxed MO is enough as it is undefined behavior
|
||||
+ if the mutex is used after it has been destroyed. But you can reinitialize
|
||||
+ it with pthread_mutex_init. */
|
||||
+ atomic_store_relaxed (&(mutex->__data.__kind), -1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
diff --git a/nptl/pthread_mutex_getprioceiling.c b/nptl/pthread_mutex_getprioceiling.c
|
||||
index efa37b0d99201f57..ee85949578475f3a 100644
|
||||
--- a/nptl/pthread_mutex_getprioceiling.c
|
||||
+++ b/nptl/pthread_mutex_getprioceiling.c
|
||||
@@ -24,7 +24,9 @@
|
||||
int
|
||||
pthread_mutex_getprioceiling (const pthread_mutex_t *mutex, int *prioceiling)
|
||||
{
|
||||
- if (__builtin_expect ((mutex->__data.__kind
|
||||
+ /* See concurrency notes regarding __kind in struct __pthread_mutex_s
|
||||
+ in sysdeps/nptl/bits/thread-shared-types.h. */
|
||||
+ if (__builtin_expect ((atomic_load_relaxed (&(mutex->__data.__kind))
|
||||
& PTHREAD_MUTEX_PRIO_PROTECT_NP) == 0, 0))
|
||||
return EINVAL;
|
||||
|
||||
diff --git a/nptl/pthread_mutex_init.c b/nptl/pthread_mutex_init.c
|
||||
index d8fe4737289c0bd7..5cf290c272e27915 100644
|
||||
--- a/nptl/pthread_mutex_init.c
|
||||
+++ b/nptl/pthread_mutex_init.c
|
||||
@@ -101,7 +101,7 @@ __pthread_mutex_init (pthread_mutex_t *mutex,
|
||||
memset (mutex, '\0', __SIZEOF_PTHREAD_MUTEX_T);
|
||||
|
||||
/* Copy the values from the attribute. */
|
||||
- mutex->__data.__kind = imutexattr->mutexkind & ~PTHREAD_MUTEXATTR_FLAG_BITS;
|
||||
+ int mutex_kind = imutexattr->mutexkind & ~PTHREAD_MUTEXATTR_FLAG_BITS;
|
||||
|
||||
if ((imutexattr->mutexkind & PTHREAD_MUTEXATTR_FLAG_ROBUST) != 0)
|
||||
{
|
||||
@@ -111,17 +111,17 @@ __pthread_mutex_init (pthread_mutex_t *mutex,
|
||||
return ENOTSUP;
|
||||
#endif
|
||||
|
||||
- mutex->__data.__kind |= PTHREAD_MUTEX_ROBUST_NORMAL_NP;
|
||||
+ mutex_kind |= PTHREAD_MUTEX_ROBUST_NORMAL_NP;
|
||||
}
|
||||
|
||||
switch (imutexattr->mutexkind & PTHREAD_MUTEXATTR_PROTOCOL_MASK)
|
||||
{
|
||||
case PTHREAD_PRIO_INHERIT << PTHREAD_MUTEXATTR_PROTOCOL_SHIFT:
|
||||
- mutex->__data.__kind |= PTHREAD_MUTEX_PRIO_INHERIT_NP;
|
||||
+ mutex_kind |= PTHREAD_MUTEX_PRIO_INHERIT_NP;
|
||||
break;
|
||||
|
||||
case PTHREAD_PRIO_PROTECT << PTHREAD_MUTEXATTR_PROTOCOL_SHIFT:
|
||||
- mutex->__data.__kind |= PTHREAD_MUTEX_PRIO_PROTECT_NP;
|
||||
+ mutex_kind |= PTHREAD_MUTEX_PRIO_PROTECT_NP;
|
||||
|
||||
int ceiling = (imutexattr->mutexkind
|
||||
& PTHREAD_MUTEXATTR_PRIO_CEILING_MASK)
|
||||
@@ -145,7 +145,11 @@ __pthread_mutex_init (pthread_mutex_t *mutex,
|
||||
FUTEX_PRIVATE_FLAG FUTEX_WAKE. */
|
||||
if ((imutexattr->mutexkind & (PTHREAD_MUTEXATTR_FLAG_PSHARED
|
||||
| PTHREAD_MUTEXATTR_FLAG_ROBUST)) != 0)
|
||||
- mutex->__data.__kind |= PTHREAD_MUTEX_PSHARED_BIT;
|
||||
+ mutex_kind |= PTHREAD_MUTEX_PSHARED_BIT;
|
||||
+
|
||||
+ /* See concurrency notes regarding __kind in struct __pthread_mutex_s
|
||||
+ in sysdeps/nptl/bits/thread-shared-types.h. */
|
||||
+ atomic_store_relaxed (&(mutex->__data.__kind), mutex_kind);
|
||||
|
||||
/* Default values: mutex not used yet. */
|
||||
// mutex->__count = 0; already done by memset
|
||||
diff --git a/nptl/pthread_mutex_lock.c b/nptl/pthread_mutex_lock.c
|
||||
index 1519c142bd6ec5cc..29cc143e6cbf2421 100644
|
||||
--- a/nptl/pthread_mutex_lock.c
|
||||
+++ b/nptl/pthread_mutex_lock.c
|
||||
@@ -62,6 +62,8 @@ static int __pthread_mutex_lock_full (pthread_mutex_t *mutex)
|
||||
int
|
||||
__pthread_mutex_lock (pthread_mutex_t *mutex)
|
||||
{
|
||||
+ /* See concurrency notes regarding mutex type which is loaded from __kind
|
||||
+ in struct __pthread_mutex_s in sysdeps/nptl/bits/thread-shared-types.h. */
|
||||
unsigned int type = PTHREAD_MUTEX_TYPE_ELISION (mutex);
|
||||
|
||||
LIBC_PROBE (mutex_entry, 1, mutex);
|
||||
@@ -350,8 +352,14 @@ __pthread_mutex_lock_full (pthread_mutex_t *mutex)
|
||||
case PTHREAD_MUTEX_PI_ROBUST_NORMAL_NP:
|
||||
case PTHREAD_MUTEX_PI_ROBUST_ADAPTIVE_NP:
|
||||
{
|
||||
- int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP;
|
||||
- int robust = mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP;
|
||||
+ int kind, robust;
|
||||
+ {
|
||||
+ /* See concurrency notes regarding __kind in struct __pthread_mutex_s
|
||||
+ in sysdeps/nptl/bits/thread-shared-types.h. */
|
||||
+ int mutex_kind = atomic_load_relaxed (&(mutex->__data.__kind));
|
||||
+ kind = mutex_kind & PTHREAD_MUTEX_KIND_MASK_NP;
|
||||
+ robust = mutex_kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP;
|
||||
+ }
|
||||
|
||||
if (robust)
|
||||
{
|
||||
@@ -502,7 +510,10 @@ __pthread_mutex_lock_full (pthread_mutex_t *mutex)
|
||||
case PTHREAD_MUTEX_PP_NORMAL_NP:
|
||||
case PTHREAD_MUTEX_PP_ADAPTIVE_NP:
|
||||
{
|
||||
- int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP;
|
||||
+ /* See concurrency notes regarding __kind in struct __pthread_mutex_s
|
||||
+ in sysdeps/nptl/bits/thread-shared-types.h. */
|
||||
+ int kind = atomic_load_relaxed (&(mutex->__data.__kind))
|
||||
+ & PTHREAD_MUTEX_KIND_MASK_NP;
|
||||
|
||||
oldval = mutex->__data.__lock;
|
||||
|
||||
@@ -607,15 +618,18 @@ hidden_def (__pthread_mutex_lock)
|
||||
void
|
||||
__pthread_mutex_cond_lock_adjust (pthread_mutex_t *mutex)
|
||||
{
|
||||
- assert ((mutex->__data.__kind & PTHREAD_MUTEX_PRIO_INHERIT_NP) != 0);
|
||||
- assert ((mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) == 0);
|
||||
- assert ((mutex->__data.__kind & PTHREAD_MUTEX_PSHARED_BIT) == 0);
|
||||
+ /* See concurrency notes regarding __kind in struct __pthread_mutex_s
|
||||
+ in sysdeps/nptl/bits/thread-shared-types.h. */
|
||||
+ int mutex_kind = atomic_load_relaxed (&(mutex->__data.__kind));
|
||||
+ assert ((mutex_kind & PTHREAD_MUTEX_PRIO_INHERIT_NP) != 0);
|
||||
+ assert ((mutex_kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) == 0);
|
||||
+ assert ((mutex_kind & PTHREAD_MUTEX_PSHARED_BIT) == 0);
|
||||
|
||||
/* Record the ownership. */
|
||||
pid_t id = THREAD_GETMEM (THREAD_SELF, tid);
|
||||
mutex->__data.__owner = id;
|
||||
|
||||
- if (mutex->__data.__kind == PTHREAD_MUTEX_PI_RECURSIVE_NP)
|
||||
+ if (mutex_kind == PTHREAD_MUTEX_PI_RECURSIVE_NP)
|
||||
++mutex->__data.__count;
|
||||
}
|
||||
#endif
|
||||
diff --git a/nptl/pthread_mutex_setprioceiling.c b/nptl/pthread_mutex_setprioceiling.c
|
||||
index 8594874f8588b7a8..8306cabcf4e56174 100644
|
||||
--- a/nptl/pthread_mutex_setprioceiling.c
|
||||
+++ b/nptl/pthread_mutex_setprioceiling.c
|
||||
@@ -27,9 +27,10 @@ int
|
||||
pthread_mutex_setprioceiling (pthread_mutex_t *mutex, int prioceiling,
|
||||
int *old_ceiling)
|
||||
{
|
||||
- /* The low bits of __kind aren't ever changed after pthread_mutex_init,
|
||||
- so we don't need a lock yet. */
|
||||
- if ((mutex->__data.__kind & PTHREAD_MUTEX_PRIO_PROTECT_NP) == 0)
|
||||
+ /* See concurrency notes regarding __kind in struct __pthread_mutex_s
|
||||
+ in sysdeps/nptl/bits/thread-shared-types.h. */
|
||||
+ if ((atomic_load_relaxed (&(mutex->__data.__kind))
|
||||
+ & PTHREAD_MUTEX_PRIO_PROTECT_NP) == 0)
|
||||
return EINVAL;
|
||||
|
||||
/* See __init_sched_fifo_prio. */
|
||||
diff --git a/nptl/pthread_mutex_timedlock.c b/nptl/pthread_mutex_timedlock.c
|
||||
index 28237b0e58cfcaf5..888c12fe28b2ebfd 100644
|
||||
--- a/nptl/pthread_mutex_timedlock.c
|
||||
+++ b/nptl/pthread_mutex_timedlock.c
|
||||
@@ -53,6 +53,8 @@ __pthread_mutex_timedlock (pthread_mutex_t *mutex,
|
||||
/* We must not check ABSTIME here. If the thread does not block
|
||||
abstime must not be checked for a valid value. */
|
||||
|
||||
+ /* See concurrency notes regarding mutex type which is loaded from __kind
|
||||
+ in struct __pthread_mutex_s in sysdeps/nptl/bits/thread-shared-types.h. */
|
||||
switch (__builtin_expect (PTHREAD_MUTEX_TYPE_ELISION (mutex),
|
||||
PTHREAD_MUTEX_TIMED_NP))
|
||||
{
|
||||
@@ -338,8 +340,14 @@ __pthread_mutex_timedlock (pthread_mutex_t *mutex,
|
||||
case PTHREAD_MUTEX_PI_ROBUST_NORMAL_NP:
|
||||
case PTHREAD_MUTEX_PI_ROBUST_ADAPTIVE_NP:
|
||||
{
|
||||
- int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP;
|
||||
- int robust = mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP;
|
||||
+ int kind, robust;
|
||||
+ {
|
||||
+ /* See concurrency notes regarding __kind in struct __pthread_mutex_s
|
||||
+ in sysdeps/nptl/bits/thread-shared-types.h. */
|
||||
+ int mutex_kind = atomic_load_relaxed (&(mutex->__data.__kind));
|
||||
+ kind = mutex_kind & PTHREAD_MUTEX_KIND_MASK_NP;
|
||||
+ robust = mutex_kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP;
|
||||
+ }
|
||||
|
||||
if (robust)
|
||||
{
|
||||
@@ -509,7 +517,10 @@ __pthread_mutex_timedlock (pthread_mutex_t *mutex,
|
||||
case PTHREAD_MUTEX_PP_NORMAL_NP:
|
||||
case PTHREAD_MUTEX_PP_ADAPTIVE_NP:
|
||||
{
|
||||
- int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP;
|
||||
+ /* See concurrency notes regarding __kind in struct __pthread_mutex_s
|
||||
+ in sysdeps/nptl/bits/thread-shared-types.h. */
|
||||
+ int kind = atomic_load_relaxed (&(mutex->__data.__kind))
|
||||
+ & PTHREAD_MUTEX_KIND_MASK_NP;
|
||||
|
||||
oldval = mutex->__data.__lock;
|
||||
|
||||
diff --git a/nptl/pthread_mutex_trylock.c b/nptl/pthread_mutex_trylock.c
|
||||
index 7de61f4f688c1537..fa90c1d1e6f5afc2 100644
|
||||
--- a/nptl/pthread_mutex_trylock.c
|
||||
+++ b/nptl/pthread_mutex_trylock.c
|
||||
@@ -36,6 +36,8 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
|
||||
int oldval;
|
||||
pid_t id = THREAD_GETMEM (THREAD_SELF, tid);
|
||||
|
||||
+ /* See concurrency notes regarding mutex type which is loaded from __kind
|
||||
+ in struct __pthread_mutex_s in sysdeps/nptl/bits/thread-shared-types.h. */
|
||||
switch (__builtin_expect (PTHREAD_MUTEX_TYPE_ELISION (mutex),
|
||||
PTHREAD_MUTEX_TIMED_NP))
|
||||
{
|
||||
@@ -199,8 +201,14 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
|
||||
case PTHREAD_MUTEX_PI_ROBUST_NORMAL_NP:
|
||||
case PTHREAD_MUTEX_PI_ROBUST_ADAPTIVE_NP:
|
||||
{
|
||||
- int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP;
|
||||
- int robust = mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP;
|
||||
+ int kind, robust;
|
||||
+ {
|
||||
+ /* See concurrency notes regarding __kind in struct __pthread_mutex_s
|
||||
+ in sysdeps/nptl/bits/thread-shared-types.h. */
|
||||
+ int mutex_kind = atomic_load_relaxed (&(mutex->__data.__kind));
|
||||
+ kind = mutex_kind & PTHREAD_MUTEX_KIND_MASK_NP;
|
||||
+ robust = mutex_kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP;
|
||||
+ }
|
||||
|
||||
if (robust)
|
||||
/* Note: robust PI futexes are signaled by setting bit 0. */
|
||||
@@ -325,7 +333,10 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
|
||||
case PTHREAD_MUTEX_PP_NORMAL_NP:
|
||||
case PTHREAD_MUTEX_PP_ADAPTIVE_NP:
|
||||
{
|
||||
- int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP;
|
||||
+ /* See concurrency notes regarding __kind in struct __pthread_mutex_s
|
||||
+ in sysdeps/nptl/bits/thread-shared-types.h. */
|
||||
+ int kind = atomic_load_relaxed (&(mutex->__data.__kind))
|
||||
+ & PTHREAD_MUTEX_KIND_MASK_NP;
|
||||
|
||||
oldval = mutex->__data.__lock;
|
||||
|
||||
diff --git a/nptl/pthread_mutex_unlock.c b/nptl/pthread_mutex_unlock.c
|
||||
index 9ea62943b7c6b159..68d04d53955584e5 100644
|
||||
--- a/nptl/pthread_mutex_unlock.c
|
||||
+++ b/nptl/pthread_mutex_unlock.c
|
||||
@@ -35,6 +35,8 @@ int
|
||||
attribute_hidden
|
||||
__pthread_mutex_unlock_usercnt (pthread_mutex_t *mutex, int decr)
|
||||
{
|
||||
+ /* See concurrency notes regarding mutex type which is loaded from __kind
|
||||
+ in struct __pthread_mutex_s in sysdeps/nptl/bits/thread-shared-types.h. */
|
||||
int type = PTHREAD_MUTEX_TYPE_ELISION (mutex);
|
||||
if (__builtin_expect (type &
|
||||
~(PTHREAD_MUTEX_KIND_MASK_NP|PTHREAD_MUTEX_ELISION_FLAGS_NP), 0))
|
||||
@@ -222,13 +224,19 @@ __pthread_mutex_unlock_full (pthread_mutex_t *mutex, int decr)
|
||||
/* If the previous owner died and the caller did not succeed in
|
||||
making the state consistent, mark the mutex as unrecoverable
|
||||
and make all waiters. */
|
||||
- if ((mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) != 0
|
||||
+ /* See concurrency notes regarding __kind in struct __pthread_mutex_s
|
||||
+ in sysdeps/nptl/bits/thread-shared-types.h. */
|
||||
+ if ((atomic_load_relaxed (&(mutex->__data.__kind))
|
||||
+ & PTHREAD_MUTEX_ROBUST_NORMAL_NP) != 0
|
||||
&& __builtin_expect (mutex->__data.__owner
|
||||
== PTHREAD_MUTEX_INCONSISTENT, 0))
|
||||
pi_notrecoverable:
|
||||
newowner = PTHREAD_MUTEX_NOTRECOVERABLE;
|
||||
|
||||
- if ((mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) != 0)
|
||||
+ /* See concurrency notes regarding __kind in struct __pthread_mutex_s
|
||||
+ in sysdeps/nptl/bits/thread-shared-types.h. */
|
||||
+ if ((atomic_load_relaxed (&(mutex->__data.__kind))
|
||||
+ & PTHREAD_MUTEX_ROBUST_NORMAL_NP) != 0)
|
||||
{
|
||||
continue_pi_robust:
|
||||
/* Remove mutex from the list.
|
||||
@@ -251,7 +259,10 @@ __pthread_mutex_unlock_full (pthread_mutex_t *mutex, int decr)
|
||||
/* Unlock. Load all necessary mutex data before releasing the mutex
|
||||
to not violate the mutex destruction requirements (see
|
||||
lll_unlock). */
|
||||
- int robust = mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP;
|
||||
+ /* See concurrency notes regarding __kind in struct __pthread_mutex_s
|
||||
+ in sysdeps/nptl/bits/thread-shared-types.h. */
|
||||
+ int robust = atomic_load_relaxed (&(mutex->__data.__kind))
|
||||
+ & PTHREAD_MUTEX_ROBUST_NORMAL_NP;
|
||||
private = (robust
|
||||
? PTHREAD_ROBUST_MUTEX_PSHARED (mutex)
|
||||
: PTHREAD_MUTEX_PSHARED (mutex));
|
||||
diff --git a/nptl/tst-mutex10.c b/nptl/tst-mutex10.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..e1113ca60a7c8db5
|
||||
--- /dev/null
|
||||
+++ b/nptl/tst-mutex10.c
|
||||
@@ -0,0 +1,109 @@
|
||||
+/* Testing race while enabling lock elision.
|
||||
+ Copyright (C) 2018 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <stdint.h>
|
||||
+#include <pthread.h>
|
||||
+#include <unistd.h>
|
||||
+#include <getopt.h>
|
||||
+#include <support/support.h>
|
||||
+#include <support/xthread.h>
|
||||
+
|
||||
+static pthread_barrier_t barrier;
|
||||
+static pthread_mutex_t mutex;
|
||||
+static long long int iteration_count = 1000000;
|
||||
+static unsigned int thread_count = 3;
|
||||
+
|
||||
+static void *
|
||||
+thr_func (void *arg)
|
||||
+{
|
||||
+ long long int i;
|
||||
+ for (i = 0; i < iteration_count; i++)
|
||||
+ {
|
||||
+ if ((uintptr_t) arg == 0)
|
||||
+ {
|
||||
+ xpthread_mutex_destroy (&mutex);
|
||||
+ xpthread_mutex_init (&mutex, NULL);
|
||||
+ }
|
||||
+
|
||||
+ xpthread_barrier_wait (&barrier);
|
||||
+
|
||||
+ /* Test if enabling lock elision works if it is enabled concurrently.
|
||||
+ There was a race in FORCE_ELISION macro which leads to either
|
||||
+ pthread_mutex_destroy returning EBUSY as the owner was recorded
|
||||
+ by pthread_mutex_lock - in "normal mutex" code path - but was not
|
||||
+ resetted in pthread_mutex_unlock - in "elision" code path.
|
||||
+ Or it leads to the assertion in nptl/pthread_mutex_lock.c:
|
||||
+ assert (mutex->__data.__owner == 0);
|
||||
+ Please ensure that the test is run with lock elision:
|
||||
+ export GLIBC_TUNABLES=glibc.elision.enable=1 */
|
||||
+ xpthread_mutex_lock (&mutex);
|
||||
+ xpthread_mutex_unlock (&mutex);
|
||||
+
|
||||
+ xpthread_barrier_wait (&barrier);
|
||||
+ }
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ unsigned int i;
|
||||
+ printf ("Starting %d threads to run %lld iterations.\n",
|
||||
+ thread_count, iteration_count);
|
||||
+
|
||||
+ pthread_t *threads = xmalloc (thread_count * sizeof (pthread_t));
|
||||
+ xpthread_barrier_init (&barrier, NULL, thread_count);
|
||||
+ xpthread_mutex_init (&mutex, NULL);
|
||||
+
|
||||
+ for (i = 0; i < thread_count; i++)
|
||||
+ threads[i] = xpthread_create (NULL, thr_func, (void *) (uintptr_t) i);
|
||||
+
|
||||
+ for (i = 0; i < thread_count; i++)
|
||||
+ xpthread_join (threads[i]);
|
||||
+
|
||||
+ xpthread_barrier_destroy (&barrier);
|
||||
+ free (threads);
|
||||
+
|
||||
+ return EXIT_SUCCESS;
|
||||
+}
|
||||
+
|
||||
+#define OPT_ITERATIONS 10000
|
||||
+#define OPT_THREADS 10001
|
||||
+#define CMDLINE_OPTIONS \
|
||||
+ { "iterations", required_argument, NULL, OPT_ITERATIONS }, \
|
||||
+ { "threads", required_argument, NULL, OPT_THREADS },
|
||||
+static void
|
||||
+cmdline_process (int c)
|
||||
+{
|
||||
+ long long int arg = strtoll (optarg, NULL, 0);
|
||||
+ switch (c)
|
||||
+ {
|
||||
+ case OPT_ITERATIONS:
|
||||
+ if (arg > 0)
|
||||
+ iteration_count = arg;
|
||||
+ break;
|
||||
+ case OPT_THREADS:
|
||||
+ if (arg > 0 && arg < 100)
|
||||
+ thread_count = arg;
|
||||
+ break;
|
||||
+ }
|
||||
+}
|
||||
+#define CMDLINE_PROCESS cmdline_process
|
||||
+#define TIMEOUT 50
|
||||
+#include <support/test-driver.c>
|
||||
diff --git a/sysdeps/nptl/bits/thread-shared-types.h b/sysdeps/nptl/bits/thread-shared-types.h
|
||||
index 1e2092a05d5610f7..05c94e7a710c0eb9 100644
|
||||
--- a/sysdeps/nptl/bits/thread-shared-types.h
|
||||
+++ b/sysdeps/nptl/bits/thread-shared-types.h
|
||||
@@ -124,7 +124,27 @@ struct __pthread_mutex_s
|
||||
unsigned int __nusers;
|
||||
#endif
|
||||
/* KIND must stay at this position in the structure to maintain
|
||||
- binary compatibility with static initializers. */
|
||||
+ binary compatibility with static initializers.
|
||||
+
|
||||
+ Concurrency notes:
|
||||
+ The __kind of a mutex is initialized either by the static
|
||||
+ PTHREAD_MUTEX_INITIALIZER or by a call to pthread_mutex_init.
|
||||
+
|
||||
+ After a mutex has been initialized, the __kind of a mutex is usually not
|
||||
+ changed. BUT it can be set to -1 in pthread_mutex_destroy or elision can
|
||||
+ be enabled. This is done concurrently in the pthread_mutex_*lock functions
|
||||
+ by using the macro FORCE_ELISION. This macro is only defined for
|
||||
+ architectures which supports lock elision.
|
||||
+
|
||||
+ For elision, there are the flags PTHREAD_MUTEX_ELISION_NP and
|
||||
+ PTHREAD_MUTEX_NO_ELISION_NP which can be set in addition to the already set
|
||||
+ type of a mutex.
|
||||
+ Before a mutex is initialized, only PTHREAD_MUTEX_NO_ELISION_NP can be set
|
||||
+ with pthread_mutexattr_settype.
|
||||
+ After a mutex has been initialized, the functions pthread_mutex_*lock can
|
||||
+ enable elision - if the mutex-type and the machine supports it - by setting
|
||||
+ the flag PTHREAD_MUTEX_ELISION_NP. This is done concurrently. Afterwards
|
||||
+ the lock / unlock functions are using specific elision code-paths. */
|
||||
int __kind;
|
||||
__PTHREAD_COMPAT_PADDING_MID
|
||||
#if __PTHREAD_MUTEX_NUSERS_AFTER_KIND
|
||||
diff --git a/sysdeps/unix/sysv/linux/powerpc/force-elision.h b/sysdeps/unix/sysv/linux/powerpc/force-elision.h
|
||||
index fe5d6ceade2bad36..d8f5a4b1c7713bd4 100644
|
||||
--- a/sysdeps/unix/sysv/linux/powerpc/force-elision.h
|
||||
+++ b/sysdeps/unix/sysv/linux/powerpc/force-elision.h
|
||||
@@ -18,9 +18,45 @@
|
||||
|
||||
/* Automatically enable elision for existing user lock kinds. */
|
||||
#define FORCE_ELISION(m, s) \
|
||||
- if (__pthread_force_elision \
|
||||
- && (m->__data.__kind & PTHREAD_MUTEX_ELISION_FLAGS_NP) == 0) \
|
||||
+ if (__pthread_force_elision) \
|
||||
{ \
|
||||
- mutex->__data.__kind |= PTHREAD_MUTEX_ELISION_NP; \
|
||||
- s; \
|
||||
+ /* See concurrency notes regarding __kind in \
|
||||
+ struct __pthread_mutex_s in \
|
||||
+ sysdeps/nptl/bits/thread-shared-types.h. \
|
||||
+ \
|
||||
+ There are the following cases for the kind of a mutex \
|
||||
+ (The mask PTHREAD_MUTEX_ELISION_FLAGS_NP covers the flags \
|
||||
+ PTHREAD_MUTEX_ELISION_NP and PTHREAD_MUTEX_NO_ELISION_NP where \
|
||||
+ only one of both flags can be set): \
|
||||
+ - both flags are not set: \
|
||||
+ This is the first lock operation for this mutex. Enable \
|
||||
+ elision as it is not enabled so far. \
|
||||
+ Note: It can happen that multiple threads are calling e.g. \
|
||||
+ pthread_mutex_lock at the same time as the first lock \
|
||||
+ operation for this mutex. Then elision is enabled for this \
|
||||
+ mutex by multiple threads. Storing with relaxed MO is enough \
|
||||
+ as all threads will store the same new value for the kind of \
|
||||
+ the mutex. But we have to ensure that we always use the \
|
||||
+ elision path regardless if this thread has enabled elision or \
|
||||
+ another one. \
|
||||
+ \
|
||||
+ - PTHREAD_MUTEX_ELISION_NP flag is set: \
|
||||
+ Elision was already enabled for this mutex by a previous lock \
|
||||
+ operation. See case above. Just use the elision path. \
|
||||
+ \
|
||||
+ - PTHREAD_MUTEX_NO_ELISION_NP flag is set: \
|
||||
+ Elision was explicitly disabled by pthread_mutexattr_settype. \
|
||||
+ Do not use the elision path. \
|
||||
+ Note: The flag PTHREAD_MUTEX_NO_ELISION_NP will never be \
|
||||
+ changed after mutex initialization. */ \
|
||||
+ int mutex_kind = atomic_load_relaxed (&((m)->__data.__kind)); \
|
||||
+ if ((mutex_kind & PTHREAD_MUTEX_ELISION_FLAGS_NP) == 0) \
|
||||
+ { \
|
||||
+ mutex_kind |= PTHREAD_MUTEX_ELISION_NP; \
|
||||
+ atomic_store_relaxed (&((m)->__data.__kind), mutex_kind); \
|
||||
+ } \
|
||||
+ if ((mutex_kind & PTHREAD_MUTEX_ELISION_NP) != 0) \
|
||||
+ { \
|
||||
+ s; \
|
||||
+ } \
|
||||
}
|
||||
diff --git a/sysdeps/unix/sysv/linux/s390/force-elision.h b/sysdeps/unix/sysv/linux/s390/force-elision.h
|
||||
index d8a1b9972f739cfe..71f32367dd6b6489 100644
|
||||
--- a/sysdeps/unix/sysv/linux/s390/force-elision.h
|
||||
+++ b/sysdeps/unix/sysv/linux/s390/force-elision.h
|
||||
@@ -18,9 +18,45 @@
|
||||
|
||||
/* Automatically enable elision for existing user lock kinds. */
|
||||
#define FORCE_ELISION(m, s) \
|
||||
- if (__pthread_force_elision \
|
||||
- && (m->__data.__kind & PTHREAD_MUTEX_ELISION_FLAGS_NP) == 0) \
|
||||
+ if (__pthread_force_elision) \
|
||||
{ \
|
||||
- mutex->__data.__kind |= PTHREAD_MUTEX_ELISION_NP; \
|
||||
- s; \
|
||||
+ /* See concurrency notes regarding __kind in \
|
||||
+ struct __pthread_mutex_s in \
|
||||
+ sysdeps/nptl/bits/thread-shared-types.h. \
|
||||
+ \
|
||||
+ There are the following cases for the kind of a mutex \
|
||||
+ (The mask PTHREAD_MUTEX_ELISION_FLAGS_NP covers the flags \
|
||||
+ PTHREAD_MUTEX_ELISION_NP and PTHREAD_MUTEX_NO_ELISION_NP where \
|
||||
+ only one of both flags can be set): \
|
||||
+ - both flags are not set: \
|
||||
+ This is the first lock operation for this mutex. Enable \
|
||||
+ elision as it is not enabled so far. \
|
||||
+ Note: It can happen that multiple threads are calling e.g. \
|
||||
+ pthread_mutex_lock at the same time as the first lock \
|
||||
+ operation for this mutex. Then elision is enabled for this \
|
||||
+ mutex by multiple threads. Storing with relaxed MO is enough \
|
||||
+ as all threads will store the same new value for the kind of \
|
||||
+ the mutex. But we have to ensure that we always use the \
|
||||
+ elision path regardless if this thread has enabled elision or \
|
||||
+ another one. \
|
||||
+ \
|
||||
+ - PTHREAD_MUTEX_ELISION_NP flag is set: \
|
||||
+ Elision was already enabled for this mutex by a previous lock \
|
||||
+ operation. See case above. Just use the elision path. \
|
||||
+ \
|
||||
+ - PTHREAD_MUTEX_NO_ELISION_NP flag is set: \
|
||||
+ Elision was explicitly disabled by pthread_mutexattr_settype. \
|
||||
+ Do not use the elision path. \
|
||||
+ Note: The flag PTHREAD_MUTEX_NO_ELISION_NP will never be \
|
||||
+ changed after mutex initialization. */ \
|
||||
+ int mutex_kind = atomic_load_relaxed (&((m)->__data.__kind)); \
|
||||
+ if ((mutex_kind & PTHREAD_MUTEX_ELISION_FLAGS_NP) == 0) \
|
||||
+ { \
|
||||
+ mutex_kind |= PTHREAD_MUTEX_ELISION_NP; \
|
||||
+ atomic_store_relaxed (&((m)->__data.__kind), mutex_kind); \
|
||||
+ } \
|
||||
+ if ((mutex_kind & PTHREAD_MUTEX_ELISION_NP) != 0) \
|
||||
+ { \
|
||||
+ s; \
|
||||
+ } \
|
||||
}
|
||||
diff --git a/sysdeps/unix/sysv/linux/x86/force-elision.h b/sysdeps/unix/sysv/linux/x86/force-elision.h
|
||||
index dd659c908f3046c1..61282d6678d89787 100644
|
||||
--- a/sysdeps/unix/sysv/linux/x86/force-elision.h
|
||||
+++ b/sysdeps/unix/sysv/linux/x86/force-elision.h
|
||||
@@ -18,9 +18,45 @@
|
||||
|
||||
/* Automatically enable elision for existing user lock kinds. */
|
||||
#define FORCE_ELISION(m, s) \
|
||||
- if (__pthread_force_elision \
|
||||
- && (m->__data.__kind & PTHREAD_MUTEX_ELISION_FLAGS_NP) == 0) \
|
||||
+ if (__pthread_force_elision) \
|
||||
{ \
|
||||
- mutex->__data.__kind |= PTHREAD_MUTEX_ELISION_NP; \
|
||||
- s; \
|
||||
+ /* See concurrency notes regarding __kind in \
|
||||
+ struct __pthread_mutex_s in \
|
||||
+ sysdeps/nptl/bits/thread-shared-types.h. \
|
||||
+ \
|
||||
+ There are the following cases for the kind of a mutex \
|
||||
+ (The mask PTHREAD_MUTEX_ELISION_FLAGS_NP covers the flags \
|
||||
+ PTHREAD_MUTEX_ELISION_NP and PTHREAD_MUTEX_NO_ELISION_NP where \
|
||||
+ only one of both flags can be set): \
|
||||
+ - both flags are not set: \
|
||||
+ This is the first lock operation for this mutex. Enable \
|
||||
+ elision as it is not enabled so far. \
|
||||
+ Note: It can happen that multiple threads are calling e.g. \
|
||||
+ pthread_mutex_lock at the same time as the first lock \
|
||||
+ operation for this mutex. Then elision is enabled for this \
|
||||
+ mutex by multiple threads. Storing with relaxed MO is enough \
|
||||
+ as all threads will store the same new value for the kind of \
|
||||
+ the mutex. But we have to ensure that we always use the \
|
||||
+ elision path regardless if this thread has enabled elision or \
|
||||
+ another one. \
|
||||
+ \
|
||||
+ - PTHREAD_MUTEX_ELISION_NP flag is set: \
|
||||
+ Elision was already enabled for this mutex by a previous lock \
|
||||
+ operation. See case above. Just use the elision path. \
|
||||
+ \
|
||||
+ - PTHREAD_MUTEX_NO_ELISION_NP flag is set: \
|
||||
+ Elision was explicitly disabled by pthread_mutexattr_settype. \
|
||||
+ Do not use the elision path. \
|
||||
+ Note: The flag PTHREAD_MUTEX_NO_ELISION_NP will never be \
|
||||
+ changed after mutex initialization. */ \
|
||||
+ int mutex_kind = atomic_load_relaxed (&((m)->__data.__kind)); \
|
||||
+ if ((mutex_kind & PTHREAD_MUTEX_ELISION_FLAGS_NP) == 0) \
|
||||
+ { \
|
||||
+ mutex_kind |= PTHREAD_MUTEX_ELISION_NP; \
|
||||
+ atomic_store_relaxed (&((m)->__data.__kind), mutex_kind); \
|
||||
+ } \
|
||||
+ if ((mutex_kind & PTHREAD_MUTEX_ELISION_NP) != 0) \
|
||||
+ { \
|
||||
+ s; \
|
||||
+ } \
|
||||
}
|
24
SOURCES/glibc-rh1646379.patch
Normal file
24
SOURCES/glibc-rh1646379.patch
Normal file
@ -0,0 +1,24 @@
|
||||
commit bd3b0fbae33a9a4cc5e2daf049443d5cf03d4251
|
||||
Author: Andreas Schwab <schwab@suse.de>
|
||||
Date: Mon Nov 5 12:47:30 2018 +0100
|
||||
|
||||
libanl: properly cleanup if first helper thread creation failed (bug 22927)
|
||||
|
||||
diff --git a/resolv/gai_misc.c b/resolv/gai_misc.c
|
||||
index e7c3b63cc5725b4f..80a2cff8353fcb6c 100644
|
||||
--- a/resolv/gai_misc.c
|
||||
+++ b/resolv/gai_misc.c
|
||||
@@ -261,8 +261,11 @@ __gai_enqueue_request (struct gaicb *gaicbp)
|
||||
/* We cannot create a thread in the moment and there is
|
||||
also no thread running. This is a problem. `errno' is
|
||||
set to EAGAIN if this is only a temporary problem. */
|
||||
- assert (lastp->next == newp);
|
||||
- lastp->next = NULL;
|
||||
+ assert (requests == newp || lastp->next == newp);
|
||||
+ if (lastp != NULL)
|
||||
+ lastp->next = NULL;
|
||||
+ else
|
||||
+ requests = NULL;
|
||||
requests_tail = lastp;
|
||||
|
||||
newp->next = freelist;
|
48
SOURCES/glibc-rh1650560-1.patch
Normal file
48
SOURCES/glibc-rh1650560-1.patch
Normal file
@ -0,0 +1,48 @@
|
||||
commit 17b26500f9bb926d85e86821d014f7c1bb88043c
|
||||
Author: Joseph Myers <joseph@codesourcery.com>
|
||||
Date: Mon Aug 13 21:35:27 2018 +0000
|
||||
|
||||
Update syscall-names.list for Linux 4.18.
|
||||
|
||||
This patch updates sysdeps/unix/sysv/linux/syscall-names.list for
|
||||
Linux 4.18. The io_pgetevents and rseq syscalls are added to the
|
||||
kernel on various architectures, so need to be mentioned in this file.
|
||||
|
||||
Tested with build-many-glibcs.py.
|
||||
|
||||
* sysdeps/unix/sysv/linux/syscall-names.list: Update kernel
|
||||
version to 4.18.
|
||||
(io_pgetevents): New syscall.
|
||||
(rseq): Likewise.
|
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list
|
||||
index 5306d538e6448163..9982a6334d46ae62 100644
|
||||
--- a/sysdeps/unix/sysv/linux/syscall-names.list
|
||||
+++ b/sysdeps/unix/sysv/linux/syscall-names.list
|
||||
@@ -22,8 +22,8 @@
|
||||
# names are only used if the installed kernel headers also provide
|
||||
# them.
|
||||
|
||||
-# The list of system calls is current as of Linux 4.17.
|
||||
-kernel 4.17
|
||||
+# The list of system calls is current as of Linux 4.18.
|
||||
+kernel 4.18
|
||||
|
||||
FAST_atomic_update
|
||||
FAST_cmpxchg
|
||||
@@ -186,6 +186,7 @@ inotify_rm_watch
|
||||
io_cancel
|
||||
io_destroy
|
||||
io_getevents
|
||||
+io_pgetevents
|
||||
io_setup
|
||||
io_submit
|
||||
ioctl
|
||||
@@ -431,6 +432,7 @@ renameat2
|
||||
request_key
|
||||
restart_syscall
|
||||
rmdir
|
||||
+rseq
|
||||
rt_sigaction
|
||||
rt_sigpending
|
||||
rt_sigprocmask
|
30
SOURCES/glibc-rh1650560-2.patch
Normal file
30
SOURCES/glibc-rh1650560-2.patch
Normal file
@ -0,0 +1,30 @@
|
||||
commit 029ad711b8ad4cf0e5d98e0c138a35a23a376a74
|
||||
Author: Joseph Myers <joseph@codesourcery.com>
|
||||
Date: Mon Oct 22 23:26:37 2018 +0000
|
||||
|
||||
Update kernel version in syscall-names.list to 4.19.
|
||||
|
||||
Linux 4.19 does not add any new syscalls (some existing ones are added
|
||||
to more architectures); this patch updates the version number in
|
||||
syscall-names.list to reflect that it's still current for 4.19.
|
||||
|
||||
Tested with build-many-glibcs.py.
|
||||
|
||||
* sysdeps/unix/sysv/linux/syscall-names.list: Update kernel
|
||||
version to 4.19.
|
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list
|
||||
index 9982a6334d46ae62..f88001c9c38d5fc7 100644
|
||||
--- a/sysdeps/unix/sysv/linux/syscall-names.list
|
||||
+++ b/sysdeps/unix/sysv/linux/syscall-names.list
|
||||
@@ -22,8 +22,8 @@
|
||||
# names are only used if the installed kernel headers also provide
|
||||
# them.
|
||||
|
||||
-# The list of system calls is current as of Linux 4.18.
|
||||
-kernel 4.18
|
||||
+# The list of system calls is current as of Linux 4.19.
|
||||
+kernel 4.19
|
||||
|
||||
FAST_atomic_update
|
||||
FAST_cmpxchg
|
127
SOURCES/glibc-rh1650563.patch
Normal file
127
SOURCES/glibc-rh1650563.patch
Normal file
@ -0,0 +1,127 @@
|
||||
commit 745664bd798ec8fd50438605948eea594179fba1
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Aug 28 13:19:27 2018 +0200
|
||||
|
||||
nscd: Fix use-after-free in addgetnetgrentX [BZ #23520]
|
||||
|
||||
addinnetgrX may use the heap-allocated buffer, so free the buffer
|
||||
in this function.
|
||||
|
||||
diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c
|
||||
index 2b35389cc816c3c8..87059fb28042f0a5 100644
|
||||
--- a/nscd/netgroupcache.c
|
||||
+++ b/nscd/netgroupcache.c
|
||||
@@ -113,7 +113,8 @@ do_notfound (struct database_dyn *db, int fd, request_header *req,
|
||||
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)
|
||||
+ struct datahead *dh, struct dataset **resultp,
|
||||
+ void **tofreep)
|
||||
{
|
||||
if (__glibc_unlikely (debug_level > 0))
|
||||
{
|
||||
@@ -139,6 +140,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
|
||||
size_t group_len = strlen (key) + 1;
|
||||
struct name_list *first_needed
|
||||
= alloca (sizeof (struct name_list) + group_len);
|
||||
+ *tofreep = NULL;
|
||||
|
||||
if (netgroup_database == NULL
|
||||
&& __nss_database_lookup ("netgroup", NULL, NULL, &netgroup_database))
|
||||
@@ -151,6 +153,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
|
||||
|
||||
memset (&data, '\0', sizeof (data));
|
||||
buffer = xmalloc (buflen);
|
||||
+ *tofreep = buffer;
|
||||
first_needed->next = first_needed;
|
||||
memcpy (first_needed->name, key, group_len);
|
||||
data.needed_groups = first_needed;
|
||||
@@ -439,8 +442,6 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
|
||||
}
|
||||
|
||||
out:
|
||||
- free (buffer);
|
||||
-
|
||||
*resultp = dataset;
|
||||
|
||||
return timeout;
|
||||
@@ -477,8 +478,12 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
|
||||
group, group_len,
|
||||
db, uid);
|
||||
time_t timeout;
|
||||
+ void *tofree;
|
||||
if (result != NULL)
|
||||
- timeout = result->head.timeout;
|
||||
+ {
|
||||
+ timeout = result->head.timeout;
|
||||
+ tofree = NULL;
|
||||
+ }
|
||||
else
|
||||
{
|
||||
request_header req_get =
|
||||
@@ -487,7 +492,7 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
|
||||
.key_len = group_len
|
||||
};
|
||||
timeout = addgetnetgrentX (db, -1, &req_get, group, uid, NULL, NULL,
|
||||
- &result);
|
||||
+ &result, &tofree);
|
||||
}
|
||||
|
||||
struct indataset
|
||||
@@ -560,7 +565,7 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
|
||||
++dh->nreloads;
|
||||
if (cacheable)
|
||||
pthread_rwlock_unlock (&db->lock);
|
||||
- return timeout;
|
||||
+ goto out;
|
||||
}
|
||||
|
||||
if (he == NULL)
|
||||
@@ -596,17 +601,30 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
|
||||
dh->usable = false;
|
||||
}
|
||||
|
||||
+ out:
|
||||
+ free (tofree);
|
||||
return timeout;
|
||||
}
|
||||
|
||||
|
||||
+static time_t
|
||||
+addgetnetgrentX_ignore (struct database_dyn *db, int fd, request_header *req,
|
||||
+ const char *key, uid_t uid, struct hashentry *he,
|
||||
+ struct datahead *dh)
|
||||
+{
|
||||
+ struct dataset *ignore;
|
||||
+ void *tofree;
|
||||
+ time_t timeout = addgetnetgrentX (db, fd, req, key, uid, he, dh,
|
||||
+ &ignore, &tofree);
|
||||
+ free (tofree);
|
||||
+ 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);
|
||||
+ addgetnetgrentX_ignore (db, fd, req, key, uid, NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -619,10 +637,8 @@ readdgetnetgrent (struct database_dyn *db, struct hashentry *he,
|
||||
.type = GETNETGRENT,
|
||||
.key_len = he->len
|
||||
};
|
||||
- struct dataset *ignore;
|
||||
-
|
||||
- return addgetnetgrentX (db, -1, &req, db->data + he->key, he->owner, he, dh,
|
||||
- &ignore);
|
||||
+ return addgetnetgrentX_ignore
|
||||
+ (db, -1, &req, db->data + he->key, he->owner, he, dh);
|
||||
}
|
||||
|
||||
|
234
SOURCES/glibc-rh1650566.patch
Normal file
234
SOURCES/glibc-rh1650566.patch
Normal file
@ -0,0 +1,234 @@
|
||||
commit a6e8926f8d49a213a9abb1a61f6af964f612ab7f
|
||||
Author: Paul Pluzhnikov <ppluzhnikov@google.com>
|
||||
Date: Fri Aug 31 18:04:32 2018 -0700
|
||||
|
||||
[BZ #20271] Add newlines in __libc_fatal calls.
|
||||
|
||||
diff --git a/grp/initgroups.c b/grp/initgroups.c
|
||||
index f056fbf5aa6aa14c..93e7f5814da6286d 100644
|
||||
--- a/grp/initgroups.c
|
||||
+++ b/grp/initgroups.c
|
||||
@@ -128,7 +128,7 @@ internal_getgrouplist (const char *user, gid_t group, long int *size,
|
||||
|
||||
/* This is really only for debugging. */
|
||||
if (NSS_STATUS_TRYAGAIN > status || status > NSS_STATUS_RETURN)
|
||||
- __libc_fatal ("illegal status in internal_getgrouplist");
|
||||
+ __libc_fatal ("Illegal status in internal_getgrouplist.\n");
|
||||
|
||||
/* For compatibility reason we will continue to look for more
|
||||
entries using the next service even though data has already
|
||||
diff --git a/include/stdio.h b/include/stdio.h
|
||||
index 9162d4e24717e31a..7a5c09089fc4d348 100644
|
||||
--- a/include/stdio.h
|
||||
+++ b/include/stdio.h
|
||||
@@ -98,7 +98,8 @@ enum __libc_message_action
|
||||
do_backtrace = 1 << 1 /* Backtrace. */
|
||||
};
|
||||
|
||||
-/* Print out MESSAGE on the error output and abort. */
|
||||
+/* Print out MESSAGE (which should end with a newline) on the error output
|
||||
+ and abort. */
|
||||
extern void __libc_fatal (const char *__message)
|
||||
__attribute__ ((__noreturn__));
|
||||
extern void __libc_message (enum __libc_message_action action,
|
||||
diff --git a/nptl/pthread_cond_wait.c b/nptl/pthread_cond_wait.c
|
||||
index 3e1105418210288e..ebf07ca82d87de7d 100644
|
||||
--- a/nptl/pthread_cond_wait.c
|
||||
+++ b/nptl/pthread_cond_wait.c
|
||||
@@ -516,7 +516,7 @@ __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||
struct timespec rt;
|
||||
if (__clock_gettime (CLOCK_MONOTONIC, &rt) != 0)
|
||||
__libc_fatal ("clock_gettime does not support "
|
||||
- "CLOCK_MONOTONIC");
|
||||
+ "CLOCK_MONOTONIC\n");
|
||||
/* Convert the absolute timeout value to a relative
|
||||
timeout. */
|
||||
rt.tv_sec = abstime->tv_sec - rt.tv_sec;
|
||||
diff --git a/nscd/initgrcache.c b/nscd/initgrcache.c
|
||||
index 2c74951f579f4afd..4764f14a45f68e0a 100644
|
||||
--- a/nscd/initgrcache.c
|
||||
+++ b/nscd/initgrcache.c
|
||||
@@ -159,7 +159,7 @@ addinitgroupsX (struct database_dyn *db, int fd, request_header *req,
|
||||
|
||||
/* This is really only for debugging. */
|
||||
if (NSS_STATUS_TRYAGAIN > status || status > NSS_STATUS_RETURN)
|
||||
- __libc_fatal ("illegal status in internal_getgrouplist");
|
||||
+ __libc_fatal ("Illegal status in internal_getgrouplist.\n");
|
||||
|
||||
any_success |= status == NSS_STATUS_SUCCESS;
|
||||
|
||||
diff --git a/nss/nsswitch.c b/nss/nsswitch.c
|
||||
index ee46f24424bc1ca2..3c48b4b85e881cdb 100644
|
||||
--- a/nss/nsswitch.c
|
||||
+++ b/nss/nsswitch.c
|
||||
@@ -235,7 +235,7 @@ __nss_next2 (service_user **ni, const char *fct_name, const char *fct2_name,
|
||||
/* This is really only for debugging. */
|
||||
if (__builtin_expect (NSS_STATUS_TRYAGAIN > status
|
||||
|| status > NSS_STATUS_RETURN, 0))
|
||||
- __libc_fatal ("illegal status in __nss_next");
|
||||
+ __libc_fatal ("Illegal status in __nss_next.\n");
|
||||
|
||||
if (nss_next_action (*ni, status) == NSS_ACTION_RETURN)
|
||||
return 1;
|
||||
diff --git a/sysdeps/aarch64/dl-irel.h b/sysdeps/aarch64/dl-irel.h
|
||||
index 5889ee187b7a1eaf..bef71ed0f31a6387 100644
|
||||
--- a/sysdeps/aarch64/dl-irel.h
|
||||
+++ b/sysdeps/aarch64/dl-irel.h
|
||||
@@ -47,7 +47,7 @@ elf_irela (const ElfW(Rela) *reloc)
|
||||
*reloc_addr = value;
|
||||
}
|
||||
else
|
||||
- __libc_fatal ("unexpected reloc type in static binary");
|
||||
+ __libc_fatal ("Unexpected reloc type in static binary.\n");
|
||||
}
|
||||
|
||||
#endif
|
||||
diff --git a/sysdeps/arm/dl-irel.h b/sysdeps/arm/dl-irel.h
|
||||
index a7b6456075659baf..be6eb7743eb5f08d 100644
|
||||
--- a/sysdeps/arm/dl-irel.h
|
||||
+++ b/sysdeps/arm/dl-irel.h
|
||||
@@ -46,7 +46,7 @@ elf_irel (const Elf32_Rel *reloc)
|
||||
*reloc_addr = value;
|
||||
}
|
||||
else
|
||||
- __libc_fatal ("unexpected reloc type in static binary");
|
||||
+ __libc_fatal ("Unexpected reloc type in static binary.\n");
|
||||
}
|
||||
|
||||
#endif /* dl-irel.h */
|
||||
diff --git a/sysdeps/generic/unwind-dw2.c b/sysdeps/generic/unwind-dw2.c
|
||||
index 082609b34a3f773b..724c16a7f0bf465b 100644
|
||||
--- a/sysdeps/generic/unwind-dw2.c
|
||||
+++ b/sysdeps/generic/unwind-dw2.c
|
||||
@@ -843,7 +843,7 @@ execute_cfa_program (const unsigned char *insn_ptr,
|
||||
struct frame_state_reg_info *old_rs = fs->regs.prev;
|
||||
#ifdef _LIBC
|
||||
if (old_rs == NULL)
|
||||
- __libc_fatal ("invalid DWARF unwind data");
|
||||
+ __libc_fatal ("Invalid DWARF unwind data.\n");
|
||||
else
|
||||
#endif
|
||||
{
|
||||
diff --git a/sysdeps/i386/dl-irel.h b/sysdeps/i386/dl-irel.h
|
||||
index 55303180c7aca495..bcaf0668acf8e2f2 100644
|
||||
--- a/sysdeps/i386/dl-irel.h
|
||||
+++ b/sysdeps/i386/dl-irel.h
|
||||
@@ -45,7 +45,7 @@ elf_irel (const Elf32_Rel *reloc)
|
||||
*reloc_addr = value;
|
||||
}
|
||||
else
|
||||
- __libc_fatal ("unexpected reloc type in static binary");
|
||||
+ __libc_fatal ("Unexpected reloc type in static binary.\n");
|
||||
}
|
||||
|
||||
#endif /* dl-irel.h */
|
||||
diff --git a/sysdeps/nptl/futex-internal.h b/sysdeps/nptl/futex-internal.h
|
||||
index 1a5624789d4ab117..6fd27f0df6c27b69 100644
|
||||
--- a/sysdeps/nptl/futex-internal.h
|
||||
+++ b/sysdeps/nptl/futex-internal.h
|
||||
@@ -197,7 +197,7 @@ futex_wake (unsigned int* futex_word, int processes_to_wake, int private);
|
||||
static __always_inline __attribute__ ((__noreturn__)) void
|
||||
futex_fatal_error (void)
|
||||
{
|
||||
- __libc_fatal ("The futex facility returned an unexpected error code.");
|
||||
+ __libc_fatal ("The futex facility returned an unexpected error code.\n");
|
||||
}
|
||||
|
||||
#endif /* futex-internal.h */
|
||||
diff --git a/sysdeps/powerpc/powerpc32/dl-irel.h b/sysdeps/powerpc/powerpc32/dl-irel.h
|
||||
index a7368b25829618cb..61d0e4cf61ec45d3 100644
|
||||
--- a/sysdeps/powerpc/powerpc32/dl-irel.h
|
||||
+++ b/sysdeps/powerpc/powerpc32/dl-irel.h
|
||||
@@ -46,7 +46,7 @@ elf_irela (const Elf32_Rela *reloc)
|
||||
*reloc_addr = value;
|
||||
}
|
||||
else
|
||||
- __libc_fatal ("unexpected reloc type in static binary");
|
||||
+ __libc_fatal ("Unexpected reloc type in static binary.\n");
|
||||
}
|
||||
|
||||
#endif /* dl-irel.h */
|
||||
diff --git a/sysdeps/powerpc/powerpc64/dl-irel.h b/sysdeps/powerpc/powerpc64/dl-irel.h
|
||||
index ab13c04358868270..2fd0ee8a86e85ba0 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/dl-irel.h
|
||||
+++ b/sysdeps/powerpc/powerpc64/dl-irel.h
|
||||
@@ -57,7 +57,7 @@ elf_irela (const Elf64_Rela *reloc)
|
||||
#endif
|
||||
}
|
||||
else
|
||||
- __libc_fatal ("unexpected reloc type in static binary");
|
||||
+ __libc_fatal ("Unexpected reloc type in static binary.\n");
|
||||
}
|
||||
|
||||
#endif /* dl-irel.h */
|
||||
diff --git a/sysdeps/s390/dl-irel.h b/sysdeps/s390/dl-irel.h
|
||||
index d8ba7ba42709f45c..ecb24f0a9be0daa7 100644
|
||||
--- a/sysdeps/s390/dl-irel.h
|
||||
+++ b/sysdeps/s390/dl-irel.h
|
||||
@@ -46,7 +46,7 @@ elf_irela (const ElfW(Rela) *reloc)
|
||||
*reloc_addr = value;
|
||||
}
|
||||
else
|
||||
- __libc_fatal ("unexpected reloc type in static binary");
|
||||
+ __libc_fatal ("Unexpected reloc type in static binary.\n");
|
||||
}
|
||||
|
||||
#endif /* dl-irel.h */
|
||||
diff --git a/sysdeps/sparc/sparc32/dl-irel.h b/sysdeps/sparc/sparc32/dl-irel.h
|
||||
index ffca36864f24d1fb..cf47cda8345b1a39 100644
|
||||
--- a/sysdeps/sparc/sparc32/dl-irel.h
|
||||
+++ b/sysdeps/sparc/sparc32/dl-irel.h
|
||||
@@ -56,7 +56,7 @@ elf_irela (const Elf32_Rela *reloc)
|
||||
else if (r_type == R_SPARC_NONE)
|
||||
;
|
||||
else
|
||||
- __libc_fatal ("unexpected reloc type in static binary");
|
||||
+ __libc_fatal ("Unexpected reloc type in static binary.\n");
|
||||
}
|
||||
|
||||
#endif /* dl-irel.h */
|
||||
diff --git a/sysdeps/sparc/sparc64/dl-irel.h b/sysdeps/sparc/sparc64/dl-irel.h
|
||||
index c5cd3057aca1baf6..446fed18365cfd13 100644
|
||||
--- a/sysdeps/sparc/sparc64/dl-irel.h
|
||||
+++ b/sysdeps/sparc/sparc64/dl-irel.h
|
||||
@@ -59,7 +59,7 @@ elf_irela (const Elf64_Rela *reloc)
|
||||
else if (r_type == R_SPARC_NONE)
|
||||
;
|
||||
else
|
||||
- __libc_fatal ("unexpected reloc type in static binary");
|
||||
+ __libc_fatal ("Unexpected reloc type in static binary.\n");
|
||||
}
|
||||
|
||||
#endif /* dl-irel.h */
|
||||
diff --git a/sysdeps/unix/sysv/linux/netlink_assert_response.c b/sysdeps/unix/sysv/linux/netlink_assert_response.c
|
||||
index f31ccb52ffa56436..6afc3a17ced18e1c 100644
|
||||
--- a/sysdeps/unix/sysv/linux/netlink_assert_response.c
|
||||
+++ b/sysdeps/unix/sysv/linux/netlink_assert_response.c
|
||||
@@ -72,12 +72,12 @@ __netlink_assert_response (int fd, ssize_t result)
|
||||
char message[200];
|
||||
if (family < 0)
|
||||
__snprintf (message, sizeof (message),
|
||||
- "Unexpected error %d on netlink descriptor %d",
|
||||
+ "Unexpected error %d on netlink descriptor %d.\n",
|
||||
error_code, fd);
|
||||
else
|
||||
__snprintf (message, sizeof (message),
|
||||
"Unexpected error %d on netlink descriptor %d"
|
||||
- " (address family %d)",
|
||||
+ " (address family %d).\n",
|
||||
error_code, fd, family);
|
||||
__libc_fatal (message);
|
||||
}
|
||||
diff --git a/sysdeps/x86_64/dl-irel.h b/sysdeps/x86_64/dl-irel.h
|
||||
index 6ecc50fb42333c19..33f100d8b1781ea7 100644
|
||||
--- a/sysdeps/x86_64/dl-irel.h
|
||||
+++ b/sysdeps/x86_64/dl-irel.h
|
||||
@@ -45,7 +45,7 @@ elf_irela (const ElfW(Rela) *reloc)
|
||||
*reloc_addr = value;
|
||||
}
|
||||
else
|
||||
- __libc_fatal ("unexpected reloc type in static binary");
|
||||
+ __libc_fatal ("Unexpected reloc type in static binary.\n");
|
||||
}
|
||||
|
||||
#endif /* dl-irel.h */
|
24
SOURCES/glibc-rh1650571.patch
Normal file
24
SOURCES/glibc-rh1650571.patch
Normal file
@ -0,0 +1,24 @@
|
||||
commit e4e4fde51a309801af5eed72d3494cbf4b7737aa
|
||||
Author: Paul Eggert <eggert@cs.ucla.edu>
|
||||
Date: Tue Sep 18 15:02:10 2018 -0700
|
||||
|
||||
Fix tzfile low-memory assertion failure
|
||||
|
||||
[BZ #21716]
|
||||
* time/tzfile.c (__tzfile_read): Check for memory exhaustion
|
||||
when registering time zone abbreviations.
|
||||
|
||||
diff --git a/time/tzfile.c b/time/tzfile.c
|
||||
index 2a385b92bcdefec0..ea6e94030392fc75 100644
|
||||
--- a/time/tzfile.c
|
||||
+++ b/time/tzfile.c
|
||||
@@ -410,7 +410,8 @@ __tzfile_read (const char *file, size_t extra, char **extrap)
|
||||
|
||||
/* First "register" all timezone names. */
|
||||
for (i = 0; i < num_types; ++i)
|
||||
- (void) __tzstring (&zone_names[types[i].idx]);
|
||||
+ if (__tzstring (&zone_names[types[i].idx]) == NULL)
|
||||
+ goto ret_free_transitions;
|
||||
|
||||
/* Find the standard and daylight time offsets used by the rule file.
|
||||
We choose the offsets in the types of each flavor that are
|
70
SOURCES/glibc-rh1651274.patch
Normal file
70
SOURCES/glibc-rh1651274.patch
Normal file
@ -0,0 +1,70 @@
|
||||
commit 35e3fbc4512c880fccb35b8e3abd132d4be18480
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Mon Nov 19 15:35:03 2018 +0100
|
||||
|
||||
support: Print timestamps in timeout handler
|
||||
|
||||
This is sometimes useful to determine if a test truly got stuck, or if
|
||||
it was making progress (logging information to standard output) and
|
||||
was merely slow to finish.
|
||||
|
||||
diff --git a/support/support_test_main.c b/support/support_test_main.c
|
||||
index 23429779aca85613..fa3c2e06dee5ae0f 100644
|
||||
--- a/support/support_test_main.c
|
||||
+++ b/support/support_test_main.c
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <string.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/resource.h>
|
||||
+#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <time.h>
|
||||
@@ -86,6 +87,19 @@ static pid_t test_pid;
|
||||
/* The cleanup handler passed to test_main. */
|
||||
static void (*cleanup_function) (void);
|
||||
|
||||
+static void
|
||||
+print_timestamp (const char *what, struct timeval tv)
|
||||
+{
|
||||
+ struct tm tm;
|
||||
+ if (gmtime_r (&tv.tv_sec, &tm) == NULL)
|
||||
+ printf ("%s: %lld.%06d\n",
|
||||
+ what, (long long int) tv.tv_sec, (int) tv.tv_usec);
|
||||
+ else
|
||||
+ printf ("%s: %04d-%02d-%02dT%02d:%02d:%02d.%06d\n",
|
||||
+ what, 1900 + tm.tm_year, tm.tm_mon + 1, tm.tm_mday,
|
||||
+ tm.tm_hour, tm.tm_min, tm.tm_sec, (int) tv.tv_usec);
|
||||
+}
|
||||
+
|
||||
/* Timeout handler. We kill the child and exit with an error. */
|
||||
static void
|
||||
__attribute__ ((noreturn))
|
||||
@@ -94,6 +108,13 @@ signal_handler (int sig)
|
||||
int killed;
|
||||
int status;
|
||||
|
||||
+ /* Do this first to avoid further interference from the
|
||||
+ subprocess. */
|
||||
+ struct timeval now;
|
||||
+ bool now_available = gettimeofday (&now, NULL) == 0;
|
||||
+ struct stat64 st;
|
||||
+ bool st_available = fstat64 (STDOUT_FILENO, &st) == 0 && st.st_mtime != 0;
|
||||
+
|
||||
assert (test_pid > 1);
|
||||
/* Kill the whole process group. */
|
||||
kill (-test_pid, SIGKILL);
|
||||
@@ -144,6 +165,13 @@ signal_handler (int sig)
|
||||
printf ("Timed out: killed the child process but it exited %d\n",
|
||||
WEXITSTATUS (status));
|
||||
|
||||
+ if (now_available)
|
||||
+ print_timestamp ("Termination time", now);
|
||||
+ if (st_available)
|
||||
+ print_timestamp ("Last write to standard output",
|
||||
+ (struct timeval) { st.st_mtim.tv_sec,
|
||||
+ st.st_mtim.tv_nsec / 1000 });
|
||||
+
|
||||
/* Exit with an error. */
|
||||
exit (1);
|
||||
}
|
31
SOURCES/glibc-rh1651283-1.patch
Normal file
31
SOURCES/glibc-rh1651283-1.patch
Normal file
@ -0,0 +1,31 @@
|
||||
commit d6db68e66dff25d12c3bc5641b60cbd7fb6ab44f
|
||||
Author: Moritz Eckert <m.eckert@cs.ucsb.edu>
|
||||
Date: Thu Aug 16 21:08:36 2018 -0400
|
||||
|
||||
malloc: Mitigate null-byte overflow attacks
|
||||
|
||||
* malloc/malloc.c (_int_free): Check for corrupt prev_size vs size.
|
||||
(malloc_consolidate): Likewise.
|
||||
|
||||
diff --git a/malloc/malloc.c b/malloc/malloc.c
|
||||
index 13c52f376859562d..e450597e2e527fb7 100644
|
||||
--- a/malloc/malloc.c
|
||||
+++ b/malloc/malloc.c
|
||||
@@ -4306,6 +4306,8 @@ _int_free (mstate av, mchunkptr p, int have_lock)
|
||||
prevsize = prev_size (p);
|
||||
size += prevsize;
|
||||
p = chunk_at_offset(p, -((long) prevsize));
|
||||
+ if (__glibc_unlikely (chunksize(p) != prevsize))
|
||||
+ malloc_printerr ("corrupted size vs. prev_size while consolidating");
|
||||
unlink(av, p, bck, fwd);
|
||||
}
|
||||
|
||||
@@ -4467,6 +4469,8 @@ static void malloc_consolidate(mstate av)
|
||||
prevsize = prev_size (p);
|
||||
size += prevsize;
|
||||
p = chunk_at_offset(p, -((long) prevsize));
|
||||
+ if (__glibc_unlikely (chunksize(p) != prevsize))
|
||||
+ malloc_printerr ("corrupted size vs. prev_size in fastbins");
|
||||
unlink(av, p, bck, fwd);
|
||||
}
|
||||
|
30
SOURCES/glibc-rh1651283-2.patch
Normal file
30
SOURCES/glibc-rh1651283-2.patch
Normal file
@ -0,0 +1,30 @@
|
||||
commit 30a17d8c95fbfb15c52d1115803b63aaa73a285c
|
||||
Author: Pochang Chen <johnchen902@gmail.com>
|
||||
Date: Thu Aug 16 15:24:24 2018 -0400
|
||||
|
||||
malloc: Verify size of top chunk.
|
||||
|
||||
The House of Force is a well-known technique to exploit heap
|
||||
overflow. In essence, this exploit takes three steps:
|
||||
1. Overwrite the size of top chunk with very large value (e.g. -1).
|
||||
2. Request x bytes from top chunk. As the size of top chunk
|
||||
is corrupted, x can be arbitrarily large and top chunk will
|
||||
still be offset by x.
|
||||
3. The next allocation from top chunk will thus be controllable.
|
||||
|
||||
If we verify the size of top chunk at step 2, we can stop such attack.
|
||||
|
||||
diff --git a/malloc/malloc.c b/malloc/malloc.c
|
||||
index e450597e2e527fb7..d8d4581a9dcea80a 100644
|
||||
--- a/malloc/malloc.c
|
||||
+++ b/malloc/malloc.c
|
||||
@@ -4084,6 +4084,9 @@ _int_malloc (mstate av, size_t bytes)
|
||||
victim = av->top;
|
||||
size = chunksize (victim);
|
||||
|
||||
+ if (__glibc_unlikely (size > av->system_mem))
|
||||
+ malloc_printerr ("malloc(): corrupted top size");
|
||||
+
|
||||
if ((unsigned long) (size) >= (unsigned long) (nb + MINSIZE))
|
||||
{
|
||||
remainder_size = size - nb;
|
122
SOURCES/glibc-rh1651283-3.patch
Normal file
122
SOURCES/glibc-rh1651283-3.patch
Normal file
@ -0,0 +1,122 @@
|
||||
commit b90ddd08f6dd688e651df9ee89ca3a69ff88cd0c
|
||||
Author: Istvan Kurucsai <pistukem@gmail.com>
|
||||
Date: Tue Jan 16 14:54:32 2018 +0100
|
||||
|
||||
malloc: Additional checks for unsorted bin integrity I.
|
||||
|
||||
On Thu, Jan 11, 2018 at 3:50 PM, Florian Weimer <fweimer@redhat.com> wrote:
|
||||
> On 11/07/2017 04:27 PM, Istvan Kurucsai wrote:
|
||||
>>
|
||||
>> + next = chunk_at_offset (victim, size);
|
||||
>
|
||||
>
|
||||
> For new code, we prefer declarations with initializers.
|
||||
|
||||
Noted.
|
||||
|
||||
>> + if (__glibc_unlikely (chunksize_nomask (victim) <= 2 * SIZE_SZ)
|
||||
>> + || __glibc_unlikely (chunksize_nomask (victim) >
|
||||
>> av->system_mem))
|
||||
>> + malloc_printerr("malloc(): invalid size (unsorted)");
|
||||
>> + if (__glibc_unlikely (chunksize_nomask (next) < 2 * SIZE_SZ)
|
||||
>> + || __glibc_unlikely (chunksize_nomask (next) >
|
||||
>> av->system_mem))
|
||||
>> + malloc_printerr("malloc(): invalid next size (unsorted)");
|
||||
>> + if (__glibc_unlikely ((prev_size (next) & ~(SIZE_BITS)) !=
|
||||
>> size))
|
||||
>> + malloc_printerr("malloc(): mismatching next->prev_size
|
||||
>> (unsorted)");
|
||||
>
|
||||
>
|
||||
> I think this check is redundant because prev_size (next) and chunksize
|
||||
> (victim) are loaded from the same memory location.
|
||||
|
||||
I'm fairly certain that it compares mchunk_size of victim against
|
||||
mchunk_prev_size of the next chunk, i.e. the size of victim in its
|
||||
header and footer.
|
||||
|
||||
>> + if (__glibc_unlikely (bck->fd != victim)
|
||||
>> + || __glibc_unlikely (victim->fd != unsorted_chunks (av)))
|
||||
>> + malloc_printerr("malloc(): unsorted double linked list
|
||||
>> corrupted");
|
||||
>> + if (__glibc_unlikely (prev_inuse(next)))
|
||||
>> + malloc_printerr("malloc(): invalid next->prev_inuse
|
||||
>> (unsorted)");
|
||||
>
|
||||
>
|
||||
> There's a missing space after malloc_printerr.
|
||||
|
||||
Noted.
|
||||
|
||||
> Why do you keep using chunksize_nomask? We never investigated why the
|
||||
> original code uses it. It may have been an accident.
|
||||
|
||||
You are right, I don't think it makes a difference in these checks. So
|
||||
the size local can be reused for the checks against victim. For next,
|
||||
leaving it as such avoids the masking operation.
|
||||
|
||||
> Again, for non-main arenas, the checks against av->system_mem could be made
|
||||
> tighter (against the heap size). Maybe you could put the condition into a
|
||||
> separate inline function?
|
||||
|
||||
We could also do a chunk boundary check similar to what I proposed in
|
||||
the thread for the first patch in the series to be even more strict.
|
||||
I'll gladly try to implement either but believe that refining these
|
||||
checks would bring less benefits than in the case of the top chunk.
|
||||
Intra-arena or intra-heap overlaps would still be doable here with
|
||||
unsorted chunks and I don't see any way to counter that besides more
|
||||
generic measures like randomizing allocations and your metadata
|
||||
encoding patches.
|
||||
|
||||
I've attached a revised version with the above comments incorporated
|
||||
but without the refined checks.
|
||||
|
||||
Thanks,
|
||||
Istvan
|
||||
|
||||
From a12d5d40fd7aed5fa10fc444dcb819947b72b315 Mon Sep 17 00:00:00 2001
|
||||
From: Istvan Kurucsai <pistukem@gmail.com>
|
||||
Date: Tue, 16 Jan 2018 14:48:16 +0100
|
||||
Subject: [PATCH v2 1/1] malloc: Additional checks for unsorted bin integrity
|
||||
I.
|
||||
|
||||
Ensure the following properties of chunks encountered during binning:
|
||||
- victim chunk has reasonable size
|
||||
- next chunk has reasonable size
|
||||
- next->prev_size == victim->size
|
||||
- valid double linked list
|
||||
- PREV_INUSE of next chunk is unset
|
||||
|
||||
* malloc/malloc.c (_int_malloc): Additional binning code checks.
|
||||
|
||||
diff --git a/malloc/malloc.c b/malloc/malloc.c
|
||||
index d8d4581a9dcea80a..dad0e73735789530 100644
|
||||
--- a/malloc/malloc.c
|
||||
+++ b/malloc/malloc.c
|
||||
@@ -3724,11 +3724,22 @@ _int_malloc (mstate av, size_t bytes)
|
||||
while ((victim = unsorted_chunks (av)->bk) != unsorted_chunks (av))
|
||||
{
|
||||
bck = victim->bk;
|
||||
- if (__builtin_expect (chunksize_nomask (victim) <= 2 * SIZE_SZ, 0)
|
||||
- || __builtin_expect (chunksize_nomask (victim)
|
||||
- > av->system_mem, 0))
|
||||
- malloc_printerr ("malloc(): memory corruption");
|
||||
size = chunksize (victim);
|
||||
+ mchunkptr next = chunk_at_offset (victim, size);
|
||||
+
|
||||
+ if (__glibc_unlikely (size <= 2 * SIZE_SZ)
|
||||
+ || __glibc_unlikely (size > av->system_mem))
|
||||
+ malloc_printerr ("malloc(): invalid size (unsorted)");
|
||||
+ if (__glibc_unlikely (chunksize_nomask (next) < 2 * SIZE_SZ)
|
||||
+ || __glibc_unlikely (chunksize_nomask (next) > av->system_mem))
|
||||
+ malloc_printerr ("malloc(): invalid next size (unsorted)");
|
||||
+ if (__glibc_unlikely ((prev_size (next) & ~(SIZE_BITS)) != size))
|
||||
+ malloc_printerr ("malloc(): mismatching next->prev_size (unsorted)");
|
||||
+ if (__glibc_unlikely (bck->fd != victim)
|
||||
+ || __glibc_unlikely (victim->fd != unsorted_chunks (av)))
|
||||
+ malloc_printerr ("malloc(): unsorted double linked list corrupted");
|
||||
+ if (__glibc_unlikely (prev_inuse(next)))
|
||||
+ malloc_printerr ("malloc(): invalid next->prev_inuse (unsorted)");
|
||||
|
||||
/*
|
||||
If a small request, try to use last remainder if it is the
|
26
SOURCES/glibc-rh1651283-4.patch
Normal file
26
SOURCES/glibc-rh1651283-4.patch
Normal file
@ -0,0 +1,26 @@
|
||||
The below commit contains only a whitespace change and was backported in
|
||||
order to avoid future conflicts.
|
||||
|
||||
commit 35cfefd96062145eeb8aee6bd72d07e0909a6b2e
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Mon Aug 20 14:57:13 2018 +0200
|
||||
|
||||
malloc: Add ChangeLog for accidentally committed change
|
||||
|
||||
Commit b90ddd08f6dd688e651df9ee89ca3a69ff88cd0c ("malloc: Additional
|
||||
checks for unsorted bin integrity I.") was committed without a
|
||||
whitespace fix, so it is adjusted here as well.
|
||||
|
||||
diff --git a/malloc/malloc.c b/malloc/malloc.c
|
||||
index c07463001a65af90..eb6a8ff33c0c313b 100644
|
||||
--- a/malloc/malloc.c
|
||||
+++ b/malloc/malloc.c
|
||||
@@ -3745,7 +3745,7 @@ _int_malloc (mstate av, size_t bytes)
|
||||
if (__glibc_unlikely (bck->fd != victim)
|
||||
|| __glibc_unlikely (victim->fd != unsorted_chunks (av)))
|
||||
malloc_printerr ("malloc(): unsorted double linked list corrupted");
|
||||
- if (__glibc_unlikely (prev_inuse(next)))
|
||||
+ if (__glibc_unlikely (prev_inuse (next)))
|
||||
malloc_printerr ("malloc(): invalid next->prev_inuse (unsorted)");
|
||||
|
||||
/*
|
38
SOURCES/glibc-rh1651283-5.patch
Normal file
38
SOURCES/glibc-rh1651283-5.patch
Normal file
@ -0,0 +1,38 @@
|
||||
commit ebe544bf6e8eec35e754fd49efb027c6f161b6cb
|
||||
Author: Istvan Kurucsai <pistukem@gmail.com>
|
||||
Date: Thu Dec 20 23:30:07 2018 -0500
|
||||
|
||||
malloc: Add more integrity checks to mremap_chunk.
|
||||
|
||||
* malloc/malloc.c (mremap_chunk): Additional checks.
|
||||
|
||||
diff --git a/malloc/malloc.c b/malloc/malloc.c
|
||||
index eb6a8ff33c0c313b..4df5cb4862a7b854 100644
|
||||
--- a/malloc/malloc.c
|
||||
+++ b/malloc/malloc.c
|
||||
@@ -2856,16 +2856,22 @@ mremap_chunk (mchunkptr p, size_t new_size)
|
||||
char *cp;
|
||||
|
||||
assert (chunk_is_mmapped (p));
|
||||
- assert (((size + offset) & (GLRO (dl_pagesize) - 1)) == 0);
|
||||
+
|
||||
+ uintptr_t block = (uintptr_t) p - offset;
|
||||
+ uintptr_t mem = (uintptr_t) chunk2mem(p);
|
||||
+ size_t total_size = offset + size;
|
||||
+ if (__glibc_unlikely ((block | total_size) & (pagesize - 1)) != 0
|
||||
+ || __glibc_unlikely (!powerof2 (mem & (pagesize - 1))))
|
||||
+ malloc_printerr("mremap_chunk(): invalid pointer");
|
||||
|
||||
/* Note the extra SIZE_SZ overhead as in mmap_chunk(). */
|
||||
new_size = ALIGN_UP (new_size + offset + SIZE_SZ, pagesize);
|
||||
|
||||
/* No need to remap if the number of pages does not change. */
|
||||
- if (size + offset == new_size)
|
||||
+ if (total_size == new_size)
|
||||
return p;
|
||||
|
||||
- cp = (char *) __mremap ((char *) p - offset, size + offset, new_size,
|
||||
+ cp = (char *) __mremap ((char *) block, total_size, new_size,
|
||||
MREMAP_MAYMOVE);
|
||||
|
||||
if (cp == MAP_FAILED)
|
38
SOURCES/glibc-rh1651283-6.patch
Normal file
38
SOURCES/glibc-rh1651283-6.patch
Normal file
@ -0,0 +1,38 @@
|
||||
commit c0e82f117357a941e4d40fcc08babbd6a3c3a1b5
|
||||
Author: Istvan Kurucsai <pistukem@gmail.com>
|
||||
Date: Fri Dec 21 00:13:01 2018 -0500
|
||||
|
||||
malloc: Check the alignment of mmapped chunks before unmapping.
|
||||
|
||||
* malloc/malloc.c (munmap_chunk): Verify chunk alignment.
|
||||
|
||||
diff --git a/malloc/malloc.c b/malloc/malloc.c
|
||||
index 4df5cb4862a7b854..4412a4ffc83b013b 100644
|
||||
--- a/malloc/malloc.c
|
||||
+++ b/malloc/malloc.c
|
||||
@@ -2817,6 +2817,7 @@ systrim (size_t pad, mstate av)
|
||||
static void
|
||||
munmap_chunk (mchunkptr p)
|
||||
{
|
||||
+ size_t pagesize = GLRO (dl_pagesize);
|
||||
INTERNAL_SIZE_T size = chunksize (p);
|
||||
|
||||
assert (chunk_is_mmapped (p));
|
||||
@@ -2826,6 +2827,7 @@ munmap_chunk (mchunkptr p)
|
||||
if (DUMPED_MAIN_ARENA_CHUNK (p))
|
||||
return;
|
||||
|
||||
+ uintptr_t mem = (uintptr_t) chunk2mem (p);
|
||||
uintptr_t block = (uintptr_t) p - prev_size (p);
|
||||
size_t total_size = prev_size (p) + size;
|
||||
/* Unfortunately we have to do the compilers job by hand here. Normally
|
||||
@@ -2833,7 +2835,8 @@ munmap_chunk (mchunkptr p)
|
||||
page size. But gcc does not recognize the optimization possibility
|
||||
(in the moment at least) so we combine the two values into one before
|
||||
the bit test. */
|
||||
- if (__builtin_expect (((block | total_size) & (GLRO (dl_pagesize) - 1)) != 0, 0))
|
||||
+ if (__glibc_unlikely ((block | total_size) & (pagesize - 1)) != 0
|
||||
+ || __glibc_unlikely (!powerof2 (mem & (pagesize - 1))))
|
||||
malloc_printerr ("munmap_chunk(): invalid pointer");
|
||||
|
||||
atomic_decrement (&mp_.n_mmaps);
|
31
SOURCES/glibc-rh1651283-7.patch
Normal file
31
SOURCES/glibc-rh1651283-7.patch
Normal file
@ -0,0 +1,31 @@
|
||||
commit 5b06f538c5aee0389ed034f60d90a8884d6d54de
|
||||
Author: Adam Maris <amaris@redhat.com>
|
||||
Date: Thu Mar 14 16:51:16 2019 -0400
|
||||
|
||||
malloc: Check for large bin list corruption when inserting unsorted chunk
|
||||
|
||||
Fixes bug 24216. This patch adds security checks for bk and bk_nextsize pointers
|
||||
of chunks in large bin when inserting chunk from unsorted bin. It was possible
|
||||
to write the pointer to victim (newly inserted chunk) to arbitrary memory
|
||||
locations if bk or bk_nextsize pointers of the next large bin chunk
|
||||
got corrupted.
|
||||
|
||||
diff --git a/malloc/malloc.c b/malloc/malloc.c
|
||||
index 4412a4ffc83b013b..723d393f529bdb4c 100644
|
||||
--- a/malloc/malloc.c
|
||||
+++ b/malloc/malloc.c
|
||||
@@ -3876,10 +3876,14 @@ _int_malloc (mstate av, size_t bytes)
|
||||
{
|
||||
victim->fd_nextsize = fwd;
|
||||
victim->bk_nextsize = fwd->bk_nextsize;
|
||||
+ if (__glibc_unlikely (fwd->bk_nextsize->fd_nextsize != fwd))
|
||||
+ malloc_printerr ("malloc(): largebin double linked list corrupted (nextsize)");
|
||||
fwd->bk_nextsize = victim;
|
||||
victim->bk_nextsize->fd_nextsize = victim;
|
||||
}
|
||||
bck = fwd->bk;
|
||||
+ if (bck->fd != fwd)
|
||||
+ malloc_printerr ("malloc(): largebin double linked list corrupted (bk)");
|
||||
}
|
||||
}
|
||||
else
|
307
SOURCES/glibc-rh1651742.patch
Normal file
307
SOURCES/glibc-rh1651742.patch
Normal file
@ -0,0 +1,307 @@
|
||||
commit f0458cf4f9ff3d870c43b624e6dccaaf657d5e83
|
||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
Date: Mon Aug 27 09:42:50 2018 -0300
|
||||
|
||||
powerpc: Only enable TLE with PPC_FEATURE2_HTM_NOSC
|
||||
|
||||
Linux from 3.9 through 4.2 does not abort HTM transaction on syscalls,
|
||||
instead it suspend and resume it when leaving the kernel. The
|
||||
side-effects of the syscall will always remain visible, even if the
|
||||
transaction is aborted. This is an issue when transaction is used along
|
||||
with futex syscall, on pthread_cond_wait for instance, where the futex
|
||||
call might succeed but the transaction is rolled back leading the
|
||||
pthread_cond object in an inconsistent state.
|
||||
|
||||
Glibc used to prevent it by always aborting a transaction before issuing
|
||||
a syscall. Linux 4.2 also decided to abort active transaction in
|
||||
syscalls which makes the glibc workaround superfluous. Worse, glibc
|
||||
transaction abortion leads to a performance issue on recent kernels
|
||||
where the HTM state is saved/restore lazily (v4.9). By aborting a
|
||||
transaction on every syscalls, regardless whether a transaction has being
|
||||
initiated before, GLIBS makes the kernel always save/restore HTM state
|
||||
(it can not even lazily disable it after a certain number of syscall
|
||||
iterations).
|
||||
|
||||
Because of this shortcoming, Transactional Lock Elision is just enabled
|
||||
when it has been explicitly set (either by tunables of by a configure
|
||||
switch) and if kernel aborts HTM transactions on syscalls
|
||||
(PPC_FEATURE2_HTM_NOSC). It is reported that using simple benchmark [1],
|
||||
the context-switch is about 5% faster by not issuing a tabort in every
|
||||
syscall in newer kernels.
|
||||
|
||||
Checked on powerpc64le-linux-gnu with 4.4.0 kernel (Ubuntu 16.04).
|
||||
|
||||
* NEWS: Add note about new TLE support on powerpc64le.
|
||||
* sysdeps/powerpc/nptl/tcb-offsets.sym (TM_CAPABLE): Remove.
|
||||
* sysdeps/powerpc/nptl/tls.h (tcbhead_t): Rename tm_capable to
|
||||
__ununsed1.
|
||||
(TLS_INIT_TP, TLS_DEFINE_INIT_TP): Remove tm_capable setup.
|
||||
(THREAD_GET_TM_CAPABLE, THREAD_SET_TM_CAPABLE): Remove macros.
|
||||
* sysdeps/powerpc/powerpc32/sysdep.h,
|
||||
sysdeps/powerpc/powerpc64/sysdep.h (ABORT_TRANSACTION_IMPL,
|
||||
ABORT_TRANSACTION): Remove macros.
|
||||
* sysdeps/powerpc/sysdep.h (ABORT_TRANSACTION): Likewise.
|
||||
* sysdeps/unix/sysv/linux/powerpc/elision-conf.c (elision_init): Set
|
||||
__pthread_force_elision iff PPC_FEATURE2_HTM_NOSC is set.
|
||||
* sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h,
|
||||
sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h
|
||||
sysdeps/unix/sysv/linux/powerpc/syscall.S (ABORT_TRANSACTION): Remove
|
||||
usage.
|
||||
* sysdeps/unix/sysv/linux/powerpc/not-errno.h: Remove file.
|
||||
|
||||
Reported-by: Breno Leitão <leitao@debian.org>
|
||||
|
||||
diff --git a/sysdeps/powerpc/nptl/tcb-offsets.sym b/sysdeps/powerpc/nptl/tcb-offsets.sym
|
||||
index e5bb2b3..4c01615 100644
|
||||
--- a/sysdeps/powerpc/nptl/tcb-offsets.sym
|
||||
+++ b/sysdeps/powerpc/nptl/tcb-offsets.sym
|
||||
@@ -21,7 +21,6 @@ DSO_SLOT2 (offsetof (tcbhead_t, dso_slot2) - TLS_TCB_OFFSET - sizeof (tcbhead_
|
||||
#ifdef __powerpc64__
|
||||
TCB_AT_PLATFORM (offsetof (tcbhead_t, at_platform) - TLS_TCB_OFFSET - sizeof(tcbhead_t))
|
||||
#endif
|
||||
-TM_CAPABLE (offsetof (tcbhead_t, tm_capable) - TLS_TCB_OFFSET - sizeof (tcbhead_t))
|
||||
#ifndef __powerpc64__
|
||||
TCB_AT_PLATFORM (offsetof (tcbhead_t, at_platform) - TLS_TCB_OFFSET - sizeof(tcbhead_t))
|
||||
PADDING (offsetof (tcbhead_t, padding) - TLS_TCB_OFFSET - sizeof(tcbhead_t))
|
||||
diff --git a/sysdeps/powerpc/nptl/tls.h b/sysdeps/powerpc/nptl/tls.h
|
||||
index f88fed5..8317ca7 100644
|
||||
--- a/sysdeps/powerpc/nptl/tls.h
|
||||
+++ b/sysdeps/powerpc/nptl/tls.h
|
||||
@@ -67,8 +67,7 @@ typedef struct
|
||||
uint32_t padding;
|
||||
uint32_t at_platform;
|
||||
#endif
|
||||
- /* Indicate if HTM capable (ISA 2.07). */
|
||||
- uint32_t tm_capable;
|
||||
+ uint32_t __unused;
|
||||
/* Reservation for AT_PLATFORM data - powerpc64. */
|
||||
#ifdef __powerpc64__
|
||||
uint32_t at_platform;
|
||||
@@ -142,7 +141,6 @@ register void *__thread_register __asm__ ("r13");
|
||||
# define TLS_INIT_TP(tcbp) \
|
||||
({ \
|
||||
__thread_register = (void *) (tcbp) + TLS_TCB_OFFSET; \
|
||||
- THREAD_SET_TM_CAPABLE (__tcb_hwcap & PPC_FEATURE2_HAS_HTM ? 1 : 0); \
|
||||
THREAD_SET_HWCAP (__tcb_hwcap); \
|
||||
THREAD_SET_AT_PLATFORM (__tcb_platform); \
|
||||
NULL; \
|
||||
@@ -151,8 +149,6 @@ register void *__thread_register __asm__ ("r13");
|
||||
/* Value passed to 'clone' for initialization of the thread register. */
|
||||
# define TLS_DEFINE_INIT_TP(tp, pd) \
|
||||
void *tp = (void *) (pd) + TLS_TCB_OFFSET + TLS_PRE_TCB_SIZE; \
|
||||
- (((tcbhead_t *) ((char *) tp - TLS_TCB_OFFSET))[-1].tm_capable) = \
|
||||
- THREAD_GET_TM_CAPABLE (); \
|
||||
(((tcbhead_t *) ((char *) tp - TLS_TCB_OFFSET))[-1].hwcap) = \
|
||||
THREAD_GET_HWCAP (); \
|
||||
(((tcbhead_t *) ((char *) tp - TLS_TCB_OFFSET))[-1].at_platform) = \
|
||||
@@ -210,13 +206,6 @@ register void *__thread_register __asm__ ("r13");
|
||||
+ TLS_PRE_TCB_SIZE))[-1].pointer_guard \
|
||||
= THREAD_GET_POINTER_GUARD())
|
||||
|
||||
-/* tm_capable field in TCB head. */
|
||||
-# define THREAD_GET_TM_CAPABLE() \
|
||||
- (((tcbhead_t *) ((char *) __thread_register \
|
||||
- - TLS_TCB_OFFSET))[-1].tm_capable)
|
||||
-# define THREAD_SET_TM_CAPABLE(value) \
|
||||
- (THREAD_GET_TM_CAPABLE () = (value))
|
||||
-
|
||||
/* hwcap field in TCB head. */
|
||||
# define THREAD_GET_HWCAP() \
|
||||
(((tcbhead_t *) ((char *) __thread_register \
|
||||
diff --git a/sysdeps/powerpc/powerpc32/sysdep.h b/sysdeps/powerpc/powerpc32/sysdep.h
|
||||
index 5f1294e..93097c5 100644
|
||||
--- a/sysdeps/powerpc/powerpc32/sysdep.h
|
||||
+++ b/sysdeps/powerpc/powerpc32/sysdep.h
|
||||
@@ -90,24 +90,7 @@ GOT_LABEL: ; \
|
||||
cfi_endproc; \
|
||||
ASM_SIZE_DIRECTIVE(name)
|
||||
|
||||
-#if !IS_IN(rtld) && !defined(__SPE__)
|
||||
-# define ABORT_TRANSACTION_IMPL \
|
||||
- cmpwi 2,0; \
|
||||
- beq 1f; \
|
||||
- lwz 0,TM_CAPABLE(2); \
|
||||
- cmpwi 0,0; \
|
||||
- beq 1f; \
|
||||
- li 11,_ABORT_SYSCALL; \
|
||||
- tabort. 11; \
|
||||
- .align 4; \
|
||||
-1:
|
||||
-#else
|
||||
-# define ABORT_TRANSACTION_IMPL
|
||||
-#endif
|
||||
-#define ABORT_TRANSACTION ABORT_TRANSACTION_IMPL
|
||||
-
|
||||
#define DO_CALL(syscall) \
|
||||
- ABORT_TRANSACTION \
|
||||
li 0,syscall; \
|
||||
sc
|
||||
|
||||
diff --git a/sysdeps/powerpc/powerpc64/sysdep.h b/sysdeps/powerpc/powerpc64/sysdep.h
|
||||
index 2df1d9b..50e64f9 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/sysdep.h
|
||||
+++ b/sysdeps/powerpc/powerpc64/sysdep.h
|
||||
@@ -263,24 +263,7 @@ LT_LABELSUFFIX(name,_name_end): ; \
|
||||
TRACEBACK_MASK(name,mask); \
|
||||
END_2(name)
|
||||
|
||||
-#if !IS_IN(rtld)
|
||||
-# define ABORT_TRANSACTION_IMPL \
|
||||
- cmpdi 13,0; \
|
||||
- beq 1f; \
|
||||
- lwz 0,TM_CAPABLE(13); \
|
||||
- cmpwi 0,0; \
|
||||
- beq 1f; \
|
||||
- li 11,_ABORT_SYSCALL; \
|
||||
- tabort. 11; \
|
||||
- .p2align 4; \
|
||||
-1:
|
||||
-#else
|
||||
-# define ABORT_TRANSACTION_IMPL
|
||||
-#endif
|
||||
-#define ABORT_TRANSACTION ABORT_TRANSACTION_IMPL
|
||||
-
|
||||
#define DO_CALL(syscall) \
|
||||
- ABORT_TRANSACTION \
|
||||
li 0,syscall; \
|
||||
sc
|
||||
|
||||
diff --git a/sysdeps/powerpc/sysdep.h b/sysdeps/powerpc/sysdep.h
|
||||
index 8a6d236..c8bf25e 100644
|
||||
--- a/sysdeps/powerpc/sysdep.h
|
||||
+++ b/sysdeps/powerpc/sysdep.h
|
||||
@@ -21,8 +21,6 @@
|
||||
*/
|
||||
#define _SYSDEPS_SYSDEP_H 1
|
||||
#include <bits/hwcap.h>
|
||||
-#include <tls.h>
|
||||
-#include <htm.h>
|
||||
|
||||
#define PPC_FEATURE_970 (PPC_FEATURE_POWER4 + PPC_FEATURE_HAS_ALTIVEC)
|
||||
|
||||
@@ -166,22 +164,4 @@
|
||||
#define ALIGNARG(log2) log2
|
||||
#define ASM_SIZE_DIRECTIVE(name) .size name,.-name
|
||||
|
||||
-#else
|
||||
-
|
||||
-/* Linux kernel powerpc documentation [1] states issuing a syscall inside a
|
||||
- transaction is not recommended and may lead to undefined behavior. It
|
||||
- also states syscalls do not abort transactions. To avoid such traps,
|
||||
- we abort transaction just before syscalls.
|
||||
-
|
||||
- [1] Documentation/powerpc/transactional_memory.txt [Syscalls] */
|
||||
-#if !IS_IN(rtld) && !defined(__SPE__)
|
||||
-# define ABORT_TRANSACTION \
|
||||
- ({ \
|
||||
- if (THREAD_GET_TM_CAPABLE ()) \
|
||||
- __libc_tabort (_ABORT_SYSCALL); \
|
||||
- })
|
||||
-#else
|
||||
-# define ABORT_TRANSACTION
|
||||
-#endif
|
||||
-
|
||||
#endif /* __ASSEMBLER__ */
|
||||
diff --git a/sysdeps/unix/sysv/linux/powerpc/elision-conf.c b/sysdeps/unix/sysv/linux/powerpc/elision-conf.c
|
||||
index 906882a..fc82bd1 100644
|
||||
--- a/sysdeps/unix/sysv/linux/powerpc/elision-conf.c
|
||||
+++ b/sysdeps/unix/sysv/linux/powerpc/elision-conf.c
|
||||
@@ -127,6 +127,26 @@ elision_init (int argc __attribute__ ((unused)),
|
||||
TUNABLE_CALLBACK (set_elision_skip_trylock_internal_abort));
|
||||
#endif
|
||||
|
||||
+ /* Linux from 3.9 through 4.2 do not abort HTM transaction on syscalls,
|
||||
+ instead it suspends the transaction and resumes it when returning to
|
||||
+ usercode. The side-effects of the syscall will always remain visible,
|
||||
+ even if the transaction is aborted. This is an issue when a transaction
|
||||
+ is used along with futex syscall, on pthread_cond_wait for instance,
|
||||
+ where futex might succeed but the transaction is rolled back leading
|
||||
+ the condition variable object in an inconsistent state.
|
||||
+
|
||||
+ Glibc used to prevent it by always aborting a transaction before issuing
|
||||
+ a syscall. Linux 4.2 also decided to abort active transaction in
|
||||
+ syscalls which makes the glibc workaround superflours. Worse, glibc
|
||||
+ transaction abortions leads to a performance issues on recent kernels.
|
||||
+
|
||||
+ So Lock Elision is just enabled when it has been explict set (either
|
||||
+ by tunables of by a configure switch) and if kernel aborts HTM
|
||||
+ transactions on syscalls (PPC_FEATURE2_HTM_NOSC) */
|
||||
+
|
||||
+ __pthread_force_elision = (__pthread_force_elision
|
||||
+ && GLRO (dl_hwcap2) & PPC_FEATURE2_HTM_NOSC);
|
||||
+
|
||||
if (!__pthread_force_elision)
|
||||
__elision_aconf.try_tbegin = 0; /* Disable elision on rwlocks. */
|
||||
}
|
||||
diff --git a/sysdeps/unix/sysv/linux/powerpc/not-errno.h b/sysdeps/unix/sysv/linux/powerpc/not-errno.h
|
||||
deleted file mode 100644
|
||||
index 27da21b..0000000
|
||||
--- a/sysdeps/unix/sysv/linux/powerpc/not-errno.h
|
||||
+++ /dev/null
|
||||
@@ -1,30 +0,0 @@
|
||||
-/* Syscall wrapper that do not set errno. Linux powerpc version.
|
||||
- Copyright (C) 2018 Free Software Foundation, Inc.
|
||||
- This file is part of the GNU C Library.
|
||||
-
|
||||
- The GNU C Library is free software; you can redistribute it and/or
|
||||
- modify it under the terms of the GNU Lesser General Public
|
||||
- License as published by the Free Software Foundation; either
|
||||
- version 2.1 of the License, or (at your option) any later version.
|
||||
-
|
||||
- The GNU C Library is distributed in the hope that it will be useful,
|
||||
- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
- Lesser General Public License for more details.
|
||||
-
|
||||
- You should have received a copy of the GNU Lesser General Public
|
||||
- License along with the GNU C Library; if not, see
|
||||
- <http://www.gnu.org/licenses/>. */
|
||||
-
|
||||
-/* __access_noerrno is used during process initialization in elf/dl-tunables.c
|
||||
- before the TCB is initialized, prohibiting the usage of
|
||||
- ABORT_TRANSACTION. */
|
||||
-#undef ABORT_TRANSACTION
|
||||
-#define ABORT_TRANSACTION
|
||||
-
|
||||
-#include "sysdeps/unix/sysv/linux/not-errno.h"
|
||||
-
|
||||
-/* Recover ABORT_TRANSACTION's previous value, in order to not affect
|
||||
- other syscalls. */
|
||||
-#undef ABORT_TRANSACTION
|
||||
-#define ABORT_TRANSACTION ABORT_TRANSACTION_IMPL
|
||||
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h b/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h
|
||||
index f7277d5..ec5c525 100644
|
||||
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h
|
||||
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h
|
||||
@@ -109,7 +109,6 @@
|
||||
register long int r11 __asm__ ("r11"); \
|
||||
register long int r12 __asm__ ("r12"); \
|
||||
LOADARGS_##nr(name, args); \
|
||||
- ABORT_TRANSACTION; \
|
||||
__asm__ __volatile__ \
|
||||
("sc \n\t" \
|
||||
"mfcr %0" \
|
||||
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h b/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h
|
||||
index 0956cf0..1f17f7b 100644
|
||||
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h
|
||||
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h
|
||||
@@ -131,7 +131,6 @@
|
||||
register long int r7 __asm__ ("r7"); \
|
||||
register long int r8 __asm__ ("r8"); \
|
||||
LOADARGS_##nr (name, ##args); \
|
||||
- ABORT_TRANSACTION; \
|
||||
__asm__ __volatile__ \
|
||||
("sc\n\t" \
|
||||
"mfcr %0\n\t" \
|
||||
diff --git a/sysdeps/unix/sysv/linux/powerpc/syscall.S b/sysdeps/unix/sysv/linux/powerpc/syscall.S
|
||||
index 2da9172..bbab613 100644
|
||||
--- a/sysdeps/unix/sysv/linux/powerpc/syscall.S
|
||||
+++ b/sysdeps/unix/sysv/linux/powerpc/syscall.S
|
||||
@@ -18,7 +18,6 @@
|
||||
#include <sysdep.h>
|
||||
|
||||
ENTRY (syscall)
|
||||
- ABORT_TRANSACTION
|
||||
mr r0,r3
|
||||
mr r3,r4
|
||||
mr r4,r5
|
35
SOURCES/glibc-rh1654010-1.patch
Normal file
35
SOURCES/glibc-rh1654010-1.patch
Normal file
@ -0,0 +1,35 @@
|
||||
commit d527c860f5a3f0ed687bd03f0cb464612dc23408
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Nov 27 16:12:43 2018 +0100
|
||||
|
||||
CVE-2018-19591: if_nametoindex: Fix descriptor for overlong name [BZ #23927]
|
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/if_index.c b/sysdeps/unix/sysv/linux/if_index.c
|
||||
index e3d08982d9931108..782fc5e1750e9ead 100644
|
||||
--- a/sysdeps/unix/sysv/linux/if_index.c
|
||||
+++ b/sysdeps/unix/sysv/linux/if_index.c
|
||||
@@ -38,11 +38,6 @@ __if_nametoindex (const char *ifname)
|
||||
return 0;
|
||||
#else
|
||||
struct ifreq ifr;
|
||||
- int fd = __opensock ();
|
||||
-
|
||||
- if (fd < 0)
|
||||
- return 0;
|
||||
-
|
||||
if (strlen (ifname) >= IFNAMSIZ)
|
||||
{
|
||||
__set_errno (ENODEV);
|
||||
@@ -50,6 +45,12 @@ __if_nametoindex (const char *ifname)
|
||||
}
|
||||
|
||||
strncpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
|
||||
+
|
||||
+ int fd = __opensock ();
|
||||
+
|
||||
+ if (fd < 0)
|
||||
+ return 0;
|
||||
+
|
||||
if (__ioctl (fd, SIOCGIFINDEX, &ifr) < 0)
|
||||
{
|
||||
int saved_errno = errno;
|
142
SOURCES/glibc-rh1654010-2.patch
Normal file
142
SOURCES/glibc-rh1654010-2.patch
Normal file
@ -0,0 +1,142 @@
|
||||
commit c74a91deaa5de416237c02bbb3e41bda76ca4c7b
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Nov 27 21:35:56 2018 +0100
|
||||
|
||||
support: Implement support_quote_string
|
||||
|
||||
Reviewed-by: Jonathan Nieder <jrnieder@gmail.com>
|
||||
|
||||
diff --git a/support/Makefile b/support/Makefile
|
||||
index 2b663fbbfa334ea2..a2536980d1d5a89b 100644
|
||||
--- a/support/Makefile
|
||||
+++ b/support/Makefile
|
||||
@@ -58,6 +58,7 @@ libsupport-routines = \
|
||||
support_openpty \
|
||||
support_paths \
|
||||
support_quote_blob \
|
||||
+ support_quote_string \
|
||||
support_record_failure \
|
||||
support_run_diff \
|
||||
support_shared_allocate \
|
||||
@@ -196,6 +197,7 @@ tests = \
|
||||
tst-support_capture_subprocess \
|
||||
tst-support_format_dns_packet \
|
||||
tst-support_quote_blob \
|
||||
+ tst-support_quote_string \
|
||||
tst-support_record_failure \
|
||||
tst-test_compare \
|
||||
tst-test_compare_blob \
|
||||
diff --git a/support/support.h b/support/support.h
|
||||
index 9418cd11ef6e684d..835e7173eb566355 100644
|
||||
--- a/support/support.h
|
||||
+++ b/support/support.h
|
||||
@@ -69,6 +69,11 @@ void support_write_file_string (const char *path, const char *contents);
|
||||
the result). */
|
||||
char *support_quote_blob (const void *blob, size_t length);
|
||||
|
||||
+/* Quote the contents of the at STR, in such a way that the result
|
||||
+ string can be included in a C literal (in single/double quotes,
|
||||
+ without putting the quotes into the result). */
|
||||
+char *support_quote_string (const char *str);
|
||||
+
|
||||
/* Returns non-zero if the file descriptor is a regular file on a file
|
||||
system which supports holes (that is, seeking and writing does not
|
||||
allocate storage for the range of zeros). FD must refer to a
|
||||
diff --git a/support/support_quote_string.c b/support/support_quote_string.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..d324371b133a4d66
|
||||
--- /dev/null
|
||||
+++ b/support/support_quote_string.c
|
||||
@@ -0,0 +1,26 @@
|
||||
+/* Quote a string so that it can be used in C literals.
|
||||
+ Copyright (C) 2018 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <string.h>
|
||||
+#include <support/support.h>
|
||||
+
|
||||
+char *
|
||||
+support_quote_string (const char *str)
|
||||
+{
|
||||
+ return support_quote_blob (str, strlen (str));
|
||||
+}
|
||||
diff --git a/support/tst-support_quote_string.c b/support/tst-support_quote_string.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..3c004759b76e21d7
|
||||
--- /dev/null
|
||||
+++ b/support/tst-support_quote_string.c
|
||||
@@ -0,0 +1,60 @@
|
||||
+/* Test the support_quote_string function.
|
||||
+ Copyright (C) 2018 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <support/check.h>
|
||||
+#include <support/support.h>
|
||||
+#include <string.h>
|
||||
+#include <stdlib.h>
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ char *p = support_quote_string ("");
|
||||
+ TEST_COMPARE (strlen (p), 0);
|
||||
+ free (p);
|
||||
+ p = support_quote_string ("X");
|
||||
+ TEST_COMPARE (strlen (p), 1);
|
||||
+ TEST_COMPARE (p[0], 'X');
|
||||
+ free (p);
|
||||
+
|
||||
+ /* Check escaping of backslash-escaped characters, and lack of
|
||||
+ escaping for other shell meta-characters. */
|
||||
+ p = support_quote_string ("$()*?`@[]{}~\'\"X");
|
||||
+ TEST_COMPARE (strcmp (p, "$()*?`@[]{}~\\'\\\"X"), 0);
|
||||
+ free (p);
|
||||
+
|
||||
+ /* Check lack of escaping for letters and digits. */
|
||||
+#define LETTERS_AND_DIGTS \
|
||||
+ "abcdefghijklmnopqrstuvwxyz" \
|
||||
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
|
||||
+ "0123456789"
|
||||
+ p = support_quote_string (LETTERS_AND_DIGTS "@");
|
||||
+ TEST_COMPARE (strcmp (p, LETTERS_AND_DIGTS "@"), 0);
|
||||
+ free (p);
|
||||
+
|
||||
+ /* Check escaping of control characters and other non-printable
|
||||
+ characters. */
|
||||
+ p = support_quote_string ("\r\n\t\a\b\f\v\1\177\200\377@");
|
||||
+ TEST_COMPARE (strcmp (p, "\\r\\n\\t\\a\\b\\f\\v\\001"
|
||||
+ "\\177\\200\\377@"), 0);
|
||||
+ free (p);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
26
SOURCES/glibc-rh1654010-3.patch
Normal file
26
SOURCES/glibc-rh1654010-3.patch
Normal file
@ -0,0 +1,26 @@
|
||||
commit 47d8d9a2172f827a8dde7695f415aa6f78a82d0e
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Wed Nov 28 07:00:48 2018 +0100
|
||||
|
||||
support_quote_string: Do not use str parameter name
|
||||
|
||||
This avoids a build failure if this identifier is used as a macro
|
||||
in a test.
|
||||
|
||||
diff --git a/support/support.h b/support/support.h
|
||||
index 835e7173eb566355..c3ad76901e352ee7 100644
|
||||
--- a/support/support.h
|
||||
+++ b/support/support.h
|
||||
@@ -69,10 +69,10 @@ void support_write_file_string (const char *path, const char *contents);
|
||||
the result). */
|
||||
char *support_quote_blob (const void *blob, size_t length);
|
||||
|
||||
-/* Quote the contents of the at STR, in such a way that the result
|
||||
+/* Quote the contents of the string, in such a way that the result
|
||||
string can be included in a C literal (in single/double quotes,
|
||||
without putting the quotes into the result). */
|
||||
-char *support_quote_string (const char *str);
|
||||
+char *support_quote_string (const char *);
|
||||
|
||||
/* Returns non-zero if the file descriptor is a regular file on a file
|
||||
system which supports holes (that is, seeking and writing does not
|
32
SOURCES/glibc-rh1654010-4.patch
Normal file
32
SOURCES/glibc-rh1654010-4.patch
Normal file
@ -0,0 +1,32 @@
|
||||
commit 02cd5c1a8d033d7f91fea12a66bb44d1bbf85f76
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Sat Dec 1 21:43:36 2018 +0100
|
||||
|
||||
support: Close original descriptors in support_capture_subprocess
|
||||
|
||||
diff --git a/support/support_capture_subprocess.c b/support/support_capture_subprocess.c
|
||||
index 6d2029e13bd6ae73..93f6ea310290000a 100644
|
||||
--- a/support/support_capture_subprocess.c
|
||||
+++ b/support/support_capture_subprocess.c
|
||||
@@ -59,8 +59,12 @@ support_capture_subprocess (void (*callback) (void *), void *closure)
|
||||
|
||||
int stdout_pipe[2];
|
||||
xpipe (stdout_pipe);
|
||||
+ TEST_VERIFY (stdout_pipe[0] > STDERR_FILENO);
|
||||
+ TEST_VERIFY (stdout_pipe[1] > STDERR_FILENO);
|
||||
int stderr_pipe[2];
|
||||
xpipe (stderr_pipe);
|
||||
+ TEST_VERIFY (stderr_pipe[0] > STDERR_FILENO);
|
||||
+ TEST_VERIFY (stderr_pipe[1] > STDERR_FILENO);
|
||||
|
||||
TEST_VERIFY (fflush (stdout) == 0);
|
||||
TEST_VERIFY (fflush (stderr) == 0);
|
||||
@@ -72,6 +76,8 @@ support_capture_subprocess (void (*callback) (void *), void *closure)
|
||||
xclose (stderr_pipe[0]);
|
||||
xdup2 (stdout_pipe[1], STDOUT_FILENO);
|
||||
xdup2 (stderr_pipe[1], STDERR_FILENO);
|
||||
+ xclose (stdout_pipe[1]);
|
||||
+ xclose (stderr_pipe[1]);
|
||||
callback (closure);
|
||||
_exit (0);
|
||||
}
|
594
SOURCES/glibc-rh1654010-5.patch
Normal file
594
SOURCES/glibc-rh1654010-5.patch
Normal file
@ -0,0 +1,594 @@
|
||||
commit f255336a9301619519045548acb2e1027065a837
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Thu Dec 6 15:39:42 2018 +0100
|
||||
|
||||
support: Implement <support/descriptors.h> to track file descriptors
|
||||
|
||||
diff --git a/support/Makefile b/support/Makefile
|
||||
index a2536980d1d5a89b..93a514301654132e 100644
|
||||
--- a/support/Makefile
|
||||
+++ b/support/Makefile
|
||||
@@ -46,6 +46,7 @@ libsupport-routines = \
|
||||
support_chroot \
|
||||
support_copy_file_range \
|
||||
support_descriptor_supports_holes \
|
||||
+ support_descriptors \
|
||||
support_enter_mount_namespace \
|
||||
support_enter_network_namespace \
|
||||
support_format_address_family \
|
||||
@@ -195,6 +196,7 @@ tests = \
|
||||
tst-support-namespace \
|
||||
tst-support_blob_repeat \
|
||||
tst-support_capture_subprocess \
|
||||
+ tst-support_descriptors \
|
||||
tst-support_format_dns_packet \
|
||||
tst-support_quote_blob \
|
||||
tst-support_quote_string \
|
||||
diff --git a/support/check.h b/support/check.h
|
||||
index e6765289f2492501..7ea9a86a9c7ed055 100644
|
||||
--- a/support/check.h
|
||||
+++ b/support/check.h
|
||||
@@ -183,6 +183,10 @@ int support_report_failure (int status)
|
||||
/* Internal function used to test the failure recording framework. */
|
||||
void support_record_failure_reset (void);
|
||||
|
||||
+/* Returns true or false depending on whether there have been test
|
||||
+ failures or not. */
|
||||
+int support_record_failure_is_failed (void);
|
||||
+
|
||||
__END_DECLS
|
||||
|
||||
#endif /* SUPPORT_CHECK_H */
|
||||
diff --git a/support/descriptors.h b/support/descriptors.h
|
||||
new file mode 100644
|
||||
index 0000000000000000..8ec4cbbdfb8f1770
|
||||
--- /dev/null
|
||||
+++ b/support/descriptors.h
|
||||
@@ -0,0 +1,47 @@
|
||||
+/* Monitoring file descriptor usage.
|
||||
+ Copyright (C) 2018 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#ifndef SUPPORT_DESCRIPTORS_H
|
||||
+#define SUPPORT_DESCRIPTORS_H
|
||||
+
|
||||
+#include <stdio.h>
|
||||
+
|
||||
+/* Opaque pointer, for capturing file descriptor lists. */
|
||||
+struct support_descriptors;
|
||||
+
|
||||
+/* Record the currently open file descriptors and store them in the
|
||||
+ returned list. Terminate the process if the listing operation
|
||||
+ fails. */
|
||||
+struct support_descriptors *support_descriptors_list (void);
|
||||
+
|
||||
+/* Deallocate the list of descriptors. */
|
||||
+void support_descriptors_free (struct support_descriptors *);
|
||||
+
|
||||
+/* Write the list of descriptors to STREAM, adding PREFIX to each
|
||||
+ line. */
|
||||
+void support_descriptors_dump (struct support_descriptors *,
|
||||
+ const char *prefix, FILE *stream);
|
||||
+
|
||||
+/* Check for file descriptor leaks and other file descriptor changes:
|
||||
+ Compare the current list of descriptors with the passed list.
|
||||
+ Record a test failure if there are additional open descriptors,
|
||||
+ descriptors have been closed, or if a change in file descriptor can
|
||||
+ be detected. */
|
||||
+void support_descriptors_check (struct support_descriptors *);
|
||||
+
|
||||
+#endif /* SUPPORT_DESCRIPTORS_H */
|
||||
diff --git a/support/support_descriptors.c b/support/support_descriptors.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..d66cf550800201c5
|
||||
--- /dev/null
|
||||
+++ b/support/support_descriptors.c
|
||||
@@ -0,0 +1,274 @@
|
||||
+/* Monitoring file descriptor usage.
|
||||
+ Copyright (C) 2018 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <dirent.h>
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
+#include <support/check.h>
|
||||
+#include <support/support.h>
|
||||
+#include <sys/stat.h>
|
||||
+#include <sys/sysmacros.h>
|
||||
+#include <xunistd.h>
|
||||
+
|
||||
+struct procfs_descriptor
|
||||
+{
|
||||
+ int fd;
|
||||
+ char *link_target;
|
||||
+ dev_t dev;
|
||||
+ ino64_t ino;
|
||||
+};
|
||||
+
|
||||
+/* Used with qsort. */
|
||||
+static int
|
||||
+descriptor_compare (const void *l, const void *r)
|
||||
+{
|
||||
+ const struct procfs_descriptor *left = l;
|
||||
+ const struct procfs_descriptor *right = r;
|
||||
+ /* Cannot overflow due to limited file descriptor range. */
|
||||
+ return left->fd - right->fd;
|
||||
+}
|
||||
+
|
||||
+#define DYNARRAY_STRUCT descriptor_list
|
||||
+#define DYNARRAY_ELEMENT struct procfs_descriptor
|
||||
+#define DYNARRAY_PREFIX descriptor_list_
|
||||
+#define DYNARRAY_ELEMENT_FREE(e) free ((e)->link_target)
|
||||
+#define DYNARRAY_INITIAL_SIZE 0
|
||||
+#include <malloc/dynarray-skeleton.c>
|
||||
+
|
||||
+struct support_descriptors
|
||||
+{
|
||||
+ struct descriptor_list list;
|
||||
+};
|
||||
+
|
||||
+struct support_descriptors *
|
||||
+support_descriptors_list (void)
|
||||
+{
|
||||
+ struct support_descriptors *result = xmalloc (sizeof (*result));
|
||||
+ descriptor_list_init (&result->list);
|
||||
+
|
||||
+ DIR *fds = opendir ("/proc/self/fd");
|
||||
+ if (fds == NULL)
|
||||
+ FAIL_EXIT1 ("opendir (\"/proc/self/fd\"): %m");
|
||||
+
|
||||
+ while (true)
|
||||
+ {
|
||||
+ errno = 0;
|
||||
+ struct dirent64 *e = readdir64 (fds);
|
||||
+ if (e == NULL)
|
||||
+ {
|
||||
+ if (errno != 0)
|
||||
+ FAIL_EXIT1 ("readdir: %m");
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (e->d_name[0] == '.')
|
||||
+ continue;
|
||||
+
|
||||
+ char *endptr;
|
||||
+ long int fd = strtol (e->d_name, &endptr, 10);
|
||||
+ if (*endptr != '\0' || fd < 0 || fd > INT_MAX)
|
||||
+ FAIL_EXIT1 ("readdir: invalid file descriptor name: /proc/self/fd/%s",
|
||||
+ e->d_name);
|
||||
+
|
||||
+ /* Skip the descriptor which is used to enumerate the
|
||||
+ descriptors. */
|
||||
+ if (fd == dirfd (fds))
|
||||
+ continue;
|
||||
+
|
||||
+ char *target;
|
||||
+ {
|
||||
+ char *path = xasprintf ("/proc/self/fd/%ld", fd);
|
||||
+ target = xreadlink (path);
|
||||
+ free (path);
|
||||
+ }
|
||||
+ struct stat64 st;
|
||||
+ if (fstat64 (fd, &st) != 0)
|
||||
+ FAIL_EXIT1 ("readdir: fstat64 (%ld) failed: %m", fd);
|
||||
+
|
||||
+ struct procfs_descriptor *item = descriptor_list_emplace (&result->list);
|
||||
+ if (item == NULL)
|
||||
+ FAIL_EXIT1 ("descriptor_list_emplace: %m");
|
||||
+ item->fd = fd;
|
||||
+ item->link_target = target;
|
||||
+ item->dev = st.st_dev;
|
||||
+ item->ino = st.st_ino;
|
||||
+ }
|
||||
+
|
||||
+ closedir (fds);
|
||||
+
|
||||
+ /* Perform a merge join between descrs and current. This assumes
|
||||
+ that the arrays are sorted by file descriptor. */
|
||||
+
|
||||
+ qsort (descriptor_list_begin (&result->list),
|
||||
+ descriptor_list_size (&result->list),
|
||||
+ sizeof (struct procfs_descriptor), descriptor_compare);
|
||||
+
|
||||
+ return result;
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+support_descriptors_free (struct support_descriptors *descrs)
|
||||
+{
|
||||
+ descriptor_list_free (&descrs->list);
|
||||
+ free (descrs);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+support_descriptors_dump (struct support_descriptors *descrs,
|
||||
+ const char *prefix, FILE *fp)
|
||||
+{
|
||||
+ struct procfs_descriptor *end = descriptor_list_end (&descrs->list);
|
||||
+ for (struct procfs_descriptor *d = descriptor_list_begin (&descrs->list);
|
||||
+ d != end; ++d)
|
||||
+ {
|
||||
+ char *quoted = support_quote_string (d->link_target);
|
||||
+ fprintf (fp, "%s%d: target=\"%s\" major=%lld minor=%lld ino=%lld\n",
|
||||
+ prefix, d->fd, quoted,
|
||||
+ (long long int) major (d->dev),
|
||||
+ (long long int) minor (d->dev),
|
||||
+ (long long int) d->ino);
|
||||
+ free (quoted);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+dump_mismatch (bool *first,
|
||||
+ struct support_descriptors *descrs,
|
||||
+ struct support_descriptors *current)
|
||||
+{
|
||||
+ if (*first)
|
||||
+ *first = false;
|
||||
+ else
|
||||
+ return;
|
||||
+
|
||||
+ puts ("error: Differences found in descriptor set");
|
||||
+ puts ("Reference descriptor set:");
|
||||
+ support_descriptors_dump (descrs, " ", stdout);
|
||||
+ puts ("Current descriptor set:");
|
||||
+ support_descriptors_dump (current, " ", stdout);
|
||||
+ puts ("Differences:");
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+report_closed_descriptor (bool *first,
|
||||
+ struct support_descriptors *descrs,
|
||||
+ struct support_descriptors *current,
|
||||
+ struct procfs_descriptor *left)
|
||||
+{
|
||||
+ support_record_failure ();
|
||||
+ dump_mismatch (first, descrs, current);
|
||||
+ printf ("error: descriptor %d was closed\n", left->fd);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+report_opened_descriptor (bool *first,
|
||||
+ struct support_descriptors *descrs,
|
||||
+ struct support_descriptors *current,
|
||||
+ struct procfs_descriptor *right)
|
||||
+{
|
||||
+ support_record_failure ();
|
||||
+ dump_mismatch (first, descrs, current);
|
||||
+ char *quoted = support_quote_string (right->link_target);
|
||||
+ printf ("error: descriptor %d was opened (\"%s\")\n", right->fd, quoted);
|
||||
+ free (quoted);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+support_descriptors_check (struct support_descriptors *descrs)
|
||||
+{
|
||||
+ struct support_descriptors *current = support_descriptors_list ();
|
||||
+
|
||||
+ /* Perform a merge join between descrs and current. This assumes
|
||||
+ that the arrays are sorted by file descriptor. */
|
||||
+
|
||||
+ struct procfs_descriptor *left = descriptor_list_begin (&descrs->list);
|
||||
+ struct procfs_descriptor *left_end = descriptor_list_end (&descrs->list);
|
||||
+ struct procfs_descriptor *right = descriptor_list_begin (¤t->list);
|
||||
+ struct procfs_descriptor *right_end = descriptor_list_end (¤t->list);
|
||||
+
|
||||
+ bool first = true;
|
||||
+ while (left != left_end && right != right_end)
|
||||
+ {
|
||||
+ if (left->fd == right->fd)
|
||||
+ {
|
||||
+ if (strcmp (left->link_target, right->link_target) != 0)
|
||||
+ {
|
||||
+ support_record_failure ();
|
||||
+ char *left_quoted = support_quote_string (left->link_target);
|
||||
+ char *right_quoted = support_quote_string (right->link_target);
|
||||
+ dump_mismatch (&first, descrs, current);
|
||||
+ printf ("error: descriptor %d changed from \"%s\" to \"%s\"\n",
|
||||
+ left->fd, left_quoted, right_quoted);
|
||||
+ free (left_quoted);
|
||||
+ free (right_quoted);
|
||||
+ }
|
||||
+ if (left->dev != right->dev)
|
||||
+ {
|
||||
+ support_record_failure ();
|
||||
+ dump_mismatch (&first, descrs, current);
|
||||
+ printf ("error: descriptor %d changed device"
|
||||
+ " from %lld:%lld to %lld:%lld\n",
|
||||
+ left->fd,
|
||||
+ (long long int) major (left->dev),
|
||||
+ (long long int) minor (left->dev),
|
||||
+ (long long int) major (right->dev),
|
||||
+ (long long int) minor (right->dev));
|
||||
+ }
|
||||
+ if (left->ino != right->ino)
|
||||
+ {
|
||||
+ support_record_failure ();
|
||||
+ dump_mismatch (&first, descrs, current);
|
||||
+ printf ("error: descriptor %d changed ino from %lld to %lld\n",
|
||||
+ left->fd,
|
||||
+ (long long int) left->ino, (long long int) right->ino);
|
||||
+ }
|
||||
+ ++left;
|
||||
+ ++right;
|
||||
+ }
|
||||
+ else if (left->fd < right->fd)
|
||||
+ {
|
||||
+ /* Gap on the right. */
|
||||
+ report_closed_descriptor (&first, descrs, current, left);
|
||||
+ ++left;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ /* Gap on the left. */
|
||||
+ TEST_VERIFY_EXIT (left->fd > right->fd);
|
||||
+ report_opened_descriptor (&first, descrs, current, right);
|
||||
+ ++right;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ while (left != left_end)
|
||||
+ {
|
||||
+ /* Closed descriptors (more descriptors on the left). */
|
||||
+ report_closed_descriptor (&first, descrs, current, left);
|
||||
+ ++left;
|
||||
+ }
|
||||
+
|
||||
+ while (right != right_end)
|
||||
+ {
|
||||
+ /* Opened descriptors (more descriptors on the right). */
|
||||
+ report_opened_descriptor (&first, descrs, current, right);
|
||||
+ ++right;
|
||||
+ }
|
||||
+
|
||||
+ support_descriptors_free (current);
|
||||
+}
|
||||
diff --git a/support/support_record_failure.c b/support/support_record_failure.c
|
||||
index 356798f55608ca71..17ab1d80ef2bbdea 100644
|
||||
--- a/support/support_record_failure.c
|
||||
+++ b/support/support_record_failure.c
|
||||
@@ -104,3 +104,11 @@ support_record_failure_reset (void)
|
||||
__atomic_store_n (&state->failed, 0, __ATOMIC_RELAXED);
|
||||
__atomic_add_fetch (&state->counter, 0, __ATOMIC_RELAXED);
|
||||
}
|
||||
+
|
||||
+int
|
||||
+support_record_failure_is_failed (void)
|
||||
+{
|
||||
+ /* Relaxed MO is sufficient because we need (blocking) external
|
||||
+ synchronization for reliable test error reporting anyway. */
|
||||
+ return __atomic_load_n (&state->failed, __ATOMIC_RELAXED);
|
||||
+}
|
||||
diff --git a/support/tst-support_descriptors.c b/support/tst-support_descriptors.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..5e9e824bc3820499
|
||||
--- /dev/null
|
||||
+++ b/support/tst-support_descriptors.c
|
||||
@@ -0,0 +1,198 @@
|
||||
+/* Tests for monitoring file descriptor usage.
|
||||
+ Copyright (C) 2018 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <fcntl.h>
|
||||
+#include <stdbool.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
+#include <support/capture_subprocess.h>
|
||||
+#include <support/check.h>
|
||||
+#include <support/descriptors.h>
|
||||
+#include <support/support.h>
|
||||
+#include <support/xunistd.h>
|
||||
+
|
||||
+/* This is the next free descriptor that the subprocess will pick. */
|
||||
+static int free_descriptor;
|
||||
+
|
||||
+static void
|
||||
+subprocess_no_change (void *closure)
|
||||
+{
|
||||
+ struct support_descriptors *descrs = support_descriptors_list ();
|
||||
+ int fd = xopen ("/dev/null", O_WRONLY, 0);
|
||||
+ TEST_COMPARE (fd, free_descriptor);
|
||||
+ xclose (fd);
|
||||
+ support_descriptors_free (descrs);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+subprocess_closed_descriptor (void *closure)
|
||||
+{
|
||||
+ int fd = xopen ("/dev/null", O_WRONLY, 0);
|
||||
+ TEST_COMPARE (fd, free_descriptor);
|
||||
+ struct support_descriptors *descrs = support_descriptors_list ();
|
||||
+ xclose (fd);
|
||||
+ support_descriptors_check (descrs); /* Will report failure. */
|
||||
+ puts ("EOT");
|
||||
+ support_descriptors_free (descrs);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+subprocess_opened_descriptor (void *closure)
|
||||
+{
|
||||
+ struct support_descriptors *descrs = support_descriptors_list ();
|
||||
+ int fd = xopen ("/dev/null", O_WRONLY, 0);
|
||||
+ TEST_COMPARE (fd, free_descriptor);
|
||||
+ support_descriptors_check (descrs); /* Will report failure. */
|
||||
+ puts ("EOT");
|
||||
+ support_descriptors_free (descrs);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+subprocess_changed_descriptor (void *closure)
|
||||
+{
|
||||
+ int fd = xopen ("/dev/null", O_WRONLY, 0);
|
||||
+ TEST_COMPARE (fd, free_descriptor);
|
||||
+ struct support_descriptors *descrs = support_descriptors_list ();
|
||||
+ xclose (fd);
|
||||
+ TEST_COMPARE (xopen ("/dev", O_DIRECTORY | O_RDONLY, 0), fd);
|
||||
+ support_descriptors_check (descrs); /* Will report failure. */
|
||||
+ puts ("EOT");
|
||||
+ support_descriptors_free (descrs);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+report_subprocess_output (const char *name,
|
||||
+ struct support_capture_subprocess *proc)
|
||||
+{
|
||||
+ printf ("info: BEGIN %s output\n"
|
||||
+ "%s"
|
||||
+ "info: END %s output\n",
|
||||
+ name, proc->out.buffer, name);
|
||||
+}
|
||||
+
|
||||
+/* Use an explicit flag to preserve failure status across
|
||||
+ support_record_failure_reset calls. */
|
||||
+static bool good = true;
|
||||
+
|
||||
+static void
|
||||
+test_run (void)
|
||||
+{
|
||||
+ struct support_capture_subprocess proc = support_capture_subprocess
|
||||
+ (&subprocess_no_change, NULL);
|
||||
+ support_capture_subprocess_check (&proc, "subprocess_no_change",
|
||||
+ 0, sc_allow_none);
|
||||
+ support_capture_subprocess_free (&proc);
|
||||
+
|
||||
+ char *expected = xasprintf ("\nDifferences:\n"
|
||||
+ "error: descriptor %d was closed\n"
|
||||
+ "EOT\n",
|
||||
+ free_descriptor);
|
||||
+ good = good && !support_record_failure_is_failed ();
|
||||
+ proc = support_capture_subprocess (&subprocess_closed_descriptor, NULL);
|
||||
+ good = good && support_record_failure_is_failed ();
|
||||
+ support_record_failure_reset (); /* Discard the reported error. */
|
||||
+ report_subprocess_output ("subprocess_closed_descriptor", &proc);
|
||||
+ TEST_VERIFY (strstr (proc.out.buffer, expected) != NULL);
|
||||
+ support_capture_subprocess_check (&proc, "subprocess_closed_descriptor",
|
||||
+ 0, sc_allow_stdout);
|
||||
+ support_capture_subprocess_free (&proc);
|
||||
+ free (expected);
|
||||
+
|
||||
+ expected = xasprintf ("\nDifferences:\n"
|
||||
+ "error: descriptor %d was opened (\"/dev/null\")\n"
|
||||
+ "EOT\n",
|
||||
+ free_descriptor);
|
||||
+ good = good && !support_record_failure_is_failed ();
|
||||
+ proc = support_capture_subprocess (&subprocess_opened_descriptor, NULL);
|
||||
+ good = good && support_record_failure_is_failed ();
|
||||
+ support_record_failure_reset (); /* Discard the reported error. */
|
||||
+ report_subprocess_output ("subprocess_opened_descriptor", &proc);
|
||||
+ TEST_VERIFY (strstr (proc.out.buffer, expected) != NULL);
|
||||
+ support_capture_subprocess_check (&proc, "subprocess_opened_descriptor",
|
||||
+ 0, sc_allow_stdout);
|
||||
+ support_capture_subprocess_free (&proc);
|
||||
+ free (expected);
|
||||
+
|
||||
+ expected = xasprintf ("\nDifferences:\n"
|
||||
+ "error: descriptor %d changed from \"/dev/null\""
|
||||
+ " to \"/dev\"\n"
|
||||
+ "error: descriptor %d changed ino ",
|
||||
+ free_descriptor, free_descriptor);
|
||||
+ good = good && !support_record_failure_is_failed ();
|
||||
+ proc = support_capture_subprocess (&subprocess_changed_descriptor, NULL);
|
||||
+ good = good && support_record_failure_is_failed ();
|
||||
+ support_record_failure_reset (); /* Discard the reported error. */
|
||||
+ report_subprocess_output ("subprocess_changed_descriptor", &proc);
|
||||
+ TEST_VERIFY (strstr (proc.out.buffer, expected) != NULL);
|
||||
+ support_capture_subprocess_check (&proc, "subprocess_changed_descriptor",
|
||||
+ 0, sc_allow_stdout);
|
||||
+ support_capture_subprocess_free (&proc);
|
||||
+ free (expected);
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ puts ("info: initial descriptor set");
|
||||
+ {
|
||||
+ struct support_descriptors *descrs = support_descriptors_list ();
|
||||
+ support_descriptors_dump (descrs, "info: ", stdout);
|
||||
+ support_descriptors_free (descrs);
|
||||
+ }
|
||||
+
|
||||
+ free_descriptor = xopen ("/dev/null", O_WRONLY, 0);
|
||||
+ puts ("info: descriptor set with additional free descriptor");
|
||||
+ {
|
||||
+ struct support_descriptors *descrs = support_descriptors_list ();
|
||||
+ support_descriptors_dump (descrs, "info: ", stdout);
|
||||
+ support_descriptors_free (descrs);
|
||||
+ }
|
||||
+ TEST_VERIFY (free_descriptor >= 3);
|
||||
+ xclose (free_descriptor);
|
||||
+
|
||||
+ /* Initial test run without a sentinel descriptor. The presence of
|
||||
+ such a descriptor exercises different conditions in the list
|
||||
+ comparison in support_descriptors_check. */
|
||||
+ test_run ();
|
||||
+
|
||||
+ /* Allocate a sentinel descriptor at the end of the descriptor list,
|
||||
+ after free_descriptor. */
|
||||
+ int sentinel_fd;
|
||||
+ {
|
||||
+ int fd = xopen ("/dev/full", O_WRONLY, 0);
|
||||
+ TEST_COMPARE (fd, free_descriptor);
|
||||
+ sentinel_fd = dup (fd);
|
||||
+ TEST_VERIFY_EXIT (sentinel_fd > fd);
|
||||
+ xclose (fd);
|
||||
+ }
|
||||
+ puts ("info: descriptor set with sentinel descriptor");
|
||||
+ {
|
||||
+ struct support_descriptors *descrs = support_descriptors_list ();
|
||||
+ support_descriptors_dump (descrs, "info: ", stdout);
|
||||
+ support_descriptors_free (descrs);
|
||||
+ }
|
||||
+
|
||||
+ /* Second test run with sentinel descriptor. */
|
||||
+ test_run ();
|
||||
+
|
||||
+ xclose (sentinel_fd);
|
||||
+
|
||||
+ return !good;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
86
SOURCES/glibc-rh1654010-6.patch
Normal file
86
SOURCES/glibc-rh1654010-6.patch
Normal file
@ -0,0 +1,86 @@
|
||||
commit 899478c2bfa00c5df8d8bedb52effbb065700278
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Thu Dec 6 15:39:50 2018 +0100
|
||||
|
||||
inet/tst-if_index-long: New test case for CVE-2018-19591 [BZ #23927]
|
||||
|
||||
diff --git a/inet/Makefile b/inet/Makefile
|
||||
index 09f5ba78fc5f3120..7782913b4c06f057 100644
|
||||
--- a/inet/Makefile
|
||||
+++ b/inet/Makefile
|
||||
@@ -52,7 +52,7 @@ aux := check_pf check_native ifreq
|
||||
tests := htontest test_ifindex tst-ntoa tst-ether_aton tst-network \
|
||||
tst-gethnm test-ifaddrs bug-if1 test-inet6_opt tst-ether_line \
|
||||
tst-getni1 tst-getni2 tst-inet6_rth tst-checks tst-checks-posix \
|
||||
- tst-sockaddr test-hnto-types
|
||||
+ tst-sockaddr test-hnto-types tst-if_index-long
|
||||
|
||||
# tst-deadline must be linked statically so that we can access
|
||||
# internal functions.
|
||||
diff --git a/inet/tst-if_index-long.c b/inet/tst-if_index-long.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..3dc74874e5310945
|
||||
--- /dev/null
|
||||
+++ b/inet/tst-if_index-long.c
|
||||
@@ -0,0 +1,61 @@
|
||||
+/* Check for descriptor leak in if_nametoindex with a long interface name.
|
||||
+ Copyright (C) 2018 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+/* This test checks for a descriptor leak in case of a long interface
|
||||
+ name (CVE-2018-19591, bug 23927). */
|
||||
+
|
||||
+#include <errno.h>
|
||||
+#include <net/if.h>
|
||||
+#include <netdb.h>
|
||||
+#include <string.h>
|
||||
+#include <support/check.h>
|
||||
+#include <support/descriptors.h>
|
||||
+#include <support/support.h>
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ struct support_descriptors *descrs = support_descriptors_list ();
|
||||
+
|
||||
+ /* Prepare a name which is just as long as required for trigging the
|
||||
+ bug. */
|
||||
+ char name[IFNAMSIZ + 1];
|
||||
+ memset (name, 'A', IFNAMSIZ);
|
||||
+ name[IFNAMSIZ] = '\0';
|
||||
+ TEST_COMPARE (strlen (name), IFNAMSIZ);
|
||||
+ struct ifreq ifr;
|
||||
+ TEST_COMPARE (strlen (name), sizeof (ifr.ifr_name));
|
||||
+
|
||||
+ /* Test directly via if_nametoindex. */
|
||||
+ TEST_COMPARE (if_nametoindex (name), 0);
|
||||
+ TEST_COMPARE (errno, ENODEV);
|
||||
+ support_descriptors_check (descrs);
|
||||
+
|
||||
+ /* Same test via getaddrinfo. */
|
||||
+ char *host = xasprintf ("fea0::%%%s", name);
|
||||
+ struct addrinfo hints = { .ai_flags = AI_NUMERICHOST, };
|
||||
+ struct addrinfo *ai;
|
||||
+ TEST_COMPARE (getaddrinfo (host, NULL, &hints, &ai), EAI_NONAME);
|
||||
+ support_descriptors_check (descrs);
|
||||
+
|
||||
+ support_descriptors_free (descrs);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
446
SOURCES/glibc-rh1654872-1.patch
Normal file
446
SOURCES/glibc-rh1654872-1.patch
Normal file
@ -0,0 +1,446 @@
|
||||
commit 3d265911c2aac65d978f679101594f9071024874
|
||||
Author: Andreas Schwab <schwab@suse.de>
|
||||
Date: Mon Nov 12 11:11:40 2018 +0100
|
||||
|
||||
Reindent nptl/pthread_rwlock_common.c
|
||||
|
||||
diff --git a/nptl/pthread_rwlock_common.c b/nptl/pthread_rwlock_common.c
|
||||
index a290d08332b802a5..5dd534271aed6b41 100644
|
||||
--- a/nptl/pthread_rwlock_common.c
|
||||
+++ b/nptl/pthread_rwlock_common.c
|
||||
@@ -34,7 +34,7 @@
|
||||
|
||||
A thread is allowed to acquire a read lock recursively (i.e., have rdlock
|
||||
critical sections that overlap in sequenced-before) unless the kind of the
|
||||
- rwlock is set to PTHREAD_RWLOCK_PREFER_WRITERS_NONRECURSIVE_NP.
|
||||
+ rwlock is set to PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP.
|
||||
|
||||
This lock is built so that workloads of mostly readers can be executed with
|
||||
low runtime overheads. This matches that the default kind of the lock is
|
||||
@@ -46,7 +46,7 @@
|
||||
An uncontended write lock acquisition is as fast as for a normal
|
||||
exclusive mutex but writer contention is somewhat more costly due to
|
||||
keeping track of the exact number of writers. If the rwlock kind requests
|
||||
- writers to be preferred (i.e., PTHREAD_RWLOCK_PREFER_WRITERS_NP or the
|
||||
+ writers to be preferred (i.e., PTHREAD_RWLOCK_PREFER_WRITER_NP or the
|
||||
no-recursive-readers variant of it), then writer--to--writer lock ownership
|
||||
hand-over is fairly fast and bypasses lock acquisition attempts by readers.
|
||||
The costs of lock ownership transfer between readers and writers vary. If
|
||||
@@ -251,7 +251,7 @@ __pthread_rwlock_rdunlock (pthread_rwlock_t *rwlock)
|
||||
the first reader's store to __wrphase_futex (or a later value) if
|
||||
the writer observes that a write phase has been started. */
|
||||
if (atomic_compare_exchange_weak_release (&rwlock->__data.__readers,
|
||||
- &r, rnew))
|
||||
+ &r, rnew))
|
||||
break;
|
||||
/* TODO Back-off. */
|
||||
}
|
||||
@@ -285,7 +285,7 @@ __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock,
|
||||
/* Make sure we are not holding the rwlock as a writer. This is a deadlock
|
||||
situation we recognize and report. */
|
||||
if (__glibc_unlikely (atomic_load_relaxed (&rwlock->__data.__cur_writer)
|
||||
- == THREAD_GETMEM (THREAD_SELF, tid)))
|
||||
+ == THREAD_GETMEM (THREAD_SELF, tid)))
|
||||
return EDEADLK;
|
||||
|
||||
/* If we prefer writers, recursive rdlock is disallowed, we are in a read
|
||||
@@ -299,9 +299,9 @@ __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock,
|
||||
if (rwlock->__data.__flags == PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP)
|
||||
{
|
||||
r = atomic_load_relaxed (&rwlock->__data.__readers);
|
||||
- while (((r & PTHREAD_RWLOCK_WRPHASE) == 0)
|
||||
- && ((r & PTHREAD_RWLOCK_WRLOCKED) != 0)
|
||||
- && ((r >> PTHREAD_RWLOCK_READER_SHIFT) > 0))
|
||||
+ while ((r & PTHREAD_RWLOCK_WRPHASE) == 0
|
||||
+ && (r & PTHREAD_RWLOCK_WRLOCKED) != 0
|
||||
+ && (r >> PTHREAD_RWLOCK_READER_SHIFT) > 0)
|
||||
{
|
||||
/* TODO Spin first. */
|
||||
/* Try setting the flag signaling that we are waiting without having
|
||||
@@ -315,11 +315,11 @@ __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock,
|
||||
__readers, and all threads set the flag under the same
|
||||
conditions. */
|
||||
while ((atomic_load_relaxed (&rwlock->__data.__readers)
|
||||
- & PTHREAD_RWLOCK_RWAITING) != 0)
|
||||
+ & PTHREAD_RWLOCK_RWAITING) != 0)
|
||||
{
|
||||
int private = __pthread_rwlock_get_private (rwlock);
|
||||
int err = futex_abstimed_wait (&rwlock->__data.__readers,
|
||||
- r, abstime, private);
|
||||
+ r, abstime, private);
|
||||
/* We ignore EAGAIN and EINTR. On time-outs, we can just
|
||||
return because we don't need to clean up anything. */
|
||||
if (err == ETIMEDOUT)
|
||||
@@ -338,8 +338,9 @@ __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock,
|
||||
expected value for future operations. Acquire MO so we synchronize with
|
||||
prior writers as well as the last reader of the previous read phase (see
|
||||
below). */
|
||||
- r = atomic_fetch_add_acquire (&rwlock->__data.__readers,
|
||||
- (1 << PTHREAD_RWLOCK_READER_SHIFT)) + (1 << PTHREAD_RWLOCK_READER_SHIFT);
|
||||
+ r = (atomic_fetch_add_acquire (&rwlock->__data.__readers,
|
||||
+ (1 << PTHREAD_RWLOCK_READER_SHIFT))
|
||||
+ + (1 << PTHREAD_RWLOCK_READER_SHIFT));
|
||||
|
||||
/* Check whether there is an overflow in the number of readers. We assume
|
||||
that the total number of threads is less than half the maximum number
|
||||
@@ -359,8 +360,9 @@ __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock,
|
||||
/* Relaxed MO is okay because we just want to undo our registration and
|
||||
cannot have changed the rwlock state substantially if the CAS
|
||||
succeeds. */
|
||||
- if (atomic_compare_exchange_weak_relaxed (&rwlock->__data.__readers, &r,
|
||||
- r - (1 << PTHREAD_RWLOCK_READER_SHIFT)))
|
||||
+ if (atomic_compare_exchange_weak_relaxed
|
||||
+ (&rwlock->__data.__readers,
|
||||
+ &r, r - (1 << PTHREAD_RWLOCK_READER_SHIFT)))
|
||||
return EAGAIN;
|
||||
}
|
||||
|
||||
@@ -378,15 +380,15 @@ __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock,
|
||||
/* Otherwise, if we were in a write phase (states #6 or #8), we must wait
|
||||
for explicit hand-over of the read phase; the only exception is if we
|
||||
can start a read phase if there is no primary writer currently. */
|
||||
- while (((r & PTHREAD_RWLOCK_WRPHASE) != 0)
|
||||
- && ((r & PTHREAD_RWLOCK_WRLOCKED) == 0))
|
||||
+ while ((r & PTHREAD_RWLOCK_WRPHASE) != 0
|
||||
+ && (r & PTHREAD_RWLOCK_WRLOCKED) == 0)
|
||||
{
|
||||
- /* Try to enter a read phase: If the CAS below succeeds, we have
|
||||
+ /* Try to enter a read phase: If the CAS below succeeds, we have
|
||||
ownership; if it fails, we will simply retry and reassess the
|
||||
situation.
|
||||
Acquire MO so we synchronize with prior writers. */
|
||||
if (atomic_compare_exchange_weak_acquire (&rwlock->__data.__readers, &r,
|
||||
- r ^ PTHREAD_RWLOCK_WRPHASE))
|
||||
+ r ^ PTHREAD_RWLOCK_WRPHASE))
|
||||
{
|
||||
/* We started the read phase, so we are also responsible for
|
||||
updating the write-phase futex. Relaxed MO is sufficient.
|
||||
@@ -397,7 +399,7 @@ __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock,
|
||||
(but we can pretend to do the setting and unsetting of WRLOCKED
|
||||
atomically, and thus can skip this step). */
|
||||
if ((atomic_exchange_relaxed (&rwlock->__data.__wrphase_futex, 0)
|
||||
- & PTHREAD_RWLOCK_FUTEX_USED) != 0)
|
||||
+ & PTHREAD_RWLOCK_FUTEX_USED) != 0)
|
||||
{
|
||||
int private = __pthread_rwlock_get_private (rwlock);
|
||||
futex_wake (&rwlock->__data.__wrphase_futex, INT_MAX, private);
|
||||
@@ -435,16 +437,17 @@ __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock,
|
||||
for (;;)
|
||||
{
|
||||
while (((wpf = atomic_load_relaxed (&rwlock->__data.__wrphase_futex))
|
||||
- | PTHREAD_RWLOCK_FUTEX_USED) == (1 | PTHREAD_RWLOCK_FUTEX_USED))
|
||||
+ | PTHREAD_RWLOCK_FUTEX_USED) == (1 | PTHREAD_RWLOCK_FUTEX_USED))
|
||||
{
|
||||
int private = __pthread_rwlock_get_private (rwlock);
|
||||
if (((wpf & PTHREAD_RWLOCK_FUTEX_USED) == 0)
|
||||
- && !atomic_compare_exchange_weak_relaxed
|
||||
+ && (!atomic_compare_exchange_weak_relaxed
|
||||
(&rwlock->__data.__wrphase_futex,
|
||||
- &wpf, wpf | PTHREAD_RWLOCK_FUTEX_USED))
|
||||
+ &wpf, wpf | PTHREAD_RWLOCK_FUTEX_USED)))
|
||||
continue;
|
||||
int err = futex_abstimed_wait (&rwlock->__data.__wrphase_futex,
|
||||
- 1 | PTHREAD_RWLOCK_FUTEX_USED, abstime, private);
|
||||
+ 1 | PTHREAD_RWLOCK_FUTEX_USED,
|
||||
+ abstime, private);
|
||||
if (err == ETIMEDOUT)
|
||||
{
|
||||
/* If we timed out, we need to unregister. If no read phase
|
||||
@@ -477,8 +480,8 @@ __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock,
|
||||
in this case and thus make the spin-waiting we need
|
||||
unnecessarily expensive. */
|
||||
while ((atomic_load_relaxed (&rwlock->__data.__wrphase_futex)
|
||||
- | PTHREAD_RWLOCK_FUTEX_USED)
|
||||
- == (1 | PTHREAD_RWLOCK_FUTEX_USED))
|
||||
+ | PTHREAD_RWLOCK_FUTEX_USED)
|
||||
+ == (1 | PTHREAD_RWLOCK_FUTEX_USED))
|
||||
{
|
||||
/* TODO Back-off? */
|
||||
}
|
||||
@@ -495,7 +498,7 @@ __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock,
|
||||
release of the writer, and so that we observe a recent value of
|
||||
__wrphase_futex (see below). */
|
||||
if ((atomic_load_acquire (&rwlock->__data.__readers)
|
||||
- & PTHREAD_RWLOCK_WRPHASE) == 0)
|
||||
+ & PTHREAD_RWLOCK_WRPHASE) == 0)
|
||||
/* We are in a read phase now, so the least recent modification of
|
||||
__wrphase_futex we can read from is the store by the writer
|
||||
with value 1. Thus, only now we can assume that if we observe
|
||||
@@ -516,8 +519,9 @@ __pthread_rwlock_wrunlock (pthread_rwlock_t *rwlock)
|
||||
atomic_store_relaxed (&rwlock->__data.__cur_writer, 0);
|
||||
/* Disable waiting by writers. We will wake up after we decided how to
|
||||
proceed. */
|
||||
- bool wake_writers = ((atomic_exchange_relaxed
|
||||
- (&rwlock->__data.__writers_futex, 0) & PTHREAD_RWLOCK_FUTEX_USED) != 0);
|
||||
+ bool wake_writers
|
||||
+ = ((atomic_exchange_relaxed (&rwlock->__data.__writers_futex, 0)
|
||||
+ & PTHREAD_RWLOCK_FUTEX_USED) != 0);
|
||||
|
||||
if (rwlock->__data.__flags != PTHREAD_RWLOCK_PREFER_READER_NP)
|
||||
{
|
||||
@@ -529,8 +533,8 @@ __pthread_rwlock_wrunlock (pthread_rwlock_t *rwlock)
|
||||
synchronize with us and thus can take over our view of
|
||||
__readers (including, for example, whether we are in a write
|
||||
phase or not). */
|
||||
- if (atomic_compare_exchange_weak_release (&rwlock->__data.__writers,
|
||||
- &w, w | PTHREAD_RWLOCK_WRHANDOVER))
|
||||
+ if (atomic_compare_exchange_weak_release
|
||||
+ (&rwlock->__data.__writers, &w, w | PTHREAD_RWLOCK_WRHANDOVER))
|
||||
/* Another writer will take over. */
|
||||
goto done;
|
||||
/* TODO Back-off. */
|
||||
@@ -543,9 +547,10 @@ __pthread_rwlock_wrunlock (pthread_rwlock_t *rwlock)
|
||||
unsigned int r = atomic_load_relaxed (&rwlock->__data.__readers);
|
||||
/* Release MO so that subsequent readers or writers synchronize with us. */
|
||||
while (!atomic_compare_exchange_weak_release
|
||||
- (&rwlock->__data.__readers, &r, (r ^ PTHREAD_RWLOCK_WRLOCKED)
|
||||
- ^ ((r >> PTHREAD_RWLOCK_READER_SHIFT) == 0 ? 0
|
||||
- : PTHREAD_RWLOCK_WRPHASE)))
|
||||
+ (&rwlock->__data.__readers, &r,
|
||||
+ ((r ^ PTHREAD_RWLOCK_WRLOCKED)
|
||||
+ ^ ((r >> PTHREAD_RWLOCK_READER_SHIFT) == 0 ? 0
|
||||
+ : PTHREAD_RWLOCK_WRPHASE))))
|
||||
{
|
||||
/* TODO Back-off. */
|
||||
}
|
||||
@@ -574,7 +579,7 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock,
|
||||
/* Make sure we are not holding the rwlock as a writer. This is a deadlock
|
||||
situation we recognize and report. */
|
||||
if (__glibc_unlikely (atomic_load_relaxed (&rwlock->__data.__cur_writer)
|
||||
- == THREAD_GETMEM (THREAD_SELF, tid)))
|
||||
+ == THREAD_GETMEM (THREAD_SELF, tid)))
|
||||
return EDEADLK;
|
||||
|
||||
/* First we try to acquire the role of primary writer by setting WRLOCKED;
|
||||
@@ -593,12 +598,12 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock,
|
||||
this could be less scalable if readers arrive and leave frequently. */
|
||||
bool may_share_futex_used_flag = false;
|
||||
unsigned int r = atomic_fetch_or_acquire (&rwlock->__data.__readers,
|
||||
- PTHREAD_RWLOCK_WRLOCKED);
|
||||
+ PTHREAD_RWLOCK_WRLOCKED);
|
||||
if (__glibc_unlikely ((r & PTHREAD_RWLOCK_WRLOCKED) != 0))
|
||||
{
|
||||
/* There is another primary writer. */
|
||||
- bool prefer_writer =
|
||||
- (rwlock->__data.__flags != PTHREAD_RWLOCK_PREFER_READER_NP);
|
||||
+ bool prefer_writer
|
||||
+ = (rwlock->__data.__flags != PTHREAD_RWLOCK_PREFER_READER_NP);
|
||||
if (prefer_writer)
|
||||
{
|
||||
/* We register as a waiting writer, so that we can make use of
|
||||
@@ -617,8 +622,7 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock,
|
||||
/* Try to become the primary writer or retry. Acquire MO as in
|
||||
the fetch_or above. */
|
||||
if (atomic_compare_exchange_weak_acquire
|
||||
- (&rwlock->__data.__readers, &r,
|
||||
- r | PTHREAD_RWLOCK_WRLOCKED))
|
||||
+ (&rwlock->__data.__readers, &r, r | PTHREAD_RWLOCK_WRLOCKED))
|
||||
{
|
||||
if (prefer_writer)
|
||||
{
|
||||
@@ -633,8 +637,7 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock,
|
||||
__writers).
|
||||
??? Perhaps this is not strictly necessary for
|
||||
reasons we do not yet know of. */
|
||||
- atomic_fetch_add_relaxed (&rwlock->__data.__writers,
|
||||
- -1);
|
||||
+ atomic_fetch_add_relaxed (&rwlock->__data.__writers, -1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -646,8 +649,7 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock,
|
||||
succeed, we own WRLOCKED. */
|
||||
if (prefer_writer)
|
||||
{
|
||||
- unsigned int w = atomic_load_relaxed
|
||||
- (&rwlock->__data.__writers);
|
||||
+ unsigned int w = atomic_load_relaxed (&rwlock->__data.__writers);
|
||||
if ((w & PTHREAD_RWLOCK_WRHANDOVER) != 0)
|
||||
{
|
||||
/* Acquire MO is required here so that we synchronize with
|
||||
@@ -677,13 +679,13 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock,
|
||||
/* We did not acquire WRLOCKED nor were able to use writer--writer
|
||||
hand-over, so we block on __writers_futex. */
|
||||
int private = __pthread_rwlock_get_private (rwlock);
|
||||
- unsigned int wf = atomic_load_relaxed
|
||||
- (&rwlock->__data.__writers_futex);
|
||||
+ unsigned int wf
|
||||
+ = atomic_load_relaxed (&rwlock->__data.__writers_futex);
|
||||
if (((wf & ~(unsigned int) PTHREAD_RWLOCK_FUTEX_USED) != 1)
|
||||
|| ((wf != (1 | PTHREAD_RWLOCK_FUTEX_USED))
|
||||
- && !atomic_compare_exchange_weak_relaxed
|
||||
+ && (!atomic_compare_exchange_weak_relaxed
|
||||
(&rwlock->__data.__writers_futex, &wf,
|
||||
- 1 | PTHREAD_RWLOCK_FUTEX_USED)))
|
||||
+ 1 | PTHREAD_RWLOCK_FUTEX_USED))))
|
||||
{
|
||||
/* If we cannot block on __writers_futex because there is no
|
||||
primary writer, or we cannot set PTHREAD_RWLOCK_FUTEX_USED,
|
||||
@@ -704,7 +706,8 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock,
|
||||
in this group. */
|
||||
may_share_futex_used_flag = true;
|
||||
int err = futex_abstimed_wait (&rwlock->__data.__writers_futex,
|
||||
- 1 | PTHREAD_RWLOCK_FUTEX_USED, abstime, private);
|
||||
+ 1 | PTHREAD_RWLOCK_FUTEX_USED,
|
||||
+ abstime, private);
|
||||
if (err == ETIMEDOUT)
|
||||
{
|
||||
if (prefer_writer)
|
||||
@@ -716,10 +719,10 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock,
|
||||
that this happened before the timeout; see
|
||||
pthread_rwlock_rdlock_full for the full reasoning.)
|
||||
Also see the similar code above. */
|
||||
- unsigned int w = atomic_load_relaxed
|
||||
- (&rwlock->__data.__writers);
|
||||
+ unsigned int w
|
||||
+ = atomic_load_relaxed (&rwlock->__data.__writers);
|
||||
while (!atomic_compare_exchange_weak_acquire
|
||||
- (&rwlock->__data.__writers, &w,
|
||||
+ (&rwlock->__data.__writers, &w,
|
||||
(w == PTHREAD_RWLOCK_WRHANDOVER + 1 ? 0 : w - 1)))
|
||||
{
|
||||
/* TODO Back-off. */
|
||||
@@ -751,7 +754,8 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock,
|
||||
modifications of __readers ensures that this store happens after the
|
||||
store of value 0 by the previous primary writer. */
|
||||
atomic_store_relaxed (&rwlock->__data.__writers_futex,
|
||||
- 1 | (may_share_futex_used_flag ? PTHREAD_RWLOCK_FUTEX_USED : 0));
|
||||
+ 1 | (may_share_futex_used_flag
|
||||
+ ? PTHREAD_RWLOCK_FUTEX_USED : 0));
|
||||
|
||||
/* If we are in a write phase, we have acquired the lock. */
|
||||
if ((r & PTHREAD_RWLOCK_WRPHASE) != 0)
|
||||
@@ -759,15 +763,15 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock,
|
||||
|
||||
/* If we are in a read phase and there are no readers, try to start a write
|
||||
phase. */
|
||||
- while (((r & PTHREAD_RWLOCK_WRPHASE) == 0)
|
||||
- && ((r >> PTHREAD_RWLOCK_READER_SHIFT) == 0))
|
||||
+ while ((r & PTHREAD_RWLOCK_WRPHASE) == 0
|
||||
+ && (r >> PTHREAD_RWLOCK_READER_SHIFT) == 0)
|
||||
{
|
||||
/* Acquire MO so that we synchronize with prior writers and do
|
||||
not interfere with their updates to __writers_futex, as well
|
||||
as regarding prior readers and their updates to __wrphase_futex,
|
||||
respectively. */
|
||||
if (atomic_compare_exchange_weak_acquire (&rwlock->__data.__readers,
|
||||
- &r, r | PTHREAD_RWLOCK_WRPHASE))
|
||||
+ &r, r | PTHREAD_RWLOCK_WRPHASE))
|
||||
{
|
||||
/* We have started a write phase, so need to enable readers to wait.
|
||||
See the similar case in __pthread_rwlock_rdlock_full. Unlike in
|
||||
@@ -792,24 +796,24 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock,
|
||||
for (;;)
|
||||
{
|
||||
while (((wpf = atomic_load_relaxed (&rwlock->__data.__wrphase_futex))
|
||||
- | PTHREAD_RWLOCK_FUTEX_USED) == PTHREAD_RWLOCK_FUTEX_USED)
|
||||
+ | PTHREAD_RWLOCK_FUTEX_USED) == PTHREAD_RWLOCK_FUTEX_USED)
|
||||
{
|
||||
int private = __pthread_rwlock_get_private (rwlock);
|
||||
- if (((wpf & PTHREAD_RWLOCK_FUTEX_USED) == 0)
|
||||
- && !atomic_compare_exchange_weak_relaxed
|
||||
+ if ((wpf & PTHREAD_RWLOCK_FUTEX_USED) == 0
|
||||
+ && (!atomic_compare_exchange_weak_relaxed
|
||||
(&rwlock->__data.__wrphase_futex, &wpf,
|
||||
- PTHREAD_RWLOCK_FUTEX_USED))
|
||||
+ PTHREAD_RWLOCK_FUTEX_USED)))
|
||||
continue;
|
||||
int err = futex_abstimed_wait (&rwlock->__data.__wrphase_futex,
|
||||
- PTHREAD_RWLOCK_FUTEX_USED, abstime, private);
|
||||
+ PTHREAD_RWLOCK_FUTEX_USED,
|
||||
+ abstime, private);
|
||||
if (err == ETIMEDOUT)
|
||||
{
|
||||
- if (rwlock->__data.__flags
|
||||
- != PTHREAD_RWLOCK_PREFER_READER_NP)
|
||||
+ if (rwlock->__data.__flags != PTHREAD_RWLOCK_PREFER_READER_NP)
|
||||
{
|
||||
/* We try writer--writer hand-over. */
|
||||
- unsigned int w = atomic_load_relaxed
|
||||
- (&rwlock->__data.__writers);
|
||||
+ unsigned int w
|
||||
+ = atomic_load_relaxed (&rwlock->__data.__writers);
|
||||
if (w != 0)
|
||||
{
|
||||
/* We are about to hand over WRLOCKED, so we must
|
||||
@@ -823,13 +827,13 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock,
|
||||
Release MO so that another writer that gets
|
||||
WRLOCKED from us can take over our view of
|
||||
__readers. */
|
||||
- unsigned int wf = atomic_exchange_relaxed
|
||||
- (&rwlock->__data.__writers_futex, 0);
|
||||
+ unsigned int wf
|
||||
+ = atomic_exchange_relaxed (&rwlock->__data.__writers_futex, 0);
|
||||
while (w != 0)
|
||||
{
|
||||
if (atomic_compare_exchange_weak_release
|
||||
(&rwlock->__data.__writers, &w,
|
||||
- w | PTHREAD_RWLOCK_WRHANDOVER))
|
||||
+ w | PTHREAD_RWLOCK_WRHANDOVER))
|
||||
{
|
||||
/* Wake other writers. */
|
||||
if ((wf & PTHREAD_RWLOCK_FUTEX_USED) != 0)
|
||||
@@ -844,8 +848,7 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock,
|
||||
again. Make sure we don't loose the flag that
|
||||
signals whether there are threads waiting on
|
||||
this futex. */
|
||||
- atomic_store_relaxed
|
||||
- (&rwlock->__data.__writers_futex, wf);
|
||||
+ atomic_store_relaxed (&rwlock->__data.__writers_futex, wf);
|
||||
}
|
||||
}
|
||||
/* If we timed out and we are not in a write phase, we can
|
||||
@@ -857,8 +860,8 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock,
|
||||
/* We are about to release WRLOCKED, so we must release
|
||||
__writers_futex too; see the handling of
|
||||
writer--writer hand-over above. */
|
||||
- unsigned int wf = atomic_exchange_relaxed
|
||||
- (&rwlock->__data.__writers_futex, 0);
|
||||
+ unsigned int wf
|
||||
+ = atomic_exchange_relaxed (&rwlock->__data.__writers_futex, 0);
|
||||
while ((r & PTHREAD_RWLOCK_WRPHASE) == 0)
|
||||
{
|
||||
/* While we don't need to make anything from a
|
||||
@@ -877,11 +880,11 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock,
|
||||
/* Wake other writers. */
|
||||
if ((wf & PTHREAD_RWLOCK_FUTEX_USED) != 0)
|
||||
futex_wake (&rwlock->__data.__writers_futex,
|
||||
- 1, private);
|
||||
+ 1, private);
|
||||
/* Wake waiting readers. */
|
||||
if ((r & PTHREAD_RWLOCK_RWAITING) != 0)
|
||||
futex_wake (&rwlock->__data.__readers,
|
||||
- INT_MAX, private);
|
||||
+ INT_MAX, private);
|
||||
return ETIMEDOUT;
|
||||
}
|
||||
}
|
||||
@@ -898,10 +901,9 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock,
|
||||
atomic_thread_fence_acquire ();
|
||||
/* We still need to wait for explicit hand-over, but we must
|
||||
not use futex_wait anymore. */
|
||||
- while ((atomic_load_relaxed
|
||||
- (&rwlock->__data.__wrphase_futex)
|
||||
- | PTHREAD_RWLOCK_FUTEX_USED)
|
||||
- == PTHREAD_RWLOCK_FUTEX_USED)
|
||||
+ while ((atomic_load_relaxed (&rwlock->__data.__wrphase_futex)
|
||||
+ | PTHREAD_RWLOCK_FUTEX_USED)
|
||||
+ == PTHREAD_RWLOCK_FUTEX_USED)
|
||||
{
|
||||
/* TODO Back-off. */
|
||||
}
|
||||
@@ -915,12 +917,12 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock,
|
||||
if (ready)
|
||||
break;
|
||||
if ((atomic_load_acquire (&rwlock->__data.__readers)
|
||||
- & PTHREAD_RWLOCK_WRPHASE) != 0)
|
||||
+ & PTHREAD_RWLOCK_WRPHASE) != 0)
|
||||
ready = true;
|
||||
}
|
||||
|
||||
done:
|
||||
atomic_store_relaxed (&rwlock->__data.__cur_writer,
|
||||
- THREAD_GETMEM (THREAD_SELF, tid));
|
||||
+ THREAD_GETMEM (THREAD_SELF, tid));
|
||||
return 0;
|
||||
}
|
134
SOURCES/glibc-rh1654872-2.patch
Normal file
134
SOURCES/glibc-rh1654872-2.patch
Normal file
@ -0,0 +1,134 @@
|
||||
commit f21e8f8ca466320fed38bdb71526c574dae98026
|
||||
Author: Andreas Schwab <schwab@suse.de>
|
||||
Date: Thu Nov 8 14:28:22 2018 +0100
|
||||
|
||||
Fix rwlock stall with PREFER_WRITER_NONRECURSIVE_NP (bug 23861)
|
||||
|
||||
In the read lock function (__pthread_rwlock_rdlock_full) there was a
|
||||
code path which would fail to reload __readers while waiting for
|
||||
PTHREAD_RWLOCK_RWAITING to change. This failure to reload __readers
|
||||
into a local value meant that various conditionals used the old value
|
||||
of __readers and with only two threads left it could result in an
|
||||
indefinite stall of one of the readers (waiting for PTHREAD_RWLOCK_RWAITING
|
||||
to go to zero, but it never would).
|
||||
|
||||
diff --git a/nptl/Makefile b/nptl/Makefile
|
||||
index ee720960d18f33d1..2d2db648f730db61 100644
|
||||
--- a/nptl/Makefile
|
||||
+++ b/nptl/Makefile
|
||||
@@ -318,7 +318,8 @@ tests = tst-attr1 tst-attr2 tst-attr3 tst-default-attr \
|
||||
tst-minstack-throw \
|
||||
tst-cnd-basic tst-mtx-trylock tst-cnd-broadcast \
|
||||
tst-cnd-timedwait tst-thrd-detach tst-mtx-basic tst-thrd-sleep \
|
||||
- tst-mtx-recursive tst-tss-basic tst-call-once tst-mtx-timedlock
|
||||
+ tst-mtx-recursive tst-tss-basic tst-call-once tst-mtx-timedlock \
|
||||
+ tst-rwlock-pwn
|
||||
|
||||
tests-internal := tst-rwlock19 tst-rwlock20 \
|
||||
tst-sem11 tst-sem12 tst-sem13 \
|
||||
diff --git a/nptl/pthread_rwlock_common.c b/nptl/pthread_rwlock_common.c
|
||||
index 5dd534271aed6b41..85fc1bcfc7f5e60d 100644
|
||||
--- a/nptl/pthread_rwlock_common.c
|
||||
+++ b/nptl/pthread_rwlock_common.c
|
||||
@@ -314,7 +314,7 @@ __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock,
|
||||
harmless because the flag is just about the state of
|
||||
__readers, and all threads set the flag under the same
|
||||
conditions. */
|
||||
- while ((atomic_load_relaxed (&rwlock->__data.__readers)
|
||||
+ while (((r = atomic_load_relaxed (&rwlock->__data.__readers))
|
||||
& PTHREAD_RWLOCK_RWAITING) != 0)
|
||||
{
|
||||
int private = __pthread_rwlock_get_private (rwlock);
|
||||
diff --git a/nptl/tst-rwlock-pwn.c b/nptl/tst-rwlock-pwn.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..c39dd70973f1a76e
|
||||
--- /dev/null
|
||||
+++ b/nptl/tst-rwlock-pwn.c
|
||||
@@ -0,0 +1,87 @@
|
||||
+/* Test rwlock with PREFER_WRITER_NONRECURSIVE_NP (bug 23861).
|
||||
+ Copyright (C) 2018 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <unistd.h>
|
||||
+#include <pthread.h>
|
||||
+#include <support/xthread.h>
|
||||
+
|
||||
+/* We choose 10 iterations because this happens to be able to trigger the
|
||||
+ stall on contemporary hardware. */
|
||||
+#define LOOPS 10
|
||||
+/* We need 3 threads to trigger bug 23861. One thread as a writer, and
|
||||
+ two reader threads. The test verifies that the second-to-last reader
|
||||
+ is able to notify the *last* reader that it should be done waiting.
|
||||
+ If the second-to-last reader fails to notify the last reader or does
|
||||
+ so incorrectly then the last reader may stall indefinitely. */
|
||||
+#define NTHREADS 3
|
||||
+
|
||||
+_Atomic int do_exit;
|
||||
+pthread_rwlockattr_t mylock_attr;
|
||||
+pthread_rwlock_t mylock;
|
||||
+
|
||||
+void *
|
||||
+run_loop (void *a)
|
||||
+{
|
||||
+ while (!do_exit)
|
||||
+ {
|
||||
+ if (random () & 1)
|
||||
+ {
|
||||
+ xpthread_rwlock_wrlock (&mylock);
|
||||
+ xpthread_rwlock_unlock (&mylock);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ xpthread_rwlock_rdlock (&mylock);
|
||||
+ xpthread_rwlock_unlock (&mylock);
|
||||
+ }
|
||||
+ }
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ xpthread_rwlockattr_init (&mylock_attr);
|
||||
+ xpthread_rwlockattr_setkind_np (&mylock_attr,
|
||||
+ PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP);
|
||||
+ xpthread_rwlock_init (&mylock, &mylock_attr);
|
||||
+
|
||||
+ for (int n = 0; n < LOOPS; n++)
|
||||
+ {
|
||||
+ pthread_t tids[NTHREADS];
|
||||
+ do_exit = 0;
|
||||
+ for (int i = 0; i < NTHREADS; i++)
|
||||
+ tids[i] = xpthread_create (NULL, run_loop, NULL);
|
||||
+ /* Let the threads run for some time. */
|
||||
+ sleep (1);
|
||||
+ printf ("Exiting...");
|
||||
+ fflush (stdout);
|
||||
+ do_exit = 1;
|
||||
+ for (int i = 0; i < NTHREADS; i++)
|
||||
+ xpthread_join (tids[i]);
|
||||
+ printf ("done.\n");
|
||||
+ }
|
||||
+ pthread_rwlock_destroy (&mylock);
|
||||
+ pthread_rwlockattr_destroy (&mylock_attr);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#define TIMEOUT (DEFAULT_TIMEOUT + 3 * LOOPS)
|
||||
+#include <support/test-driver.c>
|
140
SOURCES/glibc-rh1658901.patch
Normal file
140
SOURCES/glibc-rh1658901.patch
Normal file
@ -0,0 +1,140 @@
|
||||
Upstream commit 1d880d4a9bf7608c2cd33bbe954ce6995f79121a
|
||||
|
||||
From: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com>
|
||||
Date: Wed, 12 Dec 2018 12:41:52 +0000 (-0200)
|
||||
Subject: powerpc: Add missing CFI register information (bug #23614)
|
||||
X-Git-Tag: glibc-2.29~210
|
||||
X-Git-Url: https://sourceware.org/git/?p=glibc.git;a=commitdiff_plain;h=1d880d4a9bf7608c2cd33bbe954ce6995f79121a
|
||||
|
||||
powerpc: Add missing CFI register information (bug #23614)
|
||||
|
||||
Add CFI information about the offset of registers stored in the stack
|
||||
frame.
|
||||
|
||||
[BZ #23614]
|
||||
* sysdeps/powerpc/powerpc64/addmul_1.S (FUNC): Add CFI offset for
|
||||
registers saved in the stack frame.
|
||||
* sysdeps/powerpc/powerpc64/lshift.S (__mpn_lshift): Likewise.
|
||||
* sysdeps/powerpc/powerpc64/mul_1.S (__mpn_mul_1): Likewise.
|
||||
|
||||
Signed-off-by: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com>
|
||||
Reviewed-by: Gabriel F. T. Gomes <gabriel@inconstante.eti.br>
|
||||
---
|
||||
|
||||
diff --git a/sysdeps/powerpc/powerpc64/addmul_1.S b/sysdeps/powerpc/powerpc64/addmul_1.S
|
||||
index 48e3b1b..e450d6a 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/addmul_1.S
|
||||
+++ b/sysdeps/powerpc/powerpc64/addmul_1.S
|
||||
@@ -34,16 +34,27 @@
|
||||
#define N r5
|
||||
#define VL r6
|
||||
|
||||
+#define R27SAVE (-40)
|
||||
+#define R28SAVE (-32)
|
||||
+#define R29SAVE (-24)
|
||||
+#define R30SAVE (-16)
|
||||
+#define R31SAVE (-8)
|
||||
+
|
||||
ENTRY_TOCLESS (FUNC, 5)
|
||||
- std r31, -8(r1)
|
||||
+ std r31, R31SAVE(r1)
|
||||
rldicl. r0, N, 0, 62
|
||||
- std r30, -16(r1)
|
||||
+ std r30, R30SAVE(r1)
|
||||
cmpdi VL, r0, 2
|
||||
- std r29, -24(r1)
|
||||
+ std r29, R29SAVE(r1)
|
||||
addi N, N, 3
|
||||
- std r28, -32(r1)
|
||||
+ std r28, R28SAVE(r1)
|
||||
srdi N, N, 2
|
||||
- std r27, -40(r1)
|
||||
+ std r27, R27SAVE(r1)
|
||||
+ cfi_offset(r31, R31SAVE)
|
||||
+ cfi_offset(r30, R30SAVE)
|
||||
+ cfi_offset(r29, R29SAVE)
|
||||
+ cfi_offset(r28, R28SAVE)
|
||||
+ cfi_offset(r27, R27SAVE)
|
||||
mtctr N
|
||||
beq cr0, L(b00)
|
||||
blt cr6, L(b01)
|
||||
@@ -199,10 +210,10 @@ L(end): mulld r0, r9, VL
|
||||
addic r11, r11, 1
|
||||
#endif
|
||||
addze RP, r8
|
||||
- ld r31, -8(r1)
|
||||
- ld r30, -16(r1)
|
||||
- ld r29, -24(r1)
|
||||
- ld r28, -32(r1)
|
||||
- ld r27, -40(r1)
|
||||
+ ld r31, R31SAVE(r1)
|
||||
+ ld r30, R30SAVE(r1)
|
||||
+ ld r29, R29SAVE(r1)
|
||||
+ ld r28, R28SAVE(r1)
|
||||
+ ld r27, R27SAVE(r1)
|
||||
blr
|
||||
END(FUNC)
|
||||
diff --git a/sysdeps/powerpc/powerpc64/lshift.S b/sysdeps/powerpc/powerpc64/lshift.S
|
||||
index 8b6396e..855d6f2 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/lshift.S
|
||||
+++ b/sysdeps/powerpc/powerpc64/lshift.S
|
||||
@@ -26,11 +26,15 @@
|
||||
#define TNC r0
|
||||
#define U0 r30
|
||||
#define U1 r31
|
||||
+#define U0SAVE (-16)
|
||||
+#define U1SAVE (-8)
|
||||
#define RETVAL r5
|
||||
|
||||
ENTRY_TOCLESS (__mpn_lshift, 5)
|
||||
- std U1, -8(r1)
|
||||
- std U0, -16(r1)
|
||||
+ std U1, U1SAVE(r1)
|
||||
+ std U0, U0SAVE(r1)
|
||||
+ cfi_offset(U1, U1SAVE)
|
||||
+ cfi_offset(U0, U0SAVE)
|
||||
subfic TNC, CNT, 64
|
||||
sldi r7, N, RP
|
||||
add UP, UP, r7
|
||||
@@ -170,8 +174,8 @@ L(cj3): or r10, r12, r7
|
||||
L(cj2): std r10, -32(RP)
|
||||
std r8, -40(RP)
|
||||
|
||||
-L(ret): ld U1, -8(r1)
|
||||
- ld U0, -16(r1)
|
||||
+L(ret): ld U1, U1SAVE(r1)
|
||||
+ ld U0, U0SAVE(r1)
|
||||
mr RP, RETVAL
|
||||
blr
|
||||
END(__mpn_lshift)
|
||||
diff --git a/sysdeps/powerpc/powerpc64/mul_1.S b/sysdeps/powerpc/powerpc64/mul_1.S
|
||||
index 953ded8..cade365 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/mul_1.S
|
||||
+++ b/sysdeps/powerpc/powerpc64/mul_1.S
|
||||
@@ -24,9 +24,14 @@
|
||||
#define N r5
|
||||
#define VL r6
|
||||
|
||||
+#define R26SAVE (-48)
|
||||
+#define R27SAVE (-40)
|
||||
+
|
||||
ENTRY_TOCLESS (__mpn_mul_1, 5)
|
||||
- std r27, -40(r1)
|
||||
- std r26, -48(r1)
|
||||
+ std r27, R27SAVE(r1)
|
||||
+ std r26, R26SAVE(r1)
|
||||
+ cfi_offset(r27, R27SAVE)
|
||||
+ cfi_offset(r26, R26SAVE)
|
||||
li r12, 0
|
||||
ld r26, 0(UP)
|
||||
|
||||
@@ -129,7 +134,7 @@ L(end): mulld r0, r26, VL
|
||||
std r0, 0(RP)
|
||||
std r7, 8(RP)
|
||||
L(ret): addze RP, r8
|
||||
- ld r27, -40(r1)
|
||||
- ld r26, -48(r1)
|
||||
+ ld r27, R27SAVE(r1)
|
||||
+ ld r26, R26SAVE(r1)
|
||||
blr
|
||||
END(__mpn_mul_1)
|
663
SOURCES/glibc-rh1659293-1.patch
Normal file
663
SOURCES/glibc-rh1659293-1.patch
Normal file
@ -0,0 +1,663 @@
|
||||
nptl: Fix pthread_rwlock_try*lock stalls (Bug 23844)
|
||||
|
||||
For a full analysis of both the pthread_rwlock_tryrdlock() stall
|
||||
and the pthread_rwlock_trywrlock() stall see:
|
||||
https://sourceware.org/bugzilla/show_bug.cgi?id=23844#c14
|
||||
|
||||
In the pthread_rwlock_trydlock() function we fail to inspect for
|
||||
PTHREAD_RWLOCK_FUTEX_USED in __wrphase_futex and wake the waiting
|
||||
readers.
|
||||
|
||||
In the pthread_rwlock_trywrlock() function we write 1 to
|
||||
__wrphase_futex and loose the setting of the PTHREAD_RWLOCK_FUTEX_USED
|
||||
bit, again failing to wake waiting readers during unlock.
|
||||
|
||||
The fix in the case of pthread_rwlock_trydlock() is to check for
|
||||
PTHREAD_RWLOCK_FUTEX_USED and wake the readers.
|
||||
|
||||
The fix in the case of pthread_rwlock_trywrlock() is to only write
|
||||
1 to __wrphase_futex if we installed the write phase, since all other
|
||||
readers would be spinning waiting for this step.
|
||||
|
||||
We add two new tests, one exercises the stall for
|
||||
pthread_rwlock_trywrlock() which is easy to exercise, and one exercises
|
||||
the stall for pthread_rwlock_trydlock() which is harder to exercise.
|
||||
|
||||
The pthread_rwlock_trywrlock() test fails consistently without the fix,
|
||||
and passes after. The pthread_rwlock_tryrdlock() test fails roughly
|
||||
5-10% of the time without the fix, and passes all the time after.
|
||||
|
||||
Signed-off-by: Carlos O'Donell <carlos@redhat.com>
|
||||
Signed-off-by: Torvald Riegel <triegel@redhat.com>
|
||||
Signed-off-by: Rik Prohaska <prohaska7@gmail.com>
|
||||
Co-authored-by: Torvald Riegel <triegel@redhat.com>
|
||||
Co-authored-by: Rik Prohaska <prohaska7@gmail.com>
|
||||
(cherry picked from commit 5fc9ed4c4058bfbdf51ad6e7aac7d209b580e8c4)
|
||||
|
||||
diff --git a/ChangeLog b/ChangeLog
|
||||
index 08b42bd2f56471e3..ed1a2ffe8356fd96 100644
|
||||
--- a/ChangeLog
|
||||
+++ b/ChangeLog
|
||||
@@ -1,3 +1,20 @@
|
||||
+2019-01-31 Carlos O'Donell <carlos@redhat.com>
|
||||
+ Torvald Riegel <triegel@redhat.com>
|
||||
+ Rik Prohaska <prohaska7@gmail.com>
|
||||
+
|
||||
+ [BZ# 23844]
|
||||
+ * nptl/Makefile (tests): Add tst-rwlock-tryrdlock-stall, and
|
||||
+ tst-rwlock-trywrlock-stall.
|
||||
+ * nptl/pthread_rwlock_tryrdlock.c (__pthread_rwlock_tryrdlock):
|
||||
+ Wake waiters if PTHREAD_RWLOCK_FUTEX_USED is set.
|
||||
+ * nptl/pthread_rwlock_trywrlock.c (__pthread_rwlock_trywrlock):
|
||||
+ Set __wrphase_fute to 1 only if we started the write phase.
|
||||
+ * nptl/tst-rwlock-tryrdlock-stall.c: New file.
|
||||
+ * nptl/tst-rwlock-trywrlock-stall.c: New file.
|
||||
+ * support/Makefile (libsupport-routines): Add xpthread_rwlock_destroy.
|
||||
+ * support/xpthread_rwlock_destroy.c: New file.
|
||||
+ * support/xthread.h: Declare xpthread_rwlock_destroy.
|
||||
+
|
||||
2018-08-01 Carlos O'Donel <carlos@redhat.com>
|
||||
|
||||
* version.h (RELEASE): Set to "stable".
|
||||
diff --git a/nptl/Makefile b/nptl/Makefile
|
||||
index 2d2db648f730db61..b1003cf56b31ddfa 100644
|
||||
--- a/nptl/Makefile
|
||||
+++ b/nptl/Makefile
|
||||
@@ -319,7 +319,8 @@ tests = tst-attr1 tst-attr2 tst-attr3 tst-default-attr \
|
||||
tst-cnd-basic tst-mtx-trylock tst-cnd-broadcast \
|
||||
tst-cnd-timedwait tst-thrd-detach tst-mtx-basic tst-thrd-sleep \
|
||||
tst-mtx-recursive tst-tss-basic tst-call-once tst-mtx-timedlock \
|
||||
- tst-rwlock-pwn
|
||||
+ tst-rwlock-pwn \
|
||||
+ tst-rwlock-tryrdlock-stall tst-rwlock-trywrlock-stall
|
||||
|
||||
tests-internal := tst-rwlock19 tst-rwlock20 \
|
||||
tst-sem11 tst-sem12 tst-sem13 \
|
||||
diff --git a/nptl/pthread_rwlock_tryrdlock.c b/nptl/pthread_rwlock_tryrdlock.c
|
||||
index 4aec1fc15acb2448..31a88d33a6e8f256 100644
|
||||
--- a/nptl/pthread_rwlock_tryrdlock.c
|
||||
+++ b/nptl/pthread_rwlock_tryrdlock.c
|
||||
@@ -94,15 +94,22 @@ __pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlock)
|
||||
/* Same as in __pthread_rwlock_rdlock_full:
|
||||
We started the read phase, so we are also responsible for
|
||||
updating the write-phase futex. Relaxed MO is sufficient.
|
||||
- Note that there can be no other reader that we have to wake
|
||||
- because all other readers will see the read phase started by us
|
||||
- (or they will try to start it themselves); if a writer started
|
||||
- the read phase, we cannot have started it. Furthermore, we
|
||||
- cannot discard a PTHREAD_RWLOCK_FUTEX_USED flag because we will
|
||||
- overwrite the value set by the most recent writer (or the readers
|
||||
- before it in case of explicit hand-over) and we know that there
|
||||
- are no waiting readers. */
|
||||
- atomic_store_relaxed (&rwlock->__data.__wrphase_futex, 0);
|
||||
+ We have to do the same steps as a writer would when handing over the
|
||||
+ read phase to use because other readers cannot distinguish between
|
||||
+ us and the writer.
|
||||
+ Note that __pthread_rwlock_tryrdlock callers will not have to be
|
||||
+ woken up because they will either see the read phase started by us
|
||||
+ or they will try to start it themselves; however, callers of
|
||||
+ __pthread_rwlock_rdlock_full just increase the reader count and then
|
||||
+ check what state the lock is in, so they cannot distinguish between
|
||||
+ us and a writer that acquired and released the lock in the
|
||||
+ meantime. */
|
||||
+ if ((atomic_exchange_relaxed (&rwlock->__data.__wrphase_futex, 0)
|
||||
+ & PTHREAD_RWLOCK_FUTEX_USED) != 0)
|
||||
+ {
|
||||
+ int private = __pthread_rwlock_get_private (rwlock);
|
||||
+ futex_wake (&rwlock->__data.__wrphase_futex, INT_MAX, private);
|
||||
+ }
|
||||
}
|
||||
|
||||
return 0;
|
||||
diff --git a/nptl/pthread_rwlock_trywrlock.c b/nptl/pthread_rwlock_trywrlock.c
|
||||
index 5a73eba756077297..f2e3443466a2554f 100644
|
||||
--- a/nptl/pthread_rwlock_trywrlock.c
|
||||
+++ b/nptl/pthread_rwlock_trywrlock.c
|
||||
@@ -46,8 +46,15 @@ __pthread_rwlock_trywrlock (pthread_rwlock_t *rwlock)
|
||||
&rwlock->__data.__readers, &r,
|
||||
r | PTHREAD_RWLOCK_WRPHASE | PTHREAD_RWLOCK_WRLOCKED))
|
||||
{
|
||||
+ /* We have become the primary writer and we cannot have shared
|
||||
+ the PTHREAD_RWLOCK_FUTEX_USED flag with someone else, so we
|
||||
+ can simply enable blocking (see full wrlock code). */
|
||||
atomic_store_relaxed (&rwlock->__data.__writers_futex, 1);
|
||||
- atomic_store_relaxed (&rwlock->__data.__wrphase_futex, 1);
|
||||
+ /* If we started a write phase, we need to enable readers to
|
||||
+ wait. If we did not, we must not change it because other threads
|
||||
+ may have set the PTHREAD_RWLOCK_FUTEX_USED in the meantime. */
|
||||
+ if ((r & PTHREAD_RWLOCK_WRPHASE) == 0)
|
||||
+ atomic_store_relaxed (&rwlock->__data.__wrphase_futex, 1);
|
||||
atomic_store_relaxed (&rwlock->__data.__cur_writer,
|
||||
THREAD_GETMEM (THREAD_SELF, tid));
|
||||
return 0;
|
||||
diff --git a/nptl/tst-rwlock-tryrdlock-stall.c b/nptl/tst-rwlock-tryrdlock-stall.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..5e476da2b8d00c6a
|
||||
--- /dev/null
|
||||
+++ b/nptl/tst-rwlock-tryrdlock-stall.c
|
||||
@@ -0,0 +1,355 @@
|
||||
+/* Bug 23844: Test for pthread_rwlock_tryrdlock stalls.
|
||||
+ Copyright (C) 2019 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+/* For a full analysis see comment:
|
||||
+ https://sourceware.org/bugzilla/show_bug.cgi?id=23844#c14
|
||||
+
|
||||
+ Provided here for reference:
|
||||
+
|
||||
+ --- Analysis of pthread_rwlock_tryrdlock() stall ---
|
||||
+ A read lock begins to execute.
|
||||
+
|
||||
+ In __pthread_rwlock_rdlock_full:
|
||||
+
|
||||
+ We can attempt a read lock, but find that the lock is
|
||||
+ in a write phase (PTHREAD_RWLOCK_WRPHASE, or WP-bit
|
||||
+ is set), and the lock is held by a primary writer
|
||||
+ (PTHREAD_RWLOCK_WRLOCKED is set). In this case we must
|
||||
+ wait for explicit hand over from the writer to us or
|
||||
+ one of the other waiters. The read lock threads are
|
||||
+ about to execute:
|
||||
+
|
||||
+ 341 r = (atomic_fetch_add_acquire (&rwlock->__data.__readers,
|
||||
+ 342 (1 << PTHREAD_RWLOCK_READER_SHIFT))
|
||||
+ 343 + (1 << PTHREAD_RWLOCK_READER_SHIFT));
|
||||
+
|
||||
+ An unlock beings to execute.
|
||||
+
|
||||
+ Then in __pthread_rwlock_wrunlock:
|
||||
+
|
||||
+ 547 unsigned int r = atomic_load_relaxed (&rwlock->__data.__readers);
|
||||
+ ...
|
||||
+ 549 while (!atomic_compare_exchange_weak_release
|
||||
+ 550 (&rwlock->__data.__readers, &r,
|
||||
+ 551 ((r ^ PTHREAD_RWLOCK_WRLOCKED)
|
||||
+ 552 ^ ((r >> PTHREAD_RWLOCK_READER_SHIFT) == 0 ? 0
|
||||
+ 553 : PTHREAD_RWLOCK_WRPHASE))))
|
||||
+ 554 {
|
||||
+ ...
|
||||
+ 556 }
|
||||
+
|
||||
+ We clear PTHREAD_RWLOCK_WRLOCKED, and if there are
|
||||
+ no readers so we leave the lock in PTHRAD_RWLOCK_WRPHASE.
|
||||
+
|
||||
+ Back in the read lock.
|
||||
+
|
||||
+ The read lock adjusts __readres as above.
|
||||
+
|
||||
+ 383 while ((r & PTHREAD_RWLOCK_WRPHASE) != 0
|
||||
+ 384 && (r & PTHREAD_RWLOCK_WRLOCKED) == 0)
|
||||
+ 385 {
|
||||
+ ...
|
||||
+ 390 if (atomic_compare_exchange_weak_acquire (&rwlock->__data.__readers, &r,
|
||||
+ 391 r ^ PTHREAD_RWLOCK_WRPHASE))
|
||||
+ 392 {
|
||||
+
|
||||
+ And then attemps to start the read phase.
|
||||
+
|
||||
+ Assume there happens to be a tryrdlock at this point, noting
|
||||
+ that PTHREAD_RWLOCK_WRLOCKED is clear, and PTHREAD_RWLOCK_WRPHASE
|
||||
+ is 1. So the try lock attemps to start the read phase.
|
||||
+
|
||||
+ In __pthread_rwlock_tryrdlock:
|
||||
+
|
||||
+ 44 if ((r & PTHREAD_RWLOCK_WRPHASE) == 0)
|
||||
+ 45 {
|
||||
+ ...
|
||||
+ 49 if (((r & PTHREAD_RWLOCK_WRLOCKED) != 0)
|
||||
+ 50 && (rwlock->__data.__flags
|
||||
+ 51 == PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP))
|
||||
+ 52 return EBUSY;
|
||||
+ 53 rnew = r + (1 << PTHREAD_RWLOCK_READER_SHIFT);
|
||||
+ 54 }
|
||||
+ ...
|
||||
+ 89 while (!atomic_compare_exchange_weak_acquire (&rwlock->__data.__readers,
|
||||
+ 90 &r, rnew));
|
||||
+
|
||||
+ And succeeds.
|
||||
+
|
||||
+ Back in the write unlock:
|
||||
+
|
||||
+ 557 if ((r >> PTHREAD_RWLOCK_READER_SHIFT) != 0)
|
||||
+ 558 {
|
||||
+ ...
|
||||
+ 563 if ((atomic_exchange_relaxed (&rwlock->__data.__wrphase_futex, 0)
|
||||
+ 564 & PTHREAD_RWLOCK_FUTEX_USED) != 0)
|
||||
+ 565 futex_wake (&rwlock->__data.__wrphase_futex, INT_MAX, private);
|
||||
+ 566 }
|
||||
+
|
||||
+ We note that PTHREAD_RWLOCK_FUTEX_USED is non-zero
|
||||
+ and don't wake anyone. This is OK because we handed
|
||||
+ over to the trylock. It will be the trylock's responsibility
|
||||
+ to wake any waiters.
|
||||
+
|
||||
+ Back in the read lock:
|
||||
+
|
||||
+ The read lock fails to install PTHRAD_REWLOCK_WRPHASE as 0 because
|
||||
+ the __readers value was adjusted by the trylock, and so it falls through
|
||||
+ to waiting on the lock for explicit handover from either a new writer
|
||||
+ or a new reader.
|
||||
+
|
||||
+ 448 int err = futex_abstimed_wait (&rwlock->__data.__wrphase_futex,
|
||||
+ 449 1 | PTHREAD_RWLOCK_FUTEX_USED,
|
||||
+ 450 abstime, private);
|
||||
+
|
||||
+ We use PTHREAD_RWLOCK_FUTEX_USED to indicate the futex
|
||||
+ is in use.
|
||||
+
|
||||
+ At this point we have readers waiting on the read lock
|
||||
+ to unlock. The wrlock is done. The trylock is finishing
|
||||
+ the installation of the read phase.
|
||||
+
|
||||
+ 92 if ((r & PTHREAD_RWLOCK_WRPHASE) != 0)
|
||||
+ 93 {
|
||||
+ ...
|
||||
+ 105 atomic_store_relaxed (&rwlock->__data.__wrphase_futex, 0);
|
||||
+ 106 }
|
||||
+
|
||||
+ The trylock does note that we were the one that
|
||||
+ installed the read phase, but the comments are not
|
||||
+ correct, the execution ordering above shows that
|
||||
+ readers might indeed be waiting, and they are.
|
||||
+
|
||||
+ The atomic_store_relaxed throws away PTHREAD_RWLOCK_FUTEX_USED,
|
||||
+ and the waiting reader is never worken becuase as noted
|
||||
+ above it is conditional on the futex being used.
|
||||
+
|
||||
+ The solution is for the trylock thread to inspect
|
||||
+ PTHREAD_RWLOCK_FUTEX_USED and wake the waiting readers.
|
||||
+
|
||||
+ --- Analysis of pthread_rwlock_trywrlock() stall ---
|
||||
+
|
||||
+ A write lock begins to execute, takes the write lock,
|
||||
+ and then releases the lock...
|
||||
+
|
||||
+ In pthread_rwlock_wrunlock():
|
||||
+
|
||||
+ 547 unsigned int r = atomic_load_relaxed (&rwlock->__data.__readers);
|
||||
+ ...
|
||||
+ 549 while (!atomic_compare_exchange_weak_release
|
||||
+ 550 (&rwlock->__data.__readers, &r,
|
||||
+ 551 ((r ^ PTHREAD_RWLOCK_WRLOCKED)
|
||||
+ 552 ^ ((r >> PTHREAD_RWLOCK_READER_SHIFT) == 0 ? 0
|
||||
+ 553 : PTHREAD_RWLOCK_WRPHASE))))
|
||||
+ 554 {
|
||||
+ ...
|
||||
+ 556 }
|
||||
+
|
||||
+ ... leaving it in the write phase with zero readers
|
||||
+ (the case where we leave the write phase in place
|
||||
+ during a write unlock).
|
||||
+
|
||||
+ A write trylock begins to execute.
|
||||
+
|
||||
+ In __pthread_rwlock_trywrlock:
|
||||
+
|
||||
+ 40 while (((r & PTHREAD_RWLOCK_WRLOCKED) == 0)
|
||||
+ 41 && (((r >> PTHREAD_RWLOCK_READER_SHIFT) == 0)
|
||||
+ 42 || (prefer_writer && ((r & PTHREAD_RWLOCK_WRPHASE) != 0))))
|
||||
+ 43 {
|
||||
+
|
||||
+ The lock is not locked.
|
||||
+
|
||||
+ There are no readers.
|
||||
+
|
||||
+ 45 if (atomic_compare_exchange_weak_acquire (
|
||||
+ 46 &rwlock->__data.__readers, &r,
|
||||
+ 47 r | PTHREAD_RWLOCK_WRPHASE | PTHREAD_RWLOCK_WRLOCKED))
|
||||
+
|
||||
+ We atomically install the write phase and we take the
|
||||
+ exclusive write lock.
|
||||
+
|
||||
+ 48 {
|
||||
+ 49 atomic_store_relaxed (&rwlock->__data.__writers_futex, 1);
|
||||
+
|
||||
+ We get this far.
|
||||
+
|
||||
+ A reader lock begins to execute.
|
||||
+
|
||||
+ In pthread_rwlock_rdlock:
|
||||
+
|
||||
+ 437 for (;;)
|
||||
+ 438 {
|
||||
+ 439 while (((wpf = atomic_load_relaxed (&rwlock->__data.__wrphase_futex))
|
||||
+ 440 | PTHREAD_RWLOCK_FUTEX_USED) == (1 | PTHREAD_RWLOCK_FUTEX_USED))
|
||||
+ 441 {
|
||||
+ 442 int private = __pthread_rwlock_get_private (rwlock);
|
||||
+ 443 if (((wpf & PTHREAD_RWLOCK_FUTEX_USED) == 0)
|
||||
+ 444 && (!atomic_compare_exchange_weak_relaxed
|
||||
+ 445 (&rwlock->__data.__wrphase_futex,
|
||||
+ 446 &wpf, wpf | PTHREAD_RWLOCK_FUTEX_USED)))
|
||||
+ 447 continue;
|
||||
+ 448 int err = futex_abstimed_wait (&rwlock->__data.__wrphase_futex,
|
||||
+ 449 1 | PTHREAD_RWLOCK_FUTEX_USED,
|
||||
+ 450 abstime, private);
|
||||
+
|
||||
+ We are in a write phase, so the while() on line 439 is true.
|
||||
+
|
||||
+ The value of wpf does not have PTHREAD_RWLOCK_FUTEX_USED set
|
||||
+ since this is the first reader to lock.
|
||||
+
|
||||
+ The atomic operation sets wpf with PTHREAD_RELOCK_FUTEX_USED
|
||||
+ on the expectation that this reader will be woken during
|
||||
+ the handoff.
|
||||
+
|
||||
+ Back in pthread_rwlock_trywrlock:
|
||||
+
|
||||
+ 50 atomic_store_relaxed (&rwlock->__data.__wrphase_futex, 1);
|
||||
+ 51 atomic_store_relaxed (&rwlock->__data.__cur_writer,
|
||||
+ 52 THREAD_GETMEM (THREAD_SELF, tid));
|
||||
+ 53 return 0;
|
||||
+ 54 }
|
||||
+ ...
|
||||
+ 57 }
|
||||
+
|
||||
+ We write 1 to __wrphase_futex discarding PTHREAD_RWLOCK_FUTEX_USED,
|
||||
+ and so in the unlock we will not awaken the waiting reader.
|
||||
+
|
||||
+ The solution to this is to realize that if we did not start the write
|
||||
+ phase we need not write 1 or any other value to __wrphase_futex.
|
||||
+ This ensures that any readers (which saw __wrphase_futex != 0) can
|
||||
+ set PTHREAD_RWLOCK_FUTEX_USED and this can be used at unlock to
|
||||
+ wake them.
|
||||
+
|
||||
+ If we installed the write phase then all other readers are looping
|
||||
+ here:
|
||||
+
|
||||
+ In __pthread_rwlock_rdlock_full:
|
||||
+
|
||||
+ 437 for (;;)
|
||||
+ 438 {
|
||||
+ 439 while (((wpf = atomic_load_relaxed (&rwlock->__data.__wrphase_futex))
|
||||
+ 440 | PTHREAD_RWLOCK_FUTEX_USED) == (1 | PTHREAD_RWLOCK_FUTEX_USED))
|
||||
+ 441 {
|
||||
+ ...
|
||||
+ 508 }
|
||||
+
|
||||
+ waiting for the write phase to be installed or removed before they
|
||||
+ can begin waiting on __wrphase_futex (part of the algorithm), or
|
||||
+ taking a concurrent read lock, and thus we can safely write 1 to
|
||||
+ __wrphase_futex.
|
||||
+
|
||||
+ If we did not install the write phase then the readers may already
|
||||
+ be waiting on the futex, the original writer wrote 1 to __wrphase_futex
|
||||
+ as part of starting the write phase, and we cannot also write 1
|
||||
+ without loosing the PTHREAD_RWLOCK_FUTEX_USED bit.
|
||||
+
|
||||
+ ---
|
||||
+
|
||||
+ Summary for the pthread_rwlock_tryrdlock() stall:
|
||||
+
|
||||
+ The stall is caused by pthread_rwlock_tryrdlock failing to check
|
||||
+ that PTHREAD_RWLOCK_FUTEX_USED is set in the __wrphase_futex futex
|
||||
+ and then waking the futex.
|
||||
+
|
||||
+ The fix for bug 23844 ensures that waiters on __wrphase_futex are
|
||||
+ correctly woken. Before the fix the test stalls as readers can
|
||||
+ wait forever on __wrphase_futex. */
|
||||
+
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <unistd.h>
|
||||
+#include <pthread.h>
|
||||
+#include <support/xthread.h>
|
||||
+#include <errno.h>
|
||||
+
|
||||
+/* We need only one lock to reproduce the issue. We will need multiple
|
||||
+ threads to get the exact case where we have a read, try, and unlock
|
||||
+ all interleaving to produce the case where the readers are waiting
|
||||
+ and the try fails to wake them. */
|
||||
+pthread_rwlock_t onelock;
|
||||
+
|
||||
+/* The number of threads is arbitrary but empirically chosen to have
|
||||
+ enough threads that we see the condition where waiting readers are
|
||||
+ not woken by a successful tryrdlock. */
|
||||
+#define NTHREADS 32
|
||||
+
|
||||
+_Atomic int do_exit;
|
||||
+
|
||||
+void *
|
||||
+run_loop (void *arg)
|
||||
+{
|
||||
+ int i = 0, ret;
|
||||
+ while (!do_exit)
|
||||
+ {
|
||||
+ /* Arbitrarily choose if we are the writer or reader. Choose a
|
||||
+ high enough ratio of readers to writers to make it likely
|
||||
+ that readers block (and eventually are susceptable to
|
||||
+ stalling).
|
||||
+
|
||||
+ If we are a writer, take the write lock, and then unlock.
|
||||
+ If we are a reader, try the lock, then lock, then unlock. */
|
||||
+ if ((i % 8) != 0)
|
||||
+ xpthread_rwlock_wrlock (&onelock);
|
||||
+ else
|
||||
+ {
|
||||
+ if ((ret = pthread_rwlock_tryrdlock (&onelock)) != 0)
|
||||
+ {
|
||||
+ if (ret == EBUSY)
|
||||
+ xpthread_rwlock_rdlock (&onelock);
|
||||
+ else
|
||||
+ exit (EXIT_FAILURE);
|
||||
+ }
|
||||
+ }
|
||||
+ /* Thread does some work and then unlocks. */
|
||||
+ xpthread_rwlock_unlock (&onelock);
|
||||
+ i++;
|
||||
+ }
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ int i;
|
||||
+ pthread_t tids[NTHREADS];
|
||||
+ xpthread_rwlock_init (&onelock, NULL);
|
||||
+ for (i = 0; i < NTHREADS; i++)
|
||||
+ tids[i] = xpthread_create (NULL, run_loop, NULL);
|
||||
+ /* Run for some amount of time. Empirically speaking exercising
|
||||
+ the stall via pthread_rwlock_tryrdlock is much harder, and on
|
||||
+ a 3.5GHz 4 core x86_64 VM system it takes somewhere around
|
||||
+ 20-200s to stall, approaching 100% stall past 200s. We can't
|
||||
+ wait that long for a regression test so we just test for 20s,
|
||||
+ and expect the stall to happen with a 5-10% chance (enough for
|
||||
+ developers to see). */
|
||||
+ sleep (20);
|
||||
+ /* Then exit. */
|
||||
+ printf ("INFO: Exiting...\n");
|
||||
+ do_exit = 1;
|
||||
+ /* If any readers stalled then we will timeout waiting for them. */
|
||||
+ for (i = 0; i < NTHREADS; i++)
|
||||
+ xpthread_join (tids[i]);
|
||||
+ printf ("INFO: Done.\n");
|
||||
+ xpthread_rwlock_destroy (&onelock);
|
||||
+ printf ("PASS: No pthread_rwlock_tryrdlock stalls detected.\n");
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#define TIMEOUT 30
|
||||
+#include <support/test-driver.c>
|
||||
diff --git a/nptl/tst-rwlock-trywrlock-stall.c b/nptl/tst-rwlock-trywrlock-stall.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..14d27cbcbc882cb1
|
||||
--- /dev/null
|
||||
+++ b/nptl/tst-rwlock-trywrlock-stall.c
|
||||
@@ -0,0 +1,108 @@
|
||||
+/* Bug 23844: Test for pthread_rwlock_trywrlock stalls.
|
||||
+ Copyright (C) 2019 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+/* For a full analysis see comments in tst-rwlock-tryrdlock-stall.c.
|
||||
+
|
||||
+ Summary for the pthread_rwlock_trywrlock() stall:
|
||||
+
|
||||
+ The stall is caused by pthread_rwlock_trywrlock setting
|
||||
+ __wrphase_futex futex to 1 and loosing the
|
||||
+ PTHREAD_RWLOCK_FUTEX_USED bit.
|
||||
+
|
||||
+ The fix for bug 23844 ensures that waiters on __wrphase_futex are
|
||||
+ correctly woken. Before the fix the test stalls as readers can
|
||||
+ wait forever on __wrphase_futex. */
|
||||
+
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <unistd.h>
|
||||
+#include <pthread.h>
|
||||
+#include <support/xthread.h>
|
||||
+#include <errno.h>
|
||||
+
|
||||
+/* We need only one lock to reproduce the issue. We will need multiple
|
||||
+ threads to get the exact case where we have a read, try, and unlock
|
||||
+ all interleaving to produce the case where the readers are waiting
|
||||
+ and the try clears the PTHREAD_RWLOCK_FUTEX_USED bit and a
|
||||
+ subsequent unlock fails to wake them. */
|
||||
+pthread_rwlock_t onelock;
|
||||
+
|
||||
+/* The number of threads is arbitrary but empirically chosen to have
|
||||
+ enough threads that we see the condition where waiting readers are
|
||||
+ not woken by a successful unlock. */
|
||||
+#define NTHREADS 32
|
||||
+
|
||||
+_Atomic int do_exit;
|
||||
+
|
||||
+void *
|
||||
+run_loop (void *arg)
|
||||
+{
|
||||
+ int i = 0, ret;
|
||||
+ while (!do_exit)
|
||||
+ {
|
||||
+ /* Arbitrarily choose if we are the writer or reader. Choose a
|
||||
+ high enough ratio of readers to writers to make it likely
|
||||
+ that readers block (and eventually are susceptable to
|
||||
+ stalling).
|
||||
+
|
||||
+ If we are a writer, take the write lock, and then unlock.
|
||||
+ If we are a reader, try the lock, then lock, then unlock. */
|
||||
+ if ((i % 8) != 0)
|
||||
+ {
|
||||
+ if ((ret = pthread_rwlock_trywrlock (&onelock)) != 0)
|
||||
+ {
|
||||
+ if (ret == EBUSY)
|
||||
+ xpthread_rwlock_wrlock (&onelock);
|
||||
+ else
|
||||
+ exit (EXIT_FAILURE);
|
||||
+ }
|
||||
+ }
|
||||
+ else
|
||||
+ xpthread_rwlock_rdlock (&onelock);
|
||||
+ /* Thread does some work and then unlocks. */
|
||||
+ xpthread_rwlock_unlock (&onelock);
|
||||
+ i++;
|
||||
+ }
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ int i;
|
||||
+ pthread_t tids[NTHREADS];
|
||||
+ xpthread_rwlock_init (&onelock, NULL);
|
||||
+ for (i = 0; i < NTHREADS; i++)
|
||||
+ tids[i] = xpthread_create (NULL, run_loop, NULL);
|
||||
+ /* Run for some amount of time. The pthread_rwlock_tryrwlock stall
|
||||
+ is very easy to trigger and happens in seconds under the test
|
||||
+ conditions. */
|
||||
+ sleep (10);
|
||||
+ /* Then exit. */
|
||||
+ printf ("INFO: Exiting...\n");
|
||||
+ do_exit = 1;
|
||||
+ /* If any readers stalled then we will timeout waiting for them. */
|
||||
+ for (i = 0; i < NTHREADS; i++)
|
||||
+ xpthread_join (tids[i]);
|
||||
+ printf ("INFO: Done.\n");
|
||||
+ xpthread_rwlock_destroy (&onelock);
|
||||
+ printf ("PASS: No pthread_rwlock_tryrwlock stalls detected.\n");
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
||||
diff --git a/support/Makefile b/support/Makefile
|
||||
index 93a514301654132e..41da4abaaa5a645a 100644
|
||||
--- a/support/Makefile
|
||||
+++ b/support/Makefile
|
||||
@@ -129,6 +129,7 @@ libsupport-routines = \
|
||||
xpthread_mutexattr_settype \
|
||||
xpthread_once \
|
||||
xpthread_rwlock_init \
|
||||
+ xpthread_rwlock_destroy \
|
||||
xpthread_rwlock_rdlock \
|
||||
xpthread_rwlock_unlock \
|
||||
xpthread_rwlock_wrlock \
|
||||
diff --git a/support/xpthread_rwlock_destroy.c b/support/xpthread_rwlock_destroy.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..6d6e95356963b47f
|
||||
--- /dev/null
|
||||
+++ b/support/xpthread_rwlock_destroy.c
|
||||
@@ -0,0 +1,26 @@
|
||||
+/* pthread_rwlock_destroy with error checking.
|
||||
+ Copyright (C) 2019 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <support/xthread.h>
|
||||
+
|
||||
+void
|
||||
+xpthread_rwlock_destroy (pthread_rwlock_t *rwlock)
|
||||
+{
|
||||
+ xpthread_check_return ("pthread_rwlock_destroy",
|
||||
+ pthread_rwlock_destroy (rwlock));
|
||||
+}
|
||||
diff --git a/support/xthread.h b/support/xthread.h
|
||||
index 623f5ad0acb895ef..1af77280871464c2 100644
|
||||
--- a/support/xthread.h
|
||||
+++ b/support/xthread.h
|
||||
@@ -84,6 +84,7 @@ void xpthread_rwlockattr_setkind_np (pthread_rwlockattr_t *attr, int pref);
|
||||
void xpthread_rwlock_wrlock (pthread_rwlock_t *rwlock);
|
||||
void xpthread_rwlock_rdlock (pthread_rwlock_t *rwlock);
|
||||
void xpthread_rwlock_unlock (pthread_rwlock_t *rwlock);
|
||||
+void xpthread_rwlock_destroy (pthread_rwlock_t *rwlock);
|
||||
|
||||
__END_DECLS
|
||||
|
61
SOURCES/glibc-rh1659293-2.patch
Normal file
61
SOURCES/glibc-rh1659293-2.patch
Normal file
@ -0,0 +1,61 @@
|
||||
nptl/tst-rwlock14: Test pthread_rwlock_timedwrlock correctly
|
||||
|
||||
(cherry picked from commit 82849fde3b8cb9b9396fa8cadf842dc2b1d2cced)
|
||||
|
||||
diff --git a/ChangeLog b/ChangeLog
|
||||
index ed1a2ffe8356fd96..74e634670c62d5c2 100644
|
||||
--- a/ChangeLog
|
||||
+++ b/ChangeLog
|
||||
@@ -1,3 +1,10 @@
|
||||
+2019-03-25 Mike Crowe <mac@mcrowe.com>
|
||||
+
|
||||
+ * nptl/tst-rwlock14.c (do_test): Replace duplicate calls to
|
||||
+ pthread_rwlock_timedrdlock with calls to
|
||||
+ pthread_rwlock_timedwrlock to ensure that the latter is tested
|
||||
+ too. Use new function name in diagnostic messages too.
|
||||
+
|
||||
2019-01-31 Carlos O'Donell <carlos@redhat.com>
|
||||
Torvald Riegel <triegel@redhat.com>
|
||||
Rik Prohaska <prohaska7@gmail.com>
|
||||
diff --git a/nptl/tst-rwlock14.c b/nptl/tst-rwlock14.c
|
||||
index d6fda87c61e9aed4..073e6c98d2f5cc12 100644
|
||||
--- a/nptl/tst-rwlock14.c
|
||||
+++ b/nptl/tst-rwlock14.c
|
||||
@@ -117,15 +117,15 @@ do_test (void)
|
||||
result = 1;
|
||||
}
|
||||
|
||||
- e = pthread_rwlock_timedrdlock (&r, &ts);
|
||||
+ e = pthread_rwlock_timedwrlock (&r, &ts);
|
||||
if (e == 0)
|
||||
{
|
||||
- puts ("second rwlock_timedrdlock did not fail");
|
||||
+ puts ("second rwlock_timedwrlock did not fail");
|
||||
result = 1;
|
||||
}
|
||||
else if (e != EINVAL)
|
||||
{
|
||||
- puts ("second rwlock_timedrdlock did not return EINVAL");
|
||||
+ puts ("second rwlock_timedwrlock did not return EINVAL");
|
||||
result = 1;
|
||||
}
|
||||
|
||||
@@ -145,15 +145,15 @@ do_test (void)
|
||||
result = 1;
|
||||
}
|
||||
|
||||
- e = pthread_rwlock_timedrdlock (&r, &ts);
|
||||
+ e = pthread_rwlock_timedwrlock (&r, &ts);
|
||||
if (e == 0)
|
||||
{
|
||||
- puts ("third rwlock_timedrdlock did not fail");
|
||||
+ puts ("third rwlock_timedwrlock did not fail");
|
||||
result = 1;
|
||||
}
|
||||
else if (e != EINVAL)
|
||||
{
|
||||
- puts ("third rwlock_timedrdlock did not return EINVAL");
|
||||
+ puts ("third rwlock_timedwrlock did not return EINVAL");
|
||||
result = 1;
|
||||
}
|
||||
|
118
SOURCES/glibc-rh1659438-1.patch
Normal file
118
SOURCES/glibc-rh1659438-1.patch
Normal file
@ -0,0 +1,118 @@
|
||||
commit b8686c0d7098168481a246f8199ab2d865f52d3d
|
||||
Author: Stefan Liebler <stli@linux.ibm.com>
|
||||
Date: Tue Dec 18 13:57:03 2018 +0100
|
||||
|
||||
S390: Add configure check to detect z10 as mininum architecture level set.
|
||||
|
||||
Add a configure check for z10 in the same way as done for z196.
|
||||
|
||||
ChangeLog:
|
||||
|
||||
* config.h.in (HAVE_S390_MIN_Z10_ZARCH_ASM_SUPPORT): New undefine.
|
||||
* sysdeps/s390/configure.ac: Add check for z10 support.
|
||||
* sysdeps/s390/configure: Regenerated.
|
||||
|
||||
diff --git a/config.h.in b/config.h.in
|
||||
index 141db213a9046eb4..beecc39d5b8c3f4a 100644
|
||||
--- a/config.h.in
|
||||
+++ b/config.h.in
|
||||
@@ -62,6 +62,9 @@
|
||||
/* Define if assembler supports AVX512DQ. */
|
||||
#undef HAVE_AVX512DQ_ASM_SUPPORT
|
||||
|
||||
+/* Define if assembler supports z10 zarch instructions as default on S390. */
|
||||
+#undef HAVE_S390_MIN_Z10_ZARCH_ASM_SUPPORT
|
||||
+
|
||||
/* Define if assembler supports z196 zarch instructions as default on S390. */
|
||||
#undef HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT
|
||||
|
||||
diff --git a/sysdeps/s390/configure b/sysdeps/s390/configure
|
||||
index 74b415f2ab0fa982..f30f8644361f474a 100644
|
||||
--- a/sysdeps/s390/configure
|
||||
+++ b/sysdeps/s390/configure
|
||||
@@ -112,6 +112,45 @@ then
|
||||
|
||||
fi
|
||||
|
||||
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for S390 z10 zarch instruction support as default" >&5
|
||||
+$as_echo_n "checking for S390 z10 zarch instruction support as default... " >&6; }
|
||||
+if ${libc_cv_asm_s390_min_z10_zarch+:} false; then :
|
||||
+ $as_echo_n "(cached) " >&6
|
||||
+else
|
||||
+ cat > conftest.c <<\EOF
|
||||
+void testinsn (void *a, void *b, int n)
|
||||
+{
|
||||
+ __asm__ ("exrl %2,1f \n\t"
|
||||
+ "j 2f \n\t"
|
||||
+ "1: mvc 0(1,%0),0(%1) \n\t"
|
||||
+ "2:"
|
||||
+ : : "a" (a), "a" (b), "d" (n)
|
||||
+ : "memory", "cc");
|
||||
+}
|
||||
+EOF
|
||||
+if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS --shared conftest.c
|
||||
+ -o conftest.o &> /dev/null'
|
||||
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
|
||||
+ (eval $ac_try) 2>&5
|
||||
+ ac_status=$?
|
||||
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
+ test $ac_status = 0; }; } ;
|
||||
+then
|
||||
+ libc_cv_asm_s390_min_z10_zarch=yes
|
||||
+else
|
||||
+ libc_cv_asm_s390_min_z10_zarch=no
|
||||
+fi
|
||||
+rm -f conftest*
|
||||
+fi
|
||||
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_asm_s390_min_z10_zarch" >&5
|
||||
+$as_echo "$libc_cv_asm_s390_min_z10_zarch" >&6; }
|
||||
+
|
||||
+if test "$libc_cv_asm_s390_min_z10_zarch" = yes ;
|
||||
+then
|
||||
+ $as_echo "#define HAVE_S390_MIN_Z10_ZARCH_ASM_SUPPORT 1" >>confdefs.h
|
||||
+
|
||||
+fi
|
||||
+
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for S390 z196 zarch instruction support as default" >&5
|
||||
$as_echo_n "checking for S390 z196 zarch instruction support as default... " >&6; }
|
||||
if ${libc_cv_asm_s390_min_z196_zarch+:} false; then :
|
||||
diff --git a/sysdeps/s390/configure.ac b/sysdeps/s390/configure.ac
|
||||
index 1cdb0212825a3f18..981f7a79dd7066fc 100644
|
||||
--- a/sysdeps/s390/configure.ac
|
||||
+++ b/sysdeps/s390/configure.ac
|
||||
@@ -80,6 +80,35 @@ then
|
||||
AC_DEFINE(HAVE_S390_VX_GCC_SUPPORT)
|
||||
fi
|
||||
|
||||
+AC_CACHE_CHECK(for S390 z10 zarch instruction support as default,
|
||||
+ libc_cv_asm_s390_min_z10_zarch, [dnl
|
||||
+cat > conftest.c <<\EOF
|
||||
+void testinsn (void *a, void *b, int n)
|
||||
+{
|
||||
+ __asm__ ("exrl %2,1f \n\t"
|
||||
+ "j 2f \n\t"
|
||||
+ "1: mvc 0(1,%0),0(%1) \n\t"
|
||||
+ "2:"
|
||||
+ : : "a" (a), "a" (b), "d" (n)
|
||||
+ : "memory", "cc");
|
||||
+}
|
||||
+EOF
|
||||
+dnl
|
||||
+dnl test, if assembler supports S390 z10 zarch instructions as default
|
||||
+if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS --shared conftest.c
|
||||
+ -o conftest.o &> /dev/null]) ;
|
||||
+then
|
||||
+ libc_cv_asm_s390_min_z10_zarch=yes
|
||||
+else
|
||||
+ libc_cv_asm_s390_min_z10_zarch=no
|
||||
+fi
|
||||
+rm -f conftest* ])
|
||||
+
|
||||
+if test "$libc_cv_asm_s390_min_z10_zarch" = yes ;
|
||||
+then
|
||||
+ AC_DEFINE(HAVE_S390_MIN_Z10_ZARCH_ASM_SUPPORT)
|
||||
+fi
|
||||
+
|
||||
AC_CACHE_CHECK(for S390 z196 zarch instruction support as default,
|
||||
libc_cv_asm_s390_min_z196_zarch, [dnl
|
||||
cat > conftest.c <<\EOF
|
189
SOURCES/glibc-rh1659438-10.patch
Normal file
189
SOURCES/glibc-rh1659438-10.patch
Normal file
@ -0,0 +1,189 @@
|
||||
commit e099aab060df178a7fcd5a55282650fe45ccea66
|
||||
Author: Stefan Liebler <stli@linux.ibm.com>
|
||||
Date: Tue Dec 18 13:57:07 2018 +0100
|
||||
|
||||
S390: Remove s390 specific implementation of bcopy.
|
||||
|
||||
Nowadays gcc is automatically replacing a call to bcopy
|
||||
with a call to memmove. Thus only old binaries will call
|
||||
the s390 specific bcopy implementation.
|
||||
|
||||
The s390 specific implementation is using an own
|
||||
implementation for memcpy in the forward case and is
|
||||
relying on memmove in the backward case.
|
||||
|
||||
After removing the s390 specific bcopy, the common code
|
||||
bcopy is used. It just performs a tail call to memmove.
|
||||
|
||||
ChangeLog:
|
||||
* sysdeps/s390/s390-32/bcopy.S: Remove.
|
||||
* sysdeps/s390/s390-64/bcopy.S: Likewise.
|
||||
|
||||
diff --git a/sysdeps/s390/s390-32/bcopy.S b/sysdeps/s390/s390-32/bcopy.S
|
||||
deleted file mode 100644
|
||||
index 560e04fdee93dafb..0000000000000000
|
||||
--- a/sysdeps/s390/s390-32/bcopy.S
|
||||
+++ /dev/null
|
||||
@@ -1,85 +0,0 @@
|
||||
-/* bcopy -- copy a block from source to destination. S/390 version.
|
||||
- This file is part of the GNU C Library.
|
||||
- Copyright (C) 2000-2018 Free Software Foundation, Inc.
|
||||
- Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com).
|
||||
-
|
||||
- The GNU C Library is free software; you can redistribute it and/or
|
||||
- modify it under the terms of the GNU Lesser General Public
|
||||
- License as published by the Free Software Foundation; either
|
||||
- version 2.1 of the License, or (at your option) any later version.
|
||||
-
|
||||
- The GNU C Library is distributed in the hope that it will be useful,
|
||||
- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
- Lesser General Public License for more details.
|
||||
-
|
||||
- You should have received a copy of the GNU Lesser General Public
|
||||
- License along with the GNU C Library; if not, see
|
||||
- <http://www.gnu.org/licenses/>. */
|
||||
-
|
||||
-/* INPUT PARAMETERS
|
||||
- %r2 = address of source
|
||||
- %r3 = address of destination
|
||||
- %r4 = number of bytes to copy. */
|
||||
-
|
||||
-#include "sysdep.h"
|
||||
-#include "asm-syntax.h"
|
||||
-
|
||||
- .text
|
||||
-ENTRY(__bcopy)
|
||||
- ltr %r1,%r4 # zero bcopy ?
|
||||
- jz .L4
|
||||
- clr %r2,%r3 # check against destructive overlap
|
||||
- jnl .L0
|
||||
- alr %r1,%r2
|
||||
- clr %r1,%r3
|
||||
- jh .L7
|
||||
-.L0: ahi %r4,-1 # length - 1
|
||||
- lr %r1,%r4
|
||||
- srl %r1,8
|
||||
- ltr %r1,%r1 # < 256 bytes to move ?
|
||||
- jz .L2
|
||||
- chi %r1,255 # > 1MB to move ?
|
||||
- jh .L5
|
||||
-.L1: mvc 0(256,%r3),0(%r2) # move in 256 byte chunks
|
||||
- la %r2,256(%r2)
|
||||
- la %r3,256(%r3)
|
||||
- brct %r1,.L1
|
||||
-.L2: bras %r1,.L3 # setup base pointer for execute
|
||||
- mvc 0(1,%r3),0(%r2) # instruction for execute
|
||||
-.L3: ex %r4,0(%r1) # execute mvc with length ((%r4)&255)+1
|
||||
-.L4: br %r14
|
||||
-
|
||||
- # data copies > 1MB are faster with mvcle.
|
||||
-.L5: ahi %r4,1 # length + 1
|
||||
- lr %r5,%r4 # source length
|
||||
- lr %r4,%r2 # source address
|
||||
- lr %r2,%r3 # set destination
|
||||
- lr %r3,%r5 # destination length = source length
|
||||
-.L6: mvcle %r2,%r4,0 # thats it, MVCLE is your friend
|
||||
- jo .L6
|
||||
- br %r14
|
||||
-.L7: # destructive overlay, can not use mvcle
|
||||
- lr %r1,%r2 # bcopy is called with source,dest
|
||||
- lr %r2,%r3 # memmove with dest,source! Oh, well...
|
||||
- lr %r3,%r1
|
||||
- basr %r1,0
|
||||
-.L8:
|
||||
-#ifdef PIC
|
||||
- al %r1,.L9-.L8(%r1) # get address of global offset table
|
||||
- # load address of memmove
|
||||
- l %r1,memmove@GOT(%r1)
|
||||
- br %r1
|
||||
-.L9: .long _GLOBAL_OFFSET_TABLE_-.L8
|
||||
-#else
|
||||
- al %r1,.L9-.L8(%r1) # load address of memmove
|
||||
- br %r1 # jump to memmove
|
||||
-.L9: .long memmove-.L8
|
||||
-#endif
|
||||
-
|
||||
-END(__bcopy)
|
||||
-
|
||||
-#ifndef NO_WEAK_ALIAS
|
||||
-weak_alias (__bcopy, bcopy)
|
||||
-#endif
|
||||
-
|
||||
diff --git a/sysdeps/s390/s390-64/bcopy.S b/sysdeps/s390/s390-64/bcopy.S
|
||||
deleted file mode 100644
|
||||
index 806dd15d0203d32a..0000000000000000
|
||||
--- a/sysdeps/s390/s390-64/bcopy.S
|
||||
+++ /dev/null
|
||||
@@ -1,71 +0,0 @@
|
||||
-/* bcopy -- copy a block from source to destination. 64 bit S/390 version.
|
||||
- This file is part of the GNU C Library.
|
||||
- Copyright (C) 2000-2018 Free Software Foundation, Inc.
|
||||
- Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com).
|
||||
-
|
||||
- The GNU C Library is free software; you can redistribute it and/or
|
||||
- modify it under the terms of the GNU Lesser General Public
|
||||
- License as published by the Free Software Foundation; either
|
||||
- version 2.1 of the License, or (at your option) any later version.
|
||||
-
|
||||
- The GNU C Library is distributed in the hope that it will be useful,
|
||||
- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
- Lesser General Public License for more details.
|
||||
-
|
||||
- You should have received a copy of the GNU Lesser General Public
|
||||
- License along with the GNU C Library; if not, see
|
||||
- <http://www.gnu.org/licenses/>. */
|
||||
-
|
||||
-/* INPUT PARAMETERS
|
||||
- %r2 = address of source
|
||||
- %r3 = address of destination
|
||||
- %r4 = number of bytes to copy. */
|
||||
-
|
||||
-#include "sysdep.h"
|
||||
-#include "asm-syntax.h"
|
||||
-
|
||||
- .text
|
||||
-ENTRY(__bcopy)
|
||||
- ltgr %r1,%r4 # zero bcopy ?
|
||||
- jz .L4
|
||||
- clgr %r2,%r3 # check against destructive overlap
|
||||
- jnl .L0
|
||||
- algr %r1,%r2
|
||||
- clgr %r1,%r3
|
||||
- jh .L7
|
||||
-.L0: aghi %r4,-1 # length - 1
|
||||
- srlg %r1,%r4,8
|
||||
- ltgr %r1,%r1 # < 256 bytes to move ?
|
||||
- jz .L2
|
||||
- cghi %r1,255 # > 1MB to move ?
|
||||
- jh .L5
|
||||
-.L1: mvc 0(256,%r3),0(%r2) # move in 256 byte chunks
|
||||
- la %r2,256(%r2)
|
||||
- la %r3,256(%r3)
|
||||
- brctg %r1,.L1
|
||||
-.L2: bras %r1,.L3 # setup base pointer for execute
|
||||
- mvc 0(1,%r3),0(%r2) # instruction for execute
|
||||
-.L3: ex %r4,0(%r1) # execute mvc with length ((%r4)&255)+1
|
||||
-.L4: br %r14
|
||||
- # data copies > 1MB are faster with mvcle.
|
||||
-.L5: aghi %r4,1 # length + 1
|
||||
- lgr %r5,%r4 # source length
|
||||
- lgr %r4,%r2 # source address
|
||||
- lgr %r2,%r3 # set destination
|
||||
- lgr %r3,%r5 # destination length = source length
|
||||
-.L6: mvcle %r2,%r4,0 # thats it, MVCLE is your friend
|
||||
- jo .L6
|
||||
- br %r14
|
||||
-.L7: # destructive overlay, can not use mvcle
|
||||
- lgr %r1,%r2 # bcopy is called with source,dest
|
||||
- lgr %r2,%r3 # memmove with dest,source! Oh, well...
|
||||
- lgr %r3,%r1
|
||||
- jg HIDDEN_BUILTIN_JUMPTARGET(memmove)
|
||||
-
|
||||
-END(__bcopy)
|
||||
-
|
||||
-#ifndef NO_WEAK_ALIAS
|
||||
-weak_alias (__bcopy, bcopy)
|
||||
-#endif
|
||||
-
|
43
SOURCES/glibc-rh1659438-11.patch
Normal file
43
SOURCES/glibc-rh1659438-11.patch
Normal file
@ -0,0 +1,43 @@
|
||||
commit d097d97626e44bc6e76d5daf80ce3ff7d147b623
|
||||
Author: Stefan Liebler <stli@linux.ibm.com>
|
||||
Date: Tue Dec 18 13:57:07 2018 +0100
|
||||
|
||||
S390: Use memcpy for forward cases in memmove.
|
||||
|
||||
The s390/s390x memcpy implementations are safe to be
|
||||
used by memmove. Starting with this commit, memmove is
|
||||
using memcpy for the forward cases on s390.
|
||||
|
||||
ChangeLog:
|
||||
|
||||
* sysdeps/s390/memcopy.h: New file.
|
||||
|
||||
diff --git a/sysdeps/s390/memcopy.h b/sysdeps/s390/memcopy.h
|
||||
new file mode 100644
|
||||
index 0000000000000000..9a76196502f25bbf
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/s390/memcopy.h
|
||||
@@ -0,0 +1,23 @@
|
||||
+/* memcopy.h -- definitions for memory copy functions.
|
||||
+ Copyright (C) 2018 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <sysdeps/generic/memcopy.h>
|
||||
+
|
||||
+/* The s390/s390x memcpy implementations are safe to be used by memmove. */
|
||||
+#undef MEMCPY_OK_FOR_FWD_MEMMOVE
|
||||
+#define MEMCPY_OK_FOR_FWD_MEMMOVE 1
|
114
SOURCES/glibc-rh1659438-12.patch
Normal file
114
SOURCES/glibc-rh1659438-12.patch
Normal file
@ -0,0 +1,114 @@
|
||||
commit 2ee1bc57ab50737ee2ab88c4d796b90e08b4bf93
|
||||
Author: Stefan Liebler <stli@linux.ibm.com>
|
||||
Date: Tue Dec 18 13:57:08 2018 +0100
|
||||
|
||||
S390: Add configure check to detect z13 as mininum architecture level set.
|
||||
|
||||
Add a configure check for z13 in the same way as done for z196.
|
||||
|
||||
ChangeLog:
|
||||
|
||||
* config.h.in (HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT): New undefine.
|
||||
* sysdeps/s390/configure.ac: Add check for z13 support.
|
||||
* sysdeps/s390/configure: Regenerated.
|
||||
|
||||
diff --git a/config.h.in b/config.h.in
|
||||
index beecc39d5b8c3f4a..422a6036ab16e3b6 100644
|
||||
--- a/config.h.in
|
||||
+++ b/config.h.in
|
||||
@@ -68,6 +68,9 @@
|
||||
/* Define if assembler supports z196 zarch instructions as default on S390. */
|
||||
#undef HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT
|
||||
|
||||
+/* Define if assembler supports z13 zarch instructions as default on S390. */
|
||||
+#undef HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT
|
||||
+
|
||||
/* Define if assembler supports vector instructions on S390. */
|
||||
#undef HAVE_S390_VX_ASM_SUPPORT
|
||||
|
||||
diff --git a/sysdeps/s390/configure b/sysdeps/s390/configure
|
||||
index f30f8644361f474a..4a44775e3083d8c3 100644
|
||||
--- a/sysdeps/s390/configure
|
||||
+++ b/sysdeps/s390/configure
|
||||
@@ -187,5 +187,43 @@ then
|
||||
|
||||
fi
|
||||
|
||||
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for S390 z13 zarch instruction support as default" >&5
|
||||
+$as_echo_n "checking for S390 z13 zarch instruction support as default... " >&6; }
|
||||
+if ${libc_cv_asm_s390_min_z13_zarch+:} false; then :
|
||||
+ $as_echo_n "(cached) " >&6
|
||||
+else
|
||||
+ cat > conftest.c <<\EOF
|
||||
+int testinsn (void)
|
||||
+{
|
||||
+ int i;
|
||||
+ __asm__ ("vl %%v16,0(%%r15)\n\t"
|
||||
+ "vlgvf %0,%%v16,0"
|
||||
+ : "=d" (i) : : "memory", "v16");
|
||||
+ return i;
|
||||
+}
|
||||
+EOF
|
||||
+if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS --shared conftest.c
|
||||
+ -o conftest.o &> /dev/null'
|
||||
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
|
||||
+ (eval $ac_try) 2>&5
|
||||
+ ac_status=$?
|
||||
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
+ test $ac_status = 0; }; } ;
|
||||
+then
|
||||
+ libc_cv_asm_s390_min_z13_zarch=yes
|
||||
+else
|
||||
+ libc_cv_asm_s390_min_z13_zarch=no
|
||||
+fi
|
||||
+rm -f conftest*
|
||||
+fi
|
||||
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_asm_s390_min_z13_zarch" >&5
|
||||
+$as_echo "$libc_cv_asm_s390_min_z13_zarch" >&6; }
|
||||
+
|
||||
+if test "$libc_cv_asm_s390_min_z13_zarch" = yes ;
|
||||
+then
|
||||
+ $as_echo "#define HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT 1" >>confdefs.h
|
||||
+
|
||||
+fi
|
||||
+
|
||||
test -n "$critic_missing" && as_fn_error $? "
|
||||
*** $critic_missing" "$LINENO" 5
|
||||
diff --git a/sysdeps/s390/configure.ac b/sysdeps/s390/configure.ac
|
||||
index 981f7a79dd7066fc..4dfb5574b49d5949 100644
|
||||
--- a/sysdeps/s390/configure.ac
|
||||
+++ b/sysdeps/s390/configure.ac
|
||||
@@ -135,5 +135,33 @@ then
|
||||
AC_DEFINE(HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT)
|
||||
fi
|
||||
|
||||
+AC_CACHE_CHECK(for S390 z13 zarch instruction support as default,
|
||||
+ libc_cv_asm_s390_min_z13_zarch, [dnl
|
||||
+cat > conftest.c <<\EOF
|
||||
+int testinsn (void)
|
||||
+{
|
||||
+ int i;
|
||||
+ __asm__ ("vl %%v16,0(%%r15)\n\t"
|
||||
+ "vlgvf %0,%%v16,0"
|
||||
+ : "=d" (i) : : "memory", "v16");
|
||||
+ return i;
|
||||
+}
|
||||
+EOF
|
||||
+dnl
|
||||
+dnl test, if assembler supports S390 z13 zarch instructions as default
|
||||
+if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS --shared conftest.c
|
||||
+ -o conftest.o &> /dev/null]) ;
|
||||
+then
|
||||
+ libc_cv_asm_s390_min_z13_zarch=yes
|
||||
+else
|
||||
+ libc_cv_asm_s390_min_z13_zarch=no
|
||||
+fi
|
||||
+rm -f conftest* ])
|
||||
+
|
||||
+if test "$libc_cv_asm_s390_min_z13_zarch" = yes ;
|
||||
+then
|
||||
+ AC_DEFINE(HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT)
|
||||
+fi
|
||||
+
|
||||
test -n "$critic_missing" && AC_MSG_ERROR([
|
||||
*** $critic_missing])
|
327
SOURCES/glibc-rh1659438-13.patch
Normal file
327
SOURCES/glibc-rh1659438-13.patch
Normal file
@ -0,0 +1,327 @@
|
||||
commit cdd927d98cc38acf55e1c6594b5c9451df8f239f
|
||||
Author: Stefan Liebler <stli@linux.ibm.com>
|
||||
Date: Tue Dec 18 13:57:08 2018 +0100
|
||||
|
||||
S390: Add z13 memmove ifunc variant.
|
||||
|
||||
This patch introduces a z13 specific ifunc variant for memmove.
|
||||
As the common code implementation, it checks if we can copy from
|
||||
the beginning to the end - with z196 memcpy implementation - or
|
||||
if we have to copy from the end to the beginning.
|
||||
The latter case is done by using vector load/store instructions.
|
||||
|
||||
If vector instructions are not available, the common-code is
|
||||
used as fallback. Therefore it is implemented in memmove-c with
|
||||
a different name.
|
||||
Furthermore the ifunc logic decides if we need the common-code
|
||||
implementation at all. If vector instructions are supported
|
||||
due to the minimum architecture level set we can skip the
|
||||
common-code ifunc variant.
|
||||
|
||||
ChangeLog:
|
||||
|
||||
* sysdeps/s390/Makefile (sysdep_routines): Add memmove-c.
|
||||
* sysdeps/s390/ifunc-memcpy.h (HAVE_MEMMOVE_IFUNC,
|
||||
HAVE_MEMMOVE_IFUNC_AND_VX_SUPPORT, MEMMOVE_DEFAULT,
|
||||
HAVE_MEMMOVE_C, MEMMOVE_C, HAVE_MEMMOVE_Z13, MEMMOVE_Z13):
|
||||
New defines.
|
||||
* sysdeps/s390/memcpy-z900.S: Add z13 memmove implementation.
|
||||
* sysdeps/s390/memmove-c.c: New file.
|
||||
* sysdeps/s390/memmove.c: Likewise.
|
||||
* sysdeps/s390/multiarch/ifunc-impl-list.c
|
||||
(__libc_ifunc_impl_list): Add ifunc variants for memmove.
|
||||
|
||||
diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile
|
||||
index 838950a5ab958e31..3a7cccdf8f147398 100644
|
||||
--- a/sysdeps/s390/Makefile
|
||||
+++ b/sysdeps/s390/Makefile
|
||||
@@ -33,5 +33,6 @@ endif
|
||||
ifeq ($(subdir),string)
|
||||
sysdep_routines += bzero memset memset-z900 \
|
||||
memcmp memcmp-z900 \
|
||||
- mempcpy memcpy memcpy-z900
|
||||
+ mempcpy memcpy memcpy-z900 \
|
||||
+ memmove memmove-c
|
||||
endif
|
||||
diff --git a/sysdeps/s390/ifunc-memcpy.h b/sysdeps/s390/ifunc-memcpy.h
|
||||
index 51c71baa2c0b0452..0e701968c8f39014 100644
|
||||
--- a/sysdeps/s390/ifunc-memcpy.h
|
||||
+++ b/sysdeps/s390/ifunc-memcpy.h
|
||||
@@ -43,6 +43,29 @@
|
||||
# define HAVE_MEMCPY_Z196 HAVE_MEMCPY_IFUNC
|
||||
#endif
|
||||
|
||||
+#if defined SHARED && defined USE_MULTIARCH && IS_IN (libc) \
|
||||
+ && ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT
|
||||
+# define HAVE_MEMMOVE_IFUNC 1
|
||||
+#else
|
||||
+# define HAVE_MEMMOVE_IFUNC 0
|
||||
+#endif
|
||||
+
|
||||
+#ifdef HAVE_S390_VX_ASM_SUPPORT
|
||||
+# define HAVE_MEMMOVE_IFUNC_AND_VX_SUPPORT HAVE_MEMMOVE_IFUNC
|
||||
+#else
|
||||
+# define HAVE_MEMMOVE_IFUNC_AND_VX_SUPPORT 0
|
||||
+#endif
|
||||
+
|
||||
+#if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT
|
||||
+# define MEMMOVE_DEFAULT MEMMOVE_Z13
|
||||
+# define HAVE_MEMMOVE_C 0
|
||||
+# define HAVE_MEMMOVE_Z13 1
|
||||
+#else
|
||||
+# define MEMMOVE_DEFAULT MEMMOVE_C
|
||||
+# define HAVE_MEMMOVE_C 1
|
||||
+# define HAVE_MEMMOVE_Z13 HAVE_MEMMOVE_IFUNC_AND_VX_SUPPORT
|
||||
+#endif
|
||||
+
|
||||
#if HAVE_MEMCPY_Z900_G5
|
||||
# define MEMCPY_Z900_G5 __memcpy_default
|
||||
# define MEMPCPY_Z900_G5 __mempcpy_default
|
||||
@@ -66,3 +89,15 @@
|
||||
# define MEMCPY_Z196 NULL
|
||||
# define MEMPCPY_Z196 NULL
|
||||
#endif
|
||||
+
|
||||
+#if HAVE_MEMMOVE_C
|
||||
+# define MEMMOVE_C __memmove_c
|
||||
+#else
|
||||
+# define MEMMOVE_C NULL
|
||||
+#endif
|
||||
+
|
||||
+#if HAVE_MEMMOVE_Z13
|
||||
+# define MEMMOVE_Z13 __memmove_z13
|
||||
+#else
|
||||
+# define MEMMOVE_Z13 NULL
|
||||
+#endif
|
||||
diff --git a/sysdeps/s390/memcpy-z900.S b/sysdeps/s390/memcpy-z900.S
|
||||
index 3a50cf44d85d2417..bd3b1950ee442c0c 100644
|
||||
--- a/sysdeps/s390/memcpy-z900.S
|
||||
+++ b/sysdeps/s390/memcpy-z900.S
|
||||
@@ -182,6 +182,7 @@ ENTRY(MEMCPY_Z196)
|
||||
# endif /* !defined __s390x__ */
|
||||
ltgr %r4,%r4
|
||||
je .L_Z196_4
|
||||
+.L_Z196_start2:
|
||||
aghi %r4,-1
|
||||
srlg %r5,%r4,8
|
||||
ltgr %r5,%r5
|
||||
@@ -207,6 +208,75 @@ ENTRY(MEMCPY_Z196)
|
||||
END(MEMCPY_Z196)
|
||||
#endif /* HAVE_MEMCPY_Z196 */
|
||||
|
||||
+#if HAVE_MEMMOVE_Z13
|
||||
+ENTRY(MEMMOVE_Z13)
|
||||
+ .machine "z13"
|
||||
+ .machinemode "zarch_nohighgprs"
|
||||
+# if !defined __s390x__
|
||||
+ /* Note: The 31bit dst and src pointers are prefixed with zeroes. */
|
||||
+ llgfr %r4,%r4
|
||||
+ llgfr %r3,%r3
|
||||
+ llgfr %r2,%r2
|
||||
+# endif /* !defined __s390x__ */
|
||||
+ sgrk %r0,%r2,%r3
|
||||
+ clgijh %r4,16,.L_MEMMOVE_Z13_LARGE
|
||||
+ aghik %r5,%r4,-1
|
||||
+.L_MEMMOVE_Z13_SMALL:
|
||||
+ jl .L_MEMMOVE_Z13_END /* Jump away if len was zero. */
|
||||
+ /* Store up to 16 bytes with vll/vstl which needs the index
|
||||
+ instead of lengths. */
|
||||
+ vll %v16,%r5,0(%r3)
|
||||
+ vstl %v16,%r5,0(%r2)
|
||||
+.L_MEMMOVE_Z13_END:
|
||||
+ br %r14
|
||||
+.L_MEMMOVE_Z13_LARGE:
|
||||
+ lgr %r1,%r2 /* For memcpy: r1: Use as dest ;
|
||||
+ r2: Return dest */
|
||||
+ /* The unsigned comparison (dst - src >= len) determines if we can
|
||||
+ execute the forward case with memcpy. */
|
||||
+#if ! HAVE_MEMCPY_Z196
|
||||
+# error The z13 variant of memmove needs the z196 variant of memcpy!
|
||||
+#endif
|
||||
+ clgrjhe %r0,%r4,.L_Z196_start2
|
||||
+ risbgn %r5,%r4,4,128+63,60 /* r5 = r4 / 16 */
|
||||
+ aghi %r4,-16
|
||||
+ clgijhe %r5,8,.L_MEMMOVE_Z13_LARGE_64B
|
||||
+.L_MEMMOVE_Z13_LARGE_16B_LOOP:
|
||||
+ /* Store at least 16 bytes with vl/vst. The number of 16byte blocks
|
||||
+ is stored in r5. */
|
||||
+ vl %v16,0(%r4,%r3)
|
||||
+ vst %v16,0(%r4,%r2)
|
||||
+ aghi %r4,-16
|
||||
+ brctg %r5,.L_MEMMOVE_Z13_LARGE_16B_LOOP
|
||||
+ aghik %r5,%r4,15
|
||||
+ j .L_MEMMOVE_Z13_SMALL
|
||||
+.L_MEMMOVE_Z13_LARGE_64B:
|
||||
+ /* Store at least 128 bytes with 4x vl/vst. The number of 64byte blocks
|
||||
+ will be stored in r0. */
|
||||
+ aghi %r4,-48
|
||||
+ srlg %r0,%r5,2 /* r5 = %r0 / 4
|
||||
+ => Number of 64byte blocks. */
|
||||
+.L_MEMMOVE_Z13_LARGE_64B_LOOP:
|
||||
+ vl %v20,48(%r4,%r3)
|
||||
+ vl %v19,32(%r4,%r3)
|
||||
+ vl %v18,16(%r4,%r3)
|
||||
+ vl %v17,0(%r4,%r3)
|
||||
+ vst %v20,48(%r4,%r2)
|
||||
+ vst %v19,32(%r4,%r2)
|
||||
+ vst %v18,16(%r4,%r2)
|
||||
+ vst %v17,0(%r4,%r2)
|
||||
+ aghi %r4,-64
|
||||
+ brctg %r0,.L_MEMMOVE_Z13_LARGE_64B_LOOP
|
||||
+ aghi %r4,48
|
||||
+ /* Recalculate the number of 16byte blocks. */
|
||||
+ risbg %r5,%r5,62,128+63,0 /* r5 = r5 & 3
|
||||
+ => Remaining 16byte blocks. */
|
||||
+ jne .L_MEMMOVE_Z13_LARGE_16B_LOOP
|
||||
+ aghik %r5,%r4,15
|
||||
+ j .L_MEMMOVE_Z13_SMALL
|
||||
+END(MEMMOVE_Z13)
|
||||
+#endif /* HAVE_MEMMOVE_Z13 */
|
||||
+
|
||||
#if ! HAVE_MEMCPY_IFUNC
|
||||
/* If we don't use ifunc, define an alias for mem[p]cpy here.
|
||||
Otherwise see sysdeps/s390/mem[p]cpy.c. */
|
||||
@@ -215,10 +285,27 @@ strong_alias (MEMPCPY_DEFAULT, __mempcpy)
|
||||
weak_alias (__mempcpy, mempcpy)
|
||||
#endif
|
||||
|
||||
+#if ! HAVE_MEMMOVE_IFUNC
|
||||
+/* If we don't use ifunc, define an alias for memmove here.
|
||||
+ Otherwise see sysdeps/s390/memmove.c. */
|
||||
+# if ! HAVE_MEMMOVE_C
|
||||
+/* If the c variant is needed, then sysdeps/s390/memmove-c.c
|
||||
+ defines memmove.
|
||||
+ Otherwise MEMMOVE_DEFAULT is implemented here and we have to define it. */
|
||||
+strong_alias (MEMMOVE_DEFAULT, memmove)
|
||||
+# endif
|
||||
+#endif
|
||||
+
|
||||
#if defined SHARED && IS_IN (libc)
|
||||
/* Defines the internal symbols.
|
||||
Compare to libc_hidden_[builtin_]def (mem[p]cpy) in string/mem[p]cpy.c. */
|
||||
strong_alias (MEMCPY_DEFAULT, __GI_memcpy)
|
||||
strong_alias (MEMPCPY_DEFAULT, __GI_mempcpy)
|
||||
strong_alias (MEMPCPY_DEFAULT, __GI___mempcpy)
|
||||
+# if ! HAVE_MEMMOVE_C
|
||||
+/* If the c variant is needed, then sysdeps/s390/memmove-c.c
|
||||
+ defines the internal symbol.
|
||||
+ Otherwise MEMMOVE_DEFAULT is implemented here and we have to define it. */
|
||||
+strong_alias (MEMMOVE_DEFAULT, __GI_memmove)
|
||||
+# endif
|
||||
#endif
|
||||
diff --git a/sysdeps/s390/memmove-c.c b/sysdeps/s390/memmove-c.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..be571093e019a38d
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/s390/memmove-c.c
|
||||
@@ -0,0 +1,37 @@
|
||||
+/* Fallback C version of memmove.
|
||||
+ Copyright (C) 2018 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <ifunc-memcpy.h>
|
||||
+
|
||||
+#if HAVE_MEMMOVE_C
|
||||
+# if HAVE_MEMMOVE_IFUNC
|
||||
+/* If we use ifunc, then the memmove symbol is defined
|
||||
+ in sysdeps/s390/memmove.c and we use a different name here.
|
||||
+ Otherwise, we have to define memmove here or in
|
||||
+ sysdeps/s390/memcpy.S depending on the used default implementation. */
|
||||
+# define MEMMOVE MEMMOVE_C
|
||||
+# if defined SHARED && IS_IN (libc)
|
||||
+/* Define the internal symbol. */
|
||||
+# undef libc_hidden_builtin_def
|
||||
+# define libc_hidden_builtin_def(name) \
|
||||
+ __hidden_ver1 (__memmove_c, __GI_memmove, __memmove_c);
|
||||
+# endif
|
||||
+# endif
|
||||
+
|
||||
+# include <string/memmove.c>
|
||||
+#endif
|
||||
diff --git a/sysdeps/s390/memmove.c b/sysdeps/s390/memmove.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..ac34edf80f2678cd
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/s390/memmove.c
|
||||
@@ -0,0 +1,44 @@
|
||||
+/* Multiple versions of memmove.
|
||||
+ Copyright (C) 2016-2018 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <ifunc-memcpy.h>
|
||||
+
|
||||
+#if HAVE_MEMMOVE_IFUNC
|
||||
+/* If we don't use ifunc, an alias is defined for memmove
|
||||
+ in sysdeps/s390/memmove-c.c or sysdeps/s390/memcpy.S
|
||||
+ depending on the used default implementation. */
|
||||
+# undef memmove
|
||||
+# define memmove __redirect_memmove
|
||||
+# include <string.h>
|
||||
+# include <ifunc-resolve.h>
|
||||
+# undef memmove
|
||||
+
|
||||
+# if HAVE_MEMMOVE_C
|
||||
+extern __typeof (__redirect_memmove) MEMMOVE_C attribute_hidden;
|
||||
+# endif
|
||||
+
|
||||
+# if HAVE_MEMMOVE_Z13
|
||||
+extern __typeof (__redirect_memmove) MEMMOVE_Z13 attribute_hidden;
|
||||
+# endif
|
||||
+
|
||||
+s390_libc_ifunc_expr (__redirect_memmove, memmove,
|
||||
+ (HAVE_MEMMOVE_Z13 && (hwcap & HWCAP_S390_VX))
|
||||
+ ? MEMMOVE_Z13
|
||||
+ : MEMMOVE_DEFAULT
|
||||
+ )
|
||||
+#endif
|
||||
diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c
|
||||
index 6969c480cc40e0e2..c05c63e00608dcd7 100644
|
||||
--- a/sysdeps/s390/multiarch/ifunc-impl-list.c
|
||||
+++ b/sysdeps/s390/multiarch/ifunc-impl-list.c
|
||||
@@ -126,6 +126,18 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
)
|
||||
#endif /* HAVE_MEMCPY_IFUNC */
|
||||
|
||||
+#if HAVE_MEMMOVE_IFUNC
|
||||
+ IFUNC_IMPL (i, name, memmove,
|
||||
+# if HAVE_MEMMOVE_Z13
|
||||
+ IFUNC_IMPL_ADD (array, i, memmove,
|
||||
+ dl_hwcap & HWCAP_S390_VX, MEMMOVE_Z13)
|
||||
+# endif
|
||||
+# if HAVE_MEMMOVE_C
|
||||
+ IFUNC_IMPL_ADD (array, i, memmove, 1, MEMMOVE_C)
|
||||
+# endif
|
||||
+ )
|
||||
+#endif /* HAVE_MEMMOVE_IFUNC */
|
||||
+
|
||||
#ifdef HAVE_S390_VX_ASM_SUPPORT
|
||||
|
||||
# define IFUNC_VX_IMPL(FUNC) \
|
263
SOURCES/glibc-rh1659438-14.patch
Normal file
263
SOURCES/glibc-rh1659438-14.patch
Normal file
@ -0,0 +1,263 @@
|
||||
commit 8c25dddd2e32bce47dfe01ca51c8aab535dbe23d
|
||||
Author: Stefan Liebler <stli@linux.ibm.com>
|
||||
Date: Tue Dec 18 13:57:09 2018 +0100
|
||||
|
||||
S390: Add z13 strstr ifunc variant.
|
||||
|
||||
The new vector variant of strstr is using the common code
|
||||
implementation, but instead of calling the default
|
||||
str* / mem* functions, the vector variants are called.
|
||||
|
||||
ChangeLog:
|
||||
|
||||
* sysdeps/s390/Makefile (sysdep_routines): Add strstr variants.
|
||||
* sysdeps/s390/multiarch/ifunc-impl-list.c
|
||||
(__libc_ifunc_impl_list): Add ifunc variants for strstr.
|
||||
* sysdeps/s390/ifunc-strstr.h: New file.
|
||||
* sysdeps/s390/strstr.c: Likewise.
|
||||
* sysdeps/s390/strstr-c.c: Likewise.
|
||||
* sysdeps/s390/strstr-vx.c: Likewise.
|
||||
|
||||
diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile
|
||||
index 3a7cccdf8f147398..4441e7a5cf6fa167 100644
|
||||
--- a/sysdeps/s390/Makefile
|
||||
+++ b/sysdeps/s390/Makefile
|
||||
@@ -34,5 +34,6 @@ ifeq ($(subdir),string)
|
||||
sysdep_routines += bzero memset memset-z900 \
|
||||
memcmp memcmp-z900 \
|
||||
mempcpy memcpy memcpy-z900 \
|
||||
- memmove memmove-c
|
||||
+ memmove memmove-c \
|
||||
+ strstr strstr-vx strstr-c
|
||||
endif
|
||||
diff --git a/sysdeps/s390/ifunc-strstr.h b/sysdeps/s390/ifunc-strstr.h
|
||||
new file mode 100644
|
||||
index 0000000000000000..e6ccfd4e44a1a790
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/s390/ifunc-strstr.h
|
||||
@@ -0,0 +1,52 @@
|
||||
+/* strstr variant information on S/390 version.
|
||||
+ Copyright (C) 2018 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#if defined USE_MULTIARCH && IS_IN (libc) \
|
||||
+ && ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT
|
||||
+# define HAVE_STRSTR_IFUNC 1
|
||||
+#else
|
||||
+# define HAVE_STRSTR_IFUNC 0
|
||||
+#endif
|
||||
+
|
||||
+#ifdef HAVE_S390_VX_ASM_SUPPORT
|
||||
+# define HAVE_STRSTR_IFUNC_AND_VX_SUPPORT HAVE_STRSTR_IFUNC
|
||||
+#else
|
||||
+# define HAVE_STRSTR_IFUNC_AND_VX_SUPPORT 0
|
||||
+#endif
|
||||
+
|
||||
+#if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT
|
||||
+# define STRSTR_DEFAULT STRSTR_Z13
|
||||
+# define HAVE_STRSTR_C 0
|
||||
+# define HAVE_STRSTR_Z13 1
|
||||
+#else
|
||||
+# define STRSTR_DEFAULT STRSTR_C
|
||||
+# define HAVE_STRSTR_C 1
|
||||
+# define HAVE_STRSTR_Z13 HAVE_STRSTR_IFUNC_AND_VX_SUPPORT
|
||||
+#endif
|
||||
+
|
||||
+#if HAVE_STRSTR_C
|
||||
+# define STRSTR_C __strstr_c
|
||||
+#else
|
||||
+# define STRSTR_C NULL
|
||||
+#endif
|
||||
+
|
||||
+#if HAVE_STRSTR_Z13
|
||||
+# define STRSTR_Z13 __strstr_vx
|
||||
+#else
|
||||
+# define STRSTR_Z13 NULL
|
||||
+#endif
|
||||
diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c
|
||||
index c05c63e00608dcd7..14727f8fef5431dd 100644
|
||||
--- a/sysdeps/s390/multiarch/ifunc-impl-list.c
|
||||
+++ b/sysdeps/s390/multiarch/ifunc-impl-list.c
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <ifunc-memset.h>
|
||||
#include <ifunc-memcmp.h>
|
||||
#include <ifunc-memcpy.h>
|
||||
+#include <ifunc-strstr.h>
|
||||
|
||||
/* Maximum number of IFUNC implementations. */
|
||||
#define MAX_IFUNC 3
|
||||
@@ -138,6 +139,18 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
)
|
||||
#endif /* HAVE_MEMMOVE_IFUNC */
|
||||
|
||||
+#if HAVE_STRSTR_IFUNC
|
||||
+ IFUNC_IMPL (i, name, strstr,
|
||||
+# if HAVE_STRSTR_Z13
|
||||
+ IFUNC_IMPL_ADD (array, i, strstr,
|
||||
+ dl_hwcap & HWCAP_S390_VX, STRSTR_Z13)
|
||||
+# endif
|
||||
+# if HAVE_STRSTR_C
|
||||
+ IFUNC_IMPL_ADD (array, i, strstr, 1, STRSTR_C)
|
||||
+# endif
|
||||
+ )
|
||||
+#endif /* HAVE_STRSTR_IFUNC */
|
||||
+
|
||||
#ifdef HAVE_S390_VX_ASM_SUPPORT
|
||||
|
||||
# define IFUNC_VX_IMPL(FUNC) \
|
||||
diff --git a/sysdeps/s390/strstr-c.c b/sysdeps/s390/strstr-c.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..53717bfb276fed3d
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/s390/strstr-c.c
|
||||
@@ -0,0 +1,32 @@
|
||||
+/* Default strstr implementation for S/390.
|
||||
+ Copyright (C) 2018 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <ifunc-strstr.h>
|
||||
+
|
||||
+#if HAVE_STRSTR_C
|
||||
+# if HAVE_STRSTR_IFUNC
|
||||
+# define STRSTR STRSTR_C
|
||||
+# if defined SHARED && IS_IN (libc)
|
||||
+# undef libc_hidden_builtin_def
|
||||
+# define libc_hidden_builtin_def(name) \
|
||||
+ __hidden_ver1 (__strstr_c, __GI_strstr, __strstr_c);
|
||||
+# endif
|
||||
+# endif
|
||||
+
|
||||
+# include <string/strstr.c>
|
||||
+#endif
|
||||
diff --git a/sysdeps/s390/strstr-vx.c b/sysdeps/s390/strstr-vx.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..effae9d5eb7d2fb1
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/s390/strstr-vx.c
|
||||
@@ -0,0 +1,52 @@
|
||||
+/* Default strstr implementation with vector string functions for S/390.
|
||||
+ Copyright (C) 2018 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <ifunc-strstr.h>
|
||||
+
|
||||
+#if HAVE_STRSTR_Z13
|
||||
+# if HAVE_STRSTR_IFUNC
|
||||
+# define STRSTR STRSTR_Z13
|
||||
+# if defined SHARED && IS_IN (libc)
|
||||
+# undef libc_hidden_builtin_def
|
||||
+# if HAVE_STRSTR_C
|
||||
+# define libc_hidden_builtin_def(name)
|
||||
+# else
|
||||
+# define libc_hidden_builtin_def(name) \
|
||||
+ __hidden_ver1 (__strstr_vx, __GI_strstr, __strstr_vx);
|
||||
+# endif
|
||||
+# endif
|
||||
+# endif
|
||||
+
|
||||
+# include <string.h>
|
||||
+
|
||||
+# ifdef USE_MULTIARCH
|
||||
+extern __typeof (strchr) __strchr_vx attribute_hidden;
|
||||
+# define strchr __strchr_vx
|
||||
+
|
||||
+extern __typeof (strlen) __strlen_vx attribute_hidden;
|
||||
+# define strlen __strlen_vx
|
||||
+
|
||||
+extern __typeof (__strnlen) __strnlen_vx attribute_hidden;
|
||||
+# define __strnlen __strnlen_vx
|
||||
+
|
||||
+extern __typeof (memcmp) __memcmp_z196 attribute_hidden;
|
||||
+# define memcmp __memcmp_z196
|
||||
+# endif
|
||||
+
|
||||
+# include <string/strstr.c>
|
||||
+#endif
|
||||
diff --git a/sysdeps/s390/strstr.c b/sysdeps/s390/strstr.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..f8432349a7254cc6
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/s390/strstr.c
|
||||
@@ -0,0 +1,40 @@
|
||||
+/* Multiple versions of strstr.
|
||||
+ Copyright (C) 2018 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <ifunc-strstr.h>
|
||||
+
|
||||
+#if HAVE_STRSTR_IFUNC
|
||||
+# define strstr __redirect_strstr
|
||||
+# include <string.h>
|
||||
+# include <ifunc-resolve.h>
|
||||
+# undef strstr
|
||||
+
|
||||
+# if HAVE_STRSTR_C
|
||||
+extern __typeof (__redirect_strstr) STRSTR_C attribute_hidden;
|
||||
+# endif
|
||||
+
|
||||
+# if HAVE_STRSTR_Z13
|
||||
+extern __typeof (__redirect_strstr) STRSTR_Z13 attribute_hidden;
|
||||
+# endif
|
||||
+
|
||||
+s390_libc_ifunc_expr (__redirect_strstr, strstr,
|
||||
+ (HAVE_STRSTR_Z13 && (hwcap & HWCAP_S390_VX))
|
||||
+ ? STRSTR_Z13
|
||||
+ : STRSTR_DEFAULT
|
||||
+ )
|
||||
+#endif
|
290
SOURCES/glibc-rh1659438-15.patch
Normal file
290
SOURCES/glibc-rh1659438-15.patch
Normal file
@ -0,0 +1,290 @@
|
||||
commit d2c4c403feddd6f0b9dbf31ca7541b37f90ee30a
|
||||
Author: Stefan Liebler <stli@linux.ibm.com>
|
||||
Date: Tue Dec 18 13:57:09 2018 +0100
|
||||
|
||||
S390: Add z13 memmem ifunc variant.
|
||||
|
||||
The new vector variant of memmem is using the common code
|
||||
implementation, but instead of calling the default
|
||||
mem* functions, the vector variants are called.
|
||||
|
||||
ChangeLog:
|
||||
|
||||
* sysdeps/s390/Makefile (sysdep_routines): Add memmem variants.
|
||||
* sysdeps/s390/multiarch/ifunc-impl-list.c
|
||||
(__libc_ifunc_impl_list): Add ifunc variants for memmem.
|
||||
* sysdeps/s390/ifunc-memmem.h: New file.
|
||||
* sysdeps/s390/memmem.c: Likewise.
|
||||
* sysdeps/s390/memmem-c.c: Likewise.
|
||||
* sysdeps/s390/memmem-vx.c: Likewise.
|
||||
|
||||
diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile
|
||||
index 4441e7a5cf6fa167..47d606d3d5d99274 100644
|
||||
--- a/sysdeps/s390/Makefile
|
||||
+++ b/sysdeps/s390/Makefile
|
||||
@@ -35,5 +35,6 @@ sysdep_routines += bzero memset memset-z900 \
|
||||
memcmp memcmp-z900 \
|
||||
mempcpy memcpy memcpy-z900 \
|
||||
memmove memmove-c \
|
||||
- strstr strstr-vx strstr-c
|
||||
+ strstr strstr-vx strstr-c \
|
||||
+ memmem memmem-vx memmem-c
|
||||
endif
|
||||
diff --git a/sysdeps/s390/ifunc-memmem.h b/sysdeps/s390/ifunc-memmem.h
|
||||
new file mode 100644
|
||||
index 0000000000000000..0f860d8d40080acf
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/s390/ifunc-memmem.h
|
||||
@@ -0,0 +1,52 @@
|
||||
+/* memmem variant information on S/390 version.
|
||||
+ Copyright (C) 2018 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#if defined USE_MULTIARCH && IS_IN (libc) \
|
||||
+ && ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT
|
||||
+# define HAVE_MEMMEM_IFUNC 1
|
||||
+#else
|
||||
+# define HAVE_MEMMEM_IFUNC 0
|
||||
+#endif
|
||||
+
|
||||
+#ifdef HAVE_S390_VX_ASM_SUPPORT
|
||||
+# define HAVE_MEMMEM_IFUNC_AND_VX_SUPPORT HAVE_MEMMEM_IFUNC
|
||||
+#else
|
||||
+# define HAVE_MEMMEM_IFUNC_AND_VX_SUPPORT 0
|
||||
+#endif
|
||||
+
|
||||
+#if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT
|
||||
+# define MEMMEM_DEFAULT MEMMEM_Z13
|
||||
+# define HAVE_MEMMEM_C 0
|
||||
+# define HAVE_MEMMEM_Z13 1
|
||||
+#else
|
||||
+# define MEMMEM_DEFAULT MEMMEM_C
|
||||
+# define HAVE_MEMMEM_C 1
|
||||
+# define HAVE_MEMMEM_Z13 HAVE_MEMMEM_IFUNC_AND_VX_SUPPORT
|
||||
+#endif
|
||||
+
|
||||
+#if HAVE_MEMMEM_C
|
||||
+# define MEMMEM_C __memmem_c
|
||||
+#else
|
||||
+# define MEMMEM_C NULL
|
||||
+#endif
|
||||
+
|
||||
+#if HAVE_MEMMEM_Z13
|
||||
+# define MEMMEM_Z13 __memmem_vx
|
||||
+#else
|
||||
+# define MEMMEM_Z13 NULL
|
||||
+#endif
|
||||
diff --git a/sysdeps/s390/memmem-c.c b/sysdeps/s390/memmem-c.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..1d8ffefcb840b8d2
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/s390/memmem-c.c
|
||||
@@ -0,0 +1,47 @@
|
||||
+/* Default memmem implementation for S/390.
|
||||
+ Copyright (C) 2018 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <ifunc-memmem.h>
|
||||
+
|
||||
+#if HAVE_MEMMEM_C
|
||||
+# if HAVE_MEMMEM_IFUNC
|
||||
+# include <string.h>
|
||||
+
|
||||
+# ifndef _LIBC
|
||||
+# define memmem MEMMEM_C
|
||||
+# else
|
||||
+# define __memmem MEMMEM_C
|
||||
+# endif
|
||||
+
|
||||
+# if defined SHARED && IS_IN (libc)
|
||||
+# undef libc_hidden_def
|
||||
+# define libc_hidden_def(name) \
|
||||
+ strong_alias (__memmem_c, __memmem_c_1); \
|
||||
+ __hidden_ver1 (__memmem_c, __GI___memmem, __memmem_c);
|
||||
+
|
||||
+# undef libc_hidden_weak
|
||||
+# define libc_hidden_weak(name) \
|
||||
+ __hidden_ver1 (__memmem_c_1, __GI_memmem, __memmem_c_1) __attribute__((weak));
|
||||
+# endif
|
||||
+
|
||||
+# undef weak_alias
|
||||
+# define weak_alias(a, b)
|
||||
+# endif
|
||||
+
|
||||
+# include <string/memmem.c>
|
||||
+#endif
|
||||
diff --git a/sysdeps/s390/memmem-vx.c b/sysdeps/s390/memmem-vx.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..af6e200e4e0af1a5
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/s390/memmem-vx.c
|
||||
@@ -0,0 +1,61 @@
|
||||
+/* Default memmem implementation with vector string functions for S/390.
|
||||
+ Copyright (C) 2018 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <ifunc-memmem.h>
|
||||
+
|
||||
+#if HAVE_MEMMEM_Z13
|
||||
+# include <string.h>
|
||||
+# if HAVE_MEMMEM_IFUNC
|
||||
+
|
||||
+# ifndef _LIBC
|
||||
+# define memmem MEMMEM_Z13
|
||||
+# else
|
||||
+# define __memmem MEMMEM_Z13
|
||||
+# endif
|
||||
+
|
||||
+# if defined SHARED && IS_IN (libc)
|
||||
+# undef libc_hidden_def
|
||||
+# undef libc_hidden_weak
|
||||
+
|
||||
+# if HAVE_MEMMEM_C
|
||||
+# define libc_hidden_def(name)
|
||||
+# define libc_hidden_weak(name)
|
||||
+# else
|
||||
+# define libc_hidden_def(name) \
|
||||
+ strong_alias (__memmem_vx, __memmem_vx_1); \
|
||||
+ __hidden_ver1 (__memmem_vx, __GI___memmem, __memmem_vx);
|
||||
+
|
||||
+# define libc_hidden_weak(name) \
|
||||
+ __hidden_ver1 (__memmem_vx_1, __GI_memmem, __memmem_vx_1) __attribute__((weak));
|
||||
+# endif
|
||||
+# endif
|
||||
+
|
||||
+# undef weak_alias
|
||||
+# define weak_alias(a, b)
|
||||
+# endif
|
||||
+
|
||||
+# ifdef USE_MULTIARCH
|
||||
+extern __typeof (memchr) __memchr_vx attribute_hidden;
|
||||
+# define memchr __memchr_vx
|
||||
+
|
||||
+extern __typeof (memcmp) __memcmp_z196 attribute_hidden;
|
||||
+# define memcmp __memcmp_z196
|
||||
+# endif
|
||||
+
|
||||
+# include <string/memmem.c>
|
||||
+#endif
|
||||
diff --git a/sysdeps/s390/memmem.c b/sysdeps/s390/memmem.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..8c50b3f403eb8d1f
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/s390/memmem.c
|
||||
@@ -0,0 +1,43 @@
|
||||
+/* Multiple versions of memmem.
|
||||
+ Copyright (C) 2018 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <ifunc-memmem.h>
|
||||
+
|
||||
+#if HAVE_MEMMEM_IFUNC
|
||||
+# define memmem __redirect_memmem
|
||||
+# define __memmem __redirect___memmem
|
||||
+# include <string.h>
|
||||
+# include <ifunc-resolve.h>
|
||||
+# undef memmem
|
||||
+# undef __memmem
|
||||
+
|
||||
+# if HAVE_MEMMEM_C
|
||||
+extern __typeof (__redirect_memmem) MEMMEM_C attribute_hidden;
|
||||
+# endif
|
||||
+
|
||||
+# if HAVE_MEMMEM_Z13
|
||||
+extern __typeof (__redirect_memmem) MEMMEM_Z13 attribute_hidden;
|
||||
+# endif
|
||||
+
|
||||
+s390_libc_ifunc_expr (__redirect_memmem, __memmem,
|
||||
+ (HAVE_MEMMEM_Z13 && (hwcap & HWCAP_S390_VX))
|
||||
+ ? MEMMEM_Z13
|
||||
+ : MEMMEM_DEFAULT
|
||||
+ )
|
||||
+weak_alias (__memmem, memmem)
|
||||
+#endif
|
||||
diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c
|
||||
index 14727f8fef5431dd..da8696d917abf51c 100644
|
||||
--- a/sysdeps/s390/multiarch/ifunc-impl-list.c
|
||||
+++ b/sysdeps/s390/multiarch/ifunc-impl-list.c
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <ifunc-memcmp.h>
|
||||
#include <ifunc-memcpy.h>
|
||||
#include <ifunc-strstr.h>
|
||||
+#include <ifunc-memmem.h>
|
||||
|
||||
/* Maximum number of IFUNC implementations. */
|
||||
#define MAX_IFUNC 3
|
||||
@@ -151,6 +152,18 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
)
|
||||
#endif /* HAVE_STRSTR_IFUNC */
|
||||
|
||||
+#if HAVE_MEMMEM_IFUNC
|
||||
+ IFUNC_IMPL (i, name, memmem,
|
||||
+# if HAVE_MEMMEM_Z13
|
||||
+ IFUNC_IMPL_ADD (array, i, memmem,
|
||||
+ dl_hwcap & HWCAP_S390_VX, MEMMEM_Z13)
|
||||
+# endif
|
||||
+# if HAVE_MEMMEM_C
|
||||
+ IFUNC_IMPL_ADD (array, i, memmem, 1, MEMMEM_C)
|
||||
+# endif
|
||||
+ )
|
||||
+#endif /* HAVE_MEMMEM_IFUNC */
|
||||
+
|
||||
#ifdef HAVE_S390_VX_ASM_SUPPORT
|
||||
|
||||
# define IFUNC_VX_IMPL(FUNC) \
|
259
SOURCES/glibc-rh1659438-16.patch
Normal file
259
SOURCES/glibc-rh1659438-16.patch
Normal file
@ -0,0 +1,259 @@
|
||||
commit ff3ca3743a00af749258cc242457b648d65a1537
|
||||
Author: Stefan Liebler <stli@linux.ibm.com>
|
||||
Date: Tue Dec 18 13:57:10 2018 +0100
|
||||
|
||||
S390: Refactor strlen ifunc handling.
|
||||
|
||||
The ifunc handling for strlen is adjusted in order to omit ifunc
|
||||
variants if those will never be used as the minimum architecture level
|
||||
already supports newer CPUs by default.
|
||||
Glibc internal calls will then also use the "newer" ifunc variant.
|
||||
|
||||
ChangeLog:
|
||||
|
||||
* sysdeps/s390/multiarch/Makefile
|
||||
(sysdep_routines): Remove strlen variants.
|
||||
* sysdeps/s390/Makefile (sysdep_routines): Add strlen variants.
|
||||
* sysdeps/s390/multiarch/ifunc-impl-list.c
|
||||
(__libc_ifunc_impl_list): Refactor ifunc handling for strlen.
|
||||
* sysdeps/s390/multiarch/strlen-c.c: Move to ...
|
||||
* sysdeps/s390/strlen-c.c: ... here and adjust ifunc handling.
|
||||
* sysdeps/s390/multiarch/strlen-vx.S: Move to ...
|
||||
* sysdeps/s390/strlen-vx.S: ... here and adjust ifunc handling.
|
||||
* sysdeps/s390/multiarch/strlen.c: Move to ...
|
||||
* sysdeps/s390/strlen.c: ... here and adjust ifunc handling.
|
||||
* sysdeps/s390/ifunc-strlen.h: New file.
|
||||
|
||||
diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile
|
||||
index 47d606d3d5d99274..600d8e629df7090e 100644
|
||||
--- a/sysdeps/s390/Makefile
|
||||
+++ b/sysdeps/s390/Makefile
|
||||
@@ -36,5 +36,6 @@ sysdep_routines += bzero memset memset-z900 \
|
||||
mempcpy memcpy memcpy-z900 \
|
||||
memmove memmove-c \
|
||||
strstr strstr-vx strstr-c \
|
||||
- memmem memmem-vx memmem-c
|
||||
+ memmem memmem-vx memmem-c \
|
||||
+ strlen strlen-vx strlen-c
|
||||
endif
|
||||
diff --git a/sysdeps/s390/ifunc-strlen.h b/sysdeps/s390/ifunc-strlen.h
|
||||
new file mode 100644
|
||||
index 0000000000000000..f2070596636f29a9
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/s390/ifunc-strlen.h
|
||||
@@ -0,0 +1,52 @@
|
||||
+/* strlen variant information on S/390 version.
|
||||
+ Copyright (C) 2018 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#if defined USE_MULTIARCH && IS_IN (libc) \
|
||||
+ && ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT
|
||||
+# define HAVE_STRLEN_IFUNC 1
|
||||
+#else
|
||||
+# define HAVE_STRLEN_IFUNC 0
|
||||
+#endif
|
||||
+
|
||||
+#ifdef HAVE_S390_VX_ASM_SUPPORT
|
||||
+# define HAVE_STRLEN_IFUNC_AND_VX_SUPPORT HAVE_STRLEN_IFUNC
|
||||
+#else
|
||||
+# define HAVE_STRLEN_IFUNC_AND_VX_SUPPORT 0
|
||||
+#endif
|
||||
+
|
||||
+#if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT
|
||||
+# define STRLEN_DEFAULT STRLEN_Z13
|
||||
+# define HAVE_STRLEN_C 0
|
||||
+# define HAVE_STRLEN_Z13 1
|
||||
+#else
|
||||
+# define STRLEN_DEFAULT STRLEN_C
|
||||
+# define HAVE_STRLEN_C 1
|
||||
+# define HAVE_STRLEN_Z13 HAVE_STRLEN_IFUNC_AND_VX_SUPPORT
|
||||
+#endif
|
||||
+
|
||||
+#if HAVE_STRLEN_C
|
||||
+# define STRLEN_C __strlen_c
|
||||
+#else
|
||||
+# define STRLEN_C NULL
|
||||
+#endif
|
||||
+
|
||||
+#if HAVE_STRLEN_Z13
|
||||
+# define STRLEN_Z13 __strlen_vx
|
||||
+#else
|
||||
+# define STRLEN_Z13 NULL
|
||||
+#endif
|
||||
diff --git a/sysdeps/s390/multiarch/Makefile b/sysdeps/s390/multiarch/Makefile
|
||||
index 24949cd3a88b8015..601523919c235f76 100644
|
||||
--- a/sysdeps/s390/multiarch/Makefile
|
||||
+++ b/sysdeps/s390/multiarch/Makefile
|
||||
@@ -1,6 +1,5 @@
|
||||
ifeq ($(subdir),string)
|
||||
-sysdep_routines += strlen strlen-vx strlen-c \
|
||||
- strnlen strnlen-vx strnlen-c \
|
||||
+sysdep_routines += strnlen strnlen-vx strnlen-c \
|
||||
strcpy strcpy-vx \
|
||||
stpcpy stpcpy-vx stpcpy-c \
|
||||
strncpy strncpy-vx \
|
||||
diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c
|
||||
index da8696d917abf51c..c531be4bc7eb3f55 100644
|
||||
--- a/sysdeps/s390/multiarch/ifunc-impl-list.c
|
||||
+++ b/sysdeps/s390/multiarch/ifunc-impl-list.c
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <ifunc-memcpy.h>
|
||||
#include <ifunc-strstr.h>
|
||||
#include <ifunc-memmem.h>
|
||||
+#include <ifunc-strlen.h>
|
||||
|
||||
/* Maximum number of IFUNC implementations. */
|
||||
#define MAX_IFUNC 3
|
||||
@@ -164,6 +165,18 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
)
|
||||
#endif /* HAVE_MEMMEM_IFUNC */
|
||||
|
||||
+#if HAVE_STRLEN_IFUNC
|
||||
+ IFUNC_IMPL (i, name, strlen,
|
||||
+# if HAVE_STRLEN_Z13
|
||||
+ IFUNC_IMPL_ADD (array, i, strlen,
|
||||
+ dl_hwcap & HWCAP_S390_VX, STRLEN_Z13)
|
||||
+# endif
|
||||
+# if HAVE_STRLEN_C
|
||||
+ IFUNC_IMPL_ADD (array, i, strlen, 1, STRLEN_C)
|
||||
+# endif
|
||||
+ )
|
||||
+#endif /* HAVE_STRLEN_IFUNC */
|
||||
+
|
||||
#ifdef HAVE_S390_VX_ASM_SUPPORT
|
||||
|
||||
# define IFUNC_VX_IMPL(FUNC) \
|
||||
@@ -172,7 +185,6 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
__##FUNC##_vx) \
|
||||
IFUNC_IMPL_ADD (array, i, FUNC, 1, __##FUNC##_c))
|
||||
|
||||
- IFUNC_VX_IMPL (strlen);
|
||||
IFUNC_VX_IMPL (wcslen);
|
||||
|
||||
IFUNC_VX_IMPL (strnlen);
|
||||
diff --git a/sysdeps/s390/multiarch/strlen-c.c b/sysdeps/s390/strlen-c.c
|
||||
similarity index 78%
|
||||
rename from sysdeps/s390/multiarch/strlen-c.c
|
||||
rename to sysdeps/s390/strlen-c.c
|
||||
index a2c8e43624a9bc91..b4569701af96f4a9 100644
|
||||
--- a/sysdeps/s390/multiarch/strlen-c.c
|
||||
+++ b/sysdeps/s390/strlen-c.c
|
||||
@@ -16,13 +16,17 @@
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)
|
||||
-# define STRLEN __strlen_c
|
||||
-# ifdef SHARED
|
||||
-# undef libc_hidden_builtin_def
|
||||
-# define libc_hidden_builtin_def(name) \
|
||||
+#include <ifunc-strlen.h>
|
||||
+
|
||||
+#if HAVE_STRLEN_C
|
||||
+# if HAVE_STRLEN_IFUNC
|
||||
+# define STRLEN STRLEN_C
|
||||
+# if defined SHARED && IS_IN (libc)
|
||||
+# undef libc_hidden_builtin_def
|
||||
+# define libc_hidden_builtin_def(name) \
|
||||
__hidden_ver1 (__strlen_c, __GI_strlen, __strlen_c);
|
||||
-# endif /* SHARED */
|
||||
+# endif
|
||||
+# endif
|
||||
|
||||
# include <string/strlen.c>
|
||||
-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */
|
||||
+#endif
|
||||
diff --git a/sysdeps/s390/multiarch/strlen-vx.S b/sysdeps/s390/strlen-vx.S
|
||||
similarity index 90%
|
||||
rename from sysdeps/s390/multiarch/strlen-vx.S
|
||||
rename to sysdeps/s390/strlen-vx.S
|
||||
index 9308b332371dcdaa..39ef43107d11ec73 100644
|
||||
--- a/sysdeps/s390/multiarch/strlen-vx.S
|
||||
+++ b/sysdeps/s390/strlen-vx.S
|
||||
@@ -16,7 +16,8 @@
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)
|
||||
+#include <ifunc-strlen.h>
|
||||
+#if HAVE_STRLEN_Z13
|
||||
|
||||
# include "sysdep.h"
|
||||
# include "asm-syntax.h"
|
||||
@@ -34,7 +35,7 @@
|
||||
-r5=current_len and return_value
|
||||
-v16=part of s
|
||||
*/
|
||||
-ENTRY(__strlen_vx)
|
||||
+ENTRY(STRLEN_Z13)
|
||||
.machine "z13"
|
||||
.machinemode "zarch_nohighgprs"
|
||||
|
||||
@@ -80,5 +81,13 @@ ENTRY(__strlen_vx)
|
||||
vlgvb %r2,%v16,7 /* Load byte index of zero. */
|
||||
algr %r2,%r5
|
||||
br %r14
|
||||
-END(__strlen_vx)
|
||||
-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */
|
||||
+END(STRLEN_Z13)
|
||||
+
|
||||
+# if ! HAVE_STRLEN_IFUNC
|
||||
+strong_alias (STRLEN_Z13, strlen)
|
||||
+# endif
|
||||
+
|
||||
+# if ! HAVE_STRLEN_C && defined SHARED && IS_IN (libc)
|
||||
+strong_alias (STRLEN_Z13, __GI_strlen)
|
||||
+# endif
|
||||
+#endif
|
||||
diff --git a/sysdeps/s390/multiarch/strlen.c b/sysdeps/s390/strlen.c
|
||||
similarity index 69%
|
||||
rename from sysdeps/s390/multiarch/strlen.c
|
||||
rename to sysdeps/s390/strlen.c
|
||||
index 0edf8b7d0231cf31..6ba0fe86fe9789f0 100644
|
||||
--- a/sysdeps/s390/multiarch/strlen.c
|
||||
+++ b/sysdeps/s390/strlen.c
|
||||
@@ -16,14 +16,25 @@
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)
|
||||
+#include <ifunc-strlen.h>
|
||||
+
|
||||
+#if HAVE_STRLEN_IFUNC
|
||||
# define strlen __redirect_strlen
|
||||
# include <string.h>
|
||||
# include <ifunc-resolve.h>
|
||||
# undef strlen
|
||||
|
||||
-s390_vx_libc_ifunc2_redirected (__redirect_strlen, __strlen, strlen)
|
||||
+# if HAVE_STRLEN_C
|
||||
+extern __typeof (__redirect_strlen) STRLEN_C attribute_hidden;
|
||||
+# endif
|
||||
+
|
||||
+# if HAVE_STRLEN_Z13
|
||||
+extern __typeof (__redirect_strlen) STRLEN_Z13 attribute_hidden;
|
||||
+# endif
|
||||
|
||||
-#else
|
||||
-# include <string/strlen.c>
|
||||
-#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */
|
||||
+s390_libc_ifunc_expr (__redirect_strlen, strlen,
|
||||
+ (HAVE_STRLEN_Z13 && (hwcap & HWCAP_S390_VX))
|
||||
+ ? STRLEN_Z13
|
||||
+ : STRLEN_DEFAULT
|
||||
+ )
|
||||
+#endif
|
269
SOURCES/glibc-rh1659438-17.patch
Normal file
269
SOURCES/glibc-rh1659438-17.patch
Normal file
@ -0,0 +1,269 @@
|
||||
commit de10e44dda686e3ed6a7a1463869df846ea39825
|
||||
Author: Stefan Liebler <stli@linux.ibm.com>
|
||||
Date: Tue Dec 18 13:57:10 2018 +0100
|
||||
|
||||
S390: Refactor strnlen ifunc handling.
|
||||
|
||||
The ifunc handling for strnlen is adjusted in order to omit ifunc
|
||||
variants if those will never be used as the minimum architecture level
|
||||
already supports newer CPUs by default.
|
||||
Glibc internal calls will then also use the "newer" ifunc variant.
|
||||
|
||||
ChangeLog:
|
||||
|
||||
* sysdeps/s390/multiarch/Makefile
|
||||
(sysdep_routines): Remove strnlen variants.
|
||||
* sysdeps/s390/Makefile (sysdep_routines): Add strnlen variants.
|
||||
* sysdeps/s390/multiarch/ifunc-impl-list.c
|
||||
(__libc_ifunc_impl_list): Refactor ifunc handling for strnlen.
|
||||
* sysdeps/s390/multiarch/strnlen-c.c: Move to ...
|
||||
* sysdeps/s390/strnlen-c.c: ... here and adjust ifunc handling.
|
||||
* sysdeps/s390/multiarch/strnlen-vx.S: Move to ...
|
||||
* sysdeps/s390/strnlen-vx.S: ... here and adjust ifunc handling.
|
||||
* sysdeps/s390/multiarch/strnlen.c: Move to ...
|
||||
* sysdeps/s390/strnlen.c: ... here and adjust ifunc handling.
|
||||
* sysdeps/s390/ifunc-strnlen.h: New file.
|
||||
|
||||
diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile
|
||||
index 600d8e629df7090e..f092355743e3908f 100644
|
||||
--- a/sysdeps/s390/Makefile
|
||||
+++ b/sysdeps/s390/Makefile
|
||||
@@ -37,5 +37,6 @@ sysdep_routines += bzero memset memset-z900 \
|
||||
memmove memmove-c \
|
||||
strstr strstr-vx strstr-c \
|
||||
memmem memmem-vx memmem-c \
|
||||
- strlen strlen-vx strlen-c
|
||||
+ strlen strlen-vx strlen-c \
|
||||
+ strnlen strnlen-vx strnlen-c
|
||||
endif
|
||||
diff --git a/sysdeps/s390/ifunc-strnlen.h b/sysdeps/s390/ifunc-strnlen.h
|
||||
new file mode 100644
|
||||
index 0000000000000000..e92329888773304d
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/s390/ifunc-strnlen.h
|
||||
@@ -0,0 +1,52 @@
|
||||
+/* strnlen variant information on S/390 version.
|
||||
+ Copyright (C) 2018 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#if defined USE_MULTIARCH && IS_IN (libc) \
|
||||
+ && ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT
|
||||
+# define HAVE_STRNLEN_IFUNC 1
|
||||
+#else
|
||||
+# define HAVE_STRNLEN_IFUNC 0
|
||||
+#endif
|
||||
+
|
||||
+#ifdef HAVE_S390_VX_ASM_SUPPORT
|
||||
+# define HAVE_STRNLEN_IFUNC_AND_VX_SUPPORT HAVE_STRNLEN_IFUNC
|
||||
+#else
|
||||
+# define HAVE_STRNLEN_IFUNC_AND_VX_SUPPORT 0
|
||||
+#endif
|
||||
+
|
||||
+#if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT
|
||||
+# define STRNLEN_DEFAULT STRNLEN_Z13
|
||||
+# define HAVE_STRNLEN_C 0
|
||||
+# define HAVE_STRNLEN_Z13 1
|
||||
+#else
|
||||
+# define STRNLEN_DEFAULT STRNLEN_C
|
||||
+# define HAVE_STRNLEN_C 1
|
||||
+# define HAVE_STRNLEN_Z13 HAVE_STRNLEN_IFUNC_AND_VX_SUPPORT
|
||||
+#endif
|
||||
+
|
||||
+#if HAVE_STRNLEN_C
|
||||
+# define STRNLEN_C __strnlen_c
|
||||
+#else
|
||||
+# define STRNLEN_C NULL
|
||||
+#endif
|
||||
+
|
||||
+#if HAVE_STRNLEN_Z13
|
||||
+# define STRNLEN_Z13 __strnlen_vx
|
||||
+#else
|
||||
+# define STRNLEN_Z13 NULL
|
||||
+#endif
|
||||
diff --git a/sysdeps/s390/multiarch/Makefile b/sysdeps/s390/multiarch/Makefile
|
||||
index 601523919c235f76..35ba223c5d4fb52f 100644
|
||||
--- a/sysdeps/s390/multiarch/Makefile
|
||||
+++ b/sysdeps/s390/multiarch/Makefile
|
||||
@@ -1,6 +1,5 @@
|
||||
ifeq ($(subdir),string)
|
||||
-sysdep_routines += strnlen strnlen-vx strnlen-c \
|
||||
- strcpy strcpy-vx \
|
||||
+sysdep_routines += strcpy strcpy-vx \
|
||||
stpcpy stpcpy-vx stpcpy-c \
|
||||
strncpy strncpy-vx \
|
||||
stpncpy stpncpy-vx stpncpy-c \
|
||||
diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c
|
||||
index c531be4bc7eb3f55..680e5b738bfb7f32 100644
|
||||
--- a/sysdeps/s390/multiarch/ifunc-impl-list.c
|
||||
+++ b/sysdeps/s390/multiarch/ifunc-impl-list.c
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <ifunc-strstr.h>
|
||||
#include <ifunc-memmem.h>
|
||||
#include <ifunc-strlen.h>
|
||||
+#include <ifunc-strnlen.h>
|
||||
|
||||
/* Maximum number of IFUNC implementations. */
|
||||
#define MAX_IFUNC 3
|
||||
@@ -177,6 +178,18 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
)
|
||||
#endif /* HAVE_STRLEN_IFUNC */
|
||||
|
||||
+#if HAVE_STRNLEN_IFUNC
|
||||
+ IFUNC_IMPL (i, name, strnlen,
|
||||
+# if HAVE_STRNLEN_Z13
|
||||
+ IFUNC_IMPL_ADD (array, i, strnlen,
|
||||
+ dl_hwcap & HWCAP_S390_VX, STRNLEN_Z13)
|
||||
+# endif
|
||||
+# if HAVE_STRNLEN_C
|
||||
+ IFUNC_IMPL_ADD (array, i, strnlen, 1, STRNLEN_C)
|
||||
+# endif
|
||||
+ )
|
||||
+#endif /* HAVE_STRNLEN_IFUNC */
|
||||
+
|
||||
#ifdef HAVE_S390_VX_ASM_SUPPORT
|
||||
|
||||
# define IFUNC_VX_IMPL(FUNC) \
|
||||
@@ -187,7 +200,6 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
|
||||
IFUNC_VX_IMPL (wcslen);
|
||||
|
||||
- IFUNC_VX_IMPL (strnlen);
|
||||
IFUNC_VX_IMPL (wcsnlen);
|
||||
|
||||
IFUNC_VX_IMPL (strcpy);
|
||||
diff --git a/sysdeps/s390/multiarch/strnlen-c.c b/sysdeps/s390/strnlen-c.c
|
||||
similarity index 81%
|
||||
rename from sysdeps/s390/multiarch/strnlen-c.c
|
||||
rename to sysdeps/s390/strnlen-c.c
|
||||
index 353e83ed356ca080..c2d887f1e4f504e8 100644
|
||||
--- a/sysdeps/s390/multiarch/strnlen-c.c
|
||||
+++ b/sysdeps/s390/strnlen-c.c
|
||||
@@ -16,15 +16,19 @@
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)
|
||||
-# define STRNLEN __strnlen_c
|
||||
-# ifdef SHARED
|
||||
-# undef libc_hidden_def
|
||||
-# define libc_hidden_def(name) \
|
||||
+#include <ifunc-strnlen.h>
|
||||
+
|
||||
+#if HAVE_STRNLEN_C
|
||||
+# if HAVE_STRNLEN_IFUNC
|
||||
+# define STRNLEN STRNLEN_C
|
||||
+# if defined SHARED && IS_IN (libc)
|
||||
+# undef libc_hidden_def
|
||||
+# define libc_hidden_def(name) \
|
||||
__hidden_ver1 (__strnlen_c, __GI_strnlen, __strnlen_c); \
|
||||
strong_alias (__strnlen_c, __strnlen_c_1); \
|
||||
__hidden_ver1 (__strnlen_c_1, __GI___strnlen, __strnlen_c_1);
|
||||
-# endif /* SHARED */
|
||||
+# endif
|
||||
+# endif
|
||||
|
||||
# include <string/strnlen.c>
|
||||
-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */
|
||||
+#endif
|
||||
diff --git a/sysdeps/s390/multiarch/strnlen-vx.S b/sysdeps/s390/strnlen-vx.S
|
||||
similarity index 90%
|
||||
rename from sysdeps/s390/multiarch/strnlen-vx.S
|
||||
rename to sysdeps/s390/strnlen-vx.S
|
||||
index fc659a956cfc1fa1..0b8fe3da342f6803 100644
|
||||
--- a/sysdeps/s390/multiarch/strnlen-vx.S
|
||||
+++ b/sysdeps/s390/strnlen-vx.S
|
||||
@@ -16,7 +16,9 @@
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)
|
||||
+#include <ifunc-strnlen.h>
|
||||
+
|
||||
+#if HAVE_STRNLEN_Z13
|
||||
|
||||
# include "sysdep.h"
|
||||
# include "asm-syntax.h"
|
||||
@@ -34,7 +36,7 @@
|
||||
-r5=current_len and return_value
|
||||
-v16=part of s
|
||||
*/
|
||||
-ENTRY(__strnlen_vx)
|
||||
+ENTRY(STRNLEN_Z13)
|
||||
.machine "z13"
|
||||
.machinemode "zarch_nohighgprs"
|
||||
|
||||
@@ -130,5 +132,16 @@ ENTRY(__strnlen_vx)
|
||||
clgrjl %r1,%r3,.Lloop64
|
||||
|
||||
j .Llt64
|
||||
-END(__strnlen_vx)
|
||||
-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */
|
||||
+END(STRNLEN_Z13)
|
||||
+
|
||||
+# if ! HAVE_STRNLEN_IFUNC
|
||||
+strong_alias (STRNLEN_Z13, __strnlen)
|
||||
+weak_alias (__strnlen, strnlen)
|
||||
+# endif
|
||||
+
|
||||
+# if ! HAVE_STRNLEN_C && defined SHARED && IS_IN (libc)
|
||||
+strong_alias (STRNLEN_Z13, __GI_strnlen)
|
||||
+strong_alias (STRNLEN_Z13, __GI___strnlen)
|
||||
+# endif
|
||||
+
|
||||
+#endif /* HAVE_STRNLEN_Z13 */
|
||||
diff --git a/sysdeps/s390/multiarch/strnlen.c b/sysdeps/s390/strnlen.c
|
||||
similarity index 69%
|
||||
rename from sysdeps/s390/multiarch/strnlen.c
|
||||
rename to sysdeps/s390/strnlen.c
|
||||
index 0f9cff5d69b017ae..aa4953d5035bc2fc 100644
|
||||
--- a/sysdeps/s390/multiarch/strnlen.c
|
||||
+++ b/sysdeps/s390/strnlen.c
|
||||
@@ -16,7 +16,9 @@
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)
|
||||
+#include <ifunc-strnlen.h>
|
||||
+
|
||||
+#if HAVE_STRNLEN_IFUNC
|
||||
# define strnlen __redirect_strnlen
|
||||
# define __strnlen __redirect___strnlen
|
||||
# include <string.h>
|
||||
@@ -24,9 +26,18 @@
|
||||
# undef __strnlen
|
||||
# include <ifunc-resolve.h>
|
||||
|
||||
-s390_vx_libc_ifunc_redirected (__redirect___strnlen, __strnlen)
|
||||
-weak_alias (__strnlen, strnlen)
|
||||
+# if HAVE_STRNLEN_C
|
||||
+extern __typeof (__redirect_strnlen) STRNLEN_C attribute_hidden;
|
||||
+# endif
|
||||
|
||||
-#else
|
||||
-# include <string/strnlen.c>
|
||||
-#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */
|
||||
+# if HAVE_STRNLEN_Z13
|
||||
+extern __typeof (__redirect_strnlen) STRNLEN_Z13 attribute_hidden;
|
||||
+# endif
|
||||
+
|
||||
+s390_libc_ifunc_expr (__redirect___strnlen, __strnlen,
|
||||
+ (HAVE_STRNLEN_Z13 && (hwcap & HWCAP_S390_VX))
|
||||
+ ? STRNLEN_Z13
|
||||
+ : STRNLEN_DEFAULT
|
||||
+ )
|
||||
+weak_alias (__strnlen, strnlen)
|
||||
+#endif /* HAVE_STRNLEN_IFUNC */
|
398
SOURCES/glibc-rh1659438-18.patch
Normal file
398
SOURCES/glibc-rh1659438-18.patch
Normal file
@ -0,0 +1,398 @@
|
||||
commit 914a4e05572e108201d71dcd3e47da8aeeecd70d
|
||||
Author: Stefan Liebler <stli@linux.ibm.com>
|
||||
Date: Tue Dec 18 13:57:10 2018 +0100
|
||||
|
||||
S390: Refactor strcpy ifunc handling.
|
||||
|
||||
The ifunc handling for strcpy is adjusted in order to omit ifunc
|
||||
variants if those will never be used as the minimum architecture level
|
||||
already supports newer CPUs by default.
|
||||
Glibc internal calls will then also use the "newer" ifunc variant.
|
||||
|
||||
Note: The fallback s390-32/s390-64 ifunc variants with mvst instruction
|
||||
are now moved to the unified strcpy-z900.S file which can be used for
|
||||
31/64bit. The s390-32/s390-64 files multiarch/strcpy.c and strcpy.S
|
||||
are deleted.
|
||||
|
||||
ChangeLog:
|
||||
|
||||
* sysdeps/s390/multiarch/Makefile
|
||||
(sysdep_routines): Remove strcpy variants.
|
||||
* sysdeps/s390/Makefile (sysdep_routines): Add strcpy variants.
|
||||
* sysdeps/s390/multiarch/ifunc-impl-list.c
|
||||
(__libc_ifunc_impl_list): Refactor ifunc handling for strcpy.
|
||||
* sysdeps/s390/multiarch/strcpy-vx.S: Move to ...
|
||||
* sysdeps/s390/strcpy-vx.S: ... here and adjust ifunc handling.
|
||||
* sysdeps/s390/multiarch/strcpy.c: Move to ...
|
||||
* sysdeps/s390/strcpy.c: ... here and adjust ifunc handling.
|
||||
* sysdeps/s390/ifunc-strcpy.h: New file.
|
||||
* sysdeps/s390/s390-64/strcpy.S: Move to ...
|
||||
* sysdeps/s390/strcpy-z900.S: ... here and adjust to be usable
|
||||
for 31/64bit and ifunc handling.
|
||||
* sysdeps/s390/s390-32/multiarch/strcpy.c: Delete file.
|
||||
* sysdeps/s390/s390-64/multiarch/strcpy.c: Likewise.
|
||||
* sysdeps/s390/s390-32/strcpy.S: Likewise.
|
||||
|
||||
diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile
|
||||
index f092355743e3908f..e4191319531ecb01 100644
|
||||
--- a/sysdeps/s390/Makefile
|
||||
+++ b/sysdeps/s390/Makefile
|
||||
@@ -38,5 +38,6 @@ sysdep_routines += bzero memset memset-z900 \
|
||||
strstr strstr-vx strstr-c \
|
||||
memmem memmem-vx memmem-c \
|
||||
strlen strlen-vx strlen-c \
|
||||
- strnlen strnlen-vx strnlen-c
|
||||
+ strnlen strnlen-vx strnlen-c \
|
||||
+ strcpy strcpy-vx strcpy-z900
|
||||
endif
|
||||
diff --git a/sysdeps/s390/ifunc-strcpy.h b/sysdeps/s390/ifunc-strcpy.h
|
||||
new file mode 100644
|
||||
index 0000000000000000..85e45556e6a61dd5
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/s390/ifunc-strcpy.h
|
||||
@@ -0,0 +1,52 @@
|
||||
+/* strcpy variant information on S/390 version.
|
||||
+ Copyright (C) 2018 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#if defined USE_MULTIARCH && IS_IN (libc) \
|
||||
+ && ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT
|
||||
+# define HAVE_STRCPY_IFUNC 1
|
||||
+#else
|
||||
+# define HAVE_STRCPY_IFUNC 0
|
||||
+#endif
|
||||
+
|
||||
+#ifdef HAVE_S390_VX_ASM_SUPPORT
|
||||
+# define HAVE_STRCPY_IFUNC_AND_VX_SUPPORT HAVE_STRCPY_IFUNC
|
||||
+#else
|
||||
+# define HAVE_STRCPY_IFUNC_AND_VX_SUPPORT 0
|
||||
+#endif
|
||||
+
|
||||
+#if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT
|
||||
+# define STRCPY_DEFAULT STRCPY_Z13
|
||||
+# define HAVE_STRCPY_Z900_G5 0
|
||||
+# define HAVE_STRCPY_Z13 1
|
||||
+#else
|
||||
+# define STRCPY_DEFAULT STRCPY_Z900_G5
|
||||
+# define HAVE_STRCPY_Z900_G5 1
|
||||
+# define HAVE_STRCPY_Z13 HAVE_STRCPY_IFUNC_AND_VX_SUPPORT
|
||||
+#endif
|
||||
+
|
||||
+#if HAVE_STRCPY_Z900_G5
|
||||
+# define STRCPY_Z900_G5 __strcpy_default
|
||||
+#else
|
||||
+# define STRCPY_Z900_G5 NULL
|
||||
+#endif
|
||||
+
|
||||
+#if HAVE_STRCPY_Z13
|
||||
+# define STRCPY_Z13 __strcpy_vx
|
||||
+#else
|
||||
+# define STRCPY_Z13 NULL
|
||||
+#endif
|
||||
diff --git a/sysdeps/s390/multiarch/Makefile b/sysdeps/s390/multiarch/Makefile
|
||||
index 35ba223c5d4fb52f..50f7f0b78df723bb 100644
|
||||
--- a/sysdeps/s390/multiarch/Makefile
|
||||
+++ b/sysdeps/s390/multiarch/Makefile
|
||||
@@ -1,6 +1,5 @@
|
||||
ifeq ($(subdir),string)
|
||||
-sysdep_routines += strcpy strcpy-vx \
|
||||
- stpcpy stpcpy-vx stpcpy-c \
|
||||
+sysdep_routines += stpcpy stpcpy-vx stpcpy-c \
|
||||
strncpy strncpy-vx \
|
||||
stpncpy stpncpy-vx stpncpy-c \
|
||||
strcat strcat-vx strcat-c \
|
||||
diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c
|
||||
index 680e5b738bfb7f32..1784372db9828463 100644
|
||||
--- a/sysdeps/s390/multiarch/ifunc-impl-list.c
|
||||
+++ b/sysdeps/s390/multiarch/ifunc-impl-list.c
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <ifunc-memmem.h>
|
||||
#include <ifunc-strlen.h>
|
||||
#include <ifunc-strnlen.h>
|
||||
+#include <ifunc-strcpy.h>
|
||||
|
||||
/* Maximum number of IFUNC implementations. */
|
||||
#define MAX_IFUNC 3
|
||||
@@ -190,6 +191,18 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
)
|
||||
#endif /* HAVE_STRNLEN_IFUNC */
|
||||
|
||||
+#if HAVE_STRCPY_IFUNC
|
||||
+ IFUNC_IMPL (i, name, strcpy,
|
||||
+# if HAVE_STRCPY_Z13
|
||||
+ IFUNC_IMPL_ADD (array, i, strcpy,
|
||||
+ dl_hwcap & HWCAP_S390_VX, STRCPY_Z13)
|
||||
+# endif
|
||||
+# if HAVE_STRCPY_Z900_G5
|
||||
+ IFUNC_IMPL_ADD (array, i, strcpy, 1, STRCPY_Z900_G5)
|
||||
+# endif
|
||||
+ )
|
||||
+#endif /* HAVE_STRCPY_IFUNC */
|
||||
+
|
||||
#ifdef HAVE_S390_VX_ASM_SUPPORT
|
||||
|
||||
# define IFUNC_VX_IMPL(FUNC) \
|
||||
@@ -202,7 +215,6 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
|
||||
IFUNC_VX_IMPL (wcsnlen);
|
||||
|
||||
- IFUNC_VX_IMPL (strcpy);
|
||||
IFUNC_VX_IMPL (wcscpy);
|
||||
|
||||
IFUNC_VX_IMPL (stpcpy);
|
||||
diff --git a/sysdeps/s390/s390-32/multiarch/strcpy.c b/sysdeps/s390/s390-32/multiarch/strcpy.c
|
||||
deleted file mode 100644
|
||||
index 6a22e31a03c8c1c4..0000000000000000
|
||||
--- a/sysdeps/s390/s390-32/multiarch/strcpy.c
|
||||
+++ /dev/null
|
||||
@@ -1,21 +0,0 @@
|
||||
-/* Multiple versions of strcpy.
|
||||
- Copyright (C) 2015-2018 Free Software Foundation, Inc.
|
||||
- This file is part of the GNU C Library.
|
||||
-
|
||||
- The GNU C Library is free software; you can redistribute it and/or
|
||||
- modify it under the terms of the GNU Lesser General Public
|
||||
- License as published by the Free Software Foundation; either
|
||||
- version 2.1 of the License, or (at your option) any later version.
|
||||
-
|
||||
- The GNU C Library is distributed in the hope that it will be useful,
|
||||
- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
- Lesser General Public License for more details.
|
||||
-
|
||||
- You should have received a copy of the GNU Lesser General Public
|
||||
- License along with the GNU C Library; if not, see
|
||||
- <http://www.gnu.org/licenses/>. */
|
||||
-
|
||||
-/* This wrapper-file is needed, because otherwise file
|
||||
- sysdeps/s390/s390-[32|64]/strcpy.S will be used. */
|
||||
-#include <sysdeps/s390/multiarch/strcpy.c>
|
||||
diff --git a/sysdeps/s390/s390-32/strcpy.S b/sysdeps/s390/s390-32/strcpy.S
|
||||
deleted file mode 100644
|
||||
index d49136ee92b83378..0000000000000000
|
||||
--- a/sysdeps/s390/s390-32/strcpy.S
|
||||
+++ /dev/null
|
||||
@@ -1,36 +0,0 @@
|
||||
-/* strcpy - copy a string from source to destination. For IBM S390
|
||||
- This file is part of the GNU C Library.
|
||||
- Copyright (C) 2000-2018 Free Software Foundation, Inc.
|
||||
- Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com).
|
||||
-
|
||||
- The GNU C Library is free software; you can redistribute it and/or
|
||||
- modify it under the terms of the GNU Lesser General Public
|
||||
- License as published by the Free Software Foundation; either
|
||||
- version 2.1 of the License, or (at your option) any later version.
|
||||
-
|
||||
- The GNU C Library is distributed in the hope that it will be useful,
|
||||
- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
- Lesser General Public License for more details.
|
||||
-
|
||||
- You should have received a copy of the GNU Lesser General Public
|
||||
- License along with the GNU C Library; if not, see
|
||||
- <http://www.gnu.org/licenses/>. */
|
||||
-
|
||||
-/*
|
||||
- * R2 = address of destination
|
||||
- * R3 = address of source
|
||||
- */
|
||||
-
|
||||
-#include "sysdep.h"
|
||||
-#include "asm-syntax.h"
|
||||
-
|
||||
- .text
|
||||
-ENTRY(strcpy)
|
||||
- slr %r0,%r0
|
||||
- lr %r1,%r2
|
||||
-0: mvst %r1,%r3
|
||||
- jo 0b
|
||||
- br %r14
|
||||
-END(strcpy)
|
||||
-libc_hidden_builtin_def (strcpy)
|
||||
diff --git a/sysdeps/s390/s390-64/multiarch/strcpy.c b/sysdeps/s390/s390-64/multiarch/strcpy.c
|
||||
deleted file mode 100644
|
||||
index 6a22e31a03c8c1c4..0000000000000000
|
||||
--- a/sysdeps/s390/s390-64/multiarch/strcpy.c
|
||||
+++ /dev/null
|
||||
@@ -1,21 +0,0 @@
|
||||
-/* Multiple versions of strcpy.
|
||||
- Copyright (C) 2015-2018 Free Software Foundation, Inc.
|
||||
- This file is part of the GNU C Library.
|
||||
-
|
||||
- The GNU C Library is free software; you can redistribute it and/or
|
||||
- modify it under the terms of the GNU Lesser General Public
|
||||
- License as published by the Free Software Foundation; either
|
||||
- version 2.1 of the License, or (at your option) any later version.
|
||||
-
|
||||
- The GNU C Library is distributed in the hope that it will be useful,
|
||||
- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
- Lesser General Public License for more details.
|
||||
-
|
||||
- You should have received a copy of the GNU Lesser General Public
|
||||
- License along with the GNU C Library; if not, see
|
||||
- <http://www.gnu.org/licenses/>. */
|
||||
-
|
||||
-/* This wrapper-file is needed, because otherwise file
|
||||
- sysdeps/s390/s390-[32|64]/strcpy.S will be used. */
|
||||
-#include <sysdeps/s390/multiarch/strcpy.c>
|
||||
diff --git a/sysdeps/s390/multiarch/strcpy-vx.S b/sysdeps/s390/strcpy-vx.S
|
||||
similarity index 85%
|
||||
rename from sysdeps/s390/multiarch/strcpy-vx.S
|
||||
rename to sysdeps/s390/strcpy-vx.S
|
||||
index 52197f57f7b5d5cf..844d23e4fee32c9b 100644
|
||||
--- a/sysdeps/s390/multiarch/strcpy-vx.S
|
||||
+++ b/sysdeps/s390/strcpy-vx.S
|
||||
@@ -16,13 +16,13 @@
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)
|
||||
-
|
||||
-# include "sysdep.h"
|
||||
-# include "asm-syntax.h"
|
||||
+#include <ifunc-strcpy.h>
|
||||
+#include "sysdep.h"
|
||||
+#include "asm-syntax.h"
|
||||
|
||||
.text
|
||||
|
||||
+#if HAVE_STRCPY_Z13
|
||||
/* char * strcpy (const char *dest, const char *src)
|
||||
Copy string src to dest.
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
-v17=index of zero
|
||||
-v18=part of src
|
||||
*/
|
||||
-ENTRY(__strcpy_vx)
|
||||
+ENTRY(STRCPY_Z13)
|
||||
.machine "z13"
|
||||
.machinemode "zarch_nohighgprs"
|
||||
|
||||
@@ -97,13 +97,13 @@ ENTRY(__strcpy_vx)
|
||||
.Lfound_align:
|
||||
vstl %v16,%r5,0(%r2) /* Copy characters including zero. */
|
||||
br %r14
|
||||
-END(__strcpy_vx)
|
||||
+END(STRCPY_Z13)
|
||||
|
||||
-/* Use mvst-strcpy-implementation as default implementation. */
|
||||
-# define strcpy __strcpy_c
|
||||
-# undef libc_hidden_builtin_def
|
||||
-# define libc_hidden_builtin_def(name) strong_alias(__strcpy_c, __GI_strcpy)
|
||||
-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */
|
||||
+# if ! HAVE_STRCPY_IFUNC
|
||||
+strong_alias (STRCPY_Z13, strcpy)
|
||||
+# endif
|
||||
|
||||
-/* Include mvst-strcpy-implementation in s390-32/s390-64 subdirectory. */
|
||||
-#include <strcpy.S>
|
||||
+# if ! HAVE_STRCPY_Z900_G5 && defined SHARED && IS_IN (libc)
|
||||
+strong_alias (STRCPY_Z13, __GI_strcpy)
|
||||
+# endif
|
||||
+#endif
|
||||
diff --git a/sysdeps/s390/s390-64/strcpy.S b/sysdeps/s390/strcpy-z900.S
|
||||
similarity index 66%
|
||||
rename from sysdeps/s390/s390-64/strcpy.S
|
||||
rename to sysdeps/s390/strcpy-z900.S
|
||||
index 203c73c905d0d86c..42798b1fd5c51187 100644
|
||||
--- a/sysdeps/s390/s390-64/strcpy.S
|
||||
+++ b/sysdeps/s390/strcpy-z900.S
|
||||
@@ -1,4 +1,4 @@
|
||||
-/* strcpy - copy a string from source to destination. 64 bit S/390 version.
|
||||
+/* strcpy - copy a string from source to destination. 64/31 bit S/390 version.
|
||||
Copyright (C) 2001-2018 Free Software Foundation, Inc.
|
||||
Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com).
|
||||
This file is part of the GNU C Library.
|
||||
@@ -21,15 +21,36 @@
|
||||
%r2 = address of destination
|
||||
%r3 = address of source. */
|
||||
|
||||
+#include <ifunc-strcpy.h>
|
||||
#include "sysdep.h"
|
||||
#include "asm-syntax.h"
|
||||
|
||||
+#if HAVE_STRCPY_Z900_G5
|
||||
+# if defined __s390x__
|
||||
+# define SLGR slgr
|
||||
+# define LGR lgr
|
||||
+# else
|
||||
+# define SLGR slr
|
||||
+# define LGR lr
|
||||
+# endif /* ! defined __s390x__ */
|
||||
+
|
||||
.text
|
||||
-ENTRY(strcpy)
|
||||
- slgr %r0,%r0
|
||||
- lgr %r1,%r2
|
||||
+ENTRY(STRCPY_Z900_G5)
|
||||
+ SLGR %r0,%r0
|
||||
+ LGR %r1,%r2
|
||||
0: mvst %r1,%r3
|
||||
jo 0b
|
||||
br %r14
|
||||
-END(strcpy)
|
||||
-libc_hidden_builtin_def (strcpy)
|
||||
+END(STRCPY_Z900_G5)
|
||||
+
|
||||
+# undef SLGR
|
||||
+# undef LGR
|
||||
+
|
||||
+# if ! HAVE_STRCPY_IFUNC
|
||||
+strong_alias (STRCPY_Z900_G5, strcpy)
|
||||
+# endif
|
||||
+
|
||||
+# if defined SHARED && IS_IN (libc)
|
||||
+strong_alias (STRCPY_Z900_G5, __GI_strcpy)
|
||||
+# endif
|
||||
+#endif
|
||||
diff --git a/sysdeps/s390/multiarch/strcpy.c b/sysdeps/s390/strcpy.c
|
||||
similarity index 69%
|
||||
rename from sysdeps/s390/multiarch/strcpy.c
|
||||
rename to sysdeps/s390/strcpy.c
|
||||
index 8f32a13f6730c427..f4e28e24c85b7162 100644
|
||||
--- a/sysdeps/s390/multiarch/strcpy.c
|
||||
+++ b/sysdeps/s390/strcpy.c
|
||||
@@ -16,12 +16,25 @@
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)
|
||||
+#include <ifunc-strcpy.h>
|
||||
+
|
||||
+#if HAVE_STRCPY_IFUNC
|
||||
# define strcpy __redirect_strcpy
|
||||
# include <string.h>
|
||||
# undef strcpy
|
||||
# include <ifunc-resolve.h>
|
||||
|
||||
-s390_vx_libc_ifunc2_redirected (__redirect_strcpy, __strcpy, strcpy)
|
||||
+# if HAVE_STRCPY_Z900_G5
|
||||
+extern __typeof (__redirect_strcpy) STRCPY_Z900_G5 attribute_hidden;
|
||||
+# endif
|
||||
+
|
||||
+# if HAVE_STRCPY_Z13
|
||||
+extern __typeof (__redirect_strcpy) STRCPY_Z13 attribute_hidden;
|
||||
+# endif
|
||||
|
||||
+s390_libc_ifunc_expr (__redirect_strcpy, strcpy,
|
||||
+ (HAVE_STRCPY_Z13 && (hwcap & HWCAP_S390_VX))
|
||||
+ ? STRCPY_Z13
|
||||
+ : STRCPY_DEFAULT
|
||||
+ )
|
||||
#endif
|
279
SOURCES/glibc-rh1659438-19.patch
Normal file
279
SOURCES/glibc-rh1659438-19.patch
Normal file
@ -0,0 +1,279 @@
|
||||
commit 970449311ded3cacb6058c96143dd4c057900589
|
||||
Author: Stefan Liebler <stli@linux.ibm.com>
|
||||
Date: Tue Dec 18 13:57:11 2018 +0100
|
||||
|
||||
S390: Refactor stpcpy ifunc handling.
|
||||
|
||||
The ifunc handling for stpcpy is adjusted in order to omit ifunc
|
||||
variants if those will never be used as the minimum architecture level
|
||||
already supports newer CPUs by default.
|
||||
Glibc internal calls will then also use the "newer" ifunc variant.
|
||||
|
||||
ChangeLog:
|
||||
|
||||
* sysdeps/s390/multiarch/Makefile
|
||||
(sysdep_routines): Remove stpcpy variants.
|
||||
* sysdeps/s390/Makefile (sysdep_routines): Add stpcpy variants.
|
||||
* sysdeps/s390/multiarch/ifunc-impl-list.c
|
||||
(__libc_ifunc_impl_list): Refactor ifunc handling for stpcpy.
|
||||
* sysdeps/s390/multiarch/stpcpy-c.c: Move to ...
|
||||
* sysdeps/s390/stpcpy-c.c: ... here and adjust ifunc handling.
|
||||
* sysdeps/s390/multiarch/stpcpy-vx.S: Move to ...
|
||||
* sysdeps/s390/stpcpy-vx.S: ... here and adjust ifunc handling.
|
||||
* sysdeps/s390/multiarch/stpcpy.c: Move to ...
|
||||
* sysdeps/s390/stpcpy.c: ... here and adjust ifunc handling.
|
||||
* sysdeps/s390/ifunc-stpcpy.h: New file.
|
||||
|
||||
diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile
|
||||
index e4191319531ecb01..b7e1bc8aecf2f8c9 100644
|
||||
--- a/sysdeps/s390/Makefile
|
||||
+++ b/sysdeps/s390/Makefile
|
||||
@@ -39,5 +39,6 @@ sysdep_routines += bzero memset memset-z900 \
|
||||
memmem memmem-vx memmem-c \
|
||||
strlen strlen-vx strlen-c \
|
||||
strnlen strnlen-vx strnlen-c \
|
||||
- strcpy strcpy-vx strcpy-z900
|
||||
+ strcpy strcpy-vx strcpy-z900 \
|
||||
+ stpcpy stpcpy-vx stpcpy-c
|
||||
endif
|
||||
diff --git a/sysdeps/s390/ifunc-stpcpy.h b/sysdeps/s390/ifunc-stpcpy.h
|
||||
new file mode 100644
|
||||
index 0000000000000000..9a70cd7c8c4f4582
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/s390/ifunc-stpcpy.h
|
||||
@@ -0,0 +1,52 @@
|
||||
+/* stpcpy variant information on S/390 version.
|
||||
+ Copyright (C) 2018 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#if defined USE_MULTIARCH && IS_IN (libc) \
|
||||
+ && ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT
|
||||
+# define HAVE_STPCPY_IFUNC 1
|
||||
+#else
|
||||
+# define HAVE_STPCPY_IFUNC 0
|
||||
+#endif
|
||||
+
|
||||
+#ifdef HAVE_S390_VX_ASM_SUPPORT
|
||||
+# define HAVE_STPCPY_IFUNC_AND_VX_SUPPORT HAVE_STPCPY_IFUNC
|
||||
+#else
|
||||
+# define HAVE_STPCPY_IFUNC_AND_VX_SUPPORT 0
|
||||
+#endif
|
||||
+
|
||||
+#if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT
|
||||
+# define STPCPY_DEFAULT STPCPY_Z13
|
||||
+# define HAVE_STPCPY_C 0
|
||||
+# define HAVE_STPCPY_Z13 1
|
||||
+#else
|
||||
+# define STPCPY_DEFAULT STPCPY_C
|
||||
+# define HAVE_STPCPY_C 1
|
||||
+# define HAVE_STPCPY_Z13 HAVE_STPCPY_IFUNC_AND_VX_SUPPORT
|
||||
+#endif
|
||||
+
|
||||
+#if HAVE_STPCPY_C
|
||||
+# define STPCPY_C __stpcpy_c
|
||||
+#else
|
||||
+# define STPCPY_C NULL
|
||||
+#endif
|
||||
+
|
||||
+#if HAVE_STPCPY_Z13
|
||||
+# define STPCPY_Z13 __stpcpy_vx
|
||||
+#else
|
||||
+# define STPCPY_Z13 NULL
|
||||
+#endif
|
||||
diff --git a/sysdeps/s390/multiarch/Makefile b/sysdeps/s390/multiarch/Makefile
|
||||
index 50f7f0b78df723bb..9517417dcbe1c701 100644
|
||||
--- a/sysdeps/s390/multiarch/Makefile
|
||||
+++ b/sysdeps/s390/multiarch/Makefile
|
||||
@@ -1,6 +1,5 @@
|
||||
ifeq ($(subdir),string)
|
||||
-sysdep_routines += stpcpy stpcpy-vx stpcpy-c \
|
||||
- strncpy strncpy-vx \
|
||||
+sysdep_routines += strncpy strncpy-vx \
|
||||
stpncpy stpncpy-vx stpncpy-c \
|
||||
strcat strcat-vx strcat-c \
|
||||
strncat strncat-vx strncat-c \
|
||||
diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c
|
||||
index 1784372db9828463..678ed13833332f11 100644
|
||||
--- a/sysdeps/s390/multiarch/ifunc-impl-list.c
|
||||
+++ b/sysdeps/s390/multiarch/ifunc-impl-list.c
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <ifunc-strlen.h>
|
||||
#include <ifunc-strnlen.h>
|
||||
#include <ifunc-strcpy.h>
|
||||
+#include <ifunc-stpcpy.h>
|
||||
|
||||
/* Maximum number of IFUNC implementations. */
|
||||
#define MAX_IFUNC 3
|
||||
@@ -203,6 +204,18 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
)
|
||||
#endif /* HAVE_STRCPY_IFUNC */
|
||||
|
||||
+#if HAVE_STPCPY_IFUNC
|
||||
+ IFUNC_IMPL (i, name, stpcpy,
|
||||
+# if HAVE_STPCPY_Z13
|
||||
+ IFUNC_IMPL_ADD (array, i, stpcpy,
|
||||
+ dl_hwcap & HWCAP_S390_VX, STPCPY_Z13)
|
||||
+# endif
|
||||
+# if HAVE_STPCPY_C
|
||||
+ IFUNC_IMPL_ADD (array, i, stpcpy, 1, STPCPY_C)
|
||||
+# endif
|
||||
+ )
|
||||
+#endif /* HAVE_STPCPY_IFUNC */
|
||||
+
|
||||
#ifdef HAVE_S390_VX_ASM_SUPPORT
|
||||
|
||||
# define IFUNC_VX_IMPL(FUNC) \
|
||||
@@ -217,7 +230,6 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
|
||||
IFUNC_VX_IMPL (wcscpy);
|
||||
|
||||
- IFUNC_VX_IMPL (stpcpy);
|
||||
IFUNC_VX_IMPL (wcpcpy);
|
||||
|
||||
IFUNC_VX_IMPL (strncpy);
|
||||
diff --git a/sysdeps/s390/multiarch/stpcpy-c.c b/sysdeps/s390/stpcpy-c.c
|
||||
similarity index 74%
|
||||
rename from sysdeps/s390/multiarch/stpcpy-c.c
|
||||
rename to sysdeps/s390/stpcpy-c.c
|
||||
index 4a1c3e5832c9b544..76ec88462717799c 100644
|
||||
--- a/sysdeps/s390/multiarch/stpcpy-c.c
|
||||
+++ b/sysdeps/s390/stpcpy-c.c
|
||||
@@ -16,20 +16,25 @@
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)
|
||||
-# define STPCPY __stpcpy_c
|
||||
-# undef weak_alias
|
||||
-# define weak_alias(a, b)
|
||||
-# ifdef SHARED
|
||||
-# undef libc_hidden_def
|
||||
-# define libc_hidden_def(name) \
|
||||
+#include <ifunc-stpcpy.h>
|
||||
+
|
||||
+#if HAVE_STPCPY_C
|
||||
+# if HAVE_STPCPY_IFUNC
|
||||
+# define STPCPY STPCPY_C
|
||||
+
|
||||
+# undef weak_alias
|
||||
+# define weak_alias(a, b)
|
||||
+
|
||||
+# if defined SHARED && IS_IN (libc)
|
||||
+# undef libc_hidden_def
|
||||
+# define libc_hidden_def(name) \
|
||||
__hidden_ver1 (__stpcpy_c, __GI___stpcpy, __stpcpy_c);
|
||||
-# undef libc_hidden_builtin_def
|
||||
-# define libc_hidden_builtin_def(name) \
|
||||
+# undef libc_hidden_builtin_def
|
||||
+# define libc_hidden_builtin_def(name) \
|
||||
strong_alias (__stpcpy_c, __stpcpy_c_1); \
|
||||
__hidden_ver1 (__stpcpy_c_1, __GI_stpcpy, __stpcpy_c_1);
|
||||
-# endif /* SHARED */
|
||||
-
|
||||
+# endif
|
||||
+# endif
|
||||
|
||||
# include <string/stpcpy.c>
|
||||
-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */
|
||||
+#endif
|
||||
diff --git a/sysdeps/s390/multiarch/stpcpy-vx.S b/sysdeps/s390/stpcpy-vx.S
|
||||
similarity index 90%
|
||||
rename from sysdeps/s390/multiarch/stpcpy-vx.S
|
||||
rename to sysdeps/s390/stpcpy-vx.S
|
||||
index 6c17def0fc35d60d..d2db02d0cd714d27 100644
|
||||
--- a/sysdeps/s390/multiarch/stpcpy-vx.S
|
||||
+++ b/sysdeps/s390/stpcpy-vx.S
|
||||
@@ -16,7 +16,9 @@
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)
|
||||
+#include <ifunc-stpcpy.h>
|
||||
+
|
||||
+#if HAVE_STPCPY_Z13
|
||||
|
||||
# include "sysdep.h"
|
||||
# include "asm-syntax.h"
|
||||
@@ -36,7 +38,7 @@
|
||||
-v17=index of zero
|
||||
-v18=part of src
|
||||
*/
|
||||
-ENTRY(__stpcpy_vx)
|
||||
+ENTRY(STPCPY_Z13)
|
||||
.machine "z13"
|
||||
.machinemode "zarch_nohighgprs"
|
||||
|
||||
@@ -100,5 +102,15 @@ ENTRY(__stpcpy_vx)
|
||||
vstl %v16,%r5,0(%r2) /* Copy characters including zero. */
|
||||
la %r2,0(%r5,%r2) /* Return pointer to zero. */
|
||||
br %r14
|
||||
-END(__stpcpy_vx)
|
||||
-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */
|
||||
+END(STPCPY_Z13)
|
||||
+
|
||||
+# if ! HAVE_STPCPY_IFUNC
|
||||
+strong_alias (STPCPY_Z13, __stpcpy)
|
||||
+weak_alias (__stpcpy, stpcpy)
|
||||
+# endif
|
||||
+
|
||||
+# if ! HAVE_STPCPY_C && defined SHARED && IS_IN (libc)
|
||||
+strong_alias (STPCPY_Z13, __GI_stpcpy)
|
||||
+strong_alias (STPCPY_Z13, __GI___stpcpy)
|
||||
+# endif
|
||||
+#endif
|
||||
diff --git a/sysdeps/s390/multiarch/stpcpy.c b/sysdeps/s390/stpcpy.c
|
||||
similarity index 74%
|
||||
rename from sysdeps/s390/multiarch/stpcpy.c
|
||||
rename to sysdeps/s390/stpcpy.c
|
||||
index 654f9dfbef512e34..670604e2de3806b7 100644
|
||||
--- a/sysdeps/s390/multiarch/stpcpy.c
|
||||
+++ b/sysdeps/s390/stpcpy.c
|
||||
@@ -16,7 +16,9 @@
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)
|
||||
+#include <ifunc-stpcpy.h>
|
||||
+
|
||||
+#if HAVE_STPCPY_IFUNC
|
||||
# define stpcpy __redirect_stpcpy
|
||||
# define __stpcpy __redirect___stpcpy
|
||||
/* Omit the stpcpy inline definitions because it would redefine stpcpy. */
|
||||
@@ -27,9 +29,18 @@
|
||||
# undef __stpcpy
|
||||
# include <ifunc-resolve.h>
|
||||
|
||||
-s390_vx_libc_ifunc_redirected (__redirect___stpcpy, __stpcpy);
|
||||
-weak_alias (__stpcpy, stpcpy)
|
||||
+# if HAVE_STPCPY_C
|
||||
+extern __typeof (__redirect_stpcpy) STPCPY_C attribute_hidden;
|
||||
+# endif
|
||||
|
||||
-#else
|
||||
-# include <string/stpcpy.c>
|
||||
-#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */
|
||||
+# if HAVE_STPCPY_Z13
|
||||
+extern __typeof (__redirect_stpcpy) STPCPY_Z13 attribute_hidden;
|
||||
+# endif
|
||||
+
|
||||
+s390_libc_ifunc_expr (__redirect___stpcpy, __stpcpy,
|
||||
+ (HAVE_STPCPY_Z13 && (hwcap & HWCAP_S390_VX))
|
||||
+ ? STPCPY_Z13
|
||||
+ : STPCPY_DEFAULT
|
||||
+ )
|
||||
+weak_alias (__stpcpy, stpcpy)
|
||||
+#endif
|
58
SOURCES/glibc-rh1659438-2.patch
Normal file
58
SOURCES/glibc-rh1659438-2.patch
Normal file
@ -0,0 +1,58 @@
|
||||
commit e8023f2685c9f97e72bbe9d2a9c968e0d8438371
|
||||
Author: Stefan Liebler <stli@linux.ibm.com>
|
||||
Date: Tue Dec 18 13:57:03 2018 +0100
|
||||
|
||||
S390: Use hwcap instead of dl_hwcap in ifunc-resolvers.
|
||||
|
||||
The renaming of hwcap arguments in ifunc-resolvers is needed
|
||||
in order to prepare for further commits which refactors
|
||||
ifunc handling for memset, memcmp, and memcpy. Now you are able
|
||||
to use s390_libc_ifunc_init which stores the stfle bits
|
||||
within the expression for an ifunc-resolver generated by
|
||||
s390_libc_ifunc_expr.
|
||||
|
||||
ChangeLog:
|
||||
|
||||
* sysdeps/s390/multiarch/ifunc-resolve.h
|
||||
(s390_libc_ifunc_init, s390_libc_ifunc,
|
||||
s390_vx_libc_ifunc2_redirected): Use hwcap instead of dl_hwcap.
|
||||
|
||||
diff --git a/sysdeps/s390/multiarch/ifunc-resolve.h b/sysdeps/s390/multiarch/ifunc-resolve.h
|
||||
index b42ed922fd27834b..b7e20abc59638251 100644
|
||||
--- a/sysdeps/s390/multiarch/ifunc-resolve.h
|
||||
+++ b/sysdeps/s390/multiarch/ifunc-resolve.h
|
||||
@@ -42,9 +42,9 @@
|
||||
: : "cc");
|
||||
#define s390_libc_ifunc_init() \
|
||||
unsigned long long stfle_bits = 0ULL; \
|
||||
- if (__glibc_likely((dl_hwcap & HWCAP_S390_STFLE) \
|
||||
- && (dl_hwcap & HWCAP_S390_ZARCH) \
|
||||
- && (dl_hwcap & HWCAP_S390_HIGH_GPRS))) \
|
||||
+ if (__glibc_likely ((hwcap & HWCAP_S390_STFLE) \
|
||||
+ && (hwcap & HWCAP_S390_ZARCH) \
|
||||
+ && (hwcap & HWCAP_S390_HIGH_GPRS))) \
|
||||
{ \
|
||||
S390_STORE_STFLE (stfle_bits); \
|
||||
}
|
||||
@@ -61,7 +61,7 @@
|
||||
: __glibc_likely (S390_IS_Z10 (stfle_bits)) \
|
||||
? RESOLVERFUNC##_z10 \
|
||||
: RESOLVERFUNC##_default, \
|
||||
- unsigned long int dl_hwcap, s390_libc_ifunc_init);
|
||||
+ unsigned long int hwcap, s390_libc_ifunc_init);
|
||||
|
||||
#define s390_vx_libc_ifunc(FUNC) \
|
||||
s390_vx_libc_ifunc2_redirected(FUNC, FUNC, FUNC)
|
||||
@@ -79,10 +79,10 @@
|
||||
extern __typeof (TYPE_FUNC) RESOLVERFUNC##_vx attribute_hidden; \
|
||||
extern __typeof (TYPE_FUNC) RESOLVERFUNC##_c attribute_hidden; \
|
||||
__ifunc (TYPE_FUNC, FUNC, \
|
||||
- (dl_hwcap & HWCAP_S390_VX) \
|
||||
+ (hwcap & HWCAP_S390_VX) \
|
||||
? RESOLVERFUNC##_vx \
|
||||
: RESOLVERFUNC##_c, \
|
||||
- unsigned long int dl_hwcap, s390_vx_libc_ifunc_init);
|
||||
+ unsigned long int hwcap, s390_vx_libc_ifunc_init);
|
||||
|
||||
#define s390_libc_ifunc_expr_init()
|
||||
#define s390_libc_ifunc_expr(TYPE_FUNC, FUNC, EXPR) \
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user