parent
f77bf5e050
commit
0aad2259bd
@ -1,19 +1,25 @@
|
||||
-----BEGIN PGP SIGNED MESSAGE-----
|
||||
Hash: SHA256
|
||||
Hash: SHA512
|
||||
|
||||
DIST util-linux-2.21-20120228.diff.bz2 43809 SHA256 fc28d4f0e2737b53a4db59072ab0fcf4180a8ece28c79219a21780124798572a SHA512 94135ed18699efd949f5937576da2721957177bbef9be8234ae48ee34f30f4cb65361a541f79c636ed6d6bb5c2786e1096d096407834e1421d82ee78ae0790e9 WHIRLPOOL ba23dccc56fc49d7ad9075537317ad4580ace2a4cd8f6b0250f42035c03ba910f3cafa8e8b1da4c7e5a0960d74c42f2706fda579a3b4a6cadc61dccd2fff3ff0
|
||||
DIST util-linux-2.21.tar.xz 2954504 SHA256 5192e8ba7dcf3cf0dc447f07b3d177f6cb3fb49dfae54ac45d6c8c7d86eeab0f SHA512 aab384db2d1a3e08fd560a3e4d7ed7d6b2ceac61386db94eecae65bd540200a8549e141b99d8dad5c6f96587940b574d0544984acef6a35d1f24870e0072c552 WHIRLPOOL 1968ddd63fd21ef9542bb8afc77292ed2bad6f83e1cd67aa4159db8b320abd80ee0d20a062df35ae2ad91e0bc9068168b9f9e44aa39eaf4861d436dd855bea5d
|
||||
EBUILD loop-aes-losetup-2.21.ebuild 2733 SHA256 742967336a6c91a8489d9fd1118155b59402c24fce8acb73bd5e05ed7c5948e9 SHA512 3aa0ac5e9c48daab2f9f6ab0f82776e2456c44b0a201d092c0e960508717387c5aeae12397d8dc142d12920f974a3db7fe87fd6f89c6dda03c78c422846b3e82 WHIRLPOOL f511712ada4f9d3504e5b3a9b21284f89549625cef9bbb2591c8d6d8ed273195ed787cd38e71a8ae6c7c2b604ea85bff71975a036b2f396b0e6824e328e0c606
|
||||
MISC ChangeLog 487 SHA256 1c1a0c63fea9c287307a4b761c2585d5d332f0fa6fdad43e4c0abb6223ccda41 SHA512 d3a5219326dce54659aeeefaf22c4259f8102f9c27ff29afc928cfdb0cc73461e933537a3e48477731644b9c66dfd1f0362b30390c7ff86cb8d38e35a28d11d3 WHIRLPOOL af29af8fac83ef8d7ac76ae10fdfff202a466867c05addbd320b8d5d3f05e84b4590e898bac1b3dcc51b830aa03481f64e929d6bb1d80dafdd1903a116e1e2dd
|
||||
EBUILD loop-aes-losetup-2.21.ebuild 2729 SHA256 a7bba6de71634012c28d61e1cd2d59410fefa09768fc3ba3f93c9a82da885960 SHA512 9ac55705b8b538df00c46f64d957f5623c6b7492ccc08827ace10ff7f22a0575d2152fdf8cf62857482b19cfaf46832590f0b34cb06af43a6251dee994545b90 WHIRLPOOL cb9fdeac7417632acd7210f2805593d554b03519818ad6e84bc92dc983d81ce54729305735ebb915e58858c946c9b09b8e11e7a791a84302e294e286949bb37b
|
||||
MISC ChangeLog 598 SHA256 64811ea369ed36858eb91ce0b7d503b01e30f194f924e52ad94ebaf0e11cee4b SHA512 17305e07569d2cd5e6f3264fc580ad430a816106582a2bdd97a3b31891d59b28c3d80f7af8b6067ec5acb579c1ceb045cc99d75535971735ffde7f805793e682 WHIRLPOOL 7b3083ff2067d169e0b2d13c044ffdce9912379eef9616773fc722d066bdfaef30770a8c964a48c9d128e031af4312e2462d4dc51ca194b5eb484d12c9171aa5
|
||||
MISC metadata.xml 160 SHA256 7419f4e73ddd07284403525f1380824fc68280cad69e2dfae0645ad52b33ef10 SHA512 bfec8d424a118209f298dd88f7073aaaf6e1ad49f67a441817313a6fa525a0d228241dfb1ccd8dae45e1192db9712b1d5e9cf053f9f398eff5c17089373e7104 WHIRLPOOL 47a9e0b778a140714a565acf9db6bd59e11732af1f4cbb86af0beb36a8a9d77a29f0a875aa24537387ffe6e3143724a59cc60a0d93cf7870fd47e511d17c3de5
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
Version: GnuPG v2.0.20 (GNU/Linux)
|
||||
|
||||
iQEcBAEBCAAGBQJRuiRVAAoJEA2sAkrWKOU2rkgIAJ26BdMBCbxXndmo2z1Ml5az
|
||||
7H0ICyOmkggUfi4y5QLJCJipx2DJx9VxKelBr1Pm0VGzBmV3l/z5tePyXawtTQz6
|
||||
0xNG45lxElHFDWx/u3V69YYOpoIo+svE5uZPrWeZ9rVJOB502JhEYZknv/4LSgnc
|
||||
/s+EtfmDYwdxY1nZm0njzDBPfa6kl9kS8JZO5dfcXJiRKllQMkM4ZrOlXlu+1Leq
|
||||
OIx3lGSV+sG6BkISkkJOX5jRbLLhW3KfE/iXFo2VsaqqkXWh4c35kRbW6cT5FHw6
|
||||
w0KXJVLq2Z+5d21vgxaEB3no7izLlcZrnoK28oued6r9rhxeHFWsAhsi7AyRP/Q=
|
||||
=9JKX
|
||||
iQIcBAEBCgAGBQJRytWdAAoJELp701BxlEWfzMcQALKc632YT4Xd4XfQClEez7GX
|
||||
gBvnNCvJsjkOr0GMx3E5HSUPUouvPOjpgjZbxcbv1BaVzxAUiM/uxAKv1OYbmqSa
|
||||
2qTzLMRBoJ9awHGYZXQu4UEh5JzjnW/4CBajj14MO3KGyVwIcI8LTBX51RXj4bLK
|
||||
3gV54JYKSqXV06ld7R+53IHGFrHs/fIDulXC3HY8bLDi+qKujTRqkOKs6UleDNLw
|
||||
rtdhRslB19BtUyTQgCiM+Ge2ny25M072OrodVulDHHMACoGqJZdhS/NiJq32b0nV
|
||||
uuDOuMs8VZOWTsyIys8uMqHwkndQap5KGHfQHkqIVJ51Gxg5a5AQuiaCV0xg9CZF
|
||||
KTufr9fXwpDJvWNEmH2BwOCfrB5e05VTpZqJAmW2c8wYwkLdTybNn2YQsN6ofufQ
|
||||
b9vtplIEuRrO/nJptU1WoWoFPps26h5BH8STZY9mdW+vSRmkfYkMxGS+b5WiII7v
|
||||
d3Yb+62Np6Mm7QQTfvjsKG1tTOJefnXWURzqyK5gwaFpbLxJGzks3A06tsvAQuEd
|
||||
x9m3NY/Rl7j8HVicenDSHsFAvgwImEQcso9rsf5jmAqoncWzQJiH3j27Dyb4vCoA
|
||||
nxGfVMrFisJMXewsLRBkRMOXNjh0BnMpqLwfTJ2BL3BA4owv5VVX66sr/q1Fuq4A
|
||||
3iKGf1SKL3lh3fVra5Fy
|
||||
=UEDh
|
||||
-----END PGP SIGNATURE-----
|
||||
|
@ -1,240 +0,0 @@
|
||||
# Copyright 1999-2013 Gentoo Foundation
|
||||
# Distributed under the terms of the GNU General Public License v2
|
||||
# $Header: /var/cvsroot/gentoo-x86/app-doc/doxygen/doxygen-1.8.4.ebuild,v 1.1 2013/05/19 15:47:07 xarthisius Exp $
|
||||
|
||||
EAPI=4
|
||||
|
||||
PYTHON_COMPAT=( python{2_5,2_6,2_7} )
|
||||
inherit eutils fdo-mime flag-o-matic python-any-r1 qt4-r2 toolchain-funcs
|
||||
|
||||
DESCRIPTION="Documentation system for most programming languages"
|
||||
HOMEPAGE="http://www.doxygen.org/"
|
||||
SRC_URI="http://ftp.stack.nl/pub/users/dimitri/${P}.src.tar.gz
|
||||
http://dev.gentoo.org/~xarthisius/distfiles/doxywizard.png"
|
||||
|
||||
LICENSE="GPL-2"
|
||||
SLOT="0"
|
||||
KEYWORDS="~alpha ~amd64 ~arm ~hppa ~ia64 ~ppc ~ppc64 ~s390 ~sh ~sparc ~x86 ~amd64-fbsd ~x86-fbsd ~x86-freebsd ~amd64-linux ~x86-linux ~ppc-macos ~x86-macos ~x86-solaris"
|
||||
IUSE="debug doc dot qt4 latex sqlite elibc_FreeBSD userland_GNU"
|
||||
|
||||
#missing SerbianCyrilic, JapaneseEn, KoreanEn, Chinesetraditional
|
||||
|
||||
LANGS=(hy ar pt_BR ca zh cs de da eo es fa fi fr el hr hu id it ja ko lt mk
|
||||
nl nb pl pt ro ru sl sk sr sv tr uk vi af)
|
||||
for X in "${LANGS[@]}" ; do
|
||||
IUSE="${IUSE} linguas_${X}"
|
||||
done
|
||||
|
||||
RDEPEND="qt4? ( dev-qt/qtgui:4 )
|
||||
latex? ( app-text/texlive[extra] )
|
||||
dev-lang/perl
|
||||
virtual/libiconv
|
||||
media-libs/libpng
|
||||
app-text/ghostscript-gpl
|
||||
sqlite? ( dev-db/sqlite:3 )
|
||||
dot? (
|
||||
media-gfx/graphviz
|
||||
media-libs/freetype
|
||||
)"
|
||||
|
||||
DEPEND="sys-apps/sed
|
||||
sys-devel/flex
|
||||
sys-devel/bison
|
||||
doc? ( ${PYTHON_DEPS} )
|
||||
${RDEPEND}"
|
||||
|
||||
RESTRICT="mirror"
|
||||
EPATCH_SUFFIX="patch"
|
||||
|
||||
get_langs() {
|
||||
# using only user set linguas also fixes #263641
|
||||
my_linguas=()
|
||||
for lingua in ${LINGUAS}; do
|
||||
if has ${lingua} "${LANGS[@]}"; then
|
||||
case ${lingua} in
|
||||
hy) lingua=am ;;
|
||||
pt_BR) lingua=br ;;
|
||||
zh*) lingua=cn ;;
|
||||
cs) lingua=cz ;;
|
||||
da) lingua=dk ;;
|
||||
el*) lingua=gr ;;
|
||||
ja*) lingua=jp ;;
|
||||
ko) lingua=kr ;;
|
||||
nb) lingua=no ;;
|
||||
sl) lingua=si ;;
|
||||
tr*) lingua=tr ;;
|
||||
uk) lingua=ua ;;
|
||||
af) lingua=za ;;
|
||||
esac
|
||||
has ${lingua} "${my_linguas[@]}" ||
|
||||
my_linguas+=(${lingua})
|
||||
fi
|
||||
done
|
||||
f_langs="${my_linguas[@]}"
|
||||
echo ${f_langs// /,}
|
||||
}
|
||||
|
||||
pkg_setup() {
|
||||
tc-export CC CXX
|
||||
use doc && python-any-r1_pkg_setup
|
||||
}
|
||||
|
||||
src_prepare() {
|
||||
# use CFLAGS, CXXFLAGS, LDFLAGS
|
||||
export ECFLAGS="${CFLAGS}" ECXXFLAGS="${CXXFLAGS}" ELDFLAGS="${LDFLAGS}"
|
||||
|
||||
sed -i.orig -e 's:^\(TMAKE_CFLAGS_RELEASE\t*\)= .*$:\1= $(ECFLAGS):' \
|
||||
-e 's:^\(TMAKE_CXXFLAGS_RELEASE\t*\)= .*$:\1= $(ECXXFLAGS):' \
|
||||
-e 's:^\(TMAKE_LFLAGS_RELEASE\s*\)=.*$:\1= $(ELDFLAGS):' \
|
||||
-e "s:^\(TMAKE_CXX\s*\)=.*$:\1= $(tc-getCXX):" \
|
||||
-e "s:^\(TMAKE_LINK\s*\)=.*$:\1= $(tc-getCXX):" \
|
||||
-e "s:^\(TMAKE_LINK_SHLIB\s*\)=.*$:\1= $(tc-getCXX):" \
|
||||
-e "s:^\(TMAKE_CC\s*\)=.*$:\1= $(tc-getCC):" \
|
||||
-e "s:^\(TMAKE_AR\s*\)=.*$:\1= $(tc-getAR) cqs:" \
|
||||
tmake/lib/{{linux,gnu,freebsd,netbsd,openbsd,solaris}-g++,macosx-c++,linux-64}/tmake.conf \
|
||||
|| die
|
||||
|
||||
# Ensure we link to -liconv
|
||||
if use elibc_FreeBSD; then
|
||||
for pro in */*.pro.in */*/*.pro.in; do
|
||||
echo "unix:LIBS += -liconv" >> "${pro}"
|
||||
done
|
||||
fi
|
||||
|
||||
# Call dot with -Teps instead of -Tps for EPS generation - bug #282150
|
||||
sed -i -e '/addJob("ps"/ s/"ps"/"eps"/g' src/dot.cpp || die
|
||||
|
||||
# prefix search tools patch, plus OSX fixes
|
||||
epatch "${FILESDIR}"/${PN}-1.8.1-prefix-misc-alt.patch
|
||||
epatch "${FILESDIR}"/${PN}-1.8.3.1-empty-line-sigsegv.patch #454348
|
||||
|
||||
# fix final DESTDIR issue
|
||||
sed -i.orig -e "s:\$(INSTALL):\$(DESTDIR)/\$(INSTALL):g" \
|
||||
-e "s/all: Makefile.doxywizard/all:/g" \
|
||||
addon/doxywizard/Makefile.in || die
|
||||
|
||||
# fix pdf doc
|
||||
sed -i.orig -e "s:g_kowal:g kowal:" \
|
||||
doc/maintainers.txt || die
|
||||
|
||||
sed -e "s/\$(DATE)/$(LC_ALL="C" LANG="C" date)/g" \
|
||||
-i Makefile.in || die #428280
|
||||
|
||||
if is-flagq "-O3" ; then
|
||||
echo
|
||||
ewarn "Compiling with -O3 is known to produce incorrectly"
|
||||
ewarn "optimized code which breaks doxygen."
|
||||
echo
|
||||
elog "Continuing with -O2 instead ..."
|
||||
echo
|
||||
replace-flags "-O3" "-O2"
|
||||
fi
|
||||
}
|
||||
|
||||
src_configure() {
|
||||
# set ./configure options (prefix, Qt based wizard, docdir)
|
||||
|
||||
local my_conf="--shared --enable-langs $(get_langs)"
|
||||
|
||||
if use debug ; then
|
||||
my_conf="${my_conf} --debug"
|
||||
else
|
||||
my_conf="${my_conf} --release "
|
||||
fi
|
||||
|
||||
use ppc64 && my_conf="${my_conf} --english-only" #263641
|
||||
|
||||
use qt4 && my_conf="${my_conf} --with-doxywizard"
|
||||
|
||||
use sqlite && my_conf="${my_conf} --with-sqlite3"
|
||||
|
||||
# On non GNU userland (e.g. BSD), configure script picks up make and bails
|
||||
# out because it is not GNU make, so we force the right value.
|
||||
use userland_GNU || my_conf="${my_conf} --make ${MAKE} --install install"
|
||||
|
||||
export LINK="${QMAKE_LINK}"
|
||||
export LINK_SHLIB="${QMAKE_CXX}"
|
||||
|
||||
if use qt4 ; then
|
||||
pushd addon/doxywizard &> /dev/null
|
||||
eqmake4 doxywizard.pro -o Makefile.doxywizard
|
||||
popd &> /dev/null
|
||||
fi
|
||||
|
||||
./configure --prefix "${EPREFIX}/usr" ${my_conf} \
|
||||
|| die
|
||||
}
|
||||
|
||||
src_compile() {
|
||||
|
||||
emake CFLAGS+="${ECFLAGS}" CXXFLAGS+="${ECXXFLAGS}" \
|
||||
LFLAGS+="${ELDFLAGS}" all
|
||||
|
||||
# generate html and pdf (if tetex in use) documents.
|
||||
# errors here are not considered fatal, hence the ewarn message
|
||||
# TeX's font caching in /var/cache/fonts causes sandbox warnings,
|
||||
# so we allow it.
|
||||
if use doc; then
|
||||
if ! use dot; then
|
||||
sed -i -e "s/HAVE_DOT = YES/HAVE_DOT = NO/" \
|
||||
{Doxyfile,doc/Doxyfile} \
|
||||
|| ewarn "disabling dot failed"
|
||||
fi
|
||||
if use latex; then
|
||||
addwrite /var/cache/fonts
|
||||
addwrite /var/cache/fontconfig
|
||||
addwrite /usr/share/texmf/fonts/pk
|
||||
addwrite /usr/share/texmf/ls-R
|
||||
make pdf || ewarn '"make pdf docs" failed.'
|
||||
else
|
||||
cp doc/Doxyfile doc/Doxyfile.orig
|
||||
cp doc/Makefile doc/Makefile.orig
|
||||
sed -i.orig -e "s/GENERATE_LATEX = YES/GENERATE_LATEX = NO/" \
|
||||
doc/Doxyfile
|
||||
sed -i.orig -e "s/@epstopdf/# @epstopdf/" \
|
||||
-e "s/@cp Makefile.latex/# @cp Makefile.latex/" \
|
||||
-e "s/@sed/# @sed/" doc/Makefile
|
||||
make docs || ewarn '"make docs" failed.'
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
src_install() {
|
||||
emake DESTDIR="${D}" MAN1DIR=share/man/man1 install
|
||||
|
||||
if use qt4; then
|
||||
doicon "${DISTDIR}/doxywizard.png"
|
||||
make_desktop_entry doxywizard "DoxyWizard ${PV}" \
|
||||
"/usr/share/pixmaps/doxywizard.png" \
|
||||
"Development"
|
||||
fi
|
||||
|
||||
dodoc INSTALL LANGUAGE.HOWTO README
|
||||
|
||||
# pdf and html manuals
|
||||
if use doc; then
|
||||
dohtml -r html/*
|
||||
use latex && dodoc latex/doxygen_manual.pdf
|
||||
fi
|
||||
}
|
||||
|
||||
pkg_postinst() {
|
||||
fdo-mime_desktop_database_update
|
||||
|
||||
elog
|
||||
elog "The USE flags qt4, doc, and latex will enable doxywizard, or"
|
||||
elog "the html and pdf documentation, respectively. For examples"
|
||||
elog "and other goodies, see the source tarball. For some example"
|
||||
elog "output, run doxygen on the doxygen source using the Doxyfile"
|
||||
elog "provided in the top-level source dir."
|
||||
elog
|
||||
elog "Disabling the dot USE flag will remove the GraphViz dependency,"
|
||||
elog "along with Doxygen's ability to generate diagrams in the docs."
|
||||
elog "See the Doxygen homepage for additional helper tools to parse"
|
||||
elog "more languages."
|
||||
elog
|
||||
}
|
||||
|
||||
pkg_postrm() {
|
||||
fdo-mime_desktop_database_update
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
Fix inifite loop
|
||||
|
||||
https://bugs.gentoo.org/show_bug.cgi?id=474716
|
||||
https://bugzilla.gnome.org/show_bug.cgi?id=701295
|
||||
|
||||
Patch written by Dimitri van Heesch <dimitri@stack.nl>
|
||||
|
||||
--- a/src/util.cpp
|
||||
+++ b/src/util.cpp
|
||||
@@ -1843,11 +1843,15 @@ int findParameterList(const QString &name)
|
||||
++templateDepth;
|
||||
pos=nextOpenPos-1;
|
||||
}
|
||||
- else
|
||||
+ else if (nextClosePos!=-1)
|
||||
{
|
||||
--templateDepth;
|
||||
pos=nextClosePos-1;
|
||||
}
|
||||
+ else // more >'s than <'s, see bug701295
|
||||
+ {
|
||||
+ return -1;
|
||||
+ }
|
||||
}
|
||||
else
|
||||
{
|
@ -1,20 +1,18 @@
|
||||
-----BEGIN PGP SIGNED MESSAGE-----
|
||||
Hash: SHA256
|
||||
|
||||
AUX remove-native 280 SHA256 0369a057114cb5a4e240600ebab3f8ba8036cdca169a64faebf45c91547e9ede SHA512 35717cfc8a69d8b9d022c8ca6b984fafb56a1b49b4a8a3d7d569f5966e481520cf99f5ec75ab7916b00a29570822e4cc78782cc589e13d43485c04c0db82038d WHIRLPOOL 6b17b22f01f19d2d54abd28a282e211c4556b6429e7fe56de7eaf81fe555b134b0a275fd4f5ffe4e42ba9a38c875d207d0748ee0d4296dd8188c83bb5390619a
|
||||
DIST emul-linux-x86-medialibs-20121202.tar.xz 10366156 SHA256 87a7adbf1587d357c74372c33cdb5a8a22f201943ef57dab7ed56492770830dd SHA512 f46c514d15b95da0657fc9fb1c852a93d60aeb35d4532ce2dd66481b22911ba8f8e504879a02f9840b3cd4bf40f0732b291e0fe7d5085a7f409fe9c529569a4c WHIRLPOOL 0a286593163d87c6b9f8efc5629cf9b037923f05af82bf12591e1f1d0a3fdf3fc95f13950f15f49b21871886018dd4d171ec3e5d6b442d8ee02ba883923936e2
|
||||
DIST emul-linux-x86-medialibs-20130224.tar.xz 10416488 SHA256 a23696b51754cb838227bf24c81a785b980ad8b492a58b80623004d4634d2ed1 SHA512 56a17ec80c583f10e6754ce0101182d2d6895637b09cb3c3963663b8d3387f86de9d7ba07a7a880c22007ebc42dcfde2f63318a487825b38f4b1d1f1b15041a3 WHIRLPOOL 5d18b4fba7f24ea5fc6b212e2d67b04bfee3a8d80de11c5a53d7c684c94b0227b644e8b3f5ae420fbdd3e0b91fa818be757bb0ddbd7858d0eff1902e23d74f57
|
||||
EBUILD emul-linux-x86-medialibs-20121202.ebuild 815 SHA256 0f3a03243a1df921ec40e2671981b6f324a7ff8aa144c28b4d15dd28cbe6e7ef SHA512 7dbe3cf512760b81e7f679a3af89a0f2c16f745c5cd63e9bb9a6ac9ecd44b8cdac331c507a126f11ae0692f37e7cd55b50dad7017e5851c87f123cf49bcd344e WHIRLPOOL 70bc018e88786b34ac3997f4bfe9d29a212fcb2b3015fc17a4bdb502d9ce7a3b0abdcadfe9154f5cfc234a901e56b6e281090b578c342392636adaec36e24f5a
|
||||
EBUILD emul-linux-x86-medialibs-20130224-r1.ebuild 1127 SHA256 851183588689a48981a3a199cd53e9c4322d8cf0241a7d9b84de2f1b7d95dd93 SHA512 2798539b3687a56db3d0aef44e125b09e1d112d5f4bf6b7a320cc49824c65754e1f8ee3d34bafdf558f0310c75599564bfe5153d5d1cc4782251d777fb2790d7 WHIRLPOOL e131608165e4b20d32f3d3b9a6e013a0cd62122cf71ca15988ff0e0aff924c8d0b0916ae0a0e36d0604ddcf31e1332ebcdfea06d496dbb655c77efe1f63a0a70
|
||||
EBUILD emul-linux-x86-medialibs-20130224.ebuild 862 SHA256 67b65c3b1df77b3a800f2317bab2c7322fa5c4656e708fe02851f2d33c5c5a50 SHA512 a121ed6e95d965a5d803829e990242300f6b4dfa49e2d3acc07436e580f468fa40b03a5a7362fe59fa01145e88a3890aea2024d0936168b421713ef203556394 WHIRLPOOL bd543f51049295b92ce8b4bb2f3523b7ac87f5088f0cd0983080f691862a32ab162946418b913bc05298daaeaadeba4b799d6b8a264ef0f2ec2e065def969e1a
|
||||
MISC ChangeLog 12083 SHA256 b33ca4414405a92e822a159c6f2115b240625587a55e82d4b334fdb0c4a09b8b SHA512 1aec2484b11726365327db1e477013a520b9a9e592aae9e1b82bce0a6900fcc1095e0fdd946a1eac94a5761a68995849848af2b6d01e4d8e2d0d0ec7a07d439c WHIRLPOOL be2dd13fd9c6b0bf7be8fd78859afd7dcf60d3d5c8b8e3d0073d8c05f6b5a0c0acb18755aa6aafe74cdfbb3a7c7eb3f9be538a2e7e27c82d22e6b564d6c53fd9
|
||||
MISC ChangeLog 12475 SHA256 823acc02f151bd5fee4e53f2736255bb9c596a5fe8f38632e9f1f46d8aa1968a SHA512 d351c379f5caf2ef6241398cdd97b42f2cabe436cbdbcebf046dc64b48eaeff7307c5036ec4fbf7c936547b1109ff867efd8341fd20da409cef2dce63a4efb95 WHIRLPOOL aa6b0dcea263cc4967ec502f72cba908b14c12232269f76d1cb1be46ccae8c36ae8fb267c3d1d3a6a41b7869398b65dc19e0707b09f2684ec589da42a1b174f7
|
||||
MISC metadata.xml 225 SHA256 0ce288a649a1cbdf01d699a90300d341736ab0fd3456fd1002e2ffa8d409f453 SHA512 924fc3abc73e518a76ae8255dc51a98e2a96c5e0312b15a3b5f12e278b2b4345d0de8a7a2eb91dbad0b9e55e2c38ccc215fac8b07ff73ccd2fd9843e68531cf5 WHIRLPOOL 9ecaf784ea9cc1ae7e81cead25eb99cff6f61247a2f33ccf27782ddb17c2642f63a6892b9b664015d4f278469b2c8ef93b9f69b9a6d1f15cfcc55ce41451c503
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
Version: GnuPG v2.0.19 (GNU/Linux)
|
||||
Version: GnuPG v2.0.20 (GNU/Linux)
|
||||
|
||||
iQEcBAEBCAAGBQJRRKQ+AAoJEEdUh39IaPFNciAH/2/8v2yhjEJaCVAYKifS/94w
|
||||
Y2Zq9qcqg6VEs8Vkk0Ozj4xZvZTvc8h7vz5cYCQdgtXGmpVSXGabudR9Ue1pkppw
|
||||
F1skhGQwxQ0tlvH6qe/97VYbo0a2524iMBakdhZOz45zxeiBnOGWJqk/OWYcWceI
|
||||
6Lksv+CfLwl06l+AZj+gykU8gWC6Z16OuoSCXSjAr2uP8xmS9ECbCS9vAmS9GKdf
|
||||
ItT84SrOwzgmLV3Mmsae7t3AHIgdwFjO7jsgMq4oY+5b/XBGmKdNv5Eqo8D0CETb
|
||||
njNJahe1ifAdjxF+GWERkiA3kIUb/QCBeMkyaLrsrVuTTzhFRfqZxHc1c3rvDxg=
|
||||
=Bpn+
|
||||
iEYEAREIAAYFAlHLKJUACgkQvFcC4BYPU0rmdQCgr5uISRrO+A5UpC/lTmJ2lWtH
|
||||
fGgAoJ48P5AAn7XHdP9X8iXMm93lr1FH
|
||||
=0/0F
|
||||
-----END PGP SIGNATURE-----
|
||||
|
@ -0,0 +1,34 @@
|
||||
# Copyright 1999-2013 Gentoo Foundation
|
||||
# Distributed under the terms of the GNU General Public License v2
|
||||
# $Header: /var/cvsroot/gentoo-x86/app-emulation/emul-linux-x86-medialibs/emul-linux-x86-medialibs-20130224-r1.ebuild,v 1.1 2013/06/26 17:24:26 aballier Exp $
|
||||
|
||||
EAPI=5
|
||||
inherit emul-linux-x86
|
||||
|
||||
LICENSE="APL-1.0 GPL-2 BSD BSD-2 public-domain LGPL-2 MPL-1.1 LGPL-2.1 MPEG-4"
|
||||
KEYWORDS="-* ~amd64"
|
||||
IUSE="abi_x86_32"
|
||||
|
||||
DEPEND=""
|
||||
RDEPEND="~app-emulation/emul-linux-x86-baselibs-${PV}
|
||||
~app-emulation/emul-linux-x86-xlibs-${PV}
|
||||
~app-emulation/emul-linux-x86-db-${PV}
|
||||
!<=app-emulation/emul-linux-x86-sdl-20081109
|
||||
!<=app-emulation/emul-linux-x86-soundlibs-20110101
|
||||
!>=media-libs/libv4l-0.8.9-r1[abi_x86_32]
|
||||
abi_x86_32? (
|
||||
>=media-libs/libvpx-1.2.0_pre[abi_x86_32(-)]
|
||||
>=media-libs/xvid-1.3.2-r1[abi_x86_32(-)]
|
||||
>=media-sound/lame-3.99.5-r1[abi_x86_32(-)]
|
||||
)
|
||||
"
|
||||
PDEPEND="~app-emulation/emul-linux-x86-soundlibs-${PV}"
|
||||
|
||||
src_prepare() {
|
||||
# Include all libv4l libs, bug #348277
|
||||
ALLOWED="${S}/usr/lib32/libv4l/"
|
||||
emul-linux-x86_src_prepare
|
||||
|
||||
# Remove migrated stuff.
|
||||
use abi_x86_32 && rm -f $(cat "${FILESDIR}/remove-native")
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
usr/lib32/libxvidcore.so
|
||||
usr/lib32/libxvidcore.so.4
|
||||
usr/lib32/libxvidcore.so.4.3
|
||||
usr/lib32/libmp3lame.so
|
||||
usr/lib32/libmp3lame.so.0
|
||||
usr/lib32/libmp3lame.so.0.0.0
|
||||
usr/lib32/libvpx.so
|
||||
usr/lib32/libvpx.so.1
|
||||
usr/lib32/libvpx.so.1.0
|
||||
usr/lib32/libvpx.so.1.0.0
|
||||
usr/lib32/pkgconfig/vpx.pc
|
@ -1,16 +1,18 @@
|
||||
-----BEGIN PGP SIGNED MESSAGE-----
|
||||
Hash: SHA256
|
||||
|
||||
AUX remove-native 627 SHA256 68c9e0a29a2c2b63b6ce1fdcbed8860f38f22392b8701db97919e2884dc88310 SHA512 e04d5f72fbe93a337a867716eebdc2d0784e97a04bd57c0a371e2e19775e57a05d5f36f3eba90a77796a97461abfb243f002182eff650ebb83e2ffe4a82c45e7 WHIRLPOOL a222439f71723f083fe13747b234a108073f7576842b5f2aa351ef9909201fe9500e02862cda750149ae5ec6bf476d5cb00930351349aea870021d48aa796e59
|
||||
DIST emul-linux-x86-soundlibs-20121202.tar.xz 7097624 SHA256 f14db6acdf2203be725bf921756ae476e258f18ee93da366dd37f28443fc0f97 SHA512 96b10cfcb9144eb9e59df2935eeebf3b099390bbbdf9a03691f1edb19dc367397a906f495c00e9f05f173c2d09ba1ea45bae99d0f9aaa8ecae09371de576d298 WHIRLPOOL 78bcea03b0a1c4239c360adf7e7dc8430c3a87dee5814986ef20e18bfdc1e0d962a75a1b3295bc8b73858d10201ba174612e42af26fee7d560577b63ceb6138c
|
||||
DIST emul-linux-x86-soundlibs-20130224.tar.xz 7068240 SHA256 51ee669fb864b8522cd9ffa4aa8148c20eb07c06623a8c0bd718d444867da92a SHA512 67bca8c875e17bb8e1b3057182d08c679992ce525e124162e02e8a2c01bb5413d7ab19736a9f803d8a3835e7c5d68e556de9d3aee7240fb6708d2f3528ae56e0 WHIRLPOOL 48b9583dd91d5b1dbb4dedc1c9f5bf2937a325adad20bb45adf7de96e5d1db6a3e62a617ef85300c917faf57313a00790007d12db3a6dc9261ef627c71f14d9a
|
||||
EBUILD emul-linux-x86-soundlibs-20121202.ebuild 751 SHA256 fbc0ac6dc9ab8be17b458cddfd395eb9c4e77b858d567630c4cf6613b158fdbf SHA512 f4f4cc63c8f8ea2f2884697956a098efb8825e076619e563f5644fb9ef77d5f408a5beaa5a2355f19ad14ebf28e1830ba9bc8d8020d2337ffa03ebd3cf553c2a WHIRLPOOL c3c0546bf138432f5f0908a56f3c994d201c7a9bac10576ba75e5a8562cef65ad5557fd710232690d7458fa8887371b3a3d331d5bb40f21695b19ba1ad77fc86
|
||||
EBUILD emul-linux-x86-soundlibs-20130224-r1.ebuild 1108 SHA256 668fe1a2958b1584d594c68627507849220f4fc7d387328914cb01e45bb0f7bf SHA512 978938985ab422898965a74c53bd5ac9b73cb5a83e38e51cb95113f4d6ad7df91c80923decb2d1f647c9cedfc9c77350c9085e817e3bae9c152a7156fb608ec2 WHIRLPOOL 86ed66ddac857f7ac712800c3003b5d6a1a1e51f0b8b6dd38f4adbf0fe25a9ccdb23492542ed2d3e954a97d334488d1c998ba5575378641993cc0e4cc8422892
|
||||
EBUILD emul-linux-x86-soundlibs-20130224.ebuild 796 SHA256 820c1ff543ca0d4756ce6201ea6d92422fe86813cc0451dd8a417f55fa5789f9 SHA512 04c9297c4c1fe3e3058bb11fa15bc2088cbf3bb838a0fe6ca306b4918164beb5a0764f758391b846063ca0ab596aecc70388b3b9c0639a5a335cf5df9ae249c1 WHIRLPOOL f56fb097e6bfdccb54b664df82deb0bc1fd7e528dcfce7e6d9b486ff86bedfa3fa5a8a8038854f9af093490c958292e5bc6e0e5f200b9c01ad2877e11b187f3f
|
||||
MISC ChangeLog 16854 SHA256 4d6d689e0404d697b46afdd8cf415a4848a889bfea646b3d0fe8bae17bff9ddd SHA512 b13a5cb2ce650526c45f753619df7ae6e1f1ba14f9f27861fa8f2cc164f54094a00a46f642abb25f90dfbaf5bc315eb3cc89cd18a3b60893a88c8b396c2edc7f WHIRLPOOL 5e27bf72efa7ffb313792c26a4dd05ce72a0111d01a12b404b0b24940b0f5246493123198dc6c8880f4b73d0c76eef8a2ad7f46e82dc106472194a64c396018c
|
||||
MISC ChangeLog 17195 SHA256 2ed6ff66a191c08dafd64b47da2134433bf8570964bedcc21258cbaa24592f16 SHA512 08f2b15fac791b64fcae1bdfff44dae314825d278e6373dfec0df798c7c04ea92193c1269f49539283c9f62becc8f7d5e1388bef1dda5da9747847edc1c998c3 WHIRLPOOL fe4b3d2bbafd78d68016f5dc2e22e485dae7a77eb0c62d532fe174eaa9e0d5564227bb18be4a273bcbd6ed25df01278654d4c92cb2c5ef1eaeae0225a12fb84a
|
||||
MISC metadata.xml 225 SHA256 0ce288a649a1cbdf01d699a90300d341736ab0fd3456fd1002e2ffa8d409f453 SHA512 924fc3abc73e518a76ae8255dc51a98e2a96c5e0312b15a3b5f12e278b2b4345d0de8a7a2eb91dbad0b9e55e2c38ccc215fac8b07ff73ccd2fd9843e68531cf5 WHIRLPOOL 9ecaf784ea9cc1ae7e81cead25eb99cff6f61247a2f33ccf27782ddb17c2642f63a6892b9b664015d4f278469b2c8ef93b9f69b9a6d1f15cfcc55ce41451c503
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
Version: GnuPG v2.0.19 (GNU/Linux)
|
||||
Version: GnuPG v2.0.20 (GNU/Linux)
|
||||
|
||||
iEYEAREIAAYFAlFEjowACgkQCaWpQKGI+9RNoQCeNzPdl25UBEUJ4vNen6wjr3AJ
|
||||
AyYAnR2SYF3K/Tj9z5TXBya2Uc5CPMOz
|
||||
=yvTj
|
||||
iEYEAREIAAYFAlHLMIAACgkQvFcC4BYPU0qlcQCgjeyKTnVWnm4hzHKIQ3de2YZ4
|
||||
7yEAoLLRmmsVNJKZv0NcOvrrmimdgej6
|
||||
=JiT6
|
||||
-----END PGP SIGNATURE-----
|
||||
|
@ -0,0 +1,36 @@
|
||||
# Copyright 1999-2013 Gentoo Foundation
|
||||
# Distributed under the terms of the GNU General Public License v2
|
||||
# $Header: /var/cvsroot/gentoo-x86/app-emulation/emul-linux-x86-soundlibs/emul-linux-x86-soundlibs-20130224-r1.ebuild,v 1.1 2013/06/26 18:18:39 aballier Exp $
|
||||
|
||||
EAPI=5
|
||||
inherit emul-linux-x86
|
||||
|
||||
LICENSE="BSD FDL-1.2 GPL-2 LGPL-2.1 LGPL-2 MIT gsm public-domain"
|
||||
KEYWORDS="-* ~amd64"
|
||||
IUSE="abi_x86_32 alsa"
|
||||
|
||||
RDEPEND="~app-emulation/emul-linux-x86-baselibs-${PV}
|
||||
~app-emulation/emul-linux-x86-medialibs-${PV}
|
||||
!>=media-libs/libmikmod-3.2.0-r1[abi_x86_32]
|
||||
!>=sci-libs/fftw-3.3.3-r1[abi_x86_32]
|
||||
abi_x86_32? (
|
||||
>=media-libs/libogg-1.3.1[abi_x86_32(-)]
|
||||
>=media-libs/libvorbis-1.3.3-r1[abi_x86_32(-)]
|
||||
>=media-libs/libmodplug-0.8.8.4-r1[abi_x86_32(-)]
|
||||
>=media-sound/gsm-1.0.13-r1[abi_x86_32(-)]
|
||||
)"
|
||||
|
||||
src_prepare() {
|
||||
_ALLOWED="${S}/etc/env.d"
|
||||
use alsa && _ALLOWED="${_ALLOWED}|${S}/usr/bin/aoss"
|
||||
ALLOWED="(${_ALLOWED})"
|
||||
|
||||
emul-linux-x86_src_prepare
|
||||
|
||||
if use alsa; then
|
||||
mv -f "${S}"/usr/bin/aoss{,32} || die
|
||||
fi
|
||||
|
||||
# Remove migrated stuff.
|
||||
use abi_x86_32 && rm -f $(cat "${FILESDIR}/remove-native")
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
usr/lib32/pkgconfig/ogg.pc
|
||||
usr/lib32/libogg.so
|
||||
usr/lib32/libogg.so.0
|
||||
usr/lib32/libogg.so.0.8.0
|
||||
usr/lib32/libmodplug.so
|
||||
usr/lib32/libmodplug.so.1
|
||||
usr/lib32/libmodplug.so.1.0.0
|
||||
usr/lib32/pkgconfig/libmodplug.pc
|
||||
usr/lib32/libgsm.so
|
||||
usr/lib32/libgsm.so.1
|
||||
usr/lib32/libgsm.so.1.0.13
|
||||
usr/lib32/libvorbis.so
|
||||
usr/lib32/libvorbis.so.0
|
||||
usr/lib32/libvorbis.so.0.4.6
|
||||
usr/lib32/libvorbisenc.so
|
||||
usr/lib32/libvorbisenc.so.2
|
||||
usr/lib32/libvorbisenc.so.2.0.9
|
||||
usr/lib32/libvorbisfile.so
|
||||
usr/lib32/libvorbisfile.so.3
|
||||
usr/lib32/libvorbisfile.so.3.3.5
|
||||
usr/lib32/pkgconfig/vorbis.pc
|
||||
usr/lib32/pkgconfig/vorbisenc.pc
|
||||
usr/lib32/pkgconfig/vorbisfile.pc
|
@ -1,369 +0,0 @@
|
||||
|
||||
# HG changeset patch
|
||||
# User Ian Jackson <Ian.Jackson@eu.citrix.com>
|
||||
# Date 1351264255 -3600
|
||||
# Node ID 537776f51f79c5789d06f97b363596a197c3e71c
|
||||
# Parent 40ccbee890e1fc053de3046bbc3d13b8ff6f5d63
|
||||
libxc: builder: limit maximum size of kernel/ramdisk.
|
||||
|
||||
Allowing user supplied kernels of arbitrary sizes, especially during
|
||||
decompression, can swallow up dom0 memory leading to either virtual
|
||||
address space exhaustion in the builder process or allocation
|
||||
failures/OOM killing of both toolstack and unrelated processes.
|
||||
|
||||
We disable these checks when building in a stub domain for pvgrub
|
||||
since this uses the guest's own memory and is isolated.
|
||||
|
||||
Decompression of gzip compressed kernels and ramdisks has been safe
|
||||
since 14954:58205257517d (Xen 3.1.0 onwards).
|
||||
|
||||
This is XSA-25 / CVE-2012-4544.
|
||||
|
||||
Also make explicit checks for buffer overflows in various
|
||||
decompression routines. These were already ruled out due to other
|
||||
properties of the code but check them as a belt-and-braces measure.
|
||||
|
||||
Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
|
||||
diff -r 40ccbee890e1 -r 537776f51f79 stubdom/grub/kexec.c
|
||||
--- stubdom/grub/kexec.c Thu Oct 25 15:36:32 2012 +0200
|
||||
+++ stubdom/grub/kexec.c Fri Oct 26 16:10:55 2012 +0100
|
||||
@@ -137,6 +137,10 @@ void kexec(void *kernel, long kernel_siz
|
||||
dom = xc_dom_allocate(xc_handle, cmdline, features);
|
||||
dom->allocate = kexec_allocate;
|
||||
|
||||
+ /* We are using guest owned memory, therefore no limits. */
|
||||
+ xc_dom_kernel_max_size(dom, 0);
|
||||
+ xc_dom_ramdisk_max_size(dom, 0);
|
||||
+
|
||||
dom->kernel_blob = kernel;
|
||||
dom->kernel_size = kernel_size;
|
||||
|
||||
diff -r 40ccbee890e1 -r 537776f51f79 tools/libxc/xc_dom.h
|
||||
--- tools/libxc/xc_dom.h Thu Oct 25 15:36:32 2012 +0200
|
||||
+++ tools/libxc/xc_dom.h Fri Oct 26 16:10:55 2012 +0100
|
||||
@@ -55,6 +55,9 @@ struct xc_dom_image {
|
||||
void *ramdisk_blob;
|
||||
size_t ramdisk_size;
|
||||
|
||||
+ size_t max_kernel_size;
|
||||
+ size_t max_ramdisk_size;
|
||||
+
|
||||
/* arguments and parameters */
|
||||
char *cmdline;
|
||||
uint32_t f_requested[XENFEAT_NR_SUBMAPS];
|
||||
@@ -180,6 +183,23 @@ void xc_dom_release_phys(struct xc_dom_i
|
||||
void xc_dom_release(struct xc_dom_image *dom);
|
||||
int xc_dom_mem_init(struct xc_dom_image *dom, unsigned int mem_mb);
|
||||
|
||||
+/* Set this larger if you have enormous ramdisks/kernels. Note that
|
||||
+ * you should trust all kernels not to be maliciously large (e.g. to
|
||||
+ * exhaust all dom0 memory) if you do this (see CVE-2012-4544 /
|
||||
+ * XSA-25). You can also set the default independently for
|
||||
+ * ramdisks/kernels in xc_dom_allocate() or call
|
||||
+ * xc_dom_{kernel,ramdisk}_max_size.
|
||||
+ */
|
||||
+#ifndef XC_DOM_DECOMPRESS_MAX
|
||||
+#define XC_DOM_DECOMPRESS_MAX (1024*1024*1024) /* 1GB */
|
||||
+#endif
|
||||
+
|
||||
+int xc_dom_kernel_check_size(struct xc_dom_image *dom, size_t sz);
|
||||
+int xc_dom_kernel_max_size(struct xc_dom_image *dom, size_t sz);
|
||||
+
|
||||
+int xc_dom_ramdisk_check_size(struct xc_dom_image *dom, size_t sz);
|
||||
+int xc_dom_ramdisk_max_size(struct xc_dom_image *dom, size_t sz);
|
||||
+
|
||||
size_t xc_dom_check_gzip(xc_interface *xch,
|
||||
void *blob, size_t ziplen);
|
||||
int xc_dom_do_gunzip(xc_interface *xch,
|
||||
@@ -240,7 +260,8 @@ void xc_dom_log_memory_footprint(struct
|
||||
void *xc_dom_malloc(struct xc_dom_image *dom, size_t size);
|
||||
void *xc_dom_malloc_page_aligned(struct xc_dom_image *dom, size_t size);
|
||||
void *xc_dom_malloc_filemap(struct xc_dom_image *dom,
|
||||
- const char *filename, size_t * size);
|
||||
+ const char *filename, size_t * size,
|
||||
+ const size_t max_size);
|
||||
char *xc_dom_strdup(struct xc_dom_image *dom, const char *str);
|
||||
|
||||
/* --- alloc memory pool ------------------------------------------- */
|
||||
diff -r 40ccbee890e1 -r 537776f51f79 tools/libxc/xc_dom_bzimageloader.c
|
||||
--- tools/libxc/xc_dom_bzimageloader.c Thu Oct 25 15:36:32 2012 +0200
|
||||
+++ tools/libxc/xc_dom_bzimageloader.c Fri Oct 26 16:10:55 2012 +0100
|
||||
@@ -47,13 +47,19 @@ static int xc_try_bzip2_decode(
|
||||
char *out_buf;
|
||||
char *tmp_buf;
|
||||
int retval = -1;
|
||||
- int outsize;
|
||||
+ unsigned int outsize;
|
||||
uint64_t total;
|
||||
|
||||
stream.bzalloc = NULL;
|
||||
stream.bzfree = NULL;
|
||||
stream.opaque = NULL;
|
||||
|
||||
+ if ( dom->kernel_size == 0)
|
||||
+ {
|
||||
+ DOMPRINTF("BZIP2: Input is 0 size");
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
ret = BZ2_bzDecompressInit(&stream, 0, 0);
|
||||
if ( ret != BZ_OK )
|
||||
{
|
||||
@@ -66,6 +72,17 @@ static int xc_try_bzip2_decode(
|
||||
* the input buffer to start, and we'll realloc as needed.
|
||||
*/
|
||||
outsize = dom->kernel_size;
|
||||
+
|
||||
+ /*
|
||||
+ * stream.avail_in and outsize are unsigned int, while kernel_size
|
||||
+ * is a size_t. Check we aren't overflowing.
|
||||
+ */
|
||||
+ if ( outsize != dom->kernel_size )
|
||||
+ {
|
||||
+ DOMPRINTF("BZIP2: Input too large");
|
||||
+ goto bzip2_cleanup;
|
||||
+ }
|
||||
+
|
||||
out_buf = malloc(outsize);
|
||||
if ( out_buf == NULL )
|
||||
{
|
||||
@@ -98,13 +115,20 @@ static int xc_try_bzip2_decode(
|
||||
if ( stream.avail_out == 0 )
|
||||
{
|
||||
/* Protect against output buffer overflow */
|
||||
- if ( outsize > INT_MAX / 2 )
|
||||
+ if ( outsize > UINT_MAX / 2 )
|
||||
{
|
||||
DOMPRINTF("BZIP2: output buffer overflow");
|
||||
free(out_buf);
|
||||
goto bzip2_cleanup;
|
||||
}
|
||||
|
||||
+ if ( xc_dom_kernel_check_size(dom, outsize * 2) )
|
||||
+ {
|
||||
+ DOMPRINTF("BZIP2: output too large");
|
||||
+ free(out_buf);
|
||||
+ goto bzip2_cleanup;
|
||||
+ }
|
||||
+
|
||||
tmp_buf = realloc(out_buf, outsize * 2);
|
||||
if ( tmp_buf == NULL )
|
||||
{
|
||||
@@ -172,9 +196,15 @@ static int _xc_try_lzma_decode(
|
||||
unsigned char *out_buf;
|
||||
unsigned char *tmp_buf;
|
||||
int retval = -1;
|
||||
- int outsize;
|
||||
+ size_t outsize;
|
||||
const char *msg;
|
||||
|
||||
+ if ( dom->kernel_size == 0)
|
||||
+ {
|
||||
+ DOMPRINTF("%s: Input is 0 size", what);
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
/* sigh. We don't know up-front how much memory we are going to need
|
||||
* for the output buffer. Allocate the output buffer to be equal
|
||||
* the input buffer to start, and we'll realloc as needed.
|
||||
@@ -244,13 +274,20 @@ static int _xc_try_lzma_decode(
|
||||
if ( stream->avail_out == 0 )
|
||||
{
|
||||
/* Protect against output buffer overflow */
|
||||
- if ( outsize > INT_MAX / 2 )
|
||||
+ if ( outsize > SIZE_MAX / 2 )
|
||||
{
|
||||
DOMPRINTF("%s: output buffer overflow", what);
|
||||
free(out_buf);
|
||||
goto lzma_cleanup;
|
||||
}
|
||||
|
||||
+ if ( xc_dom_kernel_check_size(dom, outsize * 2) )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: output too large", what);
|
||||
+ free(out_buf);
|
||||
+ goto lzma_cleanup;
|
||||
+ }
|
||||
+
|
||||
tmp_buf = realloc(out_buf, outsize * 2);
|
||||
if ( tmp_buf == NULL )
|
||||
{
|
||||
@@ -359,6 +396,12 @@ static int xc_try_lzo1x_decode(
|
||||
0x89, 0x4c, 0x5a, 0x4f, 0x00, 0x0d, 0x0a, 0x1a, 0x0a
|
||||
};
|
||||
|
||||
+ /*
|
||||
+ * lzo_uint should match size_t. Check that this is the case to be
|
||||
+ * sure we won't overflow various lzo_uint fields.
|
||||
+ */
|
||||
+ XC_BUILD_BUG_ON(sizeof(lzo_uint) != sizeof(size_t));
|
||||
+
|
||||
ret = lzo_init();
|
||||
if ( ret != LZO_E_OK )
|
||||
{
|
||||
@@ -438,6 +481,14 @@ static int xc_try_lzo1x_decode(
|
||||
if ( src_len <= 0 || src_len > dst_len || src_len > left )
|
||||
break;
|
||||
|
||||
+ msg = "Output buffer overflow";
|
||||
+ if ( *size > SIZE_MAX - dst_len )
|
||||
+ break;
|
||||
+
|
||||
+ msg = "Decompressed image too large";
|
||||
+ if ( xc_dom_kernel_check_size(dom, *size + dst_len) )
|
||||
+ break;
|
||||
+
|
||||
msg = "Failed to (re)alloc memory";
|
||||
tmp_buf = realloc(out_buf, *size + dst_len);
|
||||
if ( tmp_buf == NULL )
|
||||
diff -r 40ccbee890e1 -r 537776f51f79 tools/libxc/xc_dom_core.c
|
||||
--- tools/libxc/xc_dom_core.c Thu Oct 25 15:36:32 2012 +0200
|
||||
+++ tools/libxc/xc_dom_core.c Fri Oct 26 16:10:55 2012 +0100
|
||||
@@ -159,7 +159,8 @@ void *xc_dom_malloc_page_aligned(struct
|
||||
}
|
||||
|
||||
void *xc_dom_malloc_filemap(struct xc_dom_image *dom,
|
||||
- const char *filename, size_t * size)
|
||||
+ const char *filename, size_t * size,
|
||||
+ const size_t max_size)
|
||||
{
|
||||
struct xc_dom_mem *block = NULL;
|
||||
int fd = -1;
|
||||
@@ -171,6 +172,13 @@ void *xc_dom_malloc_filemap(struct xc_do
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
*size = lseek(fd, 0, SEEK_END);
|
||||
|
||||
+ if ( max_size && *size > max_size )
|
||||
+ {
|
||||
+ xc_dom_panic(dom->xch, XC_OUT_OF_MEMORY,
|
||||
+ "tried to map file which is too large");
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
block = malloc(sizeof(*block));
|
||||
if ( block == NULL )
|
||||
goto err;
|
||||
@@ -222,6 +230,40 @@ char *xc_dom_strdup(struct xc_dom_image
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
+/* decompression buffer sizing */
|
||||
+int xc_dom_kernel_check_size(struct xc_dom_image *dom, size_t sz)
|
||||
+{
|
||||
+ /* No limit */
|
||||
+ if ( !dom->max_kernel_size )
|
||||
+ return 0;
|
||||
+
|
||||
+ if ( sz > dom->max_kernel_size )
|
||||
+ {
|
||||
+ xc_dom_panic(dom->xch, XC_INVALID_KERNEL,
|
||||
+ "kernel image too large");
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int xc_dom_ramdisk_check_size(struct xc_dom_image *dom, size_t sz)
|
||||
+{
|
||||
+ /* No limit */
|
||||
+ if ( !dom->max_ramdisk_size )
|
||||
+ return 0;
|
||||
+
|
||||
+ if ( sz > dom->max_ramdisk_size )
|
||||
+ {
|
||||
+ xc_dom_panic(dom->xch, XC_INVALID_KERNEL,
|
||||
+ "ramdisk image too large");
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/* ------------------------------------------------------------------------ */
|
||||
/* read files, copy memory blocks, with transparent gunzip */
|
||||
|
||||
size_t xc_dom_check_gzip(xc_interface *xch, void *blob, size_t ziplen)
|
||||
@@ -235,7 +277,7 @@ size_t xc_dom_check_gzip(xc_interface *x
|
||||
|
||||
gzlen = blob + ziplen - 4;
|
||||
unziplen = gzlen[3] << 24 | gzlen[2] << 16 | gzlen[1] << 8 | gzlen[0];
|
||||
- if ( (unziplen < 0) || (unziplen > (1024*1024*1024)) ) /* 1GB limit */
|
||||
+ if ( (unziplen < 0) || (unziplen > XC_DOM_DECOMPRESS_MAX) )
|
||||
{
|
||||
xc_dom_printf
|
||||
(xch,
|
||||
@@ -288,6 +330,9 @@ int xc_dom_try_gunzip(struct xc_dom_imag
|
||||
if ( unziplen == 0 )
|
||||
return 0;
|
||||
|
||||
+ if ( xc_dom_kernel_check_size(dom, unziplen) )
|
||||
+ return 0;
|
||||
+
|
||||
unzip = xc_dom_malloc(dom, unziplen);
|
||||
if ( unzip == NULL )
|
||||
return -1;
|
||||
@@ -588,6 +633,9 @@ struct xc_dom_image *xc_dom_allocate(xc_
|
||||
memset(dom, 0, sizeof(*dom));
|
||||
dom->xch = xch;
|
||||
|
||||
+ dom->max_kernel_size = XC_DOM_DECOMPRESS_MAX;
|
||||
+ dom->max_ramdisk_size = XC_DOM_DECOMPRESS_MAX;
|
||||
+
|
||||
if ( cmdline )
|
||||
dom->cmdline = xc_dom_strdup(dom, cmdline);
|
||||
if ( features )
|
||||
@@ -608,10 +656,25 @@ struct xc_dom_image *xc_dom_allocate(xc_
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+int xc_dom_kernel_max_size(struct xc_dom_image *dom, size_t sz)
|
||||
+{
|
||||
+ DOMPRINTF("%s: kernel_max_size=%zx", __FUNCTION__, sz);
|
||||
+ dom->max_kernel_size = sz;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int xc_dom_ramdisk_max_size(struct xc_dom_image *dom, size_t sz)
|
||||
+{
|
||||
+ DOMPRINTF("%s: ramdisk_max_size=%zx", __FUNCTION__, sz);
|
||||
+ dom->max_ramdisk_size = sz;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
int xc_dom_kernel_file(struct xc_dom_image *dom, const char *filename)
|
||||
{
|
||||
DOMPRINTF("%s: filename=\"%s\"", __FUNCTION__, filename);
|
||||
- dom->kernel_blob = xc_dom_malloc_filemap(dom, filename, &dom->kernel_size);
|
||||
+ dom->kernel_blob = xc_dom_malloc_filemap(dom, filename, &dom->kernel_size,
|
||||
+ dom->max_kernel_size);
|
||||
if ( dom->kernel_blob == NULL )
|
||||
return -1;
|
||||
return xc_dom_try_gunzip(dom, &dom->kernel_blob, &dom->kernel_size);
|
||||
@@ -621,7 +684,9 @@ int xc_dom_ramdisk_file(struct xc_dom_im
|
||||
{
|
||||
DOMPRINTF("%s: filename=\"%s\"", __FUNCTION__, filename);
|
||||
dom->ramdisk_blob =
|
||||
- xc_dom_malloc_filemap(dom, filename, &dom->ramdisk_size);
|
||||
+ xc_dom_malloc_filemap(dom, filename, &dom->ramdisk_size,
|
||||
+ dom->max_ramdisk_size);
|
||||
+
|
||||
if ( dom->ramdisk_blob == NULL )
|
||||
return -1;
|
||||
// return xc_dom_try_gunzip(dom, &dom->ramdisk_blob, &dom->ramdisk_size);
|
||||
@@ -781,7 +846,11 @@ int xc_dom_build_image(struct xc_dom_ima
|
||||
void *ramdiskmap;
|
||||
|
||||
unziplen = xc_dom_check_gzip(dom->xch, dom->ramdisk_blob, dom->ramdisk_size);
|
||||
+ if ( xc_dom_ramdisk_check_size(dom, unziplen) != 0 )
|
||||
+ unziplen = 0;
|
||||
+
|
||||
ramdisklen = unziplen ? unziplen : dom->ramdisk_size;
|
||||
+
|
||||
if ( xc_dom_alloc_segment(dom, &dom->ramdisk_seg, "ramdisk", 0,
|
||||
ramdisklen) != 0 )
|
||||
goto err;
|
||||
|
||||
|
@ -0,0 +1,417 @@
|
||||
From 9737484becab4a25159f1e985700eaee89690d34 Mon Sep 17 00:00:00 2001
|
||||
From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Date: Fri, 14 Jun 2013 16:43:15 +0100
|
||||
Subject: [PATCH 01/23] libelf: abolish libelf-relocate.c
|
||||
|
||||
This file is not actually used. It's not built in Xen's instance of
|
||||
libelf; in libxc's it's built but nothing in it is called. Do not
|
||||
compile it in libxc, and delete it.
|
||||
|
||||
This reduces the amount of work we need to do in forthcoming patches
|
||||
to libelf (particularly since as libelf-relocate.c is not used it is
|
||||
probably full of bugs).
|
||||
|
||||
This is part of the fix to a security issue, XSA-55.
|
||||
|
||||
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
---
|
||||
tools/libxc/Makefile | 2 +-
|
||||
xen/common/libelf/libelf-relocate.c | 372 -----------------------------------
|
||||
2 files changed, 1 insertions(+), 373 deletions(-)
|
||||
delete mode 100644 xen/common/libelf/libelf-relocate.c
|
||||
|
||||
diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile
|
||||
index ca38cbd..d8c6a60 100644
|
||||
--- a/tools/libxc/Makefile
|
||||
+++ b/tools/libxc/Makefile
|
||||
@@ -53,7 +53,7 @@ vpath %.c ../../xen/common/libelf
|
||||
CFLAGS += -I../../xen/common/libelf
|
||||
|
||||
GUEST_SRCS-y += libelf-tools.c libelf-loader.c
|
||||
-GUEST_SRCS-y += libelf-dominfo.c libelf-relocate.c
|
||||
+GUEST_SRCS-y += libelf-dominfo.c
|
||||
|
||||
# new domain builder
|
||||
GUEST_SRCS-y += xc_dom_core.c xc_dom_boot.c
|
||||
diff --git a/xen/common/libelf/libelf-relocate.c b/xen/common/libelf/libelf-relocate.c
|
||||
#deleted file mode 100644
|
||||
index 7ef4b01..0000000
|
||||
--- a/xen/common/libelf/libelf-relocate.c
|
||||
+++ /dev/null
|
||||
@@ -1,372 +0,0 @@
|
||||
-/*
|
||||
- * ELF relocation code (not used by xen kernel right now).
|
||||
- *
|
||||
- * This 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;
|
||||
- * version 2.1 of the License.
|
||||
- *
|
||||
- * This 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 this library; if not, write to the Free Software
|
||||
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
- */
|
||||
-
|
||||
-#include "libelf-private.h"
|
||||
-
|
||||
-/* ------------------------------------------------------------------------ */
|
||||
-
|
||||
-static const char *rel_names_i386[] = {
|
||||
- "R_386_NONE",
|
||||
- "R_386_32",
|
||||
- "R_386_PC32",
|
||||
- "R_386_GOT32",
|
||||
- "R_386_PLT32",
|
||||
- "R_386_COPY",
|
||||
- "R_386_GLOB_DAT",
|
||||
- "R_386_JMP_SLOT",
|
||||
- "R_386_RELATIVE",
|
||||
- "R_386_GOTOFF",
|
||||
- "R_386_GOTPC",
|
||||
- "R_386_32PLT",
|
||||
- "R_386_TLS_TPOFF",
|
||||
- "R_386_TLS_IE",
|
||||
- "R_386_TLS_GOTIE",
|
||||
- "R_386_TLS_LE",
|
||||
- "R_386_TLS_GD",
|
||||
- "R_386_TLS_LDM",
|
||||
- "R_386_16",
|
||||
- "R_386_PC16",
|
||||
- "R_386_8",
|
||||
- "R_386_PC8",
|
||||
- "R_386_TLS_GD_32",
|
||||
- "R_386_TLS_GD_PUSH",
|
||||
- "R_386_TLS_GD_CALL",
|
||||
- "R_386_TLS_GD_POP",
|
||||
- "R_386_TLS_LDM_32",
|
||||
- "R_386_TLS_LDM_PUSH",
|
||||
- "R_386_TLS_LDM_CALL",
|
||||
- "R_386_TLS_LDM_POP",
|
||||
- "R_386_TLS_LDO_32",
|
||||
- "R_386_TLS_IE_32",
|
||||
- "R_386_TLS_LE_32",
|
||||
- "R_386_TLS_DTPMOD32",
|
||||
- "R_386_TLS_DTPOFF32",
|
||||
- "R_386_TLS_TPOFF32",
|
||||
-};
|
||||
-
|
||||
-static int elf_reloc_i386(struct elf_binary *elf, int type,
|
||||
- uint64_t addr, uint64_t value)
|
||||
-{
|
||||
- void *ptr = elf_get_ptr(elf, addr);
|
||||
- uint32_t *u32;
|
||||
-
|
||||
- switch ( type )
|
||||
- {
|
||||
- case 1 /* R_386_32 */ :
|
||||
- u32 = ptr;
|
||||
- *u32 += elf->reloc_offset;
|
||||
- break;
|
||||
- case 2 /* R_386_PC32 */ :
|
||||
- /* nothing */
|
||||
- break;
|
||||
- default:
|
||||
- return -1;
|
||||
- }
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-/* ------------------------------------------------------------------------ */
|
||||
-
|
||||
-static const char *rel_names_x86_64[] = {
|
||||
- "R_X86_64_NONE",
|
||||
- "R_X86_64_64",
|
||||
- "R_X86_64_PC32",
|
||||
- "R_X86_64_GOT32",
|
||||
- "R_X86_64_PLT32",
|
||||
- "R_X86_64_COPY",
|
||||
- "R_X86_64_GLOB_DAT",
|
||||
- "R_X86_64_JUMP_SLOT",
|
||||
- "R_X86_64_RELATIVE",
|
||||
- "R_X86_64_GOTPCREL",
|
||||
- "R_X86_64_32",
|
||||
- "R_X86_64_32S",
|
||||
- "R_X86_64_16",
|
||||
- "R_X86_64_PC16",
|
||||
- "R_X86_64_8",
|
||||
- "R_X86_64_PC8",
|
||||
- "R_X86_64_DTPMOD64",
|
||||
- "R_X86_64_DTPOFF64",
|
||||
- "R_X86_64_TPOFF64",
|
||||
- "R_X86_64_TLSGD",
|
||||
- "R_X86_64_TLSLD",
|
||||
- "R_X86_64_DTPOFF32",
|
||||
- "R_X86_64_GOTTPOFF",
|
||||
- "R_X86_64_TPOFF32",
|
||||
-};
|
||||
-
|
||||
-static int elf_reloc_x86_64(struct elf_binary *elf, int type,
|
||||
- uint64_t addr, uint64_t value)
|
||||
-{
|
||||
- void *ptr = elf_get_ptr(elf, addr);
|
||||
- uint64_t *u64;
|
||||
- uint32_t *u32;
|
||||
- int32_t *s32;
|
||||
-
|
||||
- switch ( type )
|
||||
- {
|
||||
- case 1 /* R_X86_64_64 */ :
|
||||
- u64 = ptr;
|
||||
- value += elf->reloc_offset;
|
||||
- *u64 = value;
|
||||
- break;
|
||||
- case 2 /* R_X86_64_PC32 */ :
|
||||
- u32 = ptr;
|
||||
- *u32 = value - addr;
|
||||
- if ( *u32 != (uint32_t)(value - addr) )
|
||||
- {
|
||||
- elf_err(elf, "R_X86_64_PC32 overflow: 0x%" PRIx32
|
||||
- " != 0x%" PRIx32 "\n",
|
||||
- *u32, (uint32_t) (value - addr));
|
||||
- return -1;
|
||||
- }
|
||||
- break;
|
||||
- case 10 /* R_X86_64_32 */ :
|
||||
- u32 = ptr;
|
||||
- value += elf->reloc_offset;
|
||||
- *u32 = value;
|
||||
- if ( *u32 != value )
|
||||
- {
|
||||
- elf_err(elf, "R_X86_64_32 overflow: 0x%" PRIx32
|
||||
- " != 0x%" PRIx64 "\n",
|
||||
- *u32, value);
|
||||
- return -1;
|
||||
- }
|
||||
- break;
|
||||
- case 11 /* R_X86_64_32S */ :
|
||||
- s32 = ptr;
|
||||
- value += elf->reloc_offset;
|
||||
- *s32 = value;
|
||||
- if ( *s32 != (int64_t) value )
|
||||
- {
|
||||
- elf_err(elf, "R_X86_64_32S overflow: 0x%" PRIx32
|
||||
- " != 0x%" PRIx64 "\n",
|
||||
- *s32, (int64_t) value);
|
||||
- return -1;
|
||||
- }
|
||||
- break;
|
||||
- default:
|
||||
- return -1;
|
||||
- }
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-/* ------------------------------------------------------------------------ */
|
||||
-
|
||||
-static struct relocs {
|
||||
- const char **names;
|
||||
- int count;
|
||||
- int (*func) (struct elf_binary * elf, int type, uint64_t addr,
|
||||
- uint64_t value);
|
||||
-} relocs[] =
|
||||
-/* *INDENT-OFF* */
|
||||
-{
|
||||
- [EM_386] = {
|
||||
- .names = rel_names_i386,
|
||||
- .count = sizeof(rel_names_i386) / sizeof(rel_names_i386[0]),
|
||||
- .func = elf_reloc_i386,
|
||||
- },
|
||||
- [EM_X86_64] = {
|
||||
- .names = rel_names_x86_64,
|
||||
- .count = sizeof(rel_names_x86_64) / sizeof(rel_names_x86_64[0]),
|
||||
- .func = elf_reloc_x86_64,
|
||||
- }
|
||||
-};
|
||||
-/* *INDENT-ON* */
|
||||
-
|
||||
-/* ------------------------------------------------------------------------ */
|
||||
-
|
||||
-static const char *rela_name(int machine, int type)
|
||||
-{
|
||||
- if ( machine > sizeof(relocs) / sizeof(relocs[0]) )
|
||||
- return "unknown mach";
|
||||
- if ( !relocs[machine].names )
|
||||
- return "unknown mach";
|
||||
- if ( type > relocs[machine].count )
|
||||
- return "unknown rela";
|
||||
- return relocs[machine].names[type];
|
||||
-}
|
||||
-
|
||||
-static int elf_reloc_section(struct elf_binary *elf,
|
||||
- const elf_shdr * rels,
|
||||
- const elf_shdr * sect, const elf_shdr * syms)
|
||||
-{
|
||||
- const void *ptr, *end;
|
||||
- const elf_shdr *shdr;
|
||||
- const elf_rela *rela;
|
||||
- const elf_rel *rel;
|
||||
- const elf_sym *sym;
|
||||
- uint64_t s_type;
|
||||
- uint64_t r_offset;
|
||||
- uint64_t r_info;
|
||||
- uint64_t r_addend;
|
||||
- int r_type, r_sym;
|
||||
- size_t rsize;
|
||||
- uint64_t shndx, sbase, addr, value;
|
||||
- const char *sname;
|
||||
- int machine;
|
||||
-
|
||||
- machine = elf_uval(elf, elf->ehdr, e_machine);
|
||||
- if ( (machine >= (sizeof(relocs) / sizeof(relocs[0]))) ||
|
||||
- (relocs[machine].func == NULL) )
|
||||
- {
|
||||
- elf_err(elf, "%s: can't handle machine %d\n",
|
||||
- __FUNCTION__, machine);
|
||||
- return -1;
|
||||
- }
|
||||
- if ( elf_swap(elf) )
|
||||
- {
|
||||
- elf_err(elf, "%s: non-native byte order, relocation not supported\n",
|
||||
- __FUNCTION__);
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
- s_type = elf_uval(elf, rels, sh_type);
|
||||
- rsize = (SHT_REL == s_type) ? elf_size(elf, rel) : elf_size(elf, rela);
|
||||
- ptr = elf_section_start(elf, rels);
|
||||
- end = elf_section_end(elf, rels);
|
||||
-
|
||||
- for ( ; ptr < end; ptr += rsize )
|
||||
- {
|
||||
- switch ( s_type )
|
||||
- {
|
||||
- case SHT_REL:
|
||||
- rel = ptr;
|
||||
- r_offset = elf_uval(elf, rel, r_offset);
|
||||
- r_info = elf_uval(elf, rel, r_info);
|
||||
- r_addend = 0;
|
||||
- break;
|
||||
- case SHT_RELA:
|
||||
- rela = ptr;
|
||||
- r_offset = elf_uval(elf, rela, r_offset);
|
||||
- r_info = elf_uval(elf, rela, r_info);
|
||||
- r_addend = elf_uval(elf, rela, r_addend);
|
||||
- break;
|
||||
- default:
|
||||
- /* can't happen */
|
||||
- return -1;
|
||||
- }
|
||||
- if ( elf_64bit(elf) )
|
||||
- {
|
||||
- r_type = ELF64_R_TYPE(r_info);
|
||||
- r_sym = ELF64_R_SYM(r_info);
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- r_type = ELF32_R_TYPE(r_info);
|
||||
- r_sym = ELF32_R_SYM(r_info);
|
||||
- }
|
||||
-
|
||||
- sym = elf_sym_by_index(elf, r_sym);
|
||||
- shndx = elf_uval(elf, sym, st_shndx);
|
||||
- switch ( shndx )
|
||||
- {
|
||||
- case SHN_UNDEF:
|
||||
- sname = "*UNDEF*";
|
||||
- sbase = 0;
|
||||
- break;
|
||||
- case SHN_COMMON:
|
||||
- elf_err(elf, "%s: invalid section: %" PRId64 "\n",
|
||||
- __FUNCTION__, shndx);
|
||||
- return -1;
|
||||
- case SHN_ABS:
|
||||
- sname = "*ABS*";
|
||||
- sbase = 0;
|
||||
- break;
|
||||
- default:
|
||||
- shdr = elf_shdr_by_index(elf, shndx);
|
||||
- if ( shdr == NULL )
|
||||
- {
|
||||
- elf_err(elf, "%s: invalid section: %" PRId64 "\n",
|
||||
- __FUNCTION__, shndx);
|
||||
- return -1;
|
||||
- }
|
||||
- sname = elf_section_name(elf, shdr);
|
||||
- sbase = elf_uval(elf, shdr, sh_addr);
|
||||
- }
|
||||
-
|
||||
- addr = r_offset;
|
||||
- value = elf_uval(elf, sym, st_value);
|
||||
- value += r_addend;
|
||||
-
|
||||
- if ( elf->log_callback && (elf->verbose > 1) )
|
||||
- {
|
||||
- uint64_t st_name = elf_uval(elf, sym, st_name);
|
||||
- const char *name = st_name ? elf->sym_strtab + st_name : "*NONE*";
|
||||
-
|
||||
- elf_msg(elf,
|
||||
- "%s: type %s [%d], off 0x%" PRIx64 ", add 0x%" PRIx64 ","
|
||||
- " sym %s [0x%" PRIx64 "], sec %s [0x%" PRIx64 "]"
|
||||
- " -> addr 0x%" PRIx64 " value 0x%" PRIx64 "\n",
|
||||
- __FUNCTION__, rela_name(machine, r_type), r_type, r_offset,
|
||||
- r_addend, name, elf_uval(elf, sym, st_value), sname, sbase,
|
||||
- addr, value);
|
||||
- }
|
||||
-
|
||||
- if ( relocs[machine].func(elf, r_type, addr, value) == -1 )
|
||||
- {
|
||||
- elf_err(elf, "%s: unknown/unsupported reloc type %s [%d]\n",
|
||||
- __FUNCTION__, rela_name(machine, r_type), r_type);
|
||||
- return -1;
|
||||
- }
|
||||
- }
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-int elf_reloc(struct elf_binary *elf)
|
||||
-{
|
||||
- const elf_shdr *rels, *sect, *syms;
|
||||
- uint64_t i, count, type;
|
||||
-
|
||||
- count = elf_shdr_count(elf);
|
||||
- for ( i = 0; i < count; i++ )
|
||||
- {
|
||||
- rels = elf_shdr_by_index(elf, i);
|
||||
- type = elf_uval(elf, rels, sh_type);
|
||||
- if ( (type != SHT_REL) && (type != SHT_RELA) )
|
||||
- continue;
|
||||
-
|
||||
- sect = elf_shdr_by_index(elf, elf_uval(elf, rels, sh_info));
|
||||
- syms = elf_shdr_by_index(elf, elf_uval(elf, rels, sh_link));
|
||||
- if ( NULL == sect || NULL == syms )
|
||||
- continue;
|
||||
-
|
||||
- if ( !(elf_uval(elf, sect, sh_flags) & SHF_ALLOC) )
|
||||
- {
|
||||
- elf_msg(elf, "%s: relocations for %s, skipping\n",
|
||||
- __FUNCTION__, elf_section_name(elf, sect));
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- elf_msg(elf, "%s: relocations for %s @ 0x%" PRIx64 "\n",
|
||||
- __FUNCTION__, elf_section_name(elf, sect),
|
||||
- elf_uval(elf, sect, sh_addr));
|
||||
- if ( elf_reloc_section(elf, rels, sect, syms) != 0 )
|
||||
- return -1;
|
||||
- }
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-/*
|
||||
- * Local variables:
|
||||
- * mode: C
|
||||
- * c-set-style: "BSD"
|
||||
- * c-basic-offset: 4
|
||||
- * tab-width: 4
|
||||
- * indent-tabs-mode: nil
|
||||
- * End:
|
||||
- */
|
||||
--
|
||||
#1.7.2.5
|
||||
|
@ -0,0 +1,788 @@
|
||||
From cc8761371aac432318530c2ddfe2c8234bc0621f Mon Sep 17 00:00:00 2001
|
||||
From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Date: Fri, 14 Jun 2013 16:43:17 +0100
|
||||
Subject: [PATCH 11/23] libelf: check all pointer accesses
|
||||
|
||||
We change the ELF_PTRVAL and ELF_HANDLE types and associated macros:
|
||||
|
||||
* PTRVAL becomes a uintptr_t, for which we provide a typedef
|
||||
elf_ptrval. This means no arithmetic done on it can overflow so
|
||||
the compiler cannot do any malicious invalid pointer arithmetic
|
||||
"optimisations". It also means that any places where we
|
||||
dereference one of these pointers without using the appropriate
|
||||
macros or functions become a compilation error.
|
||||
|
||||
So we can be sure that we won't miss any memory accesses.
|
||||
|
||||
All the PTRVAL variables were previously void* or char*, so
|
||||
the actual address calculations are unchanged.
|
||||
|
||||
* ELF_HANDLE becomes a union, one half of which keeps the pointer
|
||||
value and the other half of which is just there to record the
|
||||
type.
|
||||
|
||||
The new type is not a pointer type so there can be no address
|
||||
calculations on it whose meaning would change. Every assignment or
|
||||
access has to go through one of our macros.
|
||||
|
||||
* The distinction between const and non-const pointers and char*s
|
||||
and void*s in libelf goes away. This was not important (and
|
||||
anyway libelf tended to cast away const in various places).
|
||||
|
||||
* The fields elf->image and elf->dest are renamed. That proves
|
||||
that we haven't missed any unchecked uses of these actual
|
||||
pointer values.
|
||||
|
||||
* The caller may fill in elf->caller_xdest_base and _size to
|
||||
specify another range of memory which is safe for libelf to
|
||||
access, besides the input and output images.
|
||||
|
||||
* When accesses fail due to being out of range, we mark the elf
|
||||
"broken". This will be checked and used for diagnostics in
|
||||
a following patch.
|
||||
|
||||
We do not check for write accesses to the input image. This is
|
||||
because libelf actually does this in a number of places. So we
|
||||
simply permit that.
|
||||
|
||||
* Each caller of libelf which used to set dest now sets
|
||||
dest_base and dest_size.
|
||||
|
||||
* In xc_dom_load_elf_symtab we provide a new actual-pointer
|
||||
value hdr_ptr which we get from mapping the guest's kernel
|
||||
area and use (checking carefully) as the caller_xdest area.
|
||||
|
||||
* The STAR(h) macro in libelf-dominfo.c now uses elf_access_unsigned.
|
||||
|
||||
* elf-init uses the new elf_uval_3264 accessor to access the 32-bit
|
||||
fields, rather than an unchecked field access (ie, unchecked
|
||||
pointer access).
|
||||
|
||||
* elf_uval has been reworked to use elf_uval_3264. Both of these
|
||||
macros are essentially new in this patch (although they are derived
|
||||
from the old elf_uval) and need careful review.
|
||||
|
||||
* ELF_ADVANCE_DEST is now safe in the sense that you can use it to
|
||||
chop parts off the front of the dest area but if you chop more than
|
||||
is available, the dest area is simply set to be empty, preventing
|
||||
future accesses.
|
||||
|
||||
* We introduce some #defines for memcpy, memset, memmove and strcpy:
|
||||
- We provide elf_memcpy_safe and elf_memset_safe which take
|
||||
PTRVALs and do checking on the supplied pointers.
|
||||
- Users inside libelf must all be changed to either
|
||||
elf_mem*_unchecked (which are just like mem*), or
|
||||
elf_mem*_safe (which take PTRVALs) and are checked. Any
|
||||
unchanged call sites become compilation errors.
|
||||
|
||||
* We do _not_ at this time fix elf_access_unsigned so that it doesn't
|
||||
make unaligned accesses. We hope that unaligned accesses are OK on
|
||||
every supported architecture. But it does check the supplied
|
||||
pointer for validity.
|
||||
|
||||
This is part of the fix to a security issue, XSA-55.
|
||||
|
||||
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
---
|
||||
tools/libxc/xc_dom_elfloader.c | 49 ++++++++--
|
||||
tools/libxc/xc_hvm_build_x86.c | 10 +-
|
||||
xen/arch/x86/domain_build.c | 3 +-
|
||||
xen/common/libelf/libelf-dominfo.c | 2 +-
|
||||
xen/common/libelf/libelf-loader.c | 16 ++--
|
||||
xen/common/libelf/libelf-private.h | 13 +++
|
||||
xen/common/libelf/libelf-tools.c | 106 ++++++++++++++++++-
|
||||
xen/include/xen/libelf.h | 198 +++++++++++++++++++++++++-----------
|
||||
8 files changed, 312 insertions(+), 85 deletions(-)
|
||||
|
||||
diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c
|
||||
index cc0f206..b82a08c 100644
|
||||
--- a/tools/libxc/xc_dom_elfloader.c
|
||||
+++ b/tools/libxc/xc_dom_elfloader.c
|
||||
@@ -130,20 +130,30 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
|
||||
if ( load )
|
||||
{
|
||||
- size_t allow_size; /* will be used in a forthcoming XSA-55 patch */
|
||||
+ char *hdr_ptr;
|
||||
+ size_t allow_size;
|
||||
+
|
||||
if ( !dom->bsd_symtab_start )
|
||||
return 0;
|
||||
size = dom->kernel_seg.vend - dom->bsd_symtab_start;
|
||||
- hdr = xc_dom_vaddr_to_ptr(dom, dom->bsd_symtab_start, &allow_size);
|
||||
- *(int *)hdr = size - sizeof(int);
|
||||
+ hdr_ptr = xc_dom_vaddr_to_ptr(dom, dom->bsd_symtab_start, &allow_size);
|
||||
+ elf->caller_xdest_base = hdr_ptr;
|
||||
+ elf->caller_xdest_size = allow_size;
|
||||
+ hdr = ELF_REALPTR2PTRVAL(hdr_ptr);
|
||||
+ elf_store_val(elf, int, hdr, size - sizeof(int));
|
||||
}
|
||||
else
|
||||
{
|
||||
+ char *hdr_ptr;
|
||||
+
|
||||
size = sizeof(int) + elf_size(elf, elf->ehdr) +
|
||||
elf_shdr_count(elf) * elf_size(elf, shdr);
|
||||
- hdr = xc_dom_malloc(dom, size);
|
||||
- if ( hdr == NULL )
|
||||
+ hdr_ptr = xc_dom_malloc(dom, size);
|
||||
+ if ( hdr_ptr == NULL )
|
||||
return 0;
|
||||
+ elf->caller_xdest_base = hdr_ptr;
|
||||
+ elf->caller_xdest_size = size;
|
||||
+ hdr = ELF_REALPTR2PTRVAL(hdr_ptr);
|
||||
dom->bsd_symtab_start = elf_round_up(elf, dom->kernel_seg.vend);
|
||||
}
|
||||
|
||||
@@ -171,9 +181,32 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
ehdr->e_shoff = elf_size(elf, elf->ehdr);
|
||||
ehdr->e_shstrndx = SHN_UNDEF;
|
||||
}
|
||||
- if ( elf_init(&syms, hdr + sizeof(int), size - sizeof(int)) )
|
||||
+ if ( elf->caller_xdest_size < sizeof(int) )
|
||||
+ {
|
||||
+ DOMPRINTF("%s/%s: header size %"PRIx64" too small",
|
||||
+ __FUNCTION__, load ? "load" : "parse",
|
||||
+ (uint64_t)elf->caller_xdest_size);
|
||||
+ return -1;
|
||||
+ }
|
||||
+ if ( elf_init(&syms, elf->caller_xdest_base + sizeof(int),
|
||||
+ elf->caller_xdest_size - sizeof(int)) )
|
||||
return -1;
|
||||
|
||||
+ /*
|
||||
+ * The caller_xdest_{base,size} and dest_{base,size} need to
|
||||
+ * remain valid so long as each struct elf_image does. The
|
||||
+ * principle we adopt is that these values are set when the
|
||||
+ * memory is allocated or mapped, and cleared when (and if)
|
||||
+ * they are unmapped.
|
||||
+ *
|
||||
+ * Mappings of the guest are normally undone by xc_dom_unmap_all
|
||||
+ * (directly or via xc_dom_release). We do not explicitly clear
|
||||
+ * these because in fact that happens only at the end of
|
||||
+ * xc_dom_boot_image, at which time all of these ELF loading
|
||||
+ * functions have returned. No relevant struct elf_binary*
|
||||
+ * escapes this file.
|
||||
+ */
|
||||
+
|
||||
xc_elf_set_logfile(dom->xch, &syms, 1);
|
||||
|
||||
symtab = dom->bsd_symtab_start + sizeof(int);
|
||||
@@ -312,8 +345,10 @@ static int xc_dom_load_elf_kernel(struct xc_dom_image *dom)
|
||||
{
|
||||
struct elf_binary *elf = dom->private_loader;
|
||||
int rc;
|
||||
+ xen_pfn_t pages;
|
||||
|
||||
- elf->dest = xc_dom_seg_to_ptr(dom, &dom->kernel_seg);
|
||||
+ elf->dest_base = xc_dom_seg_to_ptr_pages(dom, &dom->kernel_seg, &pages);
|
||||
+ elf->dest_size = pages * XC_DOM_PAGE_SIZE(dom);
|
||||
rc = elf_load_binary(elf);
|
||||
if ( rc < 0 )
|
||||
{
|
||||
diff --git a/tools/libxc/xc_hvm_build_x86.c b/tools/libxc/xc_hvm_build_x86.c
|
||||
index 15b603d..ccfd8b5 100644
|
||||
--- a/tools/libxc/xc_hvm_build_x86.c
|
||||
+++ b/tools/libxc/xc_hvm_build_x86.c
|
||||
@@ -104,11 +104,12 @@ static int loadelfimage(
|
||||
for ( i = 0; i < pages; i++ )
|
||||
entries[i].mfn = parray[(elf->pstart >> PAGE_SHIFT) + i];
|
||||
|
||||
- elf->dest = xc_map_foreign_ranges(
|
||||
+ elf->dest_base = xc_map_foreign_ranges(
|
||||
xch, dom, pages << PAGE_SHIFT, PROT_READ | PROT_WRITE, 1 << PAGE_SHIFT,
|
||||
entries, pages);
|
||||
- if ( elf->dest == NULL )
|
||||
+ if ( elf->dest_base == NULL )
|
||||
goto err;
|
||||
+ elf->dest_size = pages * PAGE_SIZE;
|
||||
|
||||
ELF_ADVANCE_DEST(elf, elf->pstart & (PAGE_SIZE - 1));
|
||||
|
||||
@@ -117,8 +118,9 @@ static int loadelfimage(
|
||||
if ( rc < 0 )
|
||||
PERROR("Failed to load elf binary\n");
|
||||
|
||||
- munmap(elf->dest, pages << PAGE_SHIFT);
|
||||
- elf->dest = NULL;
|
||||
+ munmap(elf->dest_base, pages << PAGE_SHIFT);
|
||||
+ elf->dest_base = NULL;
|
||||
+ elf->dest_size = 0;
|
||||
|
||||
err:
|
||||
free(entries);
|
||||
diff --git a/xen/arch/x86/domain_build.c b/xen/arch/x86/domain_build.c
|
||||
index 469d363..a655b21 100644
|
||||
--- a/xen/arch/x86/domain_build.c
|
||||
+++ b/xen/arch/x86/domain_build.c
|
||||
@@ -908,7 +908,8 @@ int __init construct_dom0(
|
||||
write_ptbase(v);
|
||||
|
||||
/* Copy the OS image and free temporary buffer. */
|
||||
- elf.dest = (void*)vkern_start;
|
||||
+ elf.dest_base = (void*)vkern_start;
|
||||
+ elf.dest_size = vkern_end - vkern_start;
|
||||
rc = elf_load_binary(&elf);
|
||||
if ( rc < 0 )
|
||||
{
|
||||
diff --git a/xen/common/libelf/libelf-dominfo.c b/xen/common/libelf/libelf-dominfo.c
|
||||
index b217f8f..98c80dc 100644
|
||||
--- a/xen/common/libelf/libelf-dominfo.c
|
||||
+++ b/xen/common/libelf/libelf-dominfo.c
|
||||
@@ -254,7 +254,7 @@ int elf_xen_parse_guest_info(struct elf_binary *elf,
|
||||
int len;
|
||||
|
||||
h = parms->guest_info;
|
||||
-#define STAR(h) (*(h))
|
||||
+#define STAR(h) (elf_access_unsigned(elf, (h), 0, 1))
|
||||
while ( STAR(h) )
|
||||
{
|
||||
elf_memset_unchecked(name, 0, sizeof(name));
|
||||
diff --git a/xen/common/libelf/libelf-loader.c b/xen/common/libelf/libelf-loader.c
|
||||
index 0fef84c..a3310e7 100644
|
||||
--- a/xen/common/libelf/libelf-loader.c
|
||||
+++ b/xen/common/libelf/libelf-loader.c
|
||||
@@ -24,23 +24,25 @@
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
-int elf_init(struct elf_binary *elf, const char *image, size_t size)
|
||||
+int elf_init(struct elf_binary *elf, const char *image_input, size_t size)
|
||||
{
|
||||
ELF_HANDLE_DECL(elf_shdr) shdr;
|
||||
uint64_t i, count, section, offset;
|
||||
|
||||
- if ( !elf_is_elfbinary(image) )
|
||||
+ if ( !elf_is_elfbinary(image_input) )
|
||||
{
|
||||
elf_err(elf, "%s: not an ELF binary\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
elf_memset_unchecked(elf, 0, sizeof(*elf));
|
||||
- elf->image = image;
|
||||
+ elf->image_base = image_input;
|
||||
elf->size = size;
|
||||
- elf->ehdr = (elf_ehdr *)image;
|
||||
- elf->class = elf->ehdr->e32.e_ident[EI_CLASS];
|
||||
- elf->data = elf->ehdr->e32.e_ident[EI_DATA];
|
||||
+ elf->ehdr = ELF_MAKE_HANDLE(elf_ehdr, (elf_ptrval)image_input);
|
||||
+ elf->class = elf_uval_3264(elf, elf->ehdr, e32.e_ident[EI_CLASS]);
|
||||
+ elf->data = elf_uval_3264(elf, elf->ehdr, e32.e_ident[EI_DATA]);
|
||||
+ elf->caller_xdest_base = NULL;
|
||||
+ elf->caller_xdest_size = 0;
|
||||
|
||||
/* Sanity check phdr. */
|
||||
offset = elf_uval(elf, elf->ehdr, e_phoff) +
|
||||
@@ -300,7 +302,7 @@ int elf_load_binary(struct elf_binary *elf)
|
||||
|
||||
ELF_PTRVAL_VOID elf_get_ptr(struct elf_binary *elf, unsigned long addr)
|
||||
{
|
||||
- return elf->dest + addr - elf->pstart;
|
||||
+ return ELF_REALPTR2PTRVAL(elf->dest_base) + addr - elf->pstart;
|
||||
}
|
||||
|
||||
uint64_t elf_lookup_addr(struct elf_binary * elf, const char *symbol)
|
||||
diff --git a/xen/common/libelf/libelf-private.h b/xen/common/libelf/libelf-private.h
|
||||
index 3ef753c..280dfd1 100644
|
||||
--- a/xen/common/libelf/libelf-private.h
|
||||
+++ b/xen/common/libelf/libelf-private.h
|
||||
@@ -86,6 +86,19 @@ do { strncpy((d),(s),sizeof((d))-1); \
|
||||
|
||||
#endif
|
||||
|
||||
+#undef memcpy
|
||||
+#undef memset
|
||||
+#undef memmove
|
||||
+#undef strcpy
|
||||
+
|
||||
+#define memcpy MISTAKE_unspecified_memcpy
|
||||
+#define memset MISTAKE_unspecified_memset
|
||||
+#define memmove MISTAKE_unspecified_memmove
|
||||
+#define strcpy MISTAKE_unspecified_strcpy
|
||||
+ /* This prevents libelf from using these undecorated versions
|
||||
+ * of memcpy, memset, memmove and strcpy. Every call site
|
||||
+ * must either use elf_mem*_unchecked, or elf_mem*_safe. */
|
||||
+
|
||||
#endif /* __LIBELF_PRIVATE_H_ */
|
||||
|
||||
/*
|
||||
diff --git a/xen/common/libelf/libelf-tools.c b/xen/common/libelf/libelf-tools.c
|
||||
index 3a0cde1..46ca553 100644
|
||||
--- a/xen/common/libelf/libelf-tools.c
|
||||
+++ b/xen/common/libelf/libelf-tools.c
|
||||
@@ -20,28 +20,100 @@
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
-uint64_t elf_access_unsigned(struct elf_binary * elf, const void *ptr,
|
||||
- uint64_t offset, size_t size)
|
||||
+void elf_mark_broken(struct elf_binary *elf, const char *msg)
|
||||
{
|
||||
+ if ( elf->broken == NULL )
|
||||
+ elf->broken = msg;
|
||||
+}
|
||||
+
|
||||
+const char *elf_check_broken(const struct elf_binary *elf)
|
||||
+{
|
||||
+ return elf->broken;
|
||||
+}
|
||||
+
|
||||
+static int elf_ptrval_in_range(elf_ptrval ptrval, uint64_t size,
|
||||
+ const void *region, uint64_t regionsize)
|
||||
+ /*
|
||||
+ * Returns true if the putative memory area [ptrval,ptrval+size>
|
||||
+ * is completely inside the region [region,region+regionsize>.
|
||||
+ *
|
||||
+ * ptrval and size are the untrusted inputs to be checked.
|
||||
+ * region and regionsize are trusted and must be correct and valid,
|
||||
+ * although it is OK for region to perhaps be maliciously NULL
|
||||
+ * (but not some other malicious value).
|
||||
+ */
|
||||
+{
|
||||
+ elf_ptrval regionp = (elf_ptrval)region;
|
||||
+
|
||||
+ if ( (region == NULL) ||
|
||||
+ (ptrval < regionp) || /* start is before region */
|
||||
+ (ptrval > regionp + regionsize) || /* start is after region */
|
||||
+ (size > regionsize - (ptrval - regionp)) ) /* too big */
|
||||
+ return 0;
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+int elf_access_ok(struct elf_binary * elf,
|
||||
+ uint64_t ptrval, size_t size)
|
||||
+{
|
||||
+ if ( elf_ptrval_in_range(ptrval, size, elf->image_base, elf->size) )
|
||||
+ return 1;
|
||||
+ if ( elf_ptrval_in_range(ptrval, size, elf->dest_base, elf->dest_size) )
|
||||
+ return 1;
|
||||
+ if ( elf_ptrval_in_range(ptrval, size,
|
||||
+ elf->caller_xdest_base, elf->caller_xdest_size) )
|
||||
+ return 1;
|
||||
+ elf_mark_broken(elf, "out of range access");
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+void elf_memcpy_safe(struct elf_binary *elf, elf_ptrval dst,
|
||||
+ elf_ptrval src, size_t size)
|
||||
+{
|
||||
+ if ( elf_access_ok(elf, dst, size) &&
|
||||
+ elf_access_ok(elf, src, size) )
|
||||
+ {
|
||||
+ /* use memmove because these checks do not prove that the
|
||||
+ * regions don't overlap and overlapping regions grant
|
||||
+ * permission for compiler malice */
|
||||
+ elf_memmove_unchecked(ELF_UNSAFE_PTR(dst), ELF_UNSAFE_PTR(src), size);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+void elf_memset_safe(struct elf_binary *elf, elf_ptrval dst, int c, size_t size)
|
||||
+{
|
||||
+ if ( elf_access_ok(elf, dst, size) )
|
||||
+ {
|
||||
+ elf_memset_unchecked(ELF_UNSAFE_PTR(dst), c, size);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+uint64_t elf_access_unsigned(struct elf_binary * elf, elf_ptrval base,
|
||||
+ uint64_t moreoffset, size_t size)
|
||||
+{
|
||||
+ elf_ptrval ptrval = base + moreoffset;
|
||||
int need_swap = elf_swap(elf);
|
||||
const uint8_t *u8;
|
||||
const uint16_t *u16;
|
||||
const uint32_t *u32;
|
||||
const uint64_t *u64;
|
||||
|
||||
+ if ( !elf_access_ok(elf, ptrval, size) )
|
||||
+ return 0;
|
||||
+
|
||||
switch ( size )
|
||||
{
|
||||
case 1:
|
||||
- u8 = ptr + offset;
|
||||
+ u8 = (const void*)ptrval;
|
||||
return *u8;
|
||||
case 2:
|
||||
- u16 = ptr + offset;
|
||||
+ u16 = (const void*)ptrval;
|
||||
return need_swap ? bswap_16(*u16) : *u16;
|
||||
case 4:
|
||||
- u32 = ptr + offset;
|
||||
+ u32 = (const void*)ptrval;
|
||||
return need_swap ? bswap_32(*u32) : *u32;
|
||||
case 8:
|
||||
- u64 = ptr + offset;
|
||||
+ u64 = (const void*)ptrval;
|
||||
return need_swap ? bswap_64(*u64) : *u64;
|
||||
default:
|
||||
return 0;
|
||||
@@ -122,6 +194,28 @@ const char *elf_section_name(struct elf_binary *elf,
|
||||
return elf_strval(elf, elf->sec_strtab + elf_uval(elf, shdr, sh_name));
|
||||
}
|
||||
|
||||
+const char *elf_strval(struct elf_binary *elf, elf_ptrval start)
|
||||
+{
|
||||
+ uint64_t length;
|
||||
+
|
||||
+ for ( length = 0; ; length++ ) {
|
||||
+ if ( !elf_access_ok(elf, start + length, 1) )
|
||||
+ return NULL;
|
||||
+ if ( !elf_access_unsigned(elf, start, length, 1) )
|
||||
+ /* ok */
|
||||
+ return ELF_UNSAFE_PTR(start);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+const char *elf_strfmt(struct elf_binary *elf, elf_ptrval start)
|
||||
+{
|
||||
+ const char *str = elf_strval(elf, start);
|
||||
+
|
||||
+ if ( str == NULL )
|
||||
+ return "(invalid)";
|
||||
+ return str;
|
||||
+}
|
||||
+
|
||||
ELF_PTRVAL_CONST_VOID elf_section_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr)
|
||||
{
|
||||
return ELF_IMAGE_BASE(elf) + elf_uval(elf, shdr, sh_offset);
|
||||
diff --git a/xen/include/xen/libelf.h b/xen/include/xen/libelf.h
|
||||
index af5b5c5..ddc3ed7 100644
|
||||
--- a/xen/include/xen/libelf.h
|
||||
+++ b/xen/include/xen/libelf.h
|
||||
@@ -57,8 +57,9 @@ typedef void elf_log_callback(struct elf_binary*, void *caller_data,
|
||||
* on this.
|
||||
* This replaces variables which were char*,void*
|
||||
* and their const versions, so we provide four
|
||||
- * different declaration macros:
|
||||
+ * different obsolete declaration macros:
|
||||
* ELF_PTRVAL_{,CONST}{VOID,CHAR}
|
||||
+ * New code can simply use the elf_ptrval typedef.
|
||||
* HANDLE A pointer to a struct. There is one of these types
|
||||
* for each pointer type - that is, for each "structname".
|
||||
* In the arguments to the various HANDLE macros, structname
|
||||
@@ -67,54 +68,66 @@ typedef void elf_log_callback(struct elf_binary*, void *caller_data,
|
||||
* pointers. In the current code attempts to do so will
|
||||
* compile, but in the next patch this will become a
|
||||
* compile error.
|
||||
- * We provide two declaration macros for const and
|
||||
- * non-const pointers.
|
||||
+ * We also provide a second declaration macro for
|
||||
+ * pointers which were to const; this is obsolete.
|
||||
*/
|
||||
|
||||
-#define ELF_REALPTR2PTRVAL(realpointer) (realpointer)
|
||||
+typedef uintptr_t elf_ptrval;
|
||||
+
|
||||
+#define ELF_REALPTR2PTRVAL(realpointer) ((elf_ptrval)(realpointer))
|
||||
/* Converts an actual C pointer into a PTRVAL */
|
||||
|
||||
-#define ELF_HANDLE_DECL_NONCONST(structname) structname *
|
||||
-#define ELF_HANDLE_DECL(structname) const structname *
|
||||
+#define ELF_HANDLE_DECL_NONCONST(structname) structname##_handle /*obsolete*/
|
||||
+#define ELF_HANDLE_DECL(structname) structname##_handle
|
||||
/* Provides a type declaration for a HANDLE. */
|
||||
- /* May only be used to declare ONE variable at a time */
|
||||
|
||||
-#define ELF_PTRVAL_VOID void *
|
||||
-#define ELF_PTRVAL_CHAR char *
|
||||
-#define ELF_PTRVAL_CONST_VOID const void *
|
||||
-#define ELF_PTRVAL_CONST_CHAR const char *
|
||||
- /* Provides a type declaration for a PTRVAL. */
|
||||
- /* May only be used to declare ONE variable at a time */
|
||||
+#define ELF_PTRVAL_VOID elf_ptrval /*obsolete*/
|
||||
+#define ELF_PTRVAL_CHAR elf_ptrval /*obsolete*/
|
||||
+#define ELF_PTRVAL_CONST_VOID elf_ptrval /*obsolete*/
|
||||
+#define ELF_PTRVAL_CONST_CHAR elf_ptrval /*obsolete*/
|
||||
+
|
||||
+#ifdef __XEN__
|
||||
+# define ELF_PRPTRVAL "lu"
|
||||
+ /*
|
||||
+ * PRIuPTR is misdefined in xen/include/xen/inttypes.h, on 32-bit,
|
||||
+ * to "u", when in fact uintptr_t is an unsigned long.
|
||||
+ */
|
||||
+#else
|
||||
+# define ELF_PRPTRVAL PRIuPTR
|
||||
+#endif
|
||||
+ /* printf format a la PRId... for a PTRVAL */
|
||||
|
||||
-#define ELF_DEFINE_HANDLE(structname) /* empty */
|
||||
+#define ELF_DEFINE_HANDLE(structname) \
|
||||
+ typedef union { \
|
||||
+ elf_ptrval ptrval; \
|
||||
+ const structname *typeonly; /* for sizeof, offsetof, &c only */ \
|
||||
+ } structname##_handle;
|
||||
/*
|
||||
* This must be invoked for each HANDLE type to define
|
||||
* the actual C type used for that kind of HANDLE.
|
||||
*/
|
||||
|
||||
-#define ELF_PRPTRVAL "p"
|
||||
- /* printf format a la PRId... for a PTRVAL */
|
||||
-
|
||||
-#define ELF_MAKE_HANDLE(structname, ptrval) (ptrval)
|
||||
+#define ELF_MAKE_HANDLE(structname, ptrval) ((structname##_handle){ ptrval })
|
||||
/* Converts a PTRVAL to a HANDLE */
|
||||
|
||||
-#define ELF_IMAGE_BASE(elf) ((elf)->image)
|
||||
+#define ELF_IMAGE_BASE(elf) ((elf_ptrval)(elf)->image_base)
|
||||
/* Returns the base of the image as a PTRVAL. */
|
||||
|
||||
-#define ELF_HANDLE_PTRVAL(handleval) ((void*)(handleval))
|
||||
+#define ELF_HANDLE_PTRVAL(handleval) ((handleval).ptrval)
|
||||
/* Converts a HANDLE to a PTRVAL. */
|
||||
|
||||
-#define ELF_OBSOLETE_VOIDP_CAST (void*)(uintptr_t)
|
||||
+#define ELF_OBSOLETE_VOIDP_CAST /*empty*/
|
||||
/*
|
||||
- * In some places the existing code needs to
|
||||
+ * In some places the old code used to need to
|
||||
* - cast away const (the existing code uses const a fair
|
||||
* bit but actually sometimes wants to write to its input)
|
||||
* from a PTRVAL.
|
||||
* - convert an integer representing a pointer to a PTRVAL
|
||||
- * This macro provides a suitable cast.
|
||||
+ * Nowadays all of these re uintptr_ts so there is no const problem
|
||||
+ * and no need for any casting.
|
||||
*/
|
||||
|
||||
-#define ELF_UNSAFE_PTR(ptrval) ((void*)(uintptr_t)(ptrval))
|
||||
+#define ELF_UNSAFE_PTR(ptrval) ((void*)(elf_ptrval)(ptrval))
|
||||
/*
|
||||
* Turns a PTRVAL into an actual C pointer. Before this is done
|
||||
* the caller must have ensured that the PTRVAL does in fact point
|
||||
@@ -122,18 +135,21 @@ typedef void elf_log_callback(struct elf_binary*, void *caller_data,
|
||||
*/
|
||||
|
||||
/* PTRVALs can be INVALID (ie, NULL). */
|
||||
-#define ELF_INVALID_PTRVAL (NULL) /* returns NULL PTRVAL */
|
||||
+#define ELF_INVALID_PTRVAL ((elf_ptrval)0) /* returns NULL PTRVAL */
|
||||
#define ELF_INVALID_HANDLE(structname) /* returns NULL handle */ \
|
||||
ELF_MAKE_HANDLE(structname, ELF_INVALID_PTRVAL)
|
||||
-#define ELF_PTRVAL_VALID(ptrval) (ptrval) /* } */
|
||||
-#define ELF_HANDLE_VALID(handleval) (handleval) /* } predicates */
|
||||
-#define ELF_PTRVAL_INVALID(ptrval) ((ptrval) == NULL) /* } */
|
||||
+#define ELF_PTRVAL_VALID(ptrval) (!!(ptrval)) /* } */
|
||||
+#define ELF_HANDLE_VALID(handleval) (!!(handleval).ptrval) /* } predicates */
|
||||
+#define ELF_PTRVAL_INVALID(ptrval) (!ELF_PTRVAL_VALID((ptrval))) /* } */
|
||||
+
|
||||
+#define ELF_MAX_PTRVAL (~(elf_ptrval)0)
|
||||
+ /* PTRVAL value guaranteed to compare > to any valid PTRVAL */
|
||||
|
||||
/* For internal use by other macros here */
|
||||
#define ELF__HANDLE_FIELD_TYPE(handleval, elm) \
|
||||
- typeof((handleval)->elm)
|
||||
+ typeof((handleval).typeonly->elm)
|
||||
#define ELF__HANDLE_FIELD_OFFSET(handleval, elm) \
|
||||
- offsetof(typeof(*(handleval)),elm)
|
||||
+ offsetof(typeof(*(handleval).typeonly),elm)
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
@@ -182,7 +198,7 @@ ELF_DEFINE_HANDLE(elf_note)
|
||||
|
||||
struct elf_binary {
|
||||
/* elf binary */
|
||||
- const char *image;
|
||||
+ const void *image_base;
|
||||
size_t size;
|
||||
char class;
|
||||
char data;
|
||||
@@ -190,10 +206,16 @@ struct elf_binary {
|
||||
ELF_HANDLE_DECL(elf_ehdr) ehdr;
|
||||
ELF_PTRVAL_CONST_CHAR sec_strtab;
|
||||
ELF_HANDLE_DECL(elf_shdr) sym_tab;
|
||||
- ELF_PTRVAL_CONST_CHAR sym_strtab;
|
||||
+ uint64_t sym_strtab;
|
||||
|
||||
/* loaded to */
|
||||
- char *dest;
|
||||
+ /*
|
||||
+ * dest_base and dest_size are trusted and must be correct;
|
||||
+ * whenever dest_size is not 0, both of these must be valid
|
||||
+ * so long as the struct elf_binary is in use.
|
||||
+ */
|
||||
+ char *dest_base;
|
||||
+ size_t dest_size;
|
||||
uint64_t pstart;
|
||||
uint64_t pend;
|
||||
uint64_t reloc_offset;
|
||||
@@ -201,12 +223,22 @@ struct elf_binary {
|
||||
uint64_t bsd_symtab_pstart;
|
||||
uint64_t bsd_symtab_pend;
|
||||
|
||||
+ /*
|
||||
+ * caller's other acceptable destination
|
||||
+ *
|
||||
+ * Again, these are trusted and must be valid (or 0) so long
|
||||
+ * as the struct elf_binary is in use.
|
||||
+ */
|
||||
+ void *caller_xdest_base;
|
||||
+ uint64_t caller_xdest_size;
|
||||
+
|
||||
#ifndef __XEN__
|
||||
/* misc */
|
||||
elf_log_callback *log_callback;
|
||||
void *log_caller_data;
|
||||
#endif
|
||||
int verbose;
|
||||
+ const char *broken;
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
@@ -224,22 +256,27 @@ struct elf_binary {
|
||||
#define elf_lsb(elf) (ELFDATA2LSB == (elf)->data)
|
||||
#define elf_swap(elf) (NATIVE_ELFDATA != (elf)->data)
|
||||
|
||||
-#define elf_uval(elf, str, elem) \
|
||||
- ((ELFCLASS64 == (elf)->class) \
|
||||
- ? elf_access_unsigned((elf), (str), \
|
||||
- offsetof(typeof(*(str)),e64.elem), \
|
||||
- sizeof((str)->e64.elem)) \
|
||||
- : elf_access_unsigned((elf), (str), \
|
||||
- offsetof(typeof(*(str)),e32.elem), \
|
||||
- sizeof((str)->e32.elem)))
|
||||
+#define elf_uval_3264(elf, handle, elem) \
|
||||
+ elf_access_unsigned((elf), (handle).ptrval, \
|
||||
+ offsetof(typeof(*(handle).typeonly),elem), \
|
||||
+ sizeof((handle).typeonly->elem))
|
||||
+
|
||||
+#define elf_uval(elf, handle, elem) \
|
||||
+ ((ELFCLASS64 == (elf)->class) \
|
||||
+ ? elf_uval_3264(elf, handle, e64.elem) \
|
||||
+ : elf_uval_3264(elf, handle, e32.elem))
|
||||
/*
|
||||
* Reads an unsigned field in a header structure in the ELF.
|
||||
* str is a HANDLE, and elem is the field name in it.
|
||||
*/
|
||||
|
||||
-#define elf_size(elf, str) \
|
||||
+
|
||||
+#define elf_size(elf, handle_or_handletype) ({ \
|
||||
+ typeof(handle_or_handletype) elf_size__dummy; \
|
||||
((ELFCLASS64 == (elf)->class) \
|
||||
- ? sizeof((str)->e64) : sizeof((str)->e32))
|
||||
+ ? sizeof(elf_size__dummy.typeonly->e64) \
|
||||
+ : sizeof(elf_size__dummy.typeonly->e32)); \
|
||||
+})
|
||||
/*
|
||||
* Returns the size of the substructure for the appropriate 32/64-bitness.
|
||||
* str should be a HANDLE.
|
||||
@@ -251,23 +288,37 @@ uint64_t elf_access_unsigned(struct elf_binary *elf, ELF_PTRVAL_CONST_VOID ptr,
|
||||
|
||||
uint64_t elf_round_up(struct elf_binary *elf, uint64_t addr);
|
||||
|
||||
+const char *elf_strval(struct elf_binary *elf, elf_ptrval start);
|
||||
+ /* may return NULL if the string is out of range etc. */
|
||||
|
||||
-#define elf_strval(elf,x) ((const char*)(x)) /* may return NULL in the future */
|
||||
-#define elf_strfmt(elf,x) ((const char*)(x)) /* will return (invalid) instead */
|
||||
+const char *elf_strfmt(struct elf_binary *elf, elf_ptrval start);
|
||||
+ /* like elf_strval but returns "(invalid)" instead of NULL */
|
||||
|
||||
-#define elf_memcpy_safe(elf, dst, src, sz) memcpy((dst),(src),(sz))
|
||||
-#define elf_memset_safe(elf, dst, c, sz) memset((dst),(c),(sz))
|
||||
+void elf_memcpy_safe(struct elf_binary*, elf_ptrval dst, elf_ptrval src, size_t);
|
||||
+void elf_memset_safe(struct elf_binary*, elf_ptrval dst, int c, size_t);
|
||||
/*
|
||||
- * Versions of memcpy and memset which will (in the next patch)
|
||||
- * arrange never to write outside permitted areas.
|
||||
+ * Versions of memcpy and memset which arrange never to write
|
||||
+ * outside permitted areas.
|
||||
*/
|
||||
|
||||
-#define elf_store_val(elf, type, ptr, val) (*(type*)(ptr) = (val))
|
||||
+int elf_access_ok(struct elf_binary * elf,
|
||||
+ uint64_t ptrval, size_t size);
|
||||
+
|
||||
+#define elf_store_val(elf, type, ptr, val) \
|
||||
+ ({ \
|
||||
+ typeof(type) elf_store__val = (val); \
|
||||
+ elf_ptrval elf_store__targ = ptr; \
|
||||
+ if (elf_access_ok((elf), elf_store__targ, \
|
||||
+ sizeof(elf_store__val))) { \
|
||||
+ elf_memcpy_unchecked((void*)elf_store__targ, &elf_store__val, \
|
||||
+ sizeof(elf_store__val)); \
|
||||
+ } \
|
||||
+ }) \
|
||||
/* Stores a value at a particular PTRVAL. */
|
||||
|
||||
-#define elf_store_field(elf, hdr, elm, val) \
|
||||
- (elf_store_val((elf), ELF__HANDLE_FIELD_TYPE(hdr, elm), \
|
||||
- &((hdr)->elm), \
|
||||
+#define elf_store_field(elf, hdr, elm, val) \
|
||||
+ (elf_store_val((elf), ELF__HANDLE_FIELD_TYPE(hdr, elm), \
|
||||
+ ELF_HANDLE_PTRVAL(hdr) + ELF__HANDLE_FIELD_OFFSET(hdr, elm), \
|
||||
(val)))
|
||||
/* Stores a 32/64-bit field. hdr is a HANDLE and elm is the field name. */
|
||||
|
||||
@@ -306,6 +357,10 @@ int elf_phdr_is_loadable(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr)
|
||||
/* xc_libelf_loader.c */
|
||||
|
||||
int elf_init(struct elf_binary *elf, const char *image, size_t size);
|
||||
+ /*
|
||||
+ * image and size must be correct. They will be recorded in
|
||||
+ * *elf, and must remain valid while the elf is in use.
|
||||
+ */
|
||||
#ifdef __XEN__
|
||||
void elf_set_verbose(struct elf_binary *elf);
|
||||
#else
|
||||
@@ -321,6 +376,9 @@ uint64_t elf_lookup_addr(struct elf_binary *elf, const char *symbol);
|
||||
|
||||
void elf_parse_bsdsyms(struct elf_binary *elf, uint64_t pstart); /* private */
|
||||
|
||||
+void elf_mark_broken(struct elf_binary *elf, const char *msg);
|
||||
+const char *elf_check_broken(const struct elf_binary *elf); /* NULL means OK */
|
||||
+
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* xc_libelf_relocate.c */
|
||||
|
||||
@@ -395,16 +453,38 @@ int elf_xen_parse_guest_info(struct elf_binary *elf,
|
||||
int elf_xen_parse(struct elf_binary *elf,
|
||||
struct elf_dom_parms *parms);
|
||||
|
||||
-#define elf_memcpy_unchecked memcpy
|
||||
-#define elf_memset_unchecked memset
|
||||
+static inline void *elf_memcpy_unchecked(void *dest, const void *src, size_t n)
|
||||
+ { return memcpy(dest, src, n); }
|
||||
+static inline void *elf_memmove_unchecked(void *dest, const void *src, size_t n)
|
||||
+ { return memmove(dest, src, n); }
|
||||
+static inline void *elf_memset_unchecked(void *s, int c, size_t n)
|
||||
+ { return memset(s, c, n); }
|
||||
/*
|
||||
- * Unsafe versions of memcpy and memset which take actual C
|
||||
- * pointers. These are just like real memcpy and memset.
|
||||
+ * Unsafe versions of memcpy, memmove memset which take actual C
|
||||
+ * pointers. These are just like the real functions.
|
||||
+ * We provide these so that in libelf-private.h we can #define
|
||||
+ * memcpy, memset and memmove to undefined MISTAKE things.
|
||||
*/
|
||||
|
||||
|
||||
-#define ELF_ADVANCE_DEST(elf, amount) elf->dest += (amount)
|
||||
- /* Advances past amount bytes of the current destination area. */
|
||||
+/* Advances past amount bytes of the current destination area. */
|
||||
+static inline void ELF_ADVANCE_DEST(struct elf_binary *elf, uint64_t amount)
|
||||
+{
|
||||
+ if ( elf->dest_base == NULL )
|
||||
+ {
|
||||
+ elf_mark_broken(elf, "advancing in null image");
|
||||
+ }
|
||||
+ else if ( elf->dest_size >= amount )
|
||||
+ {
|
||||
+ elf->dest_base += amount;
|
||||
+ elf->dest_size -= amount;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ elf->dest_size = 0;
|
||||
+ elf_mark_broken(elf, "advancing past end (image very short?)");
|
||||
+ }
|
||||
+}
|
||||
|
||||
|
||||
#endif /* __XEN_LIBELF_H__ */
|
||||
--
|
||||
1.7.2.5
|
||||
|
@ -0,0 +1,371 @@
|
||||
From d0790bdad7496e720416b2d4a04563c4c27e7b95 Mon Sep 17 00:00:00 2001
|
||||
From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Date: Fri, 14 Jun 2013 16:43:17 +0100
|
||||
Subject: [PATCH 12/23] libelf: Check pointer references in elf_is_elfbinary
|
||||
|
||||
elf_is_elfbinary didn't take a length parameter and could potentially
|
||||
access out of range when provided with a very short image.
|
||||
|
||||
We only need to check the size is enough for the actual dereference in
|
||||
elf_is_elfbinary; callers are just using it to check the magic number
|
||||
and do their own checks (usually via the new elf_ptrval system) before
|
||||
dereferencing other parts of the header.
|
||||
|
||||
This is part of the fix to a security issue, XSA-55.
|
||||
|
||||
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
|
||||
---
|
||||
tools/libxc/xc_dom_elfloader.c | 2 +-
|
||||
xen/arch/x86/bzimage.c | 4 ++--
|
||||
xen/common/libelf/libelf-loader.c | 2 +-
|
||||
xen/common/libelf/libelf-tools.c | 9 ++++++---
|
||||
xen/include/xen/libelf.h | 4 +++-
|
||||
5 files changed, 13 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c
|
||||
index b82a08c..ea45886 100644
|
||||
--- a/tools/libxc/xc_dom_elfloader.c
|
||||
+++ b/tools/libxc/xc_dom_elfloader.c
|
||||
@@ -95,7 +95,7 @@ static int check_elf_kernel(struct xc_dom_image *dom, int verbose)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
- if ( !elf_is_elfbinary(dom->kernel_blob) )
|
||||
+ if ( !elf_is_elfbinary(dom->kernel_blob, dom->kernel_size) )
|
||||
{
|
||||
if ( verbose )
|
||||
xc_dom_panic(dom->xch,
|
||||
diff --git a/xen/arch/x86/bzimage.c b/xen/arch/x86/bzimage.c
|
||||
index 5adc223..3600dca 100644
|
||||
--- a/xen/arch/x86/bzimage.c
|
||||
+++ b/xen/arch/x86/bzimage.c
|
||||
@@ -220,7 +220,7 @@ unsigned long __init bzimage_headroom(char *image_start,
|
||||
image_length = hdr->payload_length;
|
||||
}
|
||||
|
||||
- if ( elf_is_elfbinary(image_start) )
|
||||
+ if ( elf_is_elfbinary(image_start, image_length) )
|
||||
return 0;
|
||||
|
||||
orig_image_len = image_length;
|
||||
@@ -251,7 +251,7 @@ int __init bzimage_parse(char *image_base, char **image_start, unsigned long *im
|
||||
*image_len = hdr->payload_length;
|
||||
}
|
||||
|
||||
- if ( elf_is_elfbinary(*image_start) )
|
||||
+ if ( elf_is_elfbinary(*image_start, *image_len) )
|
||||
return 0;
|
||||
|
||||
BUG_ON(!(image_base < *image_start));
|
||||
diff --git a/xen/common/libelf/libelf-loader.c b/xen/common/libelf/libelf-loader.c
|
||||
index a3310e7..f8be635 100644
|
||||
--- a/xen/common/libelf/libelf-loader.c
|
||||
+++ b/xen/common/libelf/libelf-loader.c
|
||||
@@ -29,7 +29,7 @@ int elf_init(struct elf_binary *elf, const char *image_input, size_t size)
|
||||
ELF_HANDLE_DECL(elf_shdr) shdr;
|
||||
uint64_t i, count, section, offset;
|
||||
|
||||
- if ( !elf_is_elfbinary(image_input) )
|
||||
+ if ( !elf_is_elfbinary(image_input, size) )
|
||||
{
|
||||
elf_err(elf, "%s: not an ELF binary\n", __FUNCTION__);
|
||||
return -1;
|
||||
diff --git a/xen/common/libelf/libelf-tools.c b/xen/common/libelf/libelf-tools.c
|
||||
index 46ca553..744027e 100644
|
||||
--- a/xen/common/libelf/libelf-tools.c
|
||||
+++ b/xen/common/libelf/libelf-tools.c
|
||||
@@ -332,11 +332,14 @@ ELF_HANDLE_DECL(elf_note) elf_note_next(struct elf_binary *elf, ELF_HANDLE_DECL(
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
-int elf_is_elfbinary(const void *image)
|
||||
+int elf_is_elfbinary(const void *image_start, size_t image_size)
|
||||
{
|
||||
- const Elf32_Ehdr *ehdr = image;
|
||||
+ const Elf32_Ehdr *ehdr = image_start;
|
||||
|
||||
- return IS_ELF(*ehdr); /* fixme unchecked */
|
||||
+ if ( image_size < sizeof(*ehdr) )
|
||||
+ return 0;
|
||||
+
|
||||
+ return IS_ELF(*ehdr);
|
||||
}
|
||||
|
||||
int elf_phdr_is_loadable(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr)
|
||||
diff --git a/xen/include/xen/libelf.h b/xen/include/xen/libelf.h
|
||||
index ddc3ed7..ac93858 100644
|
||||
--- a/xen/include/xen/libelf.h
|
||||
+++ b/xen/include/xen/libelf.h
|
||||
@@ -350,7 +350,9 @@ uint64_t elf_note_numeric_array(struct elf_binary *, ELF_HANDLE_DECL(elf_note),
|
||||
unsigned int unitsz, unsigned int idx);
|
||||
ELF_HANDLE_DECL(elf_note) elf_note_next(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
|
||||
|
||||
-int elf_is_elfbinary(const void *image);
|
||||
+/* (Only) checks that the image has the right magic number. */
|
||||
+int elf_is_elfbinary(const void *image_start, size_t image_size);
|
||||
+
|
||||
int elf_phdr_is_loadable(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr);
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
--
|
||||
1.7.2.5
|
||||
#From a965b8f80388603d439ae2b8ee7b9b018a079f90 Mon Sep 17 00:00:00 2001
|
||||
#From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
#Date: Fri, 14 Jun 2013 16:43:17 +0100
|
||||
#Subject: [PATCH 13/23] libelf: Make all callers call elf_check_broken
|
||||
#
|
||||
#This arranges that if the new pointer reference error checking
|
||||
#tripped, we actually get a message about it. In this patch these
|
||||
#messages do not change the actual return values from the various
|
||||
#functions: so pointer reference errors do not prevent loading. This
|
||||
#is for fear that some existing kernels might cause the code to make
|
||||
#these wild references, which would then break, which is not a good
|
||||
#thing in a security patch.
|
||||
#
|
||||
#In xen/arch/x86/domain_build.c we have to introduce an "out" label and
|
||||
#change all of the "return rc" beyond the relevant point into "goto
|
||||
#out".
|
||||
#
|
||||
#Difference in the 4.2 series, compared to unstable:
|
||||
#
|
||||
#* tools/libxc/xc_hvm_build_x86.c:setup_guest and
|
||||
# xen/arch/arm/kernel.c:kernel_try_elf_prepare have different
|
||||
# error handling in 4.2 to unstable; patch adjusted accordingly.
|
||||
#
|
||||
#This is part of the fix to a security issue, XSA-55.
|
||||
#
|
||||
#Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
#
|
||||
#xen-unstable version Reviewed-by: George Dunlap <george.dunlap@eu.citrix.com>
|
||||
#---
|
||||
# tools/libxc/xc_dom_elfloader.c | 25 +++++++++++++++++++++----
|
||||
# tools/libxc/xc_hvm_build_x86.c | 5 +++++
|
||||
# tools/xcutils/readnotes.c | 3 +++
|
||||
# xen/arch/arm/kernel.c | 15 ++++++++++++++-
|
||||
# xen/arch/x86/domain_build.c | 28 +++++++++++++++++++++-------
|
||||
# 5 files changed, 64 insertions(+), 12 deletions(-)
|
||||
#
|
||||
diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c
|
||||
index ea45886..4fb4da2 100644
|
||||
--- a/tools/libxc/xc_dom_elfloader.c
|
||||
+++ b/tools/libxc/xc_dom_elfloader.c
|
||||
@@ -276,6 +276,13 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
elf_store_field(elf, shdr, e32.sh_name, 0);
|
||||
}
|
||||
|
||||
+ if ( elf_check_broken(&syms) )
|
||||
+ DOMPRINTF("%s: symbols ELF broken: %s", __FUNCTION__,
|
||||
+ elf_check_broken(&syms));
|
||||
+ if ( elf_check_broken(elf) )
|
||||
+ DOMPRINTF("%s: ELF broken: %s", __FUNCTION__,
|
||||
+ elf_check_broken(elf));
|
||||
+
|
||||
if ( tables == 0 )
|
||||
{
|
||||
DOMPRINTF("%s: no symbol table present", __FUNCTION__);
|
||||
@@ -312,19 +319,23 @@ static int xc_dom_parse_elf_kernel(struct xc_dom_image *dom)
|
||||
{
|
||||
xc_dom_panic(dom->xch, XC_INVALID_KERNEL, "%s: ELF image"
|
||||
" has no shstrtab", __FUNCTION__);
|
||||
- return -EINVAL;
|
||||
+ rc = -EINVAL;
|
||||
+ goto out;
|
||||
}
|
||||
|
||||
/* parse binary and get xen meta info */
|
||||
elf_parse_binary(elf);
|
||||
if ( (rc = elf_xen_parse(elf, &dom->parms)) != 0 )
|
||||
- return rc;
|
||||
+ {
|
||||
+ goto out;
|
||||
+ }
|
||||
|
||||
if ( elf_xen_feature_get(XENFEAT_dom0, dom->parms.f_required) )
|
||||
{
|
||||
xc_dom_panic(dom->xch, XC_INVALID_KERNEL, "%s: Kernel does not"
|
||||
" support unprivileged (DomU) operation", __FUNCTION__);
|
||||
- return -EINVAL;
|
||||
+ rc = -EINVAL;
|
||||
+ goto out;
|
||||
}
|
||||
|
||||
/* find kernel segment */
|
||||
@@ -338,7 +349,13 @@ static int xc_dom_parse_elf_kernel(struct xc_dom_image *dom)
|
||||
DOMPRINTF("%s: %s: 0x%" PRIx64 " -> 0x%" PRIx64 "",
|
||||
__FUNCTION__, dom->guest_type,
|
||||
dom->kernel_seg.vstart, dom->kernel_seg.vend);
|
||||
- return 0;
|
||||
+ rc = 0;
|
||||
+out:
|
||||
+ if ( elf_check_broken(elf) )
|
||||
+ DOMPRINTF("%s: ELF broken: %s", __FUNCTION__,
|
||||
+ elf_check_broken(elf));
|
||||
+
|
||||
+ return rc;
|
||||
}
|
||||
|
||||
static int xc_dom_load_elf_kernel(struct xc_dom_image *dom)
|
||||
diff --git a/tools/libxc/xc_hvm_build_x86.c b/tools/libxc/xc_hvm_build_x86.c
|
||||
index ccfd8b5..8165287 100644
|
||||
--- a/tools/libxc/xc_hvm_build_x86.c
|
||||
+++ b/tools/libxc/xc_hvm_build_x86.c
|
||||
@@ -403,11 +403,16 @@ static int setup_guest(xc_interface *xch,
|
||||
munmap(page0, PAGE_SIZE);
|
||||
}
|
||||
|
||||
+ if ( elf_check_broken(&elf) )
|
||||
+ ERROR("HVM ELF broken: %s", elf_check_broken(&elf));
|
||||
+
|
||||
free(page_array);
|
||||
return 0;
|
||||
|
||||
error_out:
|
||||
free(page_array);
|
||||
+ if ( elf_check_broken(&elf) )
|
||||
+ ERROR("HVM ELF broken, failing: %s", elf_check_broken(&elf));
|
||||
return -1;
|
||||
}
|
||||
|
||||
diff --git a/tools/xcutils/readnotes.c b/tools/xcutils/readnotes.c
|
||||
index cfae994..d1f7a30 100644
|
||||
--- a/tools/xcutils/readnotes.c
|
||||
+++ b/tools/xcutils/readnotes.c
|
||||
@@ -301,6 +301,9 @@ int main(int argc, char **argv)
|
||||
printf("__xen_guest: %s\n",
|
||||
elf_strfmt(&elf, elf_section_start(&elf, shdr)));
|
||||
|
||||
+ if (elf_check_broken(&elf))
|
||||
+ printf("warning: broken ELF: %s\n", elf_check_broken(&elf));
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
diff --git a/xen/arch/arm/kernel.c b/xen/arch/arm/kernel.c
|
||||
index 2d56130..dec0519 100644
|
||||
--- a/xen/arch/arm/kernel.c
|
||||
+++ b/xen/arch/arm/kernel.c
|
||||
@@ -146,6 +146,8 @@ static int kernel_try_elf_prepare(struct kernel_info *info)
|
||||
{
|
||||
int rc;
|
||||
|
||||
+ memset(&info->elf.elf, 0, sizeof(info->elf.elf));
|
||||
+
|
||||
info->kernel_order = get_order_from_bytes(KERNEL_FLASH_SIZE);
|
||||
info->kernel_img = alloc_xenheap_pages(info->kernel_order, 0);
|
||||
if ( info->kernel_img == NULL )
|
||||
@@ -160,7 +162,7 @@ static int kernel_try_elf_prepare(struct kernel_info *info)
|
||||
#endif
|
||||
elf_parse_binary(&info->elf.elf);
|
||||
if ( (rc = elf_xen_parse(&info->elf.elf, &info->elf.parms)) != 0 )
|
||||
- return rc;
|
||||
+ goto err;
|
||||
|
||||
/*
|
||||
* TODO: can the ELF header be used to find the physical address
|
||||
@@ -169,7 +171,18 @@ static int kernel_try_elf_prepare(struct kernel_info *info)
|
||||
info->entry = info->elf.parms.virt_entry;
|
||||
info->load = kernel_elf_load;
|
||||
|
||||
+ if ( elf_check_broken(&info->elf.elf) )
|
||||
+ printk("Xen: warning: ELF kernel broken: %s\n",
|
||||
+ elf_check_broken(&info->elf.elf));
|
||||
+
|
||||
return 0;
|
||||
+
|
||||
+err:
|
||||
+ if ( elf_check_broken(&info->elf.elf) )
|
||||
+ printk("Xen: ELF kernel broken: %s\n",
|
||||
+ elf_check_broken(&info->elf.elf));
|
||||
+
|
||||
+ return rc;
|
||||
}
|
||||
|
||||
int kernel_prepare(struct kernel_info *info)
|
||||
diff --git a/xen/arch/x86/domain_build.c b/xen/arch/x86/domain_build.c
|
||||
index a655b21..0dbec96 100644
|
||||
--- a/xen/arch/x86/domain_build.c
|
||||
+++ b/xen/arch/x86/domain_build.c
|
||||
@@ -374,7 +374,7 @@ int __init construct_dom0(
|
||||
#endif
|
||||
elf_parse_binary(&elf);
|
||||
if ( (rc = elf_xen_parse(&elf, &parms)) != 0 )
|
||||
- return rc;
|
||||
+ goto out;
|
||||
|
||||
/* compatibility check */
|
||||
compatible = 0;
|
||||
@@ -413,14 +413,16 @@ int __init construct_dom0(
|
||||
if ( !compatible )
|
||||
{
|
||||
printk("Mismatch between Xen and DOM0 kernel\n");
|
||||
- return -EINVAL;
|
||||
+ rc = -EINVAL;
|
||||
+ goto out;
|
||||
}
|
||||
|
||||
if ( parms.elf_notes[XEN_ELFNOTE_SUPPORTED_FEATURES].type != XEN_ENT_NONE &&
|
||||
!test_bit(XENFEAT_dom0, parms.f_supported) )
|
||||
{
|
||||
printk("Kernel does not support Dom0 operation\n");
|
||||
- return -EINVAL;
|
||||
+ rc = -EINVAL;
|
||||
+ goto out;
|
||||
}
|
||||
|
||||
#if defined(__x86_64__)
|
||||
@@ -734,7 +736,8 @@ int __init construct_dom0(
|
||||
(v_end > HYPERVISOR_COMPAT_VIRT_START(d)) )
|
||||
{
|
||||
printk("DOM0 image overlaps with Xen private area.\n");
|
||||
- return -EINVAL;
|
||||
+ rc = -EINVAL;
|
||||
+ goto out;
|
||||
}
|
||||
|
||||
if ( is_pv_32on64_domain(d) )
|
||||
@@ -914,7 +917,7 @@ int __init construct_dom0(
|
||||
if ( rc < 0 )
|
||||
{
|
||||
printk("Failed to load the kernel binary\n");
|
||||
- return rc;
|
||||
+ goto out;
|
||||
}
|
||||
bootstrap_map(NULL);
|
||||
|
||||
@@ -925,7 +928,8 @@ int __init construct_dom0(
|
||||
{
|
||||
write_ptbase(current);
|
||||
printk("Invalid HYPERCALL_PAGE field in ELF notes.\n");
|
||||
- return -1;
|
||||
+ rc = -1;
|
||||
+ goto out;
|
||||
}
|
||||
hypercall_page_initialise(
|
||||
d, (void *)(unsigned long)parms.virt_hypercall);
|
||||
@@ -1272,9 +1276,19 @@ int __init construct_dom0(
|
||||
|
||||
BUG_ON(rc != 0);
|
||||
|
||||
- iommu_dom0_init(dom0);
|
||||
+ if ( elf_check_broken(&elf) )
|
||||
+ printk(" Xen warning: dom0 kernel broken ELF: %s\n",
|
||||
+ elf_check_broken(&elf));
|
||||
|
||||
+ iommu_dom0_init(dom0);
|
||||
return 0;
|
||||
+
|
||||
+out:
|
||||
+ if ( elf_check_broken(&elf) )
|
||||
+ printk(" Xen dom0 kernel broken ELF: %s\n",
|
||||
+ elf_check_broken(&elf));
|
||||
+
|
||||
+ return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
--
|
||||
1.7.2.5
|
||||
|
||||
|
@ -0,0 +1,252 @@
|
||||
From 3fb6ccf2faccaf5e22e33a3155ccc72d732896d8 Mon Sep 17 00:00:00 2001
|
||||
From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Date: Fri, 14 Jun 2013 16:43:18 +0100
|
||||
Subject: [PATCH 14/23] libelf: use C99 bool for booleans
|
||||
|
||||
We want to remove uses of "int" because signed integers have
|
||||
undesirable undefined behaviours on overflow. Malicious compilers can
|
||||
turn apparently-correct code into code with security vulnerabilities
|
||||
etc.
|
||||
|
||||
In this patch we change all the booleans in libelf to C99 bool,
|
||||
from <stdbool.h>.
|
||||
|
||||
For the one visible libelf boolean in libxc's public interface we
|
||||
retain the use of int to avoid changing the ABI; libxc converts it to
|
||||
a bool for consumption by libelf.
|
||||
|
||||
It is OK to change all values only ever used as booleans to _Bool
|
||||
(bool) because conversion from any scalar type to a _Bool works the
|
||||
same as the boolean test in if() or ?: and is always defined (C99
|
||||
6.3.1.2). But we do need to check that all these variables really are
|
||||
only ever used that way. (It is theoretically possible that the old
|
||||
code truncated some 64-bit values to 32-bit ints which might become
|
||||
zero depending on the value, which would mean a behavioural change in
|
||||
this patch, but it seems implausible that treating 0x????????00000000
|
||||
as false could have been intended.)
|
||||
|
||||
This is part of the fix to a security issue, XSA-55.
|
||||
|
||||
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Acked-by: George Dunlap <george.dunlap@eu.citrix.com>
|
||||
---
|
||||
tools/libxc/xc_dom_elfloader.c | 8 ++++----
|
||||
xen/common/libelf/libelf-dominfo.c | 2 +-
|
||||
xen/common/libelf/libelf-loader.c | 4 ++--
|
||||
xen/common/libelf/libelf-private.h | 2 +-
|
||||
xen/common/libelf/libelf-tools.c | 10 +++++-----
|
||||
xen/include/xen/libelf.h | 18 ++++++++++--------
|
||||
6 files changed, 23 insertions(+), 21 deletions(-)
|
||||
|
||||
diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c
|
||||
index 4fb4da2..9ba64ae 100644
|
||||
--- a/tools/libxc/xc_dom_elfloader.c
|
||||
+++ b/tools/libxc/xc_dom_elfloader.c
|
||||
@@ -34,7 +34,7 @@
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
static void log_callback(struct elf_binary *elf, void *caller_data,
|
||||
- int iserr, const char *fmt, va_list al) {
|
||||
+ bool iserr, const char *fmt, va_list al) {
|
||||
xc_interface *xch = caller_data;
|
||||
|
||||
xc_reportv(xch,
|
||||
@@ -46,7 +46,7 @@ static void log_callback(struct elf_binary *elf, void *caller_data,
|
||||
|
||||
void xc_elf_set_logfile(xc_interface *xch, struct elf_binary *elf,
|
||||
int verbose) {
|
||||
- elf_set_log(elf, log_callback, xch, verbose);
|
||||
+ elf_set_log(elf, log_callback, xch, verbose /* convert to bool */);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
@@ -84,7 +84,7 @@ static char *xc_dom_guest_type(struct xc_dom_image *dom,
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* parse elf binary */
|
||||
|
||||
-static int check_elf_kernel(struct xc_dom_image *dom, int verbose)
|
||||
+static int check_elf_kernel(struct xc_dom_image *dom, bool verbose)
|
||||
{
|
||||
if ( dom->kernel_blob == NULL )
|
||||
{
|
||||
@@ -112,7 +112,7 @@ static int xc_dom_probe_elf_kernel(struct xc_dom_image *dom)
|
||||
}
|
||||
|
||||
static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
- struct elf_binary *elf, int load)
|
||||
+ struct elf_binary *elf, bool load)
|
||||
{
|
||||
struct elf_binary syms;
|
||||
ELF_HANDLE_DECL_NONCONST(elf_shdr) shdr; ELF_HANDLE_DECL(elf_shdr) shdr2;
|
||||
diff --git a/xen/common/libelf/libelf-dominfo.c b/xen/common/libelf/libelf-dominfo.c
|
||||
index 98c80dc..12b6c2a 100644
|
||||
--- a/xen/common/libelf/libelf-dominfo.c
|
||||
+++ b/xen/common/libelf/libelf-dominfo.c
|
||||
@@ -101,7 +101,7 @@ int elf_xen_parse_note(struct elf_binary *elf,
|
||||
/* *INDENT-OFF* */
|
||||
static const struct {
|
||||
char *name;
|
||||
- int str;
|
||||
+ bool str;
|
||||
} note_desc[] = {
|
||||
[XEN_ELFNOTE_ENTRY] = { "ENTRY", 0},
|
||||
[XEN_ELFNOTE_HYPERCALL_PAGE] = { "HYPERCALL_PAGE", 0},
|
||||
diff --git a/xen/common/libelf/libelf-loader.c b/xen/common/libelf/libelf-loader.c
|
||||
index f8be635..0dccd4d 100644
|
||||
--- a/xen/common/libelf/libelf-loader.c
|
||||
+++ b/xen/common/libelf/libelf-loader.c
|
||||
@@ -92,7 +92,7 @@ int elf_init(struct elf_binary *elf, const char *image_input, size_t size)
|
||||
}
|
||||
|
||||
#ifndef __XEN__
|
||||
-void elf_call_log_callback(struct elf_binary *elf, int iserr,
|
||||
+void elf_call_log_callback(struct elf_binary *elf, bool iserr,
|
||||
const char *fmt,...) {
|
||||
va_list al;
|
||||
|
||||
@@ -107,7 +107,7 @@ void elf_call_log_callback(struct elf_binary *elf, int iserr,
|
||||
}
|
||||
|
||||
void elf_set_log(struct elf_binary *elf, elf_log_callback *log_callback,
|
||||
- void *log_caller_data, int verbose)
|
||||
+ void *log_caller_data, bool verbose)
|
||||
{
|
||||
elf->log_callback = log_callback;
|
||||
elf->log_caller_data = log_caller_data;
|
||||
diff --git a/xen/common/libelf/libelf-private.h b/xen/common/libelf/libelf-private.h
|
||||
index 280dfd1..277be04 100644
|
||||
--- a/xen/common/libelf/libelf-private.h
|
||||
+++ b/xen/common/libelf/libelf-private.h
|
||||
@@ -77,7 +77,7 @@
|
||||
#define elf_err(elf, fmt, args ... ) \
|
||||
elf_call_log_callback(elf, 1, fmt , ## args );
|
||||
|
||||
-void elf_call_log_callback(struct elf_binary*, int iserr, const char *fmt,...);
|
||||
+void elf_call_log_callback(struct elf_binary*, bool iserr, const char *fmt,...);
|
||||
|
||||
#define safe_strcpy(d,s) \
|
||||
do { strncpy((d),(s),sizeof((d))-1); \
|
||||
diff --git a/xen/common/libelf/libelf-tools.c b/xen/common/libelf/libelf-tools.c
|
||||
index 744027e..fa58f76 100644
|
||||
--- a/xen/common/libelf/libelf-tools.c
|
||||
+++ b/xen/common/libelf/libelf-tools.c
|
||||
@@ -31,7 +31,7 @@ const char *elf_check_broken(const struct elf_binary *elf)
|
||||
return elf->broken;
|
||||
}
|
||||
|
||||
-static int elf_ptrval_in_range(elf_ptrval ptrval, uint64_t size,
|
||||
+static bool elf_ptrval_in_range(elf_ptrval ptrval, uint64_t size,
|
||||
const void *region, uint64_t regionsize)
|
||||
/*
|
||||
* Returns true if the putative memory area [ptrval,ptrval+size>
|
||||
@@ -53,7 +53,7 @@ static int elf_ptrval_in_range(elf_ptrval ptrval, uint64_t size,
|
||||
return 1;
|
||||
}
|
||||
|
||||
-int elf_access_ok(struct elf_binary * elf,
|
||||
+bool elf_access_ok(struct elf_binary * elf,
|
||||
uint64_t ptrval, size_t size)
|
||||
{
|
||||
if ( elf_ptrval_in_range(ptrval, size, elf->image_base, elf->size) )
|
||||
@@ -92,7 +92,7 @@ uint64_t elf_access_unsigned(struct elf_binary * elf, elf_ptrval base,
|
||||
uint64_t moreoffset, size_t size)
|
||||
{
|
||||
elf_ptrval ptrval = base + moreoffset;
|
||||
- int need_swap = elf_swap(elf);
|
||||
+ bool need_swap = elf_swap(elf);
|
||||
const uint8_t *u8;
|
||||
const uint16_t *u16;
|
||||
const uint32_t *u32;
|
||||
@@ -332,7 +332,7 @@ ELF_HANDLE_DECL(elf_note) elf_note_next(struct elf_binary *elf, ELF_HANDLE_DECL(
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
-int elf_is_elfbinary(const void *image_start, size_t image_size)
|
||||
+bool elf_is_elfbinary(const void *image_start, size_t image_size)
|
||||
{
|
||||
const Elf32_Ehdr *ehdr = image_start;
|
||||
|
||||
@@ -342,7 +342,7 @@ int elf_is_elfbinary(const void *image_start, size_t image_size)
|
||||
return IS_ELF(*ehdr);
|
||||
}
|
||||
|
||||
-int elf_phdr_is_loadable(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr)
|
||||
+bool elf_phdr_is_loadable(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr)
|
||||
{
|
||||
uint64_t p_type = elf_uval(elf, phdr, p_type);
|
||||
uint64_t p_flags = elf_uval(elf, phdr, p_flags);
|
||||
diff --git a/xen/include/xen/libelf.h b/xen/include/xen/libelf.h
|
||||
index ac93858..951430f 100644
|
||||
--- a/xen/include/xen/libelf.h
|
||||
+++ b/xen/include/xen/libelf.h
|
||||
@@ -29,6 +29,8 @@
|
||||
#error define architectural endianness
|
||||
#endif
|
||||
|
||||
+#include <stdbool.h>
|
||||
+
|
||||
#undef ELFSIZE
|
||||
#include "elfstructs.h"
|
||||
#ifdef __XEN__
|
||||
@@ -42,7 +44,7 @@
|
||||
|
||||
struct elf_binary;
|
||||
typedef void elf_log_callback(struct elf_binary*, void *caller_data,
|
||||
- int iserr, const char *fmt, va_list al);
|
||||
+ bool iserr, const char *fmt, va_list al);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -237,7 +239,7 @@ struct elf_binary {
|
||||
elf_log_callback *log_callback;
|
||||
void *log_caller_data;
|
||||
#endif
|
||||
- int verbose;
|
||||
+ bool verbose;
|
||||
const char *broken;
|
||||
};
|
||||
|
||||
@@ -301,8 +303,8 @@ void elf_memset_safe(struct elf_binary*, elf_ptrval dst, int c, size_t);
|
||||
* outside permitted areas.
|
||||
*/
|
||||
|
||||
-int elf_access_ok(struct elf_binary * elf,
|
||||
- uint64_t ptrval, size_t size);
|
||||
+bool elf_access_ok(struct elf_binary * elf,
|
||||
+ uint64_t ptrval, size_t size);
|
||||
|
||||
#define elf_store_val(elf, type, ptr, val) \
|
||||
({ \
|
||||
@@ -351,9 +353,9 @@ uint64_t elf_note_numeric_array(struct elf_binary *, ELF_HANDLE_DECL(elf_note),
|
||||
ELF_HANDLE_DECL(elf_note) elf_note_next(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
|
||||
|
||||
/* (Only) checks that the image has the right magic number. */
|
||||
-int elf_is_elfbinary(const void *image_start, size_t image_size);
|
||||
+bool elf_is_elfbinary(const void *image_start, size_t image_size);
|
||||
|
||||
-int elf_phdr_is_loadable(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr);
|
||||
+bool elf_phdr_is_loadable(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr);
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* xc_libelf_loader.c */
|
||||
@@ -367,7 +369,7 @@ int elf_init(struct elf_binary *elf, const char *image, size_t size);
|
||||
void elf_set_verbose(struct elf_binary *elf);
|
||||
#else
|
||||
void elf_set_log(struct elf_binary *elf, elf_log_callback*,
|
||||
- void *log_caller_pointer, int verbose);
|
||||
+ void *log_caller_pointer, bool verbose);
|
||||
#endif
|
||||
|
||||
void elf_parse_binary(struct elf_binary *elf);
|
||||
@@ -419,7 +421,7 @@ struct elf_dom_parms {
|
||||
char xen_ver[16];
|
||||
char loader[16];
|
||||
int pae;
|
||||
- int bsd_symtab;
|
||||
+ bool bsd_symtab;
|
||||
uint64_t virt_base;
|
||||
uint64_t virt_entry;
|
||||
uint64_t virt_hypercall;
|
||||
--
|
||||
1.7.2.5
|
||||
|
@ -0,0 +1,759 @@
|
||||
From e673ca50127b6c1263727aa31de0b8bb966ca7a2 Mon Sep 17 00:00:00 2001
|
||||
From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Date: Fri, 14 Jun 2013 16:43:18 +0100
|
||||
Subject: [PATCH 15/23] libelf: use only unsigned integers
|
||||
|
||||
Signed integers have undesirable undefined behaviours on overflow.
|
||||
Malicious compilers can turn apparently-correct code into code with
|
||||
security vulnerabilities etc.
|
||||
|
||||
So use only unsigned integers. Exceptions are booleans (which we have
|
||||
already changed) and error codes.
|
||||
|
||||
We _do_ change all the chars which aren't fixed constants from our own
|
||||
text segment, but not the char*s. This is because it is safe to
|
||||
access an arbitrary byte through a char*, but not necessarily safe to
|
||||
convert an arbitrary value to a char.
|
||||
|
||||
As a consequence we need to compile libelf with -Wno-pointer-sign.
|
||||
|
||||
It is OK to change all the signed integers to unsigned because all the
|
||||
inequalities in libelf are in contexts where we don't "expect"
|
||||
negative numbers.
|
||||
|
||||
In libelf-dominfo.c:elf_xen_parse we rename a variable "rc" to
|
||||
"more_notes" as it actually contains a note count derived from the
|
||||
input image. The "error" return value from elf_xen_parse_notes is
|
||||
changed from -1 to ~0U.
|
||||
|
||||
grepping shows only one occurrence of "PRId" or "%d" or "%ld" in
|
||||
libelf and xc_dom_elfloader.c (a "%d" which becomes "%u").
|
||||
|
||||
This is part of the fix to a security issue, XSA-55.
|
||||
|
||||
For those concerned about unintentional functional changes, the
|
||||
following rune produces a version of the patch which is much smaller
|
||||
and eliminates only non-functional changes:
|
||||
|
||||
GIT_EXTERNAL_DIFF=.../unsigned-differ git-diff <before>..<after>
|
||||
|
||||
where <before> and <after> are git refs for the code before and after
|
||||
this patch, and unsigned-differ is this shell script:
|
||||
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
seddery () {
|
||||
perl -pe 's/\b(?:elf_errorstatus|elf_negerrnoval)\b/int/g'
|
||||
}
|
||||
|
||||
path="$1"
|
||||
in="$2"
|
||||
out="$5"
|
||||
|
||||
set +e
|
||||
diff -pu --label "$path~" <(seddery <"$in") --label "$path" <(seddery <"$out")
|
||||
rc=$?
|
||||
set -e
|
||||
if [ $rc = 1 ]; then rc=0; fi
|
||||
exit $rc
|
||||
|
||||
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
---
|
||||
tools/libxc/Makefile | 9 +++++-
|
||||
tools/libxc/xc_dom.h | 7 +++--
|
||||
tools/libxc/xc_dom_elfloader.c | 42 ++++++++++++++++-------------
|
||||
tools/xcutils/readnotes.c | 15 +++++-----
|
||||
xen/common/libelf/Makefile | 2 +
|
||||
xen/common/libelf/libelf-dominfo.c | 52 ++++++++++++++++++-----------------
|
||||
xen/common/libelf/libelf-loader.c | 20 +++++++-------
|
||||
xen/common/libelf/libelf-tools.c | 24 ++++++++--------
|
||||
xen/include/xen/libelf.h | 21 ++++++++------
|
||||
9 files changed, 105 insertions(+), 87 deletions(-)
|
||||
|
||||
diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile
|
||||
index d8c6a60..a3fd90c 100644
|
||||
--- a/tools/libxc/Makefile
|
||||
+++ b/tools/libxc/Makefile
|
||||
@@ -52,8 +52,13 @@ endif
|
||||
vpath %.c ../../xen/common/libelf
|
||||
CFLAGS += -I../../xen/common/libelf
|
||||
|
||||
-GUEST_SRCS-y += libelf-tools.c libelf-loader.c
|
||||
-GUEST_SRCS-y += libelf-dominfo.c
|
||||
+ELF_SRCS-y += libelf-tools.c libelf-loader.c
|
||||
+ELF_SRCS-y += libelf-dominfo.c
|
||||
+
|
||||
+GUEST_SRCS-y += $(ELF_SRCS-y)
|
||||
+
|
||||
+$(patsubst %.c,%.o,$(ELF_SRCS-y)): CFLAGS += -Wno-pointer-sign
|
||||
+$(patsubst %.c,%.opic,$(ELF_SRCS-y)): CFLAGS += -Wno-pointer-sign
|
||||
|
||||
# new domain builder
|
||||
GUEST_SRCS-y += xc_dom_core.c xc_dom_boot.c
|
||||
diff --git a/tools/libxc/xc_dom.h b/tools/libxc/xc_dom.h
|
||||
index 9f8037e..0161459 100644
|
||||
--- a/tools/libxc/xc_dom.h
|
||||
+++ b/tools/libxc/xc_dom.h
|
||||
@@ -140,9 +140,10 @@ struct xc_dom_image {
|
||||
|
||||
struct xc_dom_loader {
|
||||
char *name;
|
||||
- int (*probe) (struct xc_dom_image * dom);
|
||||
- int (*parser) (struct xc_dom_image * dom);
|
||||
- int (*loader) (struct xc_dom_image * dom);
|
||||
+ /* Sadly the error returns from these functions are not consistent: */
|
||||
+ elf_negerrnoval (*probe) (struct xc_dom_image * dom);
|
||||
+ elf_negerrnoval (*parser) (struct xc_dom_image * dom);
|
||||
+ elf_errorstatus (*loader) (struct xc_dom_image * dom);
|
||||
|
||||
struct xc_dom_loader *next;
|
||||
};
|
||||
diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c
|
||||
index 9ba64ae..62a0d3b 100644
|
||||
--- a/tools/libxc/xc_dom_elfloader.c
|
||||
+++ b/tools/libxc/xc_dom_elfloader.c
|
||||
@@ -84,7 +84,7 @@ static char *xc_dom_guest_type(struct xc_dom_image *dom,
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* parse elf binary */
|
||||
|
||||
-static int check_elf_kernel(struct xc_dom_image *dom, bool verbose)
|
||||
+static elf_negerrnoval check_elf_kernel(struct xc_dom_image *dom, bool verbose)
|
||||
{
|
||||
if ( dom->kernel_blob == NULL )
|
||||
{
|
||||
@@ -106,12 +106,12 @@ static int check_elf_kernel(struct xc_dom_image *dom, bool verbose)
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int xc_dom_probe_elf_kernel(struct xc_dom_image *dom)
|
||||
+static elf_negerrnoval xc_dom_probe_elf_kernel(struct xc_dom_image *dom)
|
||||
{
|
||||
return check_elf_kernel(dom, 0);
|
||||
}
|
||||
|
||||
-static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
+static elf_errorstatus xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
struct elf_binary *elf, bool load)
|
||||
{
|
||||
struct elf_binary syms;
|
||||
@@ -119,7 +119,7 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
xen_vaddr_t symtab, maxaddr;
|
||||
ELF_PTRVAL_CHAR hdr;
|
||||
size_t size;
|
||||
- int h, count, type, i, tables = 0;
|
||||
+ unsigned h, count, type, i, tables = 0;
|
||||
|
||||
if ( elf_swap(elf) )
|
||||
{
|
||||
@@ -140,13 +140,13 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
elf->caller_xdest_base = hdr_ptr;
|
||||
elf->caller_xdest_size = allow_size;
|
||||
hdr = ELF_REALPTR2PTRVAL(hdr_ptr);
|
||||
- elf_store_val(elf, int, hdr, size - sizeof(int));
|
||||
+ elf_store_val(elf, unsigned, hdr, size - sizeof(unsigned));
|
||||
}
|
||||
else
|
||||
{
|
||||
char *hdr_ptr;
|
||||
|
||||
- size = sizeof(int) + elf_size(elf, elf->ehdr) +
|
||||
+ size = sizeof(unsigned) + elf_size(elf, elf->ehdr) +
|
||||
elf_shdr_count(elf) * elf_size(elf, shdr);
|
||||
hdr_ptr = xc_dom_malloc(dom, size);
|
||||
if ( hdr_ptr == NULL )
|
||||
@@ -157,15 +157,15 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
dom->bsd_symtab_start = elf_round_up(elf, dom->kernel_seg.vend);
|
||||
}
|
||||
|
||||
- elf_memcpy_safe(elf, hdr + sizeof(int),
|
||||
+ elf_memcpy_safe(elf, hdr + sizeof(unsigned),
|
||||
ELF_IMAGE_BASE(elf),
|
||||
elf_size(elf, elf->ehdr));
|
||||
- elf_memcpy_safe(elf, hdr + sizeof(int) + elf_size(elf, elf->ehdr),
|
||||
+ elf_memcpy_safe(elf, hdr + sizeof(unsigned) + elf_size(elf, elf->ehdr),
|
||||
ELF_IMAGE_BASE(elf) + elf_uval(elf, elf->ehdr, e_shoff),
|
||||
elf_shdr_count(elf) * elf_size(elf, shdr));
|
||||
if ( elf_64bit(elf) )
|
||||
{
|
||||
- Elf64_Ehdr *ehdr = (Elf64_Ehdr *)(hdr + sizeof(int));
|
||||
+ Elf64_Ehdr *ehdr = (Elf64_Ehdr *)(hdr + sizeof(unsigned));
|
||||
ehdr->e_phoff = 0;
|
||||
ehdr->e_phentsize = 0;
|
||||
ehdr->e_phnum = 0;
|
||||
@@ -174,22 +174,22 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
}
|
||||
else
|
||||
{
|
||||
- Elf32_Ehdr *ehdr = (Elf32_Ehdr *)(hdr + sizeof(int));
|
||||
+ Elf32_Ehdr *ehdr = (Elf32_Ehdr *)(hdr + sizeof(unsigned));
|
||||
ehdr->e_phoff = 0;
|
||||
ehdr->e_phentsize = 0;
|
||||
ehdr->e_phnum = 0;
|
||||
ehdr->e_shoff = elf_size(elf, elf->ehdr);
|
||||
ehdr->e_shstrndx = SHN_UNDEF;
|
||||
}
|
||||
- if ( elf->caller_xdest_size < sizeof(int) )
|
||||
+ if ( elf->caller_xdest_size < sizeof(unsigned) )
|
||||
{
|
||||
DOMPRINTF("%s/%s: header size %"PRIx64" too small",
|
||||
__FUNCTION__, load ? "load" : "parse",
|
||||
(uint64_t)elf->caller_xdest_size);
|
||||
return -1;
|
||||
}
|
||||
- if ( elf_init(&syms, elf->caller_xdest_base + sizeof(int),
|
||||
- elf->caller_xdest_size - sizeof(int)) )
|
||||
+ if ( elf_init(&syms, elf->caller_xdest_base + sizeof(unsigned),
|
||||
+ elf->caller_xdest_size - sizeof(unsigned)) )
|
||||
return -1;
|
||||
|
||||
/*
|
||||
@@ -209,7 +209,7 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
|
||||
xc_elf_set_logfile(dom->xch, &syms, 1);
|
||||
|
||||
- symtab = dom->bsd_symtab_start + sizeof(int);
|
||||
+ symtab = dom->bsd_symtab_start + sizeof(unsigned);
|
||||
maxaddr = elf_round_up(&syms, symtab + elf_size(&syms, syms.ehdr) +
|
||||
elf_shdr_count(&syms) * elf_size(&syms, shdr));
|
||||
|
||||
@@ -255,7 +255,7 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
size = elf_uval(&syms, shdr, sh_size);
|
||||
maxaddr = elf_round_up(&syms, maxaddr + size);
|
||||
tables++;
|
||||
- DOMPRINTF("%s: h=%d %s, size=0x%zx, maxaddr=0x%" PRIx64 "",
|
||||
+ DOMPRINTF("%s: h=%u %s, size=0x%zx, maxaddr=0x%" PRIx64 "",
|
||||
__FUNCTION__, h,
|
||||
type == SHT_SYMTAB ? "symtab" : "strtab",
|
||||
size, maxaddr);
|
||||
@@ -294,10 +294,14 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int xc_dom_parse_elf_kernel(struct xc_dom_image *dom)
|
||||
+static elf_errorstatus xc_dom_parse_elf_kernel(struct xc_dom_image *dom)
|
||||
+ /*
|
||||
+ * This function sometimes returns -1 for error and sometimes
|
||||
+ * an errno value. ?!?!
|
||||
+ */
|
||||
{
|
||||
struct elf_binary *elf;
|
||||
- int rc;
|
||||
+ elf_errorstatus rc;
|
||||
|
||||
rc = check_elf_kernel(dom, 1);
|
||||
if ( rc != 0 )
|
||||
@@ -358,10 +362,10 @@ out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
-static int xc_dom_load_elf_kernel(struct xc_dom_image *dom)
|
||||
+static elf_errorstatus xc_dom_load_elf_kernel(struct xc_dom_image *dom)
|
||||
{
|
||||
struct elf_binary *elf = dom->private_loader;
|
||||
- int rc;
|
||||
+ elf_errorstatus rc;
|
||||
xen_pfn_t pages;
|
||||
|
||||
elf->dest_base = xc_dom_seg_to_ptr_pages(dom, &dom->kernel_seg, &pages);
|
||||
diff --git a/tools/xcutils/readnotes.c b/tools/xcutils/readnotes.c
|
||||
index d1f7a30..2ca7732 100644
|
||||
--- a/tools/xcutils/readnotes.c
|
||||
+++ b/tools/xcutils/readnotes.c
|
||||
@@ -70,7 +70,7 @@ static void print_numeric_note(const char *prefix, struct elf_binary *elf,
|
||||
ELF_HANDLE_DECL(elf_note) note)
|
||||
{
|
||||
uint64_t value = elf_note_numeric(elf, note);
|
||||
- int descsz = elf_uval(elf, note, descsz);
|
||||
+ unsigned descsz = elf_uval(elf, note, descsz);
|
||||
|
||||
printf("%s: %#*" PRIx64 " (%d bytes)\n",
|
||||
prefix, 2+2*descsz, value, descsz);
|
||||
@@ -79,7 +79,7 @@ static void print_numeric_note(const char *prefix, struct elf_binary *elf,
|
||||
static void print_l1_mfn_valid_note(const char *prefix, struct elf_binary *elf,
|
||||
ELF_HANDLE_DECL(elf_note) note)
|
||||
{
|
||||
- int descsz = elf_uval(elf, note, descsz);
|
||||
+ unsigned descsz = elf_uval(elf, note, descsz);
|
||||
ELF_PTRVAL_CONST_VOID desc = elf_note_desc(elf, note);
|
||||
|
||||
/* XXX should be able to cope with a list of values. */
|
||||
@@ -99,10 +99,10 @@ static void print_l1_mfn_valid_note(const char *prefix, struct elf_binary *elf,
|
||||
|
||||
}
|
||||
|
||||
-static int print_notes(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) start, ELF_HANDLE_DECL(elf_note) end)
|
||||
+static unsigned print_notes(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) start, ELF_HANDLE_DECL(elf_note) end)
|
||||
{
|
||||
ELF_HANDLE_DECL(elf_note) note;
|
||||
- int notes_found = 0;
|
||||
+ unsigned notes_found = 0;
|
||||
const char *this_note_name;
|
||||
|
||||
for ( note = start; ELF_HANDLE_PTRVAL(note) < ELF_HANDLE_PTRVAL(end); note = elf_note_next(elf, note) )
|
||||
@@ -161,7 +161,7 @@ static int print_notes(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) start,
|
||||
break;
|
||||
default:
|
||||
printf("unknown note type %#x\n",
|
||||
- (int)elf_uval(elf, note, type));
|
||||
+ (unsigned)elf_uval(elf, note, type));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -171,12 +171,13 @@ static int print_notes(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) start,
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char *f;
|
||||
- int fd,h,size,usize,count;
|
||||
+ int fd;
|
||||
+ unsigned h,size,usize,count;
|
||||
void *image,*tmp;
|
||||
struct stat st;
|
||||
struct elf_binary elf;
|
||||
ELF_HANDLE_DECL(elf_shdr) shdr;
|
||||
- int notes_found = 0;
|
||||
+ unsigned notes_found = 0;
|
||||
|
||||
struct setup_header *hdr;
|
||||
uint64_t payload_offset, payload_length;
|
||||
diff --git a/xen/common/libelf/Makefile b/xen/common/libelf/Makefile
|
||||
index 18dc8e2..5bf8f76 100644
|
||||
--- a/xen/common/libelf/Makefile
|
||||
+++ b/xen/common/libelf/Makefile
|
||||
@@ -2,6 +2,8 @@ obj-bin-y := libelf.o
|
||||
|
||||
SECTIONS := text data $(SPECIAL_DATA_SECTIONS)
|
||||
|
||||
+CFLAGS += -Wno-pointer-sign
|
||||
+
|
||||
libelf.o: libelf-temp.o Makefile
|
||||
$(OBJCOPY) $(foreach s,$(SECTIONS),--rename-section .$(s)=.init.$(s)) $< $@
|
||||
|
||||
diff --git a/xen/common/libelf/libelf-dominfo.c b/xen/common/libelf/libelf-dominfo.c
|
||||
index 12b6c2a..cdd0d31 100644
|
||||
--- a/xen/common/libelf/libelf-dominfo.c
|
||||
+++ b/xen/common/libelf/libelf-dominfo.c
|
||||
@@ -29,15 +29,15 @@ static const char *const elf_xen_feature_names[] = {
|
||||
[XENFEAT_pae_pgdir_above_4gb] = "pae_pgdir_above_4gb",
|
||||
[XENFEAT_dom0] = "dom0"
|
||||
};
|
||||
-static const int elf_xen_features =
|
||||
+static const unsigned elf_xen_features =
|
||||
sizeof(elf_xen_feature_names) / sizeof(elf_xen_feature_names[0]);
|
||||
|
||||
-int elf_xen_parse_features(const char *features,
|
||||
+elf_errorstatus elf_xen_parse_features(const char *features,
|
||||
uint32_t *supported,
|
||||
uint32_t *required)
|
||||
{
|
||||
- char feature[64];
|
||||
- int pos, len, i;
|
||||
+ unsigned char feature[64];
|
||||
+ unsigned pos, len, i;
|
||||
|
||||
if ( features == NULL )
|
||||
return 0;
|
||||
@@ -94,7 +94,7 @@ int elf_xen_parse_features(const char *features,
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* xen elf notes */
|
||||
|
||||
-int elf_xen_parse_note(struct elf_binary *elf,
|
||||
+elf_errorstatus elf_xen_parse_note(struct elf_binary *elf,
|
||||
struct elf_dom_parms *parms,
|
||||
ELF_HANDLE_DECL(elf_note) note)
|
||||
{
|
||||
@@ -125,7 +125,7 @@ int elf_xen_parse_note(struct elf_binary *elf,
|
||||
const char *str = NULL;
|
||||
uint64_t val = 0;
|
||||
unsigned int i;
|
||||
- int type = elf_uval(elf, note, type);
|
||||
+ unsigned type = elf_uval(elf, note, type);
|
||||
|
||||
if ( (type >= sizeof(note_desc) / sizeof(note_desc[0])) ||
|
||||
(note_desc[type].name == NULL) )
|
||||
@@ -216,12 +216,14 @@ int elf_xen_parse_note(struct elf_binary *elf,
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int elf_xen_parse_notes(struct elf_binary *elf,
|
||||
+#define ELF_NOTE_INVALID (~0U)
|
||||
+
|
||||
+static unsigned elf_xen_parse_notes(struct elf_binary *elf,
|
||||
struct elf_dom_parms *parms,
|
||||
ELF_PTRVAL_CONST_VOID start,
|
||||
ELF_PTRVAL_CONST_VOID end)
|
||||
{
|
||||
- int xen_elfnotes = 0;
|
||||
+ unsigned xen_elfnotes = 0;
|
||||
ELF_HANDLE_DECL(elf_note) note;
|
||||
const char *note_name;
|
||||
|
||||
@@ -237,7 +239,7 @@ static int elf_xen_parse_notes(struct elf_binary *elf,
|
||||
if ( strcmp(note_name, "Xen") )
|
||||
continue;
|
||||
if ( elf_xen_parse_note(elf, parms, note) )
|
||||
- return -1;
|
||||
+ return ELF_NOTE_INVALID;
|
||||
xen_elfnotes++;
|
||||
}
|
||||
return xen_elfnotes;
|
||||
@@ -246,12 +248,12 @@ static int elf_xen_parse_notes(struct elf_binary *elf,
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* __xen_guest section */
|
||||
|
||||
-int elf_xen_parse_guest_info(struct elf_binary *elf,
|
||||
+elf_errorstatus elf_xen_parse_guest_info(struct elf_binary *elf,
|
||||
struct elf_dom_parms *parms)
|
||||
{
|
||||
ELF_PTRVAL_CONST_CHAR h;
|
||||
- char name[32], value[128];
|
||||
- int len;
|
||||
+ unsigned char name[32], value[128];
|
||||
+ unsigned len;
|
||||
|
||||
h = parms->guest_info;
|
||||
#define STAR(h) (elf_access_unsigned(elf, (h), 0, 1))
|
||||
@@ -334,13 +336,13 @@ int elf_xen_parse_guest_info(struct elf_binary *elf,
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* sanity checks */
|
||||
|
||||
-static int elf_xen_note_check(struct elf_binary *elf,
|
||||
+static elf_errorstatus elf_xen_note_check(struct elf_binary *elf,
|
||||
struct elf_dom_parms *parms)
|
||||
{
|
||||
if ( (ELF_PTRVAL_INVALID(parms->elf_note_start)) &&
|
||||
(ELF_PTRVAL_INVALID(parms->guest_info)) )
|
||||
{
|
||||
- int machine = elf_uval(elf, elf->ehdr, e_machine);
|
||||
+ unsigned machine = elf_uval(elf, elf->ehdr, e_machine);
|
||||
if ( (machine == EM_386) || (machine == EM_X86_64) )
|
||||
{
|
||||
elf_err(elf, "%s: ERROR: Not a Xen-ELF image: "
|
||||
@@ -378,7 +380,7 @@ static int elf_xen_note_check(struct elf_binary *elf,
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int elf_xen_addr_calc_check(struct elf_binary *elf,
|
||||
+static elf_errorstatus elf_xen_addr_calc_check(struct elf_binary *elf,
|
||||
struct elf_dom_parms *parms)
|
||||
{
|
||||
if ( (parms->elf_paddr_offset != UNSET_ADDR) &&
|
||||
@@ -464,13 +466,13 @@ static int elf_xen_addr_calc_check(struct elf_binary *elf,
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* glue it all together ... */
|
||||
|
||||
-int elf_xen_parse(struct elf_binary *elf,
|
||||
+elf_errorstatus elf_xen_parse(struct elf_binary *elf,
|
||||
struct elf_dom_parms *parms)
|
||||
{
|
||||
ELF_HANDLE_DECL(elf_shdr) shdr;
|
||||
ELF_HANDLE_DECL(elf_phdr) phdr;
|
||||
- int xen_elfnotes = 0;
|
||||
- int i, count, rc;
|
||||
+ unsigned xen_elfnotes = 0;
|
||||
+ unsigned i, count, more_notes;
|
||||
|
||||
elf_memset_unchecked(parms, 0, sizeof(*parms));
|
||||
parms->virt_base = UNSET_ADDR;
|
||||
@@ -495,13 +497,13 @@ int elf_xen_parse(struct elf_binary *elf,
|
||||
if (elf_uval(elf, phdr, p_offset) == 0)
|
||||
continue;
|
||||
|
||||
- rc = elf_xen_parse_notes(elf, parms,
|
||||
+ more_notes = elf_xen_parse_notes(elf, parms,
|
||||
elf_segment_start(elf, phdr),
|
||||
elf_segment_end(elf, phdr));
|
||||
- if ( rc == -1 )
|
||||
+ if ( more_notes == ELF_NOTE_INVALID )
|
||||
return -1;
|
||||
|
||||
- xen_elfnotes += rc;
|
||||
+ xen_elfnotes += more_notes;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -518,17 +520,17 @@ int elf_xen_parse(struct elf_binary *elf,
|
||||
if ( elf_uval(elf, shdr, sh_type) != SHT_NOTE )
|
||||
continue;
|
||||
|
||||
- rc = elf_xen_parse_notes(elf, parms,
|
||||
+ more_notes = elf_xen_parse_notes(elf, parms,
|
||||
elf_section_start(elf, shdr),
|
||||
elf_section_end(elf, shdr));
|
||||
|
||||
- if ( rc == -1 )
|
||||
+ if ( more_notes == ELF_NOTE_INVALID )
|
||||
return -1;
|
||||
|
||||
- if ( xen_elfnotes == 0 && rc > 0 )
|
||||
+ if ( xen_elfnotes == 0 && more_notes > 0 )
|
||||
elf_msg(elf, "%s: using notes from SHT_NOTE section\n", __FUNCTION__);
|
||||
|
||||
- xen_elfnotes += rc;
|
||||
+ xen_elfnotes += more_notes;
|
||||
}
|
||||
|
||||
}
|
||||
diff --git a/xen/common/libelf/libelf-loader.c b/xen/common/libelf/libelf-loader.c
|
||||
index 0dccd4d..c3a9e51 100644
|
||||
--- a/xen/common/libelf/libelf-loader.c
|
||||
+++ b/xen/common/libelf/libelf-loader.c
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
-int elf_init(struct elf_binary *elf, const char *image_input, size_t size)
|
||||
+elf_errorstatus elf_init(struct elf_binary *elf, const char *image_input, size_t size)
|
||||
{
|
||||
ELF_HANDLE_DECL(elf_shdr) shdr;
|
||||
uint64_t i, count, section, offset;
|
||||
@@ -114,7 +114,7 @@ void elf_set_log(struct elf_binary *elf, elf_log_callback *log_callback,
|
||||
elf->verbose = verbose;
|
||||
}
|
||||
|
||||
-static int elf_load_image(struct elf_binary *elf,
|
||||
+static elf_errorstatus elf_load_image(struct elf_binary *elf,
|
||||
ELF_PTRVAL_VOID dst, ELF_PTRVAL_CONST_VOID src,
|
||||
uint64_t filesz, uint64_t memsz)
|
||||
{
|
||||
@@ -129,9 +129,9 @@ void elf_set_verbose(struct elf_binary *elf)
|
||||
elf->verbose = 1;
|
||||
}
|
||||
|
||||
-static int elf_load_image(struct elf_binary *elf, ELF_PTRVAL_VOID dst, ELF_PTRVAL_CONST_VOID src, uint64_t filesz, uint64_t memsz)
|
||||
+static elf_errorstatus elf_load_image(struct elf_binary *elf, ELF_PTRVAL_VOID dst, ELF_PTRVAL_CONST_VOID src, uint64_t filesz, uint64_t memsz)
|
||||
{
|
||||
- int rc;
|
||||
+ elf_errorstatus rc;
|
||||
if ( filesz > ULONG_MAX || memsz > ULONG_MAX )
|
||||
return -1;
|
||||
/* We trust the dom0 kernel image completely, so we don't care
|
||||
@@ -151,7 +151,7 @@ void elf_parse_bsdsyms(struct elf_binary *elf, uint64_t pstart)
|
||||
{
|
||||
uint64_t sz;
|
||||
ELF_HANDLE_DECL(elf_shdr) shdr;
|
||||
- int i, type;
|
||||
+ unsigned i, type;
|
||||
|
||||
if ( !ELF_HANDLE_VALID(elf->sym_tab) )
|
||||
return;
|
||||
@@ -187,7 +187,7 @@ static void elf_load_bsdsyms(struct elf_binary *elf)
|
||||
ELF_PTRVAL_VOID symbase;
|
||||
ELF_PTRVAL_VOID symtab_addr;
|
||||
ELF_HANDLE_DECL_NONCONST(elf_shdr) shdr;
|
||||
- int i, type;
|
||||
+ unsigned i, type;
|
||||
|
||||
if ( !elf->bsd_symtab_pstart )
|
||||
return;
|
||||
@@ -220,7 +220,7 @@ do { \
|
||||
elf_memcpy_safe(elf, ELF_HANDLE_PTRVAL(shdr),
|
||||
ELF_IMAGE_BASE(elf) + elf_uval(elf, elf->ehdr, e_shoff),
|
||||
sz);
|
||||
- maxva = ELF_OBSOLETE_VOIDP_CAST elf_round_up(elf, (long)maxva + sz);
|
||||
+ maxva = ELF_OBSOLETE_VOIDP_CAST elf_round_up(elf, (unsigned long)maxva + sz);
|
||||
|
||||
for ( i = 0; i < elf_shdr_count(elf); i++ )
|
||||
{
|
||||
@@ -233,10 +233,10 @@ do { \
|
||||
elf_memcpy_safe(elf, maxva, elf_section_start(elf, shdr), sz);
|
||||
/* Mangled to be based on ELF header location. */
|
||||
elf_hdr_elm(elf, shdr, sh_offset, maxva - symtab_addr);
|
||||
- maxva = ELF_OBSOLETE_VOIDP_CAST elf_round_up(elf, (long)maxva + sz);
|
||||
+ maxva = ELF_OBSOLETE_VOIDP_CAST elf_round_up(elf, (unsigned long)maxva + sz);
|
||||
}
|
||||
shdr = ELF_MAKE_HANDLE(elf_shdr, ELF_HANDLE_PTRVAL(shdr) +
|
||||
- (long)elf_uval(elf, elf->ehdr, e_shentsize));
|
||||
+ (unsigned long)elf_uval(elf, elf->ehdr, e_shentsize));
|
||||
}
|
||||
|
||||
/* Write down the actual sym size. */
|
||||
@@ -273,7 +273,7 @@ void elf_parse_binary(struct elf_binary *elf)
|
||||
__FUNCTION__, elf->pstart, elf->pend);
|
||||
}
|
||||
|
||||
-int elf_load_binary(struct elf_binary *elf)
|
||||
+elf_errorstatus elf_load_binary(struct elf_binary *elf)
|
||||
{
|
||||
ELF_HANDLE_DECL(elf_phdr) phdr;
|
||||
uint64_t i, count, paddr, offset, filesz, memsz;
|
||||
diff --git a/xen/common/libelf/libelf-tools.c b/xen/common/libelf/libelf-tools.c
|
||||
index fa58f76..46d4ab1 100644
|
||||
--- a/xen/common/libelf/libelf-tools.c
|
||||
+++ b/xen/common/libelf/libelf-tools.c
|
||||
@@ -122,19 +122,19 @@ uint64_t elf_access_unsigned(struct elf_binary * elf, elf_ptrval base,
|
||||
|
||||
uint64_t elf_round_up(struct elf_binary *elf, uint64_t addr)
|
||||
{
|
||||
- int elf_round = (elf_64bit(elf) ? 8 : 4) - 1;
|
||||
+ uint64_t elf_round = (elf_64bit(elf) ? 8 : 4) - 1;
|
||||
|
||||
return (addr + elf_round) & ~elf_round;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
-int elf_shdr_count(struct elf_binary *elf)
|
||||
+unsigned elf_shdr_count(struct elf_binary *elf)
|
||||
{
|
||||
return elf_uval(elf, elf->ehdr, e_shnum);
|
||||
}
|
||||
|
||||
-int elf_phdr_count(struct elf_binary *elf)
|
||||
+unsigned elf_phdr_count(struct elf_binary *elf)
|
||||
{
|
||||
return elf_uval(elf, elf->ehdr, e_phnum);
|
||||
}
|
||||
@@ -144,7 +144,7 @@ ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_name(struct elf_binary *elf, const char *n
|
||||
uint64_t count = elf_shdr_count(elf);
|
||||
ELF_HANDLE_DECL(elf_shdr) shdr;
|
||||
const char *sname;
|
||||
- int i;
|
||||
+ unsigned i;
|
||||
|
||||
for ( i = 0; i < count; i++ )
|
||||
{
|
||||
@@ -156,7 +156,7 @@ ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_name(struct elf_binary *elf, const char *n
|
||||
return ELF_INVALID_HANDLE(elf_shdr);
|
||||
}
|
||||
|
||||
-ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_index(struct elf_binary *elf, int index)
|
||||
+ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_index(struct elf_binary *elf, unsigned index)
|
||||
{
|
||||
uint64_t count = elf_shdr_count(elf);
|
||||
ELF_PTRVAL_CONST_VOID ptr;
|
||||
@@ -170,7 +170,7 @@ ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_index(struct elf_binary *elf, int index)
|
||||
return ELF_MAKE_HANDLE(elf_shdr, ptr);
|
||||
}
|
||||
|
||||
-ELF_HANDLE_DECL(elf_phdr) elf_phdr_by_index(struct elf_binary *elf, int index)
|
||||
+ELF_HANDLE_DECL(elf_phdr) elf_phdr_by_index(struct elf_binary *elf, unsigned index)
|
||||
{
|
||||
uint64_t count = elf_uval(elf, elf->ehdr, e_phnum);
|
||||
ELF_PTRVAL_CONST_VOID ptr;
|
||||
@@ -264,7 +264,7 @@ ELF_HANDLE_DECL(elf_sym) elf_sym_by_name(struct elf_binary *elf, const char *sym
|
||||
return ELF_INVALID_HANDLE(elf_sym);
|
||||
}
|
||||
|
||||
-ELF_HANDLE_DECL(elf_sym) elf_sym_by_index(struct elf_binary *elf, int index)
|
||||
+ELF_HANDLE_DECL(elf_sym) elf_sym_by_index(struct elf_binary *elf, unsigned index)
|
||||
{
|
||||
ELF_PTRVAL_CONST_VOID ptr = elf_section_start(elf, elf->sym_tab);
|
||||
ELF_HANDLE_DECL(elf_sym) sym;
|
||||
@@ -280,7 +280,7 @@ const char *elf_note_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note
|
||||
|
||||
ELF_PTRVAL_CONST_VOID elf_note_desc(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note)
|
||||
{
|
||||
- int namesz = (elf_uval(elf, note, namesz) + 3) & ~3;
|
||||
+ unsigned namesz = (elf_uval(elf, note, namesz) + 3) & ~3;
|
||||
|
||||
return ELF_HANDLE_PTRVAL(note) + elf_size(elf, note) + namesz;
|
||||
}
|
||||
@@ -288,7 +288,7 @@ ELF_PTRVAL_CONST_VOID elf_note_desc(struct elf_binary *elf, ELF_HANDLE_DECL(elf_
|
||||
uint64_t elf_note_numeric(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note)
|
||||
{
|
||||
ELF_PTRVAL_CONST_VOID desc = elf_note_desc(elf, note);
|
||||
- int descsz = elf_uval(elf, note, descsz);
|
||||
+ unsigned descsz = elf_uval(elf, note, descsz);
|
||||
|
||||
switch (descsz)
|
||||
{
|
||||
@@ -306,7 +306,7 @@ uint64_t elf_note_numeric_array(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note
|
||||
unsigned int unitsz, unsigned int idx)
|
||||
{
|
||||
ELF_PTRVAL_CONST_VOID desc = elf_note_desc(elf, note);
|
||||
- int descsz = elf_uval(elf, note, descsz);
|
||||
+ unsigned descsz = elf_uval(elf, note, descsz);
|
||||
|
||||
if ( descsz % unitsz || idx >= descsz / unitsz )
|
||||
return 0;
|
||||
@@ -324,8 +324,8 @@ uint64_t elf_note_numeric_array(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note
|
||||
|
||||
ELF_HANDLE_DECL(elf_note) elf_note_next(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note)
|
||||
{
|
||||
- int namesz = (elf_uval(elf, note, namesz) + 3) & ~3;
|
||||
- int descsz = (elf_uval(elf, note, descsz) + 3) & ~3;
|
||||
+ unsigned namesz = (elf_uval(elf, note, namesz) + 3) & ~3;
|
||||
+ unsigned descsz = (elf_uval(elf, note, descsz) + 3) & ~3;
|
||||
|
||||
return ELF_MAKE_HANDLE(elf_note, ELF_HANDLE_PTRVAL(note) + elf_size(elf, note) + namesz + descsz);
|
||||
}
|
||||
diff --git a/xen/include/xen/libelf.h b/xen/include/xen/libelf.h
|
||||
index 951430f..87e126a 100644
|
||||
--- a/xen/include/xen/libelf.h
|
||||
+++ b/xen/include/xen/libelf.h
|
||||
@@ -31,6 +31,9 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
+typedef int elf_errorstatus; /* 0: ok; -ve (normally -1): error */
|
||||
+typedef int elf_negerrnoval; /* 0: ok; -EFOO: error */
|
||||
+
|
||||
#undef ELFSIZE
|
||||
#include "elfstructs.h"
|
||||
#ifdef __XEN__
|
||||
@@ -328,12 +331,12 @@ bool elf_access_ok(struct elf_binary * elf,
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* xc_libelf_tools.c */
|
||||
|
||||
-int elf_shdr_count(struct elf_binary *elf);
|
||||
-int elf_phdr_count(struct elf_binary *elf);
|
||||
+unsigned elf_shdr_count(struct elf_binary *elf);
|
||||
+unsigned elf_phdr_count(struct elf_binary *elf);
|
||||
|
||||
ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_name(struct elf_binary *elf, const char *name);
|
||||
-ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_index(struct elf_binary *elf, int index);
|
||||
-ELF_HANDLE_DECL(elf_phdr) elf_phdr_by_index(struct elf_binary *elf, int index);
|
||||
+ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_index(struct elf_binary *elf, unsigned index);
|
||||
+ELF_HANDLE_DECL(elf_phdr) elf_phdr_by_index(struct elf_binary *elf, unsigned index);
|
||||
|
||||
const char *elf_section_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr); /* might return NULL if inputs are invalid */
|
||||
ELF_PTRVAL_CONST_VOID elf_section_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr);
|
||||
@@ -343,7 +346,7 @@ ELF_PTRVAL_CONST_VOID elf_segment_start(struct elf_binary *elf, ELF_HANDLE_DECL(
|
||||
ELF_PTRVAL_CONST_VOID elf_segment_end(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr);
|
||||
|
||||
ELF_HANDLE_DECL(elf_sym) elf_sym_by_name(struct elf_binary *elf, const char *symbol);
|
||||
-ELF_HANDLE_DECL(elf_sym) elf_sym_by_index(struct elf_binary *elf, int index);
|
||||
+ELF_HANDLE_DECL(elf_sym) elf_sym_by_index(struct elf_binary *elf, unsigned index);
|
||||
|
||||
const char *elf_note_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note); /* may return NULL */
|
||||
ELF_PTRVAL_CONST_VOID elf_note_desc(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
|
||||
@@ -360,7 +363,7 @@ bool elf_phdr_is_loadable(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* xc_libelf_loader.c */
|
||||
|
||||
-int elf_init(struct elf_binary *elf, const char *image, size_t size);
|
||||
+elf_errorstatus elf_init(struct elf_binary *elf, const char *image, size_t size);
|
||||
/*
|
||||
* image and size must be correct. They will be recorded in
|
||||
* *elf, and must remain valid while the elf is in use.
|
||||
@@ -373,7 +376,7 @@ void elf_set_log(struct elf_binary *elf, elf_log_callback*,
|
||||
#endif
|
||||
|
||||
void elf_parse_binary(struct elf_binary *elf);
|
||||
-int elf_load_binary(struct elf_binary *elf);
|
||||
+elf_errorstatus elf_load_binary(struct elf_binary *elf);
|
||||
|
||||
ELF_PTRVAL_VOID elf_get_ptr(struct elf_binary *elf, unsigned long addr);
|
||||
uint64_t elf_lookup_addr(struct elf_binary *elf, const char *symbol);
|
||||
@@ -386,7 +389,7 @@ const char *elf_check_broken(const struct elf_binary *elf); /* NULL means OK */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* xc_libelf_relocate.c */
|
||||
|
||||
-int elf_reloc(struct elf_binary *elf);
|
||||
+elf_errorstatus elf_reloc(struct elf_binary *elf);
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* xc_libelf_dominfo.c */
|
||||
@@ -420,7 +423,7 @@ struct elf_dom_parms {
|
||||
char guest_ver[16];
|
||||
char xen_ver[16];
|
||||
char loader[16];
|
||||
- int pae;
|
||||
+ int pae; /* some kind of enum apparently */
|
||||
bool bsd_symtab;
|
||||
uint64_t virt_base;
|
||||
uint64_t virt_entry;
|
||||
--
|
||||
1.7.2.5
|
||||
|
@ -0,0 +1,409 @@
|
||||
From 52d8cc2dd3bb3e0f6d51e00280da934e8d91653a Mon Sep 17 00:00:00 2001
|
||||
From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Date: Fri, 14 Jun 2013 16:43:18 +0100
|
||||
Subject: [PATCH 16/23] libelf: check loops for running away
|
||||
|
||||
Ensure that libelf does not have any loops which can run away
|
||||
indefinitely even if the input is bogus. (Grepped for \bfor, \bwhile
|
||||
and \bgoto in libelf and xc_dom_*loader*.c.)
|
||||
|
||||
Changes needed:
|
||||
* elf_note_next uses the note's unchecked alleged length, which might
|
||||
wrap round. If it does, return ELF_MAX_PTRVAL (0xfff..fff) instead,
|
||||
which will be beyond the end of the section and so terminate the
|
||||
caller's loop. Also check that the returned psuedopointer is sane.
|
||||
* In various loops over section and program headers, check that the
|
||||
calculated header pointer is still within the image, and quit the
|
||||
loop if it isn't.
|
||||
* Some fixed limits to avoid potentially O(image_size^2) loops:
|
||||
- maximum length of strings: 4K (longer ones ignored totally)
|
||||
- maximum total number of ELF notes: 65536 (any more are ignored)
|
||||
* Check that the total program contents (text, data) we copy or
|
||||
initialise doesn't exceed twice the output image area size.
|
||||
* Remove an entirely useless loop from elf_xen_parse (!)
|
||||
* Replace a nested search loop in in xc_dom_load_elf_symtab in
|
||||
xc_dom_elfloader.c by a precomputation of a bitmap of referenced
|
||||
symtabs.
|
||||
|
||||
We have not changed loops which might, in principle, iterate over the
|
||||
whole image - even if they might do so one byte at a time with a
|
||||
nontrivial access check function in the middle.
|
||||
|
||||
This is part of the fix to a security issue, XSA-55.
|
||||
|
||||
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
---
|
||||
tools/libxc/xc_dom_elfloader.c | 33 ++++++++++++++++++-------
|
||||
xen/common/libelf/libelf-dominfo.c | 43 ++++++++++++++++++++------------
|
||||
xen/common/libelf/libelf-loader.c | 47 ++++++++++++++++++++++++++++++++++-
|
||||
xen/common/libelf/libelf-tools.c | 28 ++++++++++++++++++++-
|
||||
xen/include/xen/libelf.h | 13 ++++++++++
|
||||
5 files changed, 135 insertions(+), 29 deletions(-)
|
||||
|
||||
diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c
|
||||
index 62a0d3b..c5014d2 100644
|
||||
--- a/tools/libxc/xc_dom_elfloader.c
|
||||
+++ b/tools/libxc/xc_dom_elfloader.c
|
||||
@@ -28,6 +28,7 @@
|
||||
|
||||
#include "xg_private.h"
|
||||
#include "xc_dom.h"
|
||||
+#include "xc_bitops.h"
|
||||
|
||||
#define XEN_VER "xen-3.0"
|
||||
|
||||
@@ -120,6 +121,7 @@ static elf_errorstatus xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
ELF_PTRVAL_CHAR hdr;
|
||||
size_t size;
|
||||
unsigned h, count, type, i, tables = 0;
|
||||
+ unsigned long *strtab_referenced = NULL;
|
||||
|
||||
if ( elf_swap(elf) )
|
||||
{
|
||||
@@ -220,22 +222,35 @@ static elf_errorstatus xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
symtab, maxaddr);
|
||||
|
||||
count = elf_shdr_count(&syms);
|
||||
+ /* elf_shdr_count guarantees that count is reasonable */
|
||||
+
|
||||
+ strtab_referenced = xc_dom_malloc(dom, bitmap_size(count));
|
||||
+ if ( strtab_referenced == NULL )
|
||||
+ return -1;
|
||||
+ bitmap_clear(strtab_referenced, count);
|
||||
+ /* Note the symtabs @h linked to by any strtab @i. */
|
||||
+ for ( i = 0; i < count; i++ )
|
||||
+ {
|
||||
+ shdr2 = elf_shdr_by_index(&syms, i);
|
||||
+ if ( elf_uval(&syms, shdr2, sh_type) == SHT_SYMTAB )
|
||||
+ {
|
||||
+ h = elf_uval(&syms, shdr2, sh_link);
|
||||
+ if (h < count)
|
||||
+ set_bit(h, strtab_referenced);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
for ( h = 0; h < count; h++ )
|
||||
{
|
||||
shdr = ELF_OBSOLETE_VOIDP_CAST elf_shdr_by_index(&syms, h);
|
||||
+ if ( !elf_access_ok(elf, ELF_HANDLE_PTRVAL(shdr), 1) )
|
||||
+ /* input has an insane section header count field */
|
||||
+ break;
|
||||
type = elf_uval(&syms, shdr, sh_type);
|
||||
if ( type == SHT_STRTAB )
|
||||
{
|
||||
- /* Look for a strtab @i linked to symtab @h. */
|
||||
- for ( i = 0; i < count; i++ )
|
||||
- {
|
||||
- shdr2 = elf_shdr_by_index(&syms, i);
|
||||
- if ( (elf_uval(&syms, shdr2, sh_type) == SHT_SYMTAB) &&
|
||||
- (elf_uval(&syms, shdr2, sh_link) == h) )
|
||||
- break;
|
||||
- }
|
||||
/* Skip symtab @h if we found no corresponding strtab @i. */
|
||||
- if ( i == count )
|
||||
+ if ( !test_bit(h, strtab_referenced) )
|
||||
{
|
||||
if ( elf_64bit(&syms) )
|
||||
elf_store_field(elf, shdr, e64.sh_offset, 0);
|
||||
diff --git a/xen/common/libelf/libelf-dominfo.c b/xen/common/libelf/libelf-dominfo.c
|
||||
index cdd0d31..25a10d7 100644
|
||||
--- a/xen/common/libelf/libelf-dominfo.c
|
||||
+++ b/xen/common/libelf/libelf-dominfo.c
|
||||
@@ -221,7 +221,8 @@ elf_errorstatus elf_xen_parse_note(struct elf_binary *elf,
|
||||
static unsigned elf_xen_parse_notes(struct elf_binary *elf,
|
||||
struct elf_dom_parms *parms,
|
||||
ELF_PTRVAL_CONST_VOID start,
|
||||
- ELF_PTRVAL_CONST_VOID end)
|
||||
+ ELF_PTRVAL_CONST_VOID end,
|
||||
+ unsigned *total_note_count)
|
||||
{
|
||||
unsigned xen_elfnotes = 0;
|
||||
ELF_HANDLE_DECL(elf_note) note;
|
||||
@@ -233,6 +234,12 @@ static unsigned elf_xen_parse_notes(struct elf_binary *elf,
|
||||
ELF_HANDLE_PTRVAL(note) < parms->elf_note_end;
|
||||
note = elf_note_next(elf, note) )
|
||||
{
|
||||
+ if ( *total_note_count >= ELF_MAX_TOTAL_NOTE_COUNT )
|
||||
+ {
|
||||
+ elf_mark_broken(elf, "too many ELF notes");
|
||||
+ break;
|
||||
+ }
|
||||
+ (*total_note_count)++;
|
||||
note_name = elf_note_name(elf, note);
|
||||
if ( note_name == NULL )
|
||||
continue;
|
||||
@@ -473,6 +480,7 @@ elf_errorstatus elf_xen_parse(struct elf_binary *elf,
|
||||
ELF_HANDLE_DECL(elf_phdr) phdr;
|
||||
unsigned xen_elfnotes = 0;
|
||||
unsigned i, count, more_notes;
|
||||
+ unsigned total_note_count = 0;
|
||||
|
||||
elf_memset_unchecked(parms, 0, sizeof(*parms));
|
||||
parms->virt_base = UNSET_ADDR;
|
||||
@@ -487,6 +495,9 @@ elf_errorstatus elf_xen_parse(struct elf_binary *elf,
|
||||
for ( i = 0; i < count; i++ )
|
||||
{
|
||||
phdr = elf_phdr_by_index(elf, i);
|
||||
+ if ( !elf_access_ok(elf, ELF_HANDLE_PTRVAL(phdr), 1) )
|
||||
+ /* input has an insane program header count field */
|
||||
+ break;
|
||||
if ( elf_uval(elf, phdr, p_type) != PT_NOTE )
|
||||
continue;
|
||||
|
||||
@@ -499,7 +510,8 @@ elf_errorstatus elf_xen_parse(struct elf_binary *elf,
|
||||
|
||||
more_notes = elf_xen_parse_notes(elf, parms,
|
||||
elf_segment_start(elf, phdr),
|
||||
- elf_segment_end(elf, phdr));
|
||||
+ elf_segment_end(elf, phdr),
|
||||
+ &total_note_count);
|
||||
if ( more_notes == ELF_NOTE_INVALID )
|
||||
return -1;
|
||||
|
||||
@@ -516,13 +528,17 @@ elf_errorstatus elf_xen_parse(struct elf_binary *elf,
|
||||
for ( i = 0; i < count; i++ )
|
||||
{
|
||||
shdr = elf_shdr_by_index(elf, i);
|
||||
+ if ( !elf_access_ok(elf, ELF_HANDLE_PTRVAL(shdr), 1) )
|
||||
+ /* input has an insane section header count field */
|
||||
+ break;
|
||||
|
||||
if ( elf_uval(elf, shdr, sh_type) != SHT_NOTE )
|
||||
continue;
|
||||
|
||||
more_notes = elf_xen_parse_notes(elf, parms,
|
||||
elf_section_start(elf, shdr),
|
||||
- elf_section_end(elf, shdr));
|
||||
+ elf_section_end(elf, shdr),
|
||||
+ &total_note_count);
|
||||
|
||||
if ( more_notes == ELF_NOTE_INVALID )
|
||||
return -1;
|
||||
@@ -540,20 +556,15 @@ elf_errorstatus elf_xen_parse(struct elf_binary *elf,
|
||||
*/
|
||||
if ( xen_elfnotes == 0 )
|
||||
{
|
||||
- count = elf_shdr_count(elf);
|
||||
- for ( i = 0; i < count; i++ )
|
||||
+ shdr = elf_shdr_by_name(elf, "__xen_guest");
|
||||
+ if ( ELF_HANDLE_VALID(shdr) )
|
||||
{
|
||||
- shdr = elf_shdr_by_name(elf, "__xen_guest");
|
||||
- if ( ELF_HANDLE_VALID(shdr) )
|
||||
- {
|
||||
- parms->guest_info = elf_section_start(elf, shdr);
|
||||
- parms->elf_note_start = ELF_INVALID_PTRVAL;
|
||||
- parms->elf_note_end = ELF_INVALID_PTRVAL;
|
||||
- elf_msg(elf, "%s: __xen_guest: \"%s\"\n", __FUNCTION__,
|
||||
- elf_strfmt(elf, parms->guest_info));
|
||||
- elf_xen_parse_guest_info(elf, parms);
|
||||
- break;
|
||||
- }
|
||||
+ parms->guest_info = elf_section_start(elf, shdr);
|
||||
+ parms->elf_note_start = ELF_INVALID_PTRVAL;
|
||||
+ parms->elf_note_end = ELF_INVALID_PTRVAL;
|
||||
+ elf_msg(elf, "%s: __xen_guest: \"%s\"\n", __FUNCTION__,
|
||||
+ elf_strfmt(elf, parms->guest_info));
|
||||
+ elf_xen_parse_guest_info(elf, parms);
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/xen/common/libelf/libelf-loader.c b/xen/common/libelf/libelf-loader.c
|
||||
index c3a9e51..06799af 100644
|
||||
--- a/xen/common/libelf/libelf-loader.c
|
||||
+++ b/xen/common/libelf/libelf-loader.c
|
||||
@@ -75,6 +75,9 @@ elf_errorstatus elf_init(struct elf_binary *elf, const char *image_input, size_t
|
||||
for ( i = 0; i < count; i++ )
|
||||
{
|
||||
shdr = elf_shdr_by_index(elf, i);
|
||||
+ if ( !elf_access_ok(elf, ELF_HANDLE_PTRVAL(shdr), 1) )
|
||||
+ /* input has an insane section header count field */
|
||||
+ break;
|
||||
if ( elf_uval(elf, shdr, sh_type) != SHT_SYMTAB )
|
||||
continue;
|
||||
elf->sym_tab = shdr;
|
||||
@@ -170,6 +173,9 @@ void elf_parse_bsdsyms(struct elf_binary *elf, uint64_t pstart)
|
||||
for ( i = 0; i < elf_shdr_count(elf); i++ )
|
||||
{
|
||||
shdr = elf_shdr_by_index(elf, i);
|
||||
+ if ( !elf_access_ok(elf, ELF_HANDLE_PTRVAL(shdr), 1) )
|
||||
+ /* input has an insane section header count field */
|
||||
+ break;
|
||||
type = elf_uval(elf, shdr, sh_type);
|
||||
if ( (type == SHT_STRTAB) || (type == SHT_SYMTAB) )
|
||||
sz = elf_round_up(elf, sz + elf_uval(elf, shdr, sh_size));
|
||||
@@ -224,6 +230,9 @@ do { \
|
||||
|
||||
for ( i = 0; i < elf_shdr_count(elf); i++ )
|
||||
{
|
||||
+ elf_ptrval old_shdr_p;
|
||||
+ elf_ptrval new_shdr_p;
|
||||
+
|
||||
type = elf_uval(elf, shdr, sh_type);
|
||||
if ( (type == SHT_STRTAB) || (type == SHT_SYMTAB) )
|
||||
{
|
||||
@@ -235,8 +244,16 @@ do { \
|
||||
elf_hdr_elm(elf, shdr, sh_offset, maxva - symtab_addr);
|
||||
maxva = ELF_OBSOLETE_VOIDP_CAST elf_round_up(elf, (unsigned long)maxva + sz);
|
||||
}
|
||||
- shdr = ELF_MAKE_HANDLE(elf_shdr, ELF_HANDLE_PTRVAL(shdr) +
|
||||
- (unsigned long)elf_uval(elf, elf->ehdr, e_shentsize));
|
||||
+ old_shdr_p = ELF_HANDLE_PTRVAL(shdr);
|
||||
+ new_shdr_p = old_shdr_p + elf_uval(elf, elf->ehdr, e_shentsize);
|
||||
+ if ( new_shdr_p <= old_shdr_p ) /* wrapped or stuck */
|
||||
+ {
|
||||
+ elf_mark_broken(elf, "bad section header length");
|
||||
+ break;
|
||||
+ }
|
||||
+ if ( !elf_access_ok(elf, new_shdr_p, 1) ) /* outside image */
|
||||
+ break;
|
||||
+ shdr = ELF_MAKE_HANDLE(elf_shdr, new_shdr_p);
|
||||
}
|
||||
|
||||
/* Write down the actual sym size. */
|
||||
@@ -256,6 +273,9 @@ void elf_parse_binary(struct elf_binary *elf)
|
||||
for ( i = 0; i < count; i++ )
|
||||
{
|
||||
phdr = elf_phdr_by_index(elf, i);
|
||||
+ if ( !elf_access_ok(elf, ELF_HANDLE_PTRVAL(phdr), 1) )
|
||||
+ /* input has an insane program header count field */
|
||||
+ break;
|
||||
if ( !elf_phdr_is_loadable(elf, phdr) )
|
||||
continue;
|
||||
paddr = elf_uval(elf, phdr, p_paddr);
|
||||
@@ -278,11 +298,20 @@ elf_errorstatus elf_load_binary(struct elf_binary *elf)
|
||||
ELF_HANDLE_DECL(elf_phdr) phdr;
|
||||
uint64_t i, count, paddr, offset, filesz, memsz;
|
||||
ELF_PTRVAL_VOID dest;
|
||||
+ /*
|
||||
+ * Let bizarre ELFs write the output image up to twice; this
|
||||
+ * calculation is just to ensure our copying loop is no worse than
|
||||
+ * O(domain_size).
|
||||
+ */
|
||||
+ uint64_t remain_allow_copy = (uint64_t)elf->dest_size * 2;
|
||||
|
||||
count = elf_uval(elf, elf->ehdr, e_phnum);
|
||||
for ( i = 0; i < count; i++ )
|
||||
{
|
||||
phdr = elf_phdr_by_index(elf, i);
|
||||
+ if ( !elf_access_ok(elf, ELF_HANDLE_PTRVAL(phdr), 1) )
|
||||
+ /* input has an insane program header count field */
|
||||
+ break;
|
||||
if ( !elf_phdr_is_loadable(elf, phdr) )
|
||||
continue;
|
||||
paddr = elf_uval(elf, phdr, p_paddr);
|
||||
@@ -290,6 +319,20 @@ elf_errorstatus elf_load_binary(struct elf_binary *elf)
|
||||
filesz = elf_uval(elf, phdr, p_filesz);
|
||||
memsz = elf_uval(elf, phdr, p_memsz);
|
||||
dest = elf_get_ptr(elf, paddr);
|
||||
+
|
||||
+ /*
|
||||
+ * We need to check that the input image doesn't have us copy
|
||||
+ * the whole image zillions of times, as that could lead to
|
||||
+ * O(n^2) time behaviour and possible DoS by a malicous ELF.
|
||||
+ */
|
||||
+ if ( remain_allow_copy < memsz )
|
||||
+ {
|
||||
+ elf_mark_broken(elf, "program segments total to more"
|
||||
+ " than the input image size");
|
||||
+ break;
|
||||
+ }
|
||||
+ remain_allow_copy -= memsz;
|
||||
+
|
||||
elf_msg(elf, "%s: phdr %" PRIu64 " at 0x%"ELF_PRPTRVAL" -> 0x%"ELF_PRPTRVAL"\n",
|
||||
__func__, i, dest, (ELF_PTRVAL_VOID)(dest + filesz));
|
||||
if ( elf_load_image(elf, dest, ELF_IMAGE_BASE(elf) + offset, filesz, memsz) != 0 )
|
||||
diff --git a/xen/common/libelf/libelf-tools.c b/xen/common/libelf/libelf-tools.c
|
||||
index 46d4ab1..4a83133 100644
|
||||
--- a/xen/common/libelf/libelf-tools.c
|
||||
+++ b/xen/common/libelf/libelf-tools.c
|
||||
@@ -131,7 +131,16 @@ uint64_t elf_round_up(struct elf_binary *elf, uint64_t addr)
|
||||
|
||||
unsigned elf_shdr_count(struct elf_binary *elf)
|
||||
{
|
||||
- return elf_uval(elf, elf->ehdr, e_shnum);
|
||||
+ unsigned count = elf_uval(elf, elf->ehdr, e_shnum);
|
||||
+ uint64_t max = elf->size / sizeof(Elf32_Shdr);
|
||||
+ if (max > ~(unsigned)0)
|
||||
+ max = ~(unsigned)0; /* Xen doesn't have limits.h :-/ */
|
||||
+ if (count > max)
|
||||
+ {
|
||||
+ elf_mark_broken(elf, "far too many section headers");
|
||||
+ count = max;
|
||||
+ }
|
||||
+ return count;
|
||||
}
|
||||
|
||||
unsigned elf_phdr_count(struct elf_binary *elf)
|
||||
@@ -149,6 +158,9 @@ ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_name(struct elf_binary *elf, const char *n
|
||||
for ( i = 0; i < count; i++ )
|
||||
{
|
||||
shdr = elf_shdr_by_index(elf, i);
|
||||
+ if ( !elf_access_ok(elf, ELF_HANDLE_PTRVAL(shdr), 1) )
|
||||
+ /* input has an insane section header count field */
|
||||
+ break;
|
||||
sname = elf_section_name(elf, shdr);
|
||||
if ( sname && !strcmp(sname, name) )
|
||||
return shdr;
|
||||
@@ -204,6 +216,11 @@ const char *elf_strval(struct elf_binary *elf, elf_ptrval start)
|
||||
if ( !elf_access_unsigned(elf, start, length, 1) )
|
||||
/* ok */
|
||||
return ELF_UNSAFE_PTR(start);
|
||||
+ if ( length >= ELF_MAX_STRING_LENGTH )
|
||||
+ {
|
||||
+ elf_mark_broken(elf, "excessively long string");
|
||||
+ return NULL;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -327,7 +344,14 @@ ELF_HANDLE_DECL(elf_note) elf_note_next(struct elf_binary *elf, ELF_HANDLE_DECL(
|
||||
unsigned namesz = (elf_uval(elf, note, namesz) + 3) & ~3;
|
||||
unsigned descsz = (elf_uval(elf, note, descsz) + 3) & ~3;
|
||||
|
||||
- return ELF_MAKE_HANDLE(elf_note, ELF_HANDLE_PTRVAL(note) + elf_size(elf, note) + namesz + descsz);
|
||||
+ elf_ptrval ptrval = ELF_HANDLE_PTRVAL(note)
|
||||
+ + elf_size(elf, note) + namesz + descsz;
|
||||
+
|
||||
+ if ( ( ptrval <= ELF_HANDLE_PTRVAL(note) || /* wrapped or stuck */
|
||||
+ !elf_access_ok(elf, ELF_HANDLE_PTRVAL(note), 1) ) )
|
||||
+ ptrval = ELF_MAX_PTRVAL; /* terminate caller's loop */
|
||||
+
|
||||
+ return ELF_MAKE_HANDLE(elf_note, ptrval);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
diff --git a/xen/include/xen/libelf.h b/xen/include/xen/libelf.h
|
||||
index 87e126a..f95fe88 100644
|
||||
--- a/xen/include/xen/libelf.h
|
||||
+++ b/xen/include/xen/libelf.h
|
||||
@@ -51,6 +51,9 @@ typedef void elf_log_callback(struct elf_binary*, void *caller_data,
|
||||
|
||||
#endif
|
||||
|
||||
+#define ELF_MAX_STRING_LENGTH 4096
|
||||
+#define ELF_MAX_TOTAL_NOTE_COUNT 65536
|
||||
+
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
/* Macros for accessing the input image and output area. */
|
||||
@@ -353,6 +356,16 @@ ELF_PTRVAL_CONST_VOID elf_note_desc(struct elf_binary *elf, ELF_HANDLE_DECL(elf_
|
||||
uint64_t elf_note_numeric(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
|
||||
uint64_t elf_note_numeric_array(struct elf_binary *, ELF_HANDLE_DECL(elf_note),
|
||||
unsigned int unitsz, unsigned int idx);
|
||||
+
|
||||
+/*
|
||||
+ * If you use elf_note_next in a loop, you must put a nontrivial upper
|
||||
+ * bound on the returned value as part of your loop condition. In
|
||||
+ * some cases elf_note_next will substitute ELF_PTRVAL_MAX as return
|
||||
+ * value to indicate that the iteration isn't going well (for example,
|
||||
+ * the putative "next" value would be earlier in memory). In this
|
||||
+ * case the caller's loop must terminate. Checking against the
|
||||
+ * end of the notes segment with a strict inequality is sufficient.
|
||||
+ */
|
||||
ELF_HANDLE_DECL(elf_note) elf_note_next(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
|
||||
|
||||
/* (Only) checks that the image has the right magic number. */
|
||||
--
|
||||
1.7.2.5
|
||||
|
@ -0,0 +1,406 @@
|
||||
From 3baaa4ffcd3e7dd6227f9bdf817f90e5b75aeda2 Mon Sep 17 00:00:00 2001
|
||||
From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Date: Fri, 14 Jun 2013 16:43:19 +0100
|
||||
Subject: [PATCH 17/23] libelf: abolish obsolete macros
|
||||
|
||||
Abolish ELF_PTRVAL_[CONST_]{CHAR,VOID}; change uses to elf_ptrval.
|
||||
Abolish ELF_HANDLE_DECL_NONCONST; change uses to ELF_HANDLE_DECL.
|
||||
Abolish ELF_OBSOLETE_VOIDP_CAST; simply remove all uses.
|
||||
|
||||
No functional change. (Verified by diffing assembler output.)
|
||||
|
||||
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
|
||||
v2: New patch.
|
||||
---
|
||||
tools/libxc/xc_dom_elfloader.c | 8 +++---
|
||||
tools/xcutils/readnotes.c | 2 +-
|
||||
xen/common/libelf/libelf-dominfo.c | 6 ++--
|
||||
xen/common/libelf/libelf-loader.c | 24 +++++++++---------
|
||||
xen/common/libelf/libelf-tools.c | 24 +++++++++---------
|
||||
xen/include/xen/libelf.h | 48 +++++++++---------------------------
|
||||
6 files changed, 44 insertions(+), 68 deletions(-)
|
||||
|
||||
diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c
|
||||
index c5014d2..9fc4b94 100644
|
||||
--- a/tools/libxc/xc_dom_elfloader.c
|
||||
+++ b/tools/libxc/xc_dom_elfloader.c
|
||||
@@ -116,9 +116,9 @@ static elf_errorstatus xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
struct elf_binary *elf, bool load)
|
||||
{
|
||||
struct elf_binary syms;
|
||||
- ELF_HANDLE_DECL_NONCONST(elf_shdr) shdr; ELF_HANDLE_DECL(elf_shdr) shdr2;
|
||||
+ ELF_HANDLE_DECL(elf_shdr) shdr; ELF_HANDLE_DECL(elf_shdr) shdr2;
|
||||
xen_vaddr_t symtab, maxaddr;
|
||||
- ELF_PTRVAL_CHAR hdr;
|
||||
+ elf_ptrval hdr;
|
||||
size_t size;
|
||||
unsigned h, count, type, i, tables = 0;
|
||||
unsigned long *strtab_referenced = NULL;
|
||||
@@ -242,7 +242,7 @@ static elf_errorstatus xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
|
||||
for ( h = 0; h < count; h++ )
|
||||
{
|
||||
- shdr = ELF_OBSOLETE_VOIDP_CAST elf_shdr_by_index(&syms, h);
|
||||
+ shdr = elf_shdr_by_index(&syms, h);
|
||||
if ( !elf_access_ok(elf, ELF_HANDLE_PTRVAL(shdr), 1) )
|
||||
/* input has an insane section header count field */
|
||||
break;
|
||||
@@ -278,7 +278,7 @@ static elf_errorstatus xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
if ( load )
|
||||
{
|
||||
shdr2 = elf_shdr_by_index(elf, h);
|
||||
- elf_memcpy_safe(elf, ELF_OBSOLETE_VOIDP_CAST elf_section_start(&syms, shdr),
|
||||
+ elf_memcpy_safe(elf, elf_section_start(&syms, shdr),
|
||||
elf_section_start(elf, shdr2),
|
||||
size);
|
||||
}
|
||||
diff --git a/tools/xcutils/readnotes.c b/tools/xcutils/readnotes.c
|
||||
index 2ca7732..5fa445e 100644
|
||||
--- a/tools/xcutils/readnotes.c
|
||||
+++ b/tools/xcutils/readnotes.c
|
||||
@@ -80,7 +80,7 @@ static void print_l1_mfn_valid_note(const char *prefix, struct elf_binary *elf,
|
||||
ELF_HANDLE_DECL(elf_note) note)
|
||||
{
|
||||
unsigned descsz = elf_uval(elf, note, descsz);
|
||||
- ELF_PTRVAL_CONST_VOID desc = elf_note_desc(elf, note);
|
||||
+ elf_ptrval desc = elf_note_desc(elf, note);
|
||||
|
||||
/* XXX should be able to cope with a list of values. */
|
||||
switch ( descsz / 2 )
|
||||
diff --git a/xen/common/libelf/libelf-dominfo.c b/xen/common/libelf/libelf-dominfo.c
|
||||
index 25a10d7..412ea70 100644
|
||||
--- a/xen/common/libelf/libelf-dominfo.c
|
||||
+++ b/xen/common/libelf/libelf-dominfo.c
|
||||
@@ -220,8 +220,8 @@ elf_errorstatus elf_xen_parse_note(struct elf_binary *elf,
|
||||
|
||||
static unsigned elf_xen_parse_notes(struct elf_binary *elf,
|
||||
struct elf_dom_parms *parms,
|
||||
- ELF_PTRVAL_CONST_VOID start,
|
||||
- ELF_PTRVAL_CONST_VOID end,
|
||||
+ elf_ptrval start,
|
||||
+ elf_ptrval end,
|
||||
unsigned *total_note_count)
|
||||
{
|
||||
unsigned xen_elfnotes = 0;
|
||||
@@ -258,7 +258,7 @@ static unsigned elf_xen_parse_notes(struct elf_binary *elf,
|
||||
elf_errorstatus elf_xen_parse_guest_info(struct elf_binary *elf,
|
||||
struct elf_dom_parms *parms)
|
||||
{
|
||||
- ELF_PTRVAL_CONST_CHAR h;
|
||||
+ elf_ptrval h;
|
||||
unsigned char name[32], value[128];
|
||||
unsigned len;
|
||||
|
||||
diff --git a/xen/common/libelf/libelf-loader.c b/xen/common/libelf/libelf-loader.c
|
||||
index 06799af..e2e75af 100644
|
||||
--- a/xen/common/libelf/libelf-loader.c
|
||||
+++ b/xen/common/libelf/libelf-loader.c
|
||||
@@ -118,7 +118,7 @@ void elf_set_log(struct elf_binary *elf, elf_log_callback *log_callback,
|
||||
}
|
||||
|
||||
static elf_errorstatus elf_load_image(struct elf_binary *elf,
|
||||
- ELF_PTRVAL_VOID dst, ELF_PTRVAL_CONST_VOID src,
|
||||
+ elf_ptrval dst, elf_ptrval src,
|
||||
uint64_t filesz, uint64_t memsz)
|
||||
{
|
||||
elf_memcpy_safe(elf, dst, src, filesz);
|
||||
@@ -132,7 +132,7 @@ void elf_set_verbose(struct elf_binary *elf)
|
||||
elf->verbose = 1;
|
||||
}
|
||||
|
||||
-static elf_errorstatus elf_load_image(struct elf_binary *elf, ELF_PTRVAL_VOID dst, ELF_PTRVAL_CONST_VOID src, uint64_t filesz, uint64_t memsz)
|
||||
+static elf_errorstatus elf_load_image(struct elf_binary *elf, elf_ptrval dst, elf_ptrval src, uint64_t filesz, uint64_t memsz)
|
||||
{
|
||||
elf_errorstatus rc;
|
||||
if ( filesz > ULONG_MAX || memsz > ULONG_MAX )
|
||||
@@ -187,12 +187,12 @@ void elf_parse_bsdsyms(struct elf_binary *elf, uint64_t pstart)
|
||||
|
||||
static void elf_load_bsdsyms(struct elf_binary *elf)
|
||||
{
|
||||
- ELF_HANDLE_DECL_NONCONST(elf_ehdr) sym_ehdr;
|
||||
+ ELF_HANDLE_DECL(elf_ehdr) sym_ehdr;
|
||||
unsigned long sz;
|
||||
- ELF_PTRVAL_VOID maxva;
|
||||
- ELF_PTRVAL_VOID symbase;
|
||||
- ELF_PTRVAL_VOID symtab_addr;
|
||||
- ELF_HANDLE_DECL_NONCONST(elf_shdr) shdr;
|
||||
+ elf_ptrval maxva;
|
||||
+ elf_ptrval symbase;
|
||||
+ elf_ptrval symtab_addr;
|
||||
+ ELF_HANDLE_DECL(elf_shdr) shdr;
|
||||
unsigned i, type;
|
||||
|
||||
if ( !elf->bsd_symtab_pstart )
|
||||
@@ -226,7 +226,7 @@ do { \
|
||||
elf_memcpy_safe(elf, ELF_HANDLE_PTRVAL(shdr),
|
||||
ELF_IMAGE_BASE(elf) + elf_uval(elf, elf->ehdr, e_shoff),
|
||||
sz);
|
||||
- maxva = ELF_OBSOLETE_VOIDP_CAST elf_round_up(elf, (unsigned long)maxva + sz);
|
||||
+ maxva = elf_round_up(elf, (unsigned long)maxva + sz);
|
||||
|
||||
for ( i = 0; i < elf_shdr_count(elf); i++ )
|
||||
{
|
||||
@@ -242,7 +242,7 @@ do { \
|
||||
elf_memcpy_safe(elf, maxva, elf_section_start(elf, shdr), sz);
|
||||
/* Mangled to be based on ELF header location. */
|
||||
elf_hdr_elm(elf, shdr, sh_offset, maxva - symtab_addr);
|
||||
- maxva = ELF_OBSOLETE_VOIDP_CAST elf_round_up(elf, (unsigned long)maxva + sz);
|
||||
+ maxva = elf_round_up(elf, (unsigned long)maxva + sz);
|
||||
}
|
||||
old_shdr_p = ELF_HANDLE_PTRVAL(shdr);
|
||||
new_shdr_p = old_shdr_p + elf_uval(elf, elf->ehdr, e_shentsize);
|
||||
@@ -297,7 +297,7 @@ elf_errorstatus elf_load_binary(struct elf_binary *elf)
|
||||
{
|
||||
ELF_HANDLE_DECL(elf_phdr) phdr;
|
||||
uint64_t i, count, paddr, offset, filesz, memsz;
|
||||
- ELF_PTRVAL_VOID dest;
|
||||
+ elf_ptrval dest;
|
||||
/*
|
||||
* Let bizarre ELFs write the output image up to twice; this
|
||||
* calculation is just to ensure our copying loop is no worse than
|
||||
@@ -334,7 +334,7 @@ elf_errorstatus elf_load_binary(struct elf_binary *elf)
|
||||
remain_allow_copy -= memsz;
|
||||
|
||||
elf_msg(elf, "%s: phdr %" PRIu64 " at 0x%"ELF_PRPTRVAL" -> 0x%"ELF_PRPTRVAL"\n",
|
||||
- __func__, i, dest, (ELF_PTRVAL_VOID)(dest + filesz));
|
||||
+ __func__, i, dest, (elf_ptrval)(dest + filesz));
|
||||
if ( elf_load_image(elf, dest, ELF_IMAGE_BASE(elf) + offset, filesz, memsz) != 0 )
|
||||
return -1;
|
||||
}
|
||||
@@ -343,7 +343,7 @@ elf_errorstatus elf_load_binary(struct elf_binary *elf)
|
||||
return 0;
|
||||
}
|
||||
|
||||
-ELF_PTRVAL_VOID elf_get_ptr(struct elf_binary *elf, unsigned long addr)
|
||||
+elf_ptrval elf_get_ptr(struct elf_binary *elf, unsigned long addr)
|
||||
{
|
||||
return ELF_REALPTR2PTRVAL(elf->dest_base) + addr - elf->pstart;
|
||||
}
|
||||
diff --git a/xen/common/libelf/libelf-tools.c b/xen/common/libelf/libelf-tools.c
|
||||
index 4a83133..e202249 100644
|
||||
--- a/xen/common/libelf/libelf-tools.c
|
||||
+++ b/xen/common/libelf/libelf-tools.c
|
||||
@@ -171,7 +171,7 @@ ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_name(struct elf_binary *elf, const char *n
|
||||
ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_index(struct elf_binary *elf, unsigned index)
|
||||
{
|
||||
uint64_t count = elf_shdr_count(elf);
|
||||
- ELF_PTRVAL_CONST_VOID ptr;
|
||||
+ elf_ptrval ptr;
|
||||
|
||||
if ( index >= count )
|
||||
return ELF_INVALID_HANDLE(elf_shdr);
|
||||
@@ -185,7 +185,7 @@ ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_index(struct elf_binary *elf, unsigned ind
|
||||
ELF_HANDLE_DECL(elf_phdr) elf_phdr_by_index(struct elf_binary *elf, unsigned index)
|
||||
{
|
||||
uint64_t count = elf_uval(elf, elf->ehdr, e_phnum);
|
||||
- ELF_PTRVAL_CONST_VOID ptr;
|
||||
+ elf_ptrval ptr;
|
||||
|
||||
if ( index >= count )
|
||||
return ELF_INVALID_HANDLE(elf_phdr);
|
||||
@@ -233,24 +233,24 @@ const char *elf_strfmt(struct elf_binary *elf, elf_ptrval start)
|
||||
return str;
|
||||
}
|
||||
|
||||
-ELF_PTRVAL_CONST_VOID elf_section_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr)
|
||||
+elf_ptrval elf_section_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr)
|
||||
{
|
||||
return ELF_IMAGE_BASE(elf) + elf_uval(elf, shdr, sh_offset);
|
||||
}
|
||||
|
||||
-ELF_PTRVAL_CONST_VOID elf_section_end(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr)
|
||||
+elf_ptrval elf_section_end(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr)
|
||||
{
|
||||
return ELF_IMAGE_BASE(elf)
|
||||
+ elf_uval(elf, shdr, sh_offset) + elf_uval(elf, shdr, sh_size);
|
||||
}
|
||||
|
||||
-ELF_PTRVAL_CONST_VOID elf_segment_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr)
|
||||
+elf_ptrval elf_segment_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr)
|
||||
{
|
||||
return ELF_IMAGE_BASE(elf)
|
||||
+ elf_uval(elf, phdr, p_offset);
|
||||
}
|
||||
|
||||
-ELF_PTRVAL_CONST_VOID elf_segment_end(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr)
|
||||
+elf_ptrval elf_segment_end(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr)
|
||||
{
|
||||
return ELF_IMAGE_BASE(elf)
|
||||
+ elf_uval(elf, phdr, p_offset) + elf_uval(elf, phdr, p_filesz);
|
||||
@@ -258,8 +258,8 @@ ELF_PTRVAL_CONST_VOID elf_segment_end(struct elf_binary *elf, ELF_HANDLE_DECL(el
|
||||
|
||||
ELF_HANDLE_DECL(elf_sym) elf_sym_by_name(struct elf_binary *elf, const char *symbol)
|
||||
{
|
||||
- ELF_PTRVAL_CONST_VOID ptr = elf_section_start(elf, elf->sym_tab);
|
||||
- ELF_PTRVAL_CONST_VOID end = elf_section_end(elf, elf->sym_tab);
|
||||
+ elf_ptrval ptr = elf_section_start(elf, elf->sym_tab);
|
||||
+ elf_ptrval end = elf_section_end(elf, elf->sym_tab);
|
||||
ELF_HANDLE_DECL(elf_sym) sym;
|
||||
uint64_t info, name;
|
||||
const char *sym_name;
|
||||
@@ -283,7 +283,7 @@ ELF_HANDLE_DECL(elf_sym) elf_sym_by_name(struct elf_binary *elf, const char *sym
|
||||
|
||||
ELF_HANDLE_DECL(elf_sym) elf_sym_by_index(struct elf_binary *elf, unsigned index)
|
||||
{
|
||||
- ELF_PTRVAL_CONST_VOID ptr = elf_section_start(elf, elf->sym_tab);
|
||||
+ elf_ptrval ptr = elf_section_start(elf, elf->sym_tab);
|
||||
ELF_HANDLE_DECL(elf_sym) sym;
|
||||
|
||||
sym = ELF_MAKE_HANDLE(elf_sym, ptr + index * elf_size(elf, sym));
|
||||
@@ -295,7 +295,7 @@ const char *elf_note_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note
|
||||
return elf_strval(elf, ELF_HANDLE_PTRVAL(note) + elf_size(elf, note));
|
||||
}
|
||||
|
||||
-ELF_PTRVAL_CONST_VOID elf_note_desc(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note)
|
||||
+elf_ptrval elf_note_desc(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note)
|
||||
{
|
||||
unsigned namesz = (elf_uval(elf, note, namesz) + 3) & ~3;
|
||||
|
||||
@@ -304,7 +304,7 @@ ELF_PTRVAL_CONST_VOID elf_note_desc(struct elf_binary *elf, ELF_HANDLE_DECL(elf_
|
||||
|
||||
uint64_t elf_note_numeric(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note)
|
||||
{
|
||||
- ELF_PTRVAL_CONST_VOID desc = elf_note_desc(elf, note);
|
||||
+ elf_ptrval desc = elf_note_desc(elf, note);
|
||||
unsigned descsz = elf_uval(elf, note, descsz);
|
||||
|
||||
switch (descsz)
|
||||
@@ -322,7 +322,7 @@ uint64_t elf_note_numeric(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note
|
||||
uint64_t elf_note_numeric_array(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note,
|
||||
unsigned int unitsz, unsigned int idx)
|
||||
{
|
||||
- ELF_PTRVAL_CONST_VOID desc = elf_note_desc(elf, note);
|
||||
+ elf_ptrval desc = elf_note_desc(elf, note);
|
||||
unsigned descsz = elf_uval(elf, note, descsz);
|
||||
|
||||
if ( descsz % unitsz || idx >= descsz / unitsz )
|
||||
diff --git a/xen/include/xen/libelf.h b/xen/include/xen/libelf.h
|
||||
index f95fe88..174f8da 100644
|
||||
--- a/xen/include/xen/libelf.h
|
||||
+++ b/xen/include/xen/libelf.h
|
||||
@@ -61,13 +61,8 @@ typedef void elf_log_callback(struct elf_binary*, void *caller_data,
|
||||
/*
|
||||
* We abstract away the pointerness of these pointers, replacing
|
||||
* various void*, char* and struct* with the following:
|
||||
- * PTRVAL A pointer to a byte; one can do pointer arithmetic
|
||||
+ * elf_ptrval A pointer to a byte; one can do pointer arithmetic
|
||||
* on this.
|
||||
- * This replaces variables which were char*,void*
|
||||
- * and their const versions, so we provide four
|
||||
- * different obsolete declaration macros:
|
||||
- * ELF_PTRVAL_{,CONST}{VOID,CHAR}
|
||||
- * New code can simply use the elf_ptrval typedef.
|
||||
* HANDLE A pointer to a struct. There is one of these types
|
||||
* for each pointer type - that is, for each "structname".
|
||||
* In the arguments to the various HANDLE macros, structname
|
||||
@@ -76,8 +71,6 @@ typedef void elf_log_callback(struct elf_binary*, void *caller_data,
|
||||
* pointers. In the current code attempts to do so will
|
||||
* compile, but in the next patch this will become a
|
||||
* compile error.
|
||||
- * We also provide a second declaration macro for
|
||||
- * pointers which were to const; this is obsolete.
|
||||
*/
|
||||
|
||||
typedef uintptr_t elf_ptrval;
|
||||
@@ -85,15 +78,9 @@ typedef uintptr_t elf_ptrval;
|
||||
#define ELF_REALPTR2PTRVAL(realpointer) ((elf_ptrval)(realpointer))
|
||||
/* Converts an actual C pointer into a PTRVAL */
|
||||
|
||||
-#define ELF_HANDLE_DECL_NONCONST(structname) structname##_handle /*obsolete*/
|
||||
#define ELF_HANDLE_DECL(structname) structname##_handle
|
||||
/* Provides a type declaration for a HANDLE. */
|
||||
|
||||
-#define ELF_PTRVAL_VOID elf_ptrval /*obsolete*/
|
||||
-#define ELF_PTRVAL_CHAR elf_ptrval /*obsolete*/
|
||||
-#define ELF_PTRVAL_CONST_VOID elf_ptrval /*obsolete*/
|
||||
-#define ELF_PTRVAL_CONST_CHAR elf_ptrval /*obsolete*/
|
||||
-
|
||||
#ifdef __XEN__
|
||||
# define ELF_PRPTRVAL "lu"
|
||||
/*
|
||||
@@ -124,17 +111,6 @@ typedef uintptr_t elf_ptrval;
|
||||
#define ELF_HANDLE_PTRVAL(handleval) ((handleval).ptrval)
|
||||
/* Converts a HANDLE to a PTRVAL. */
|
||||
|
||||
-#define ELF_OBSOLETE_VOIDP_CAST /*empty*/
|
||||
- /*
|
||||
- * In some places the old code used to need to
|
||||
- * - cast away const (the existing code uses const a fair
|
||||
- * bit but actually sometimes wants to write to its input)
|
||||
- * from a PTRVAL.
|
||||
- * - convert an integer representing a pointer to a PTRVAL
|
||||
- * Nowadays all of these re uintptr_ts so there is no const problem
|
||||
- * and no need for any casting.
|
||||
- */
|
||||
-
|
||||
#define ELF_UNSAFE_PTR(ptrval) ((void*)(elf_ptrval)(ptrval))
|
||||
/*
|
||||
* Turns a PTRVAL into an actual C pointer. Before this is done
|
||||
@@ -212,7 +188,7 @@ struct elf_binary {
|
||||
char data;
|
||||
|
||||
ELF_HANDLE_DECL(elf_ehdr) ehdr;
|
||||
- ELF_PTRVAL_CONST_CHAR sec_strtab;
|
||||
+ elf_ptrval sec_strtab;
|
||||
ELF_HANDLE_DECL(elf_shdr) sym_tab;
|
||||
uint64_t sym_strtab;
|
||||
|
||||
@@ -290,7 +266,7 @@ struct elf_binary {
|
||||
* str should be a HANDLE.
|
||||
*/
|
||||
|
||||
-uint64_t elf_access_unsigned(struct elf_binary *elf, ELF_PTRVAL_CONST_VOID ptr,
|
||||
+uint64_t elf_access_unsigned(struct elf_binary *elf, elf_ptrval ptr,
|
||||
uint64_t offset, size_t size);
|
||||
/* Reads a field at arbitrary offset and alignemnt */
|
||||
|
||||
@@ -342,17 +318,17 @@ ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_index(struct elf_binary *elf, unsigned ind
|
||||
ELF_HANDLE_DECL(elf_phdr) elf_phdr_by_index(struct elf_binary *elf, unsigned index);
|
||||
|
||||
const char *elf_section_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr); /* might return NULL if inputs are invalid */
|
||||
-ELF_PTRVAL_CONST_VOID elf_section_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr);
|
||||
-ELF_PTRVAL_CONST_VOID elf_section_end(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr);
|
||||
+elf_ptrval elf_section_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr);
|
||||
+elf_ptrval elf_section_end(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr);
|
||||
|
||||
-ELF_PTRVAL_CONST_VOID elf_segment_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr);
|
||||
-ELF_PTRVAL_CONST_VOID elf_segment_end(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr);
|
||||
+elf_ptrval elf_segment_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr);
|
||||
+elf_ptrval elf_segment_end(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr);
|
||||
|
||||
ELF_HANDLE_DECL(elf_sym) elf_sym_by_name(struct elf_binary *elf, const char *symbol);
|
||||
ELF_HANDLE_DECL(elf_sym) elf_sym_by_index(struct elf_binary *elf, unsigned index);
|
||||
|
||||
const char *elf_note_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note); /* may return NULL */
|
||||
-ELF_PTRVAL_CONST_VOID elf_note_desc(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
|
||||
+elf_ptrval elf_note_desc(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
|
||||
uint64_t elf_note_numeric(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
|
||||
uint64_t elf_note_numeric_array(struct elf_binary *, ELF_HANDLE_DECL(elf_note),
|
||||
unsigned int unitsz, unsigned int idx);
|
||||
@@ -391,7 +367,7 @@ void elf_set_log(struct elf_binary *elf, elf_log_callback*,
|
||||
void elf_parse_binary(struct elf_binary *elf);
|
||||
elf_errorstatus elf_load_binary(struct elf_binary *elf);
|
||||
|
||||
-ELF_PTRVAL_VOID elf_get_ptr(struct elf_binary *elf, unsigned long addr);
|
||||
+elf_ptrval elf_get_ptr(struct elf_binary *elf, unsigned long addr);
|
||||
uint64_t elf_lookup_addr(struct elf_binary *elf, const char *symbol);
|
||||
|
||||
void elf_parse_bsdsyms(struct elf_binary *elf, uint64_t pstart); /* private */
|
||||
@@ -426,9 +402,9 @@ struct xen_elfnote {
|
||||
|
||||
struct elf_dom_parms {
|
||||
/* raw */
|
||||
- ELF_PTRVAL_CONST_CHAR guest_info;
|
||||
- ELF_PTRVAL_CONST_VOID elf_note_start;
|
||||
- ELF_PTRVAL_CONST_VOID elf_note_end;
|
||||
+ elf_ptrval guest_info;
|
||||
+ elf_ptrval elf_note_start;
|
||||
+ elf_ptrval elf_note_end;
|
||||
struct xen_elfnote elf_notes[XEN_ELFNOTE_MAX + 1];
|
||||
|
||||
/* parsed */
|
||||
--
|
||||
1.7.2.5
|
||||
|
@ -0,0 +1,450 @@
|
||||
From b06e277b1fc08c7da3befeb3ac3950e1d941585d Mon Sep 17 00:00:00 2001
|
||||
From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Date: Fri, 14 Jun 2013 16:43:19 +0100
|
||||
Subject: [PATCH 18/23] libxc: Add range checking to xc_dom_binloader
|
||||
|
||||
This is a simple binary image loader with its own metadata format.
|
||||
However, it is too careless with image-supplied values.
|
||||
|
||||
Add the following checks:
|
||||
|
||||
* That the image is bigger than the metadata table; otherwise the
|
||||
pointer arithmetic to calculate the metadata table location may
|
||||
yield undefined and dangerous values.
|
||||
|
||||
* When clamping the end of the region to search, that we do not
|
||||
calculate pointers beyond the end of the image. The C
|
||||
specification does not permit this and compilers are becoming ever
|
||||
more determined to miscompile code when they can "prove" various
|
||||
falsehoods based on assertions from the C spec.
|
||||
|
||||
* That the supplied image is big enough for the text we are allegedly
|
||||
copying from it. Otherwise we might have a read overrun and copy
|
||||
the results (perhaps a lot of secret data) into the guest.
|
||||
|
||||
This is part of the fix to a security issue, XSA-55.
|
||||
|
||||
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
---
|
||||
tools/libxc/xc_dom_binloader.c | 15 +++++++++++++--
|
||||
1 files changed, 13 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/tools/libxc/xc_dom_binloader.c b/tools/libxc/xc_dom_binloader.c
|
||||
index bde93f7..8596a28 100644
|
||||
--- a/tools/libxc/xc_dom_binloader.c
|
||||
+++ b/tools/libxc/xc_dom_binloader.c
|
||||
@@ -123,10 +123,13 @@ static struct xen_bin_image_table *find_table(struct xc_dom_image *dom)
|
||||
uint32_t *probe_ptr;
|
||||
uint32_t *probe_end;
|
||||
|
||||
+ if ( dom->kernel_size < sizeof(*table) )
|
||||
+ return NULL;
|
||||
probe_ptr = dom->kernel_blob;
|
||||
- probe_end = dom->kernel_blob + dom->kernel_size - sizeof(*table);
|
||||
- if ( (void*)probe_end > (dom->kernel_blob + 8192) )
|
||||
+ if ( dom->kernel_size > (8192 + sizeof(*table)) )
|
||||
probe_end = dom->kernel_blob + 8192;
|
||||
+ else
|
||||
+ probe_end = dom->kernel_blob + dom->kernel_size - sizeof(*table);
|
||||
|
||||
for ( table = NULL; probe_ptr < probe_end; probe_ptr++ )
|
||||
{
|
||||
@@ -282,6 +285,14 @@ static int xc_dom_load_bin_kernel(struct xc_dom_image *dom)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
+ if ( image_size < skip ||
|
||||
+ image_size - skip < text_size )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: image is too small for declared text size",
|
||||
+ __FUNCTION__);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
memcpy(dest, image + skip, text_size);
|
||||
memset(dest + text_size, 0, bss_size);
|
||||
|
||||
--
|
||||
1.7.2.5
|
||||
#From 77c0829fa751f052f7b8ec08287aef6e7ba97bc5 Mon Sep 17 00:00:00 2001
|
||||
#From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
#Date: Fri, 14 Jun 2013 16:43:19 +0100
|
||||
#Subject: [PATCH 19/23] libxc: check failure of xc_dom_*_to_ptr, xc_map_foreign_range
|
||||
#
|
||||
#The return values from xc_dom_*_to_ptr and xc_map_foreign_range are
|
||||
#sometimes dereferenced, or subjected to pointer arithmetic, without
|
||||
#checking whether the relevant function failed and returned NULL.
|
||||
#
|
||||
#Add an appropriate error check at every call site.
|
||||
#
|
||||
#Changes in the 4.2 backport of this series:
|
||||
#* Fix tools/libxc/xc_dom_x86.c:setup_pgtables_x86_32.
|
||||
#* Fix tools/libxc/xc_dom_ia64.c:start_info_ia64.
|
||||
#* Fix tools/libxc/ia64/xc_ia64_dom_fwloader.c:xc_dom_load_fw_kernel.
|
||||
#
|
||||
#This is part of the fix to a security issue, XSA-55.
|
||||
#
|
||||
#Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
#---
|
||||
# tools/libxc/ia64/xc_ia64_dom_fwloader.c | 2 +
|
||||
# tools/libxc/xc_dom_binloader.c | 6 +++
|
||||
# tools/libxc/xc_dom_core.c | 6 +++
|
||||
# tools/libxc/xc_dom_elfloader.c | 13 +++++++
|
||||
# tools/libxc/xc_dom_ia64.c | 6 +++
|
||||
# tools/libxc/xc_dom_x86.c | 55 +++++++++++++++++++++++++++++++
|
||||
# tools/libxc/xc_domain_restore.c | 27 +++++++++++++++
|
||||
# tools/libxc/xc_offline_page.c | 5 +++
|
||||
# 8 files changed, 120 insertions(+), 0 deletions(-)
|
||||
#
|
||||
diff --git a/tools/libxc/ia64/xc_ia64_dom_fwloader.c b/tools/libxc/ia64/xc_ia64_dom_fwloader.c
|
||||
index cdf3333..dbd3349 100644
|
||||
--- a/tools/libxc/ia64/xc_ia64_dom_fwloader.c
|
||||
+++ b/tools/libxc/ia64/xc_ia64_dom_fwloader.c
|
||||
@@ -60,6 +60,8 @@ static int xc_dom_load_fw_kernel(struct xc_dom_image *dom)
|
||||
unsigned long i;
|
||||
|
||||
dest = xc_dom_vaddr_to_ptr(dom, dom->kernel_seg.vstart);
|
||||
+ if ( dest == NULL )
|
||||
+ return -1;
|
||||
memcpy(dest, dom->kernel_blob, FW_SIZE);
|
||||
|
||||
/* Synchronize cache. */
|
||||
diff --git a/tools/libxc/xc_dom_binloader.c b/tools/libxc/xc_dom_binloader.c
|
||||
index 8596a28..553b366 100644
|
||||
--- a/tools/libxc/xc_dom_binloader.c
|
||||
+++ b/tools/libxc/xc_dom_binloader.c
|
||||
@@ -277,6 +277,12 @@ static int xc_dom_load_bin_kernel(struct xc_dom_image *dom)
|
||||
DOMPRINTF(" bss_size: 0x%" PRIx32 "", bss_size);
|
||||
|
||||
dest = xc_dom_vaddr_to_ptr(dom, dom->kernel_seg.vstart, &dest_size);
|
||||
+ if ( dest == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: xc_dom_vaddr_to_ptr(dom, dom->kernel_seg.vstart)"
|
||||
+ " => NULL", __FUNCTION__);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
|
||||
if ( dest_size < text_size ||
|
||||
dest_size - text_size < bss_size )
|
||||
diff --git a/tools/libxc/xc_dom_core.c b/tools/libxc/xc_dom_core.c
|
||||
index 8913e41..a54ddae 100644
|
||||
--- a/tools/libxc/xc_dom_core.c
|
||||
+++ b/tools/libxc/xc_dom_core.c
|
||||
@@ -868,6 +868,12 @@ int xc_dom_build_image(struct xc_dom_image *dom)
|
||||
ramdisklen) != 0 )
|
||||
goto err;
|
||||
ramdiskmap = xc_dom_seg_to_ptr(dom, &dom->ramdisk_seg);
|
||||
+ if ( ramdiskmap == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: xc_dom_seg_to_ptr(dom, &dom->ramdisk_seg) => NULL",
|
||||
+ __FUNCTION__);
|
||||
+ goto err;
|
||||
+ }
|
||||
if ( unziplen )
|
||||
{
|
||||
if ( xc_dom_do_gunzip(dom->xch,
|
||||
diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c
|
||||
index 9fc4b94..61b5798 100644
|
||||
--- a/tools/libxc/xc_dom_elfloader.c
|
||||
+++ b/tools/libxc/xc_dom_elfloader.c
|
||||
@@ -139,6 +139,12 @@ static elf_errorstatus xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
return 0;
|
||||
size = dom->kernel_seg.vend - dom->bsd_symtab_start;
|
||||
hdr_ptr = xc_dom_vaddr_to_ptr(dom, dom->bsd_symtab_start, &allow_size);
|
||||
+ if ( hdr_ptr == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s/load: xc_dom_vaddr_to_ptr(dom,dom->bsd_symtab_start"
|
||||
+ " => NULL", __FUNCTION__);
|
||||
+ return -1;
|
||||
+ }
|
||||
elf->caller_xdest_base = hdr_ptr;
|
||||
elf->caller_xdest_size = allow_size;
|
||||
hdr = ELF_REALPTR2PTRVAL(hdr_ptr);
|
||||
@@ -384,7 +390,14 @@ static elf_errorstatus xc_dom_load_elf_kernel(struct xc_dom_image *dom)
|
||||
xen_pfn_t pages;
|
||||
|
||||
elf->dest_base = xc_dom_seg_to_ptr_pages(dom, &dom->kernel_seg, &pages);
|
||||
+ if ( elf->dest_base == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: xc_dom_vaddr_to_ptr(dom,dom->kernel_seg)"
|
||||
+ " => NULL", __FUNCTION__);
|
||||
+ return -1;
|
||||
+ }
|
||||
elf->dest_size = pages * XC_DOM_PAGE_SIZE(dom);
|
||||
+
|
||||
rc = elf_load_binary(elf);
|
||||
if ( rc < 0 )
|
||||
{
|
||||
diff --git a/tools/libxc/xc_dom_ia64.c b/tools/libxc/xc_dom_ia64.c
|
||||
index dcd1523..7c0eff1 100644
|
||||
--- a/tools/libxc/xc_dom_ia64.c
|
||||
+++ b/tools/libxc/xc_dom_ia64.c
|
||||
@@ -60,6 +60,12 @@ int start_info_ia64(struct xc_dom_image *dom)
|
||||
|
||||
DOMPRINTF_CALLED(dom->xch);
|
||||
|
||||
+ if ( start_info == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: xc_dom_pfn_to_ptr failed on start_info", __FUNCTION__);
|
||||
+ return -1; /* our caller throws away our return value :-/ */
|
||||
+ }
|
||||
+
|
||||
memset(start_info, 0, sizeof(*start_info));
|
||||
sprintf(start_info->magic, dom->guest_type);
|
||||
start_info->flags = dom->flags;
|
||||
diff --git a/tools/libxc/xc_dom_x86.c b/tools/libxc/xc_dom_x86.c
|
||||
index 0cf1687..75d6b83 100644
|
||||
--- a/tools/libxc/xc_dom_x86.c
|
||||
+++ b/tools/libxc/xc_dom_x86.c
|
||||
@@ -144,6 +144,9 @@ static int setup_pgtables_x86_32(struct xc_dom_image *dom)
|
||||
xen_vaddr_t addr;
|
||||
xen_pfn_t pgpfn;
|
||||
|
||||
+ if ( l2tab == NULL )
|
||||
+ goto pfn_error;
|
||||
+
|
||||
for ( addr = dom->parms.virt_base; addr < dom->virt_pgtab_end;
|
||||
addr += PAGE_SIZE_X86 )
|
||||
{
|
||||
@@ -151,6 +154,8 @@ static int setup_pgtables_x86_32(struct xc_dom_image *dom)
|
||||
{
|
||||
/* get L1 tab, make L2 entry */
|
||||
l1tab = xc_dom_pfn_to_ptr(dom, l1pfn, 1);
|
||||
+ if ( l1tab == NULL )
|
||||
+ goto pfn_error;
|
||||
l2off = l2_table_offset_i386(addr);
|
||||
l2tab[l2off] =
|
||||
pfn_to_paddr(xc_dom_p2m_guest(dom, l1pfn)) | L2_PROT;
|
||||
@@ -169,6 +174,11 @@ static int setup_pgtables_x86_32(struct xc_dom_image *dom)
|
||||
l1tab = NULL;
|
||||
}
|
||||
return 0;
|
||||
+
|
||||
+pfn_error:
|
||||
+ xc_dom_panic(dom->xch, XC_INTERNAL_ERROR,
|
||||
+ "%s: xc_dom_pfn_to_ptr failed", __FUNCTION__);
|
||||
+ return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -219,6 +229,12 @@ static xen_pfn_t move_l3_below_4G(struct xc_dom_image *dom,
|
||||
goto out;
|
||||
|
||||
l3tab = xc_dom_pfn_to_ptr(dom, l3pfn, 1);
|
||||
+ if ( l3tab == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: xc_dom_pfn_to_ptr(dom, l3pfn, 1) => NULL",
|
||||
+ __FUNCTION__);
|
||||
+ return l3mfn; /* our one call site will call xc_dom_panic and fail */
|
||||
+ }
|
||||
memset(l3tab, 0, XC_DOM_PAGE_SIZE(dom));
|
||||
|
||||
DOMPRINTF("%s: successfully relocated L3 below 4G. "
|
||||
@@ -262,6 +278,8 @@ static int setup_pgtables_x86_32_pae(struct xc_dom_image *dom)
|
||||
}
|
||||
|
||||
l3tab = xc_dom_pfn_to_ptr(dom, l3pfn, 1);
|
||||
+ if ( l3tab == NULL )
|
||||
+ goto pfn_error;
|
||||
|
||||
for ( addr = dom->parms.virt_base; addr < dom->virt_pgtab_end;
|
||||
addr += PAGE_SIZE_X86 )
|
||||
@@ -270,6 +288,8 @@ static int setup_pgtables_x86_32_pae(struct xc_dom_image *dom)
|
||||
{
|
||||
/* get L2 tab, make L3 entry */
|
||||
l2tab = xc_dom_pfn_to_ptr(dom, l2pfn, 1);
|
||||
+ if ( l2tab == NULL )
|
||||
+ goto pfn_error;
|
||||
l3off = l3_table_offset_pae(addr);
|
||||
l3tab[l3off] =
|
||||
pfn_to_paddr(xc_dom_p2m_guest(dom, l2pfn)) | L3_PROT;
|
||||
@@ -280,6 +300,8 @@ static int setup_pgtables_x86_32_pae(struct xc_dom_image *dom)
|
||||
{
|
||||
/* get L1 tab, make L2 entry */
|
||||
l1tab = xc_dom_pfn_to_ptr(dom, l1pfn, 1);
|
||||
+ if ( l1tab == NULL )
|
||||
+ goto pfn_error;
|
||||
l2off = l2_table_offset_pae(addr);
|
||||
l2tab[l2off] =
|
||||
pfn_to_paddr(xc_dom_p2m_guest(dom, l1pfn)) | L2_PROT;
|
||||
@@ -306,6 +328,11 @@ static int setup_pgtables_x86_32_pae(struct xc_dom_image *dom)
|
||||
l3tab[3] = pfn_to_paddr(xc_dom_p2m_guest(dom, l2pfn)) | L3_PROT;
|
||||
}
|
||||
return 0;
|
||||
+
|
||||
+pfn_error:
|
||||
+ xc_dom_panic(dom->xch, XC_INTERNAL_ERROR,
|
||||
+ "%s: xc_dom_pfn_to_ptr failed", __FUNCTION__);
|
||||
+ return -EINVAL;
|
||||
}
|
||||
|
||||
#undef L1_PROT
|
||||
@@ -344,6 +371,9 @@ static int setup_pgtables_x86_64(struct xc_dom_image *dom)
|
||||
uint64_t addr;
|
||||
xen_pfn_t pgpfn;
|
||||
|
||||
+ if ( l4tab == NULL )
|
||||
+ goto pfn_error;
|
||||
+
|
||||
for ( addr = dom->parms.virt_base; addr < dom->virt_pgtab_end;
|
||||
addr += PAGE_SIZE_X86 )
|
||||
{
|
||||
@@ -351,6 +381,8 @@ static int setup_pgtables_x86_64(struct xc_dom_image *dom)
|
||||
{
|
||||
/* get L3 tab, make L4 entry */
|
||||
l3tab = xc_dom_pfn_to_ptr(dom, l3pfn, 1);
|
||||
+ if ( l3tab == NULL )
|
||||
+ goto pfn_error;
|
||||
l4off = l4_table_offset_x86_64(addr);
|
||||
l4tab[l4off] =
|
||||
pfn_to_paddr(xc_dom_p2m_guest(dom, l3pfn)) | L4_PROT;
|
||||
@@ -361,6 +393,8 @@ static int setup_pgtables_x86_64(struct xc_dom_image *dom)
|
||||
{
|
||||
/* get L2 tab, make L3 entry */
|
||||
l2tab = xc_dom_pfn_to_ptr(dom, l2pfn, 1);
|
||||
+ if ( l2tab == NULL )
|
||||
+ goto pfn_error;
|
||||
l3off = l3_table_offset_x86_64(addr);
|
||||
l3tab[l3off] =
|
||||
pfn_to_paddr(xc_dom_p2m_guest(dom, l2pfn)) | L3_PROT;
|
||||
@@ -373,6 +407,8 @@ static int setup_pgtables_x86_64(struct xc_dom_image *dom)
|
||||
{
|
||||
/* get L1 tab, make L2 entry */
|
||||
l1tab = xc_dom_pfn_to_ptr(dom, l1pfn, 1);
|
||||
+ if ( l1tab == NULL )
|
||||
+ goto pfn_error;
|
||||
l2off = l2_table_offset_x86_64(addr);
|
||||
l2tab[l2off] =
|
||||
pfn_to_paddr(xc_dom_p2m_guest(dom, l1pfn)) | L2_PROT;
|
||||
@@ -393,6 +429,11 @@ static int setup_pgtables_x86_64(struct xc_dom_image *dom)
|
||||
l1tab = NULL;
|
||||
}
|
||||
return 0;
|
||||
+
|
||||
+pfn_error:
|
||||
+ xc_dom_panic(dom->xch, XC_INTERNAL_ERROR,
|
||||
+ "%s: xc_dom_pfn_to_ptr failed", __FUNCTION__);
|
||||
+ return -EINVAL;
|
||||
}
|
||||
|
||||
#undef L1_PROT
|
||||
@@ -410,6 +451,8 @@ static int alloc_magic_pages(struct xc_dom_image *dom)
|
||||
if ( xc_dom_alloc_segment(dom, &dom->p2m_seg, "phys2mach", 0, p2m_size) )
|
||||
return -1;
|
||||
dom->p2m_guest = xc_dom_seg_to_ptr(dom, &dom->p2m_seg);
|
||||
+ if ( dom->p2m_guest == NULL )
|
||||
+ return -1;
|
||||
|
||||
/* allocate special pages */
|
||||
dom->start_info_pfn = xc_dom_alloc_page(dom, "start info");
|
||||
@@ -434,6 +477,12 @@ static int start_info_x86_32(struct xc_dom_image *dom)
|
||||
|
||||
DOMPRINTF_CALLED(dom->xch);
|
||||
|
||||
+ if ( start_info == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: xc_dom_pfn_to_ptr failed on start_info", __FUNCTION__);
|
||||
+ return -1; /* our caller throws away our return value :-/ */
|
||||
+ }
|
||||
+
|
||||
memset(start_info, 0, sizeof(*start_info));
|
||||
strncpy(start_info->magic, dom->guest_type, sizeof(start_info->magic));
|
||||
start_info->magic[sizeof(start_info->magic) - 1] = '\0';
|
||||
@@ -474,6 +523,12 @@ static int start_info_x86_64(struct xc_dom_image *dom)
|
||||
|
||||
DOMPRINTF_CALLED(dom->xch);
|
||||
|
||||
+ if ( start_info == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: xc_dom_pfn_to_ptr failed on start_info", __FUNCTION__);
|
||||
+ return -1; /* our caller throws away our return value :-/ */
|
||||
+ }
|
||||
+
|
||||
memset(start_info, 0, sizeof(*start_info));
|
||||
strncpy(start_info->magic, dom->guest_type, sizeof(start_info->magic));
|
||||
start_info->magic[sizeof(start_info->magic) - 1] = '\0';
|
||||
diff --git a/tools/libxc/xc_domain_restore.c b/tools/libxc/xc_domain_restore.c
|
||||
index b4c0b10..3994f8f 100644
|
||||
--- a/tools/libxc/xc_domain_restore.c
|
||||
+++ b/tools/libxc/xc_domain_restore.c
|
||||
@@ -1556,6 +1556,12 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
|
||||
mfn = ctx->p2m[pfn];
|
||||
buf = xc_map_foreign_range(xch, dom, PAGE_SIZE,
|
||||
PROT_READ | PROT_WRITE, mfn);
|
||||
+ if ( buf == NULL )
|
||||
+ {
|
||||
+ ERROR("xc_map_foreign_range for generation id"
|
||||
+ " buffer failed");
|
||||
+ goto out;
|
||||
+ }
|
||||
|
||||
generationid = *(unsigned long long *)(buf + offset);
|
||||
*(unsigned long long *)(buf + offset) = generationid + 1;
|
||||
@@ -1713,6 +1719,11 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
|
||||
l3tab = (uint64_t *)
|
||||
xc_map_foreign_range(xch, dom, PAGE_SIZE,
|
||||
PROT_READ, ctx->p2m[i]);
|
||||
+ if ( l3tab == NULL )
|
||||
+ {
|
||||
+ PERROR("xc_map_foreign_range failed (for l3tab)");
|
||||
+ goto out;
|
||||
+ }
|
||||
|
||||
for ( j = 0; j < 4; j++ )
|
||||
l3ptes[j] = l3tab[j];
|
||||
@@ -1739,6 +1750,11 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
|
||||
l3tab = (uint64_t *)
|
||||
xc_map_foreign_range(xch, dom, PAGE_SIZE,
|
||||
PROT_READ | PROT_WRITE, ctx->p2m[i]);
|
||||
+ if ( l3tab == NULL )
|
||||
+ {
|
||||
+ PERROR("xc_map_foreign_range failed (for l3tab, 2nd)");
|
||||
+ goto out;
|
||||
+ }
|
||||
|
||||
for ( j = 0; j < 4; j++ )
|
||||
l3tab[j] = l3ptes[j];
|
||||
@@ -1909,6 +1925,12 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
|
||||
SET_FIELD(ctxt, user_regs.edx, mfn);
|
||||
start_info = xc_map_foreign_range(
|
||||
xch, dom, PAGE_SIZE, PROT_READ | PROT_WRITE, mfn);
|
||||
+ if ( start_info == NULL )
|
||||
+ {
|
||||
+ PERROR("xc_map_foreign_range failed (for start_info)");
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
SET_FIELD(start_info, nr_pages, dinfo->p2m_size);
|
||||
SET_FIELD(start_info, shared_info, shared_info_frame<<PAGE_SHIFT);
|
||||
SET_FIELD(start_info, flags, 0);
|
||||
@@ -2056,6 +2078,11 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
|
||||
/* Restore contents of shared-info page. No checking needed. */
|
||||
new_shared_info = xc_map_foreign_range(
|
||||
xch, dom, PAGE_SIZE, PROT_WRITE, shared_info_frame);
|
||||
+ if ( new_shared_info == NULL )
|
||||
+ {
|
||||
+ PERROR("xc_map_foreign_range failed (for new_shared_info)");
|
||||
+ goto out;
|
||||
+ }
|
||||
|
||||
/* restore saved vcpu_info and arch specific info */
|
||||
MEMCPY_FIELD(new_shared_info, old_shared_info, vcpu_info);
|
||||
diff --git a/tools/libxc/xc_offline_page.c b/tools/libxc/xc_offline_page.c
|
||||
index 089a361..36b9812 100644
|
||||
--- a/tools/libxc/xc_offline_page.c
|
||||
+++ b/tools/libxc/xc_offline_page.c
|
||||
@@ -714,6 +714,11 @@ int xc_exchange_page(xc_interface *xch, int domid, xen_pfn_t mfn)
|
||||
|
||||
new_p = xc_map_foreign_range(xch, domid, PAGE_SIZE,
|
||||
PROT_READ|PROT_WRITE, new_mfn);
|
||||
+ if ( new_p == NULL )
|
||||
+ {
|
||||
+ ERROR("failed to map new_p for copy, guest may be broken?");
|
||||
+ goto failed;
|
||||
+ }
|
||||
memcpy(new_p, backup, PAGE_SIZE);
|
||||
munmap(new_p, PAGE_SIZE);
|
||||
mops.arg1.mfn = new_mfn;
|
||||
--
|
||||
1.7.2.5
|
||||
|
@ -0,0 +1,56 @@
|
||||
From a672da4b2d58ef12be9d7407160e9fb43cac75d9 Mon Sep 17 00:00:00 2001
|
||||
From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Date: Fri, 14 Jun 2013 16:43:16 +0100
|
||||
Subject: [PATCH 02/23] libxc: introduce xc_dom_seg_to_ptr_pages
|
||||
|
||||
Provide a version of xc_dom_seg_to_ptr which returns the number of
|
||||
guest pages it has actually mapped. This is useful for callers who
|
||||
want to do range checking; we will use this later in this series.
|
||||
|
||||
This is part of the fix to a security issue, XSA-55.
|
||||
|
||||
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
|
||||
---
|
||||
tools/libxc/xc_dom.h | 19 ++++++++++++++++---
|
||||
1 files changed, 16 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/tools/libxc/xc_dom.h b/tools/libxc/xc_dom.h
|
||||
index 6a72aa9..9af2195 100644
|
||||
--- a/tools/libxc/xc_dom.h
|
||||
+++ b/tools/libxc/xc_dom.h
|
||||
@@ -278,14 +278,27 @@ void *xc_dom_pfn_to_ptr(struct xc_dom_image *dom, xen_pfn_t first,
|
||||
void xc_dom_unmap_one(struct xc_dom_image *dom, xen_pfn_t pfn);
|
||||
void xc_dom_unmap_all(struct xc_dom_image *dom);
|
||||
|
||||
-static inline void *xc_dom_seg_to_ptr(struct xc_dom_image *dom,
|
||||
- struct xc_dom_seg *seg)
|
||||
+static inline void *xc_dom_seg_to_ptr_pages(struct xc_dom_image *dom,
|
||||
+ struct xc_dom_seg *seg,
|
||||
+ xen_pfn_t *pages_out)
|
||||
{
|
||||
xen_vaddr_t segsize = seg->vend - seg->vstart;
|
||||
unsigned int page_size = XC_DOM_PAGE_SIZE(dom);
|
||||
xen_pfn_t pages = (segsize + page_size - 1) / page_size;
|
||||
+ void *retval;
|
||||
+
|
||||
+ retval = xc_dom_pfn_to_ptr(dom, seg->pfn, pages);
|
||||
+
|
||||
+ *pages_out = retval ? pages : 0;
|
||||
+ return retval;
|
||||
+}
|
||||
+
|
||||
+static inline void *xc_dom_seg_to_ptr(struct xc_dom_image *dom,
|
||||
+ struct xc_dom_seg *seg)
|
||||
+{
|
||||
+ xen_pfn_t dummy;
|
||||
|
||||
- return xc_dom_pfn_to_ptr(dom, seg->pfn, pages);
|
||||
+ return xc_dom_seg_to_ptr_pages(dom, seg, &dummy);
|
||||
}
|
||||
|
||||
static inline void *xc_dom_vaddr_to_ptr(struct xc_dom_image *dom,
|
||||
--
|
||||
1.7.2.5
|
||||
|
@ -0,0 +1,381 @@
|
||||
From 8dc90d163650ce8aa36ae0b46debab83cc61edb6 Mon Sep 17 00:00:00 2001
|
||||
From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Date: Fri, 14 Jun 2013 16:43:19 +0100
|
||||
Subject: [PATCH 20/23] libxc: check return values from malloc
|
||||
|
||||
A sufficiently malformed input to libxc (such as a malformed input ELF
|
||||
or other guest-controlled data) might cause one of libxc's malloc() to
|
||||
fail. In this case we need to make sure we don't dereference or do
|
||||
pointer arithmetic on the result.
|
||||
|
||||
Search for all occurrences of \b(m|c|re)alloc in libxc, and all
|
||||
functions which call them, and add appropriate error checking where
|
||||
missing.
|
||||
|
||||
This includes the functions xc_dom_malloc*, which now print a message
|
||||
when they fail so that callers don't have to do so.
|
||||
|
||||
The function xc_cpuid_to_str wasn't provided with a sane return value
|
||||
and has a pretty strange API, which now becomes a little stranger.
|
||||
There are no in-tree callers.
|
||||
|
||||
Changes in the Xen 4.2 version of this series:
|
||||
* No need to fix code relating to ARM.
|
||||
* No need to fix code relating to superpage support.
|
||||
* Additionally fix `dom->p2m_host = xc_dom_malloc...' in xc_dom_ia64.c.
|
||||
|
||||
This is part of the fix to a security issue, XSA-55.
|
||||
|
||||
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
---
|
||||
tools/libxc/xc_cpuid_x86.c | 20 ++++++++++++++++++--
|
||||
tools/libxc/xc_dom_core.c | 13 +++++++++++++
|
||||
tools/libxc/xc_dom_elfloader.c | 2 ++
|
||||
tools/libxc/xc_dom_ia64.c | 6 ++++++
|
||||
tools/libxc/xc_dom_x86.c | 3 +++
|
||||
tools/libxc/xc_domain_restore.c | 5 +++++
|
||||
tools/libxc/xc_linux_osdep.c | 4 ++++
|
||||
tools/libxc/xc_private.c | 2 ++
|
||||
tools/libxc/xenctrl.h | 2 +-
|
||||
9 files changed, 54 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/tools/libxc/xc_cpuid_x86.c b/tools/libxc/xc_cpuid_x86.c
|
||||
index 0882ce6..da435ce 100644
|
||||
--- a/tools/libxc/xc_cpuid_x86.c
|
||||
+++ b/tools/libxc/xc_cpuid_x86.c
|
||||
@@ -589,6 +589,8 @@ static int xc_cpuid_do_domctl(
|
||||
static char *alloc_str(void)
|
||||
{
|
||||
char *s = malloc(33);
|
||||
+ if ( s == NULL )
|
||||
+ return s;
|
||||
memset(s, 0, 33);
|
||||
return s;
|
||||
}
|
||||
@@ -600,6 +602,8 @@ void xc_cpuid_to_str(const unsigned int *regs, char **strs)
|
||||
for ( i = 0; i < 4; i++ )
|
||||
{
|
||||
strs[i] = alloc_str();
|
||||
+ if ( strs[i] == NULL )
|
||||
+ continue;
|
||||
for ( j = 0; j < 32; j++ )
|
||||
strs[i][j] = !!((regs[i] & (1U << (31 - j)))) ? '1' : '0';
|
||||
}
|
||||
@@ -680,7 +684,7 @@ int xc_cpuid_check(
|
||||
const char **config,
|
||||
char **config_transformed)
|
||||
{
|
||||
- int i, j;
|
||||
+ int i, j, rc;
|
||||
unsigned int regs[4];
|
||||
|
||||
memset(config_transformed, 0, 4 * sizeof(*config_transformed));
|
||||
@@ -692,6 +696,11 @@ int xc_cpuid_check(
|
||||
if ( config[i] == NULL )
|
||||
continue;
|
||||
config_transformed[i] = alloc_str();
|
||||
+ if ( config_transformed[i] == NULL )
|
||||
+ {
|
||||
+ rc = -ENOMEM;
|
||||
+ goto fail_rc;
|
||||
+ }
|
||||
for ( j = 0; j < 32; j++ )
|
||||
{
|
||||
unsigned char val = !!((regs[i] & (1U << (31 - j))));
|
||||
@@ -708,12 +717,14 @@ int xc_cpuid_check(
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
+ rc = -EPERM;
|
||||
+ fail_rc:
|
||||
for ( i = 0; i < 4; i++ )
|
||||
{
|
||||
free(config_transformed[i]);
|
||||
config_transformed[i] = NULL;
|
||||
}
|
||||
- return -EPERM;
|
||||
+ return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -758,6 +769,11 @@ int xc_cpuid_set(
|
||||
}
|
||||
|
||||
config_transformed[i] = alloc_str();
|
||||
+ if ( config_transformed[i] == NULL )
|
||||
+ {
|
||||
+ rc = -ENOMEM;
|
||||
+ goto fail;
|
||||
+ }
|
||||
|
||||
for ( j = 0; j < 32; j++ )
|
||||
{
|
||||
diff --git a/tools/libxc/xc_dom_core.c b/tools/libxc/xc_dom_core.c
|
||||
index a54ddae..3cbf9f7 100644
|
||||
--- a/tools/libxc/xc_dom_core.c
|
||||
+++ b/tools/libxc/xc_dom_core.c
|
||||
@@ -120,9 +120,17 @@ void *xc_dom_malloc(struct xc_dom_image *dom, size_t size)
|
||||
{
|
||||
struct xc_dom_mem *block;
|
||||
|
||||
+ if ( size > SIZE_MAX - sizeof(*block) )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: unreasonable allocation size", __FUNCTION__);
|
||||
+ return NULL;
|
||||
+ }
|
||||
block = malloc(sizeof(*block) + size);
|
||||
if ( block == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: allocation failed", __FUNCTION__);
|
||||
return NULL;
|
||||
+ }
|
||||
memset(block, 0, sizeof(*block) + size);
|
||||
block->next = dom->memblocks;
|
||||
dom->memblocks = block;
|
||||
@@ -138,7 +146,10 @@ void *xc_dom_malloc_page_aligned(struct xc_dom_image *dom, size_t size)
|
||||
|
||||
block = malloc(sizeof(*block));
|
||||
if ( block == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: allocation failed", __FUNCTION__);
|
||||
return NULL;
|
||||
+ }
|
||||
memset(block, 0, sizeof(*block));
|
||||
block->mmap_len = size;
|
||||
block->mmap_ptr = mmap(NULL, block->mmap_len,
|
||||
@@ -146,6 +157,7 @@ void *xc_dom_malloc_page_aligned(struct xc_dom_image *dom, size_t size)
|
||||
-1, 0);
|
||||
if ( block->mmap_ptr == MAP_FAILED )
|
||||
{
|
||||
+ DOMPRINTF("%s: mmap failed", __FUNCTION__);
|
||||
free(block);
|
||||
return NULL;
|
||||
}
|
||||
@@ -202,6 +214,7 @@ void *xc_dom_malloc_filemap(struct xc_dom_image *dom,
|
||||
close(fd);
|
||||
if ( block != NULL )
|
||||
free(block);
|
||||
+ DOMPRINTF("%s: failed (on file `%s')", __FUNCTION__, filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c
|
||||
index 61b5798..be58276 100644
|
||||
--- a/tools/libxc/xc_dom_elfloader.c
|
||||
+++ b/tools/libxc/xc_dom_elfloader.c
|
||||
@@ -329,6 +329,8 @@ static elf_errorstatus xc_dom_parse_elf_kernel(struct xc_dom_image *dom)
|
||||
return rc;
|
||||
|
||||
elf = xc_dom_malloc(dom, sizeof(*elf));
|
||||
+ if ( elf == NULL )
|
||||
+ return -1;
|
||||
dom->private_loader = elf;
|
||||
rc = elf_init(elf, dom->kernel_blob, dom->kernel_size);
|
||||
xc_elf_set_logfile(dom->xch, elf, 1);
|
||||
diff --git a/tools/libxc/xc_dom_ia64.c b/tools/libxc/xc_dom_ia64.c
|
||||
index 7c0eff1..076821c 100644
|
||||
--- a/tools/libxc/xc_dom_ia64.c
|
||||
+++ b/tools/libxc/xc_dom_ia64.c
|
||||
@@ -188,6 +188,12 @@ int arch_setup_meminit(struct xc_dom_image *dom)
|
||||
|
||||
/* setup initial p2m */
|
||||
dom->p2m_host = xc_dom_malloc(dom, sizeof(xen_pfn_t) * nbr);
|
||||
+ if ( dom->p2m_host == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: xc_dom_malloc failed for p2m_host",
|
||||
+ __FUNCTION__);
|
||||
+ return -1;
|
||||
+ }
|
||||
for ( pfn = 0; pfn < nbr; pfn++ )
|
||||
dom->p2m_host[pfn] = start + pfn;
|
||||
|
||||
diff --git a/tools/libxc/xc_dom_x86.c b/tools/libxc/xc_dom_x86.c
|
||||
index 75d6b83..448d9a1 100644
|
||||
--- a/tools/libxc/xc_dom_x86.c
|
||||
+++ b/tools/libxc/xc_dom_x86.c
|
||||
@@ -780,6 +780,9 @@ int arch_setup_meminit(struct xc_dom_image *dom)
|
||||
}
|
||||
|
||||
dom->p2m_host = xc_dom_malloc(dom, sizeof(xen_pfn_t) * dom->total_pages);
|
||||
+ if ( dom->p2m_host == NULL )
|
||||
+ return -EINVAL;
|
||||
+
|
||||
if ( dom->superpages )
|
||||
{
|
||||
int count = dom->total_pages >> SUPERPAGE_PFN_SHIFT;
|
||||
diff --git a/tools/libxc/xc_domain_restore.c b/tools/libxc/xc_domain_restore.c
|
||||
index 3994f8f..f9ed6b2 100644
|
||||
--- a/tools/libxc/xc_domain_restore.c
|
||||
+++ b/tools/libxc/xc_domain_restore.c
|
||||
@@ -1180,6 +1180,11 @@ static int apply_batch(xc_interface *xch, uint32_t dom, struct restore_ctx *ctx,
|
||||
|
||||
/* Map relevant mfns */
|
||||
pfn_err = calloc(j, sizeof(*pfn_err));
|
||||
+ if ( pfn_err == NULL )
|
||||
+ {
|
||||
+ PERROR("allocation for pfn_err failed");
|
||||
+ return -1;
|
||||
+ }
|
||||
region_base = xc_map_foreign_bulk(
|
||||
xch, dom, PROT_WRITE, region_mfn, pfn_err, j);
|
||||
|
||||
diff --git a/tools/libxc/xc_linux_osdep.c b/tools/libxc/xc_linux_osdep.c
|
||||
index 787e742..98e041c 100644
|
||||
--- a/tools/libxc/xc_linux_osdep.c
|
||||
+++ b/tools/libxc/xc_linux_osdep.c
|
||||
@@ -378,6 +378,8 @@ static void *linux_privcmd_map_foreign_range(xc_interface *xch, xc_osdep_handle
|
||||
|
||||
num = (size + XC_PAGE_SIZE - 1) >> XC_PAGE_SHIFT;
|
||||
arr = calloc(num, sizeof(xen_pfn_t));
|
||||
+ if ( arr == NULL )
|
||||
+ return NULL;
|
||||
|
||||
for ( i = 0; i < num; i++ )
|
||||
arr[i] = mfn + i;
|
||||
@@ -402,6 +404,8 @@ static void *linux_privcmd_map_foreign_ranges(xc_interface *xch, xc_osdep_handle
|
||||
num_per_entry = chunksize >> XC_PAGE_SHIFT;
|
||||
num = num_per_entry * nentries;
|
||||
arr = calloc(num, sizeof(xen_pfn_t));
|
||||
+ if ( arr == NULL )
|
||||
+ return NULL;
|
||||
|
||||
for ( i = 0; i < nentries; i++ )
|
||||
for ( j = 0; j < num_per_entry; j++ )
|
||||
diff --git a/tools/libxc/xc_private.c b/tools/libxc/xc_private.c
|
||||
index 3e03a91..848ceed 100644
|
||||
--- a/tools/libxc/xc_private.c
|
||||
+++ b/tools/libxc/xc_private.c
|
||||
@@ -771,6 +771,8 @@ const char *xc_strerror(xc_interface *xch, int errcode)
|
||||
errbuf = pthread_getspecific(errbuf_pkey);
|
||||
if (errbuf == NULL) {
|
||||
errbuf = malloc(XS_BUFSIZE);
|
||||
+ if ( errbuf == NULL )
|
||||
+ return "(failed to allocate errbuf)";
|
||||
pthread_setspecific(errbuf_pkey, errbuf);
|
||||
}
|
||||
|
||||
diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h
|
||||
index b7741ca..8952048 100644
|
||||
--- a/tools/libxc/xenctrl.h
|
||||
+++ b/tools/libxc/xenctrl.h
|
||||
@@ -1778,7 +1778,7 @@ int xc_cpuid_set(xc_interface *xch,
|
||||
int xc_cpuid_apply_policy(xc_interface *xch,
|
||||
domid_t domid);
|
||||
void xc_cpuid_to_str(const unsigned int *regs,
|
||||
- char **strs);
|
||||
+ char **strs); /* some strs[] may be NULL if ENOMEM */
|
||||
int xc_mca_op(xc_interface *xch, struct xen_mc *mc);
|
||||
#endif
|
||||
|
||||
--
|
||||
1.7.2.5
|
||||
#From 052a689aa526ca51fd70528d4b0f83dfb2de99c1 Mon Sep 17 00:00:00 2001
|
||||
#From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
#Date: Fri, 14 Jun 2013 16:43:19 +0100
|
||||
#Subject: [PATCH 21/23] libxc: range checks in xc_dom_p2m_host and _guest
|
||||
#
|
||||
#These functions take guest pfns and look them up in the p2m. They did
|
||||
#no range checking.
|
||||
#
|
||||
#However, some callers, notably xc_dom_boot.c:setup_hypercall_page want
|
||||
#to pass untrusted guest-supplied value(s). It is most convenient to
|
||||
#detect this here and return INVALID_MFN.
|
||||
#
|
||||
#This is part of the fix to a security issue, XSA-55.
|
||||
#
|
||||
#Changes from Xen 4.2 version of this patch:
|
||||
#* 4.2 lacks dom->rambase_pfn, so don't add/subtract/check it.
|
||||
#
|
||||
#Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
#---
|
||||
# tools/libxc/xc_dom.h | 4 ++++
|
||||
# 1 files changed, 4 insertions(+), 0 deletions(-)
|
||||
#
|
||||
diff --git a/tools/libxc/xc_dom.h b/tools/libxc/xc_dom.h
|
||||
index 0161459..d801f66 100644
|
||||
--- a/tools/libxc/xc_dom.h
|
||||
+++ b/tools/libxc/xc_dom.h
|
||||
@@ -331,6 +331,8 @@ static inline xen_pfn_t xc_dom_p2m_host(struct xc_dom_image *dom, xen_pfn_t pfn)
|
||||
{
|
||||
if (dom->shadow_enabled)
|
||||
return pfn;
|
||||
+ if (pfn >= dom->total_pages)
|
||||
+ return INVALID_MFN;
|
||||
return dom->p2m_host[pfn];
|
||||
}
|
||||
|
||||
@@ -339,6 +341,8 @@ static inline xen_pfn_t xc_dom_p2m_guest(struct xc_dom_image *dom,
|
||||
{
|
||||
if (xc_dom_feature_translated(dom))
|
||||
return pfn;
|
||||
+ if (pfn >= dom->total_pages)
|
||||
+ return INVALID_MFN;
|
||||
return dom->p2m_host[pfn];
|
||||
}
|
||||
|
||||
--
|
||||
1.7.2.5
|
||||
#From 2a548e22915535ac13694eb38222903bca7245e3 Mon Sep 17 00:00:00 2001
|
||||
#From: Matthew Daley <mattjd@gmail.com>
|
||||
#Date: Fri, 14 Jun 2013 16:43:19 +0100
|
||||
#Subject: [PATCH 22/23] libxc: check blob size before proceeding in xc_dom_check_gzip
|
||||
#
|
||||
#This is part of the fix to a security issue, XSA-55.
|
||||
#
|
||||
#Signed-off-by: Matthew Daley <mattjd@gmail.com>
|
||||
#---
|
||||
# tools/libxc/xc_dom_core.c | 5 +++++
|
||||
# 1 files changed, 5 insertions(+), 0 deletions(-)
|
||||
#
|
||||
diff --git a/tools/libxc/xc_dom_core.c b/tools/libxc/xc_dom_core.c
|
||||
index 3cbf9f7..f8d1b08 100644
|
||||
--- a/tools/libxc/xc_dom_core.c
|
||||
+++ b/tools/libxc/xc_dom_core.c
|
||||
@@ -284,6 +284,11 @@ size_t xc_dom_check_gzip(xc_interface *xch, void *blob, size_t ziplen)
|
||||
unsigned char *gzlen;
|
||||
size_t unziplen;
|
||||
|
||||
+ if ( ziplen < 6 )
|
||||
+ /* Too small. We need (i.e. the subsequent code relies on)
|
||||
+ * 2 bytes for the magic number plus 4 bytes length. */
|
||||
+ return 0;
|
||||
+
|
||||
if ( strncmp(blob, "\037\213", 2) )
|
||||
/* not gzipped */
|
||||
return 0;
|
||||
--
|
||||
1.7.2.5
|
||||
#From d21d36e84354c04638b60a739a5f7c3d9f8adaf8 Mon Sep 17 00:00:00 2001
|
||||
#From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
#Date: Fri, 14 Jun 2013 16:43:19 +0100
|
||||
#Subject: [PATCH 23/23] libxc: Better range check in xc_dom_alloc_segment
|
||||
#
|
||||
#If seg->pfn is too large, the arithmetic in the range check might
|
||||
#overflow, defeating the range check.
|
||||
#
|
||||
#This is part of the fix to a security issue, XSA-55.
|
||||
#
|
||||
#Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
#Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
|
||||
#---
|
||||
# tools/libxc/xc_dom_core.c | 3 ++-
|
||||
# 1 files changed, 2 insertions(+), 1 deletions(-)
|
||||
#
|
||||
diff --git a/tools/libxc/xc_dom_core.c b/tools/libxc/xc_dom_core.c
|
||||
index f8d1b08..e79e38d 100644
|
||||
--- a/tools/libxc/xc_dom_core.c
|
||||
+++ b/tools/libxc/xc_dom_core.c
|
||||
@@ -509,7 +509,8 @@ int xc_dom_alloc_segment(struct xc_dom_image *dom,
|
||||
seg->vstart = start;
|
||||
seg->pfn = (seg->vstart - dom->parms.virt_base) / page_size;
|
||||
|
||||
- if ( pages > dom->total_pages || /* double test avoids overflow probs */
|
||||
+ if ( pages > dom->total_pages || /* multiple test avoids overflow probs */
|
||||
+ seg->pfn > dom->total_pages ||
|
||||
pages > dom->total_pages - seg->pfn)
|
||||
{
|
||||
xc_dom_panic(dom->xch, XC_OUT_OF_MEMORY,
|
||||
--
|
||||
1.7.2.5
|
||||
|
||||
|
@ -0,0 +1,156 @@
|
||||
From 8c738fa5c1f3cfcd935b6191b3526f7ac8b2a5bd Mon Sep 17 00:00:00 2001
|
||||
From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Date: Fri, 14 Jun 2013 16:43:16 +0100
|
||||
Subject: [PATCH 03/23] libxc: Fix range checking in xc_dom_pfn_to_ptr etc.
|
||||
|
||||
* Ensure that xc_dom_pfn_to_ptr (when called with count==0) does not
|
||||
return a previously-allocated block which is entirely before the
|
||||
requested pfn (!)
|
||||
|
||||
* Provide a version of xc_dom_pfn_to_ptr, xc_dom_pfn_to_ptr_retcount,
|
||||
which provides the length of the mapped region via an out parameter.
|
||||
|
||||
* Change xc_dom_vaddr_to_ptr to always provide the length of the
|
||||
mapped region and change the call site in xc_dom_binloader.c to
|
||||
check it. The call site in xc_dom_load_elf_symtab will be corrected
|
||||
in a forthcoming patch, and for now ignores the returned length.
|
||||
|
||||
This is part of the fix to a security issue, XSA-55.
|
||||
|
||||
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
---
|
||||
tools/libxc/xc_dom.h | 16 +++++++++++++---
|
||||
tools/libxc/xc_dom_binloader.c | 11 ++++++++++-
|
||||
tools/libxc/xc_dom_core.c | 13 +++++++++++++
|
||||
tools/libxc/xc_dom_elfloader.c | 3 ++-
|
||||
4 files changed, 38 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/tools/libxc/xc_dom.h b/tools/libxc/xc_dom.h
|
||||
index 9af2195..9f8037e 100644
|
||||
--- a/tools/libxc/xc_dom.h
|
||||
+++ b/tools/libxc/xc_dom.h
|
||||
@@ -275,6 +275,8 @@ int xc_dom_alloc_segment(struct xc_dom_image *dom,
|
||||
|
||||
void *xc_dom_pfn_to_ptr(struct xc_dom_image *dom, xen_pfn_t first,
|
||||
xen_pfn_t count);
|
||||
+void *xc_dom_pfn_to_ptr_retcount(struct xc_dom_image *dom, xen_pfn_t first,
|
||||
+ xen_pfn_t count, xen_pfn_t *count_out);
|
||||
void xc_dom_unmap_one(struct xc_dom_image *dom, xen_pfn_t pfn);
|
||||
void xc_dom_unmap_all(struct xc_dom_image *dom);
|
||||
|
||||
@@ -302,13 +304,21 @@ static inline void *xc_dom_seg_to_ptr(struct xc_dom_image *dom,
|
||||
}
|
||||
|
||||
static inline void *xc_dom_vaddr_to_ptr(struct xc_dom_image *dom,
|
||||
- xen_vaddr_t vaddr)
|
||||
+ xen_vaddr_t vaddr,
|
||||
+ size_t *safe_region_out)
|
||||
{
|
||||
unsigned int page_size = XC_DOM_PAGE_SIZE(dom);
|
||||
xen_pfn_t page = (vaddr - dom->parms.virt_base) / page_size;
|
||||
unsigned int offset = (vaddr - dom->parms.virt_base) % page_size;
|
||||
- void *ptr = xc_dom_pfn_to_ptr(dom, page, 0);
|
||||
- return (ptr ? (ptr + offset) : NULL);
|
||||
+ xen_pfn_t safe_region_count;
|
||||
+ void *ptr;
|
||||
+
|
||||
+ *safe_region_out = 0;
|
||||
+ ptr = xc_dom_pfn_to_ptr_retcount(dom, page, 0, &safe_region_count);
|
||||
+ if ( ptr == NULL )
|
||||
+ return ptr;
|
||||
+ *safe_region_out = (safe_region_count << XC_DOM_PAGE_SHIFT(dom)) - offset;
|
||||
+ return ptr;
|
||||
}
|
||||
|
||||
static inline int xc_dom_feature_translated(struct xc_dom_image *dom)
|
||||
diff --git a/tools/libxc/xc_dom_binloader.c b/tools/libxc/xc_dom_binloader.c
|
||||
index 769e97d..bde93f7 100644
|
||||
--- a/tools/libxc/xc_dom_binloader.c
|
||||
+++ b/tools/libxc/xc_dom_binloader.c
|
||||
@@ -249,6 +249,7 @@ static int xc_dom_load_bin_kernel(struct xc_dom_image *dom)
|
||||
char *image = dom->kernel_blob;
|
||||
char *dest;
|
||||
size_t image_size = dom->kernel_size;
|
||||
+ size_t dest_size;
|
||||
uint32_t start_addr;
|
||||
uint32_t load_end_addr;
|
||||
uint32_t bss_end_addr;
|
||||
@@ -272,7 +273,15 @@ static int xc_dom_load_bin_kernel(struct xc_dom_image *dom)
|
||||
DOMPRINTF(" text_size: 0x%" PRIx32 "", text_size);
|
||||
DOMPRINTF(" bss_size: 0x%" PRIx32 "", bss_size);
|
||||
|
||||
- dest = xc_dom_vaddr_to_ptr(dom, dom->kernel_seg.vstart);
|
||||
+ dest = xc_dom_vaddr_to_ptr(dom, dom->kernel_seg.vstart, &dest_size);
|
||||
+
|
||||
+ if ( dest_size < text_size ||
|
||||
+ dest_size - text_size < bss_size )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: mapped region is too small for image", __FUNCTION__);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
memcpy(dest, image + skip, text_size);
|
||||
memset(dest + text_size, 0, bss_size);
|
||||
|
||||
diff --git a/tools/libxc/xc_dom_core.c b/tools/libxc/xc_dom_core.c
|
||||
index 2a01d7c..8913e41 100644
|
||||
--- a/tools/libxc/xc_dom_core.c
|
||||
+++ b/tools/libxc/xc_dom_core.c
|
||||
@@ -351,10 +351,19 @@ int xc_dom_try_gunzip(struct xc_dom_image *dom, void **blob, size_t * size)
|
||||
void *xc_dom_pfn_to_ptr(struct xc_dom_image *dom, xen_pfn_t pfn,
|
||||
xen_pfn_t count)
|
||||
{
|
||||
+ xen_pfn_t count_out_dummy;
|
||||
+ return xc_dom_pfn_to_ptr_retcount(dom, pfn, count, &count_out_dummy);
|
||||
+}
|
||||
+
|
||||
+void *xc_dom_pfn_to_ptr_retcount(struct xc_dom_image *dom, xen_pfn_t pfn,
|
||||
+ xen_pfn_t count, xen_pfn_t *count_out)
|
||||
+{
|
||||
struct xc_dom_phys *phys;
|
||||
unsigned int page_shift = XC_DOM_PAGE_SHIFT(dom);
|
||||
char *mode = "unset";
|
||||
|
||||
+ *count_out = 0;
|
||||
+
|
||||
if ( pfn > dom->total_pages || /* multiple checks to avoid overflows */
|
||||
count > dom->total_pages ||
|
||||
pfn > dom->total_pages - count )
|
||||
@@ -384,6 +393,7 @@ void *xc_dom_pfn_to_ptr(struct xc_dom_image *dom, xen_pfn_t pfn,
|
||||
phys->count);
|
||||
return NULL;
|
||||
}
|
||||
+ *count_out = count;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -391,6 +401,9 @@ void *xc_dom_pfn_to_ptr(struct xc_dom_image *dom, xen_pfn_t pfn,
|
||||
just hand out a pointer to it */
|
||||
if ( pfn < phys->first )
|
||||
continue;
|
||||
+ if ( pfn >= phys->first + phys->count )
|
||||
+ continue;
|
||||
+ *count_out = phys->count - (pfn - phys->first);
|
||||
}
|
||||
return phys->ptr + ((pfn - phys->first) << page_shift);
|
||||
}
|
||||
diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c
|
||||
index 2e69559..031b5b6 100644
|
||||
--- a/tools/libxc/xc_dom_elfloader.c
|
||||
+++ b/tools/libxc/xc_dom_elfloader.c
|
||||
@@ -130,10 +130,11 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
|
||||
if ( load )
|
||||
{
|
||||
+ size_t allow_size; /* will be used in a forthcoming XSA-55 patch */
|
||||
if ( !dom->bsd_symtab_start )
|
||||
return 0;
|
||||
size = dom->kernel_seg.vend - dom->bsd_symtab_start;
|
||||
- hdr = xc_dom_vaddr_to_ptr(dom, dom->bsd_symtab_start);
|
||||
+ hdr = xc_dom_vaddr_to_ptr(dom, dom->bsd_symtab_start, &allow_size);
|
||||
*(int *)hdr = size - sizeof(int);
|
||||
}
|
||||
else
|
||||
--
|
||||
1.7.2.5
|
||||
|
@ -0,0 +1,55 @@
|
||||
From 035634047d10c678cbb8801c4263747bdaf4e5b1 Mon Sep 17 00:00:00 2001
|
||||
From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Date: Fri, 14 Jun 2013 16:43:16 +0100
|
||||
Subject: [PATCH 04/23] libelf: add `struct elf_binary*' parameter to elf_load_image
|
||||
|
||||
The meat of this function is going to need a copy of the elf pointer,
|
||||
in forthcoming patches.
|
||||
|
||||
No functional change in this patch.
|
||||
|
||||
This is part of the fix to a security issue, XSA-55.
|
||||
|
||||
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
|
||||
---
|
||||
xen/common/libelf/libelf-loader.c | 8 +++++---
|
||||
1 files changed, 5 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/xen/common/libelf/libelf-loader.c b/xen/common/libelf/libelf-loader.c
|
||||
index ab58b8b..0559d88 100644
|
||||
--- a/xen/common/libelf/libelf-loader.c
|
||||
+++ b/xen/common/libelf/libelf-loader.c
|
||||
@@ -108,7 +108,8 @@ void elf_set_log(struct elf_binary *elf, elf_log_callback *log_callback,
|
||||
elf->verbose = verbose;
|
||||
}
|
||||
|
||||
-static int elf_load_image(void *dst, const void *src, uint64_t filesz, uint64_t memsz)
|
||||
+static int elf_load_image(struct elf_binary *elf,
|
||||
+ void *dst, const void *src, uint64_t filesz, uint64_t memsz)
|
||||
{
|
||||
memcpy(dst, src, filesz);
|
||||
memset(dst + filesz, 0, memsz - filesz);
|
||||
@@ -122,7 +123,8 @@ void elf_set_verbose(struct elf_binary *elf)
|
||||
elf->verbose = 1;
|
||||
}
|
||||
|
||||
-static int elf_load_image(void *dst, const void *src, uint64_t filesz, uint64_t memsz)
|
||||
+static int elf_load_image(struct elf_binary *elf,
|
||||
+ void *dst, const void *src, uint64_t filesz, uint64_t memsz)
|
||||
{
|
||||
int rc;
|
||||
if ( filesz > ULONG_MAX || memsz > ULONG_MAX )
|
||||
@@ -279,7 +281,7 @@ int elf_load_binary(struct elf_binary *elf)
|
||||
dest = elf_get_ptr(elf, paddr);
|
||||
elf_msg(elf, "%s: phdr %" PRIu64 " at 0x%p -> 0x%p\n",
|
||||
__func__, i, dest, dest + filesz);
|
||||
- if ( elf_load_image(dest, elf->image + offset, filesz, memsz) != 0 )
|
||||
+ if ( elf_load_image(elf, dest, elf->image + offset, filesz, memsz) != 0 )
|
||||
return -1;
|
||||
}
|
||||
|
||||
--
|
||||
1.7.2.5
|
||||
|
@ -0,0 +1,174 @@
|
||||
From 83ec905922b496e1a5756e3a88405eb6c2c6ba88 Mon Sep 17 00:00:00 2001
|
||||
From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Date: Fri, 14 Jun 2013 16:43:16 +0100
|
||||
Subject: [PATCH 05/23] libelf: abolish elf_sval and elf_access_signed
|
||||
|
||||
These are not used anywhere.
|
||||
|
||||
This is part of the fix to a security issue, XSA-55.
|
||||
|
||||
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
---
|
||||
xen/common/libelf/libelf-tools.c | 28 ----------------------------
|
||||
xen/include/xen/libelf.h | 11 -----------
|
||||
2 files changed, 0 insertions(+), 39 deletions(-)
|
||||
|
||||
diff --git a/xen/common/libelf/libelf-tools.c b/xen/common/libelf/libelf-tools.c
|
||||
index cb97908..2f54142 100644
|
||||
--- a/xen/common/libelf/libelf-tools.c
|
||||
+++ b/xen/common/libelf/libelf-tools.c
|
||||
@@ -48,34 +48,6 @@ uint64_t elf_access_unsigned(struct elf_binary * elf, const void *ptr,
|
||||
}
|
||||
}
|
||||
|
||||
-int64_t elf_access_signed(struct elf_binary *elf, const void *ptr,
|
||||
- uint64_t offset, size_t size)
|
||||
-{
|
||||
- int need_swap = elf_swap(elf);
|
||||
- const int8_t *s8;
|
||||
- const int16_t *s16;
|
||||
- const int32_t *s32;
|
||||
- const int64_t *s64;
|
||||
-
|
||||
- switch ( size )
|
||||
- {
|
||||
- case 1:
|
||||
- s8 = ptr + offset;
|
||||
- return *s8;
|
||||
- case 2:
|
||||
- s16 = ptr + offset;
|
||||
- return need_swap ? bswap_16(*s16) : *s16;
|
||||
- case 4:
|
||||
- s32 = ptr + offset;
|
||||
- return need_swap ? bswap_32(*s32) : *s32;
|
||||
- case 8:
|
||||
- s64 = ptr + offset;
|
||||
- return need_swap ? bswap_64(*s64) : *s64;
|
||||
- default:
|
||||
- return 0;
|
||||
- }
|
||||
-}
|
||||
-
|
||||
uint64_t elf_round_up(struct elf_binary *elf, uint64_t addr)
|
||||
{
|
||||
int elf_round = (elf_64bit(elf) ? 8 : 4) - 1;
|
||||
diff --git a/xen/include/xen/libelf.h b/xen/include/xen/libelf.h
|
||||
index e8f6508..38e490c 100644
|
||||
--- a/xen/include/xen/libelf.h
|
||||
+++ b/xen/include/xen/libelf.h
|
||||
@@ -136,23 +136,12 @@ struct elf_binary {
|
||||
offsetof(typeof(*(str)),e32.elem), \
|
||||
sizeof((str)->e32.elem)))
|
||||
|
||||
-#define elf_sval(elf, str, elem) \
|
||||
- ((ELFCLASS64 == (elf)->class) \
|
||||
- ? elf_access_signed((elf), (str), \
|
||||
- offsetof(typeof(*(str)),e64.elem), \
|
||||
- sizeof((str)->e64.elem)) \
|
||||
- : elf_access_signed((elf), (str), \
|
||||
- offsetof(typeof(*(str)),e32.elem), \
|
||||
- sizeof((str)->e32.elem)))
|
||||
-
|
||||
#define elf_size(elf, str) \
|
||||
((ELFCLASS64 == (elf)->class) \
|
||||
? sizeof((str)->e64) : sizeof((str)->e32))
|
||||
|
||||
uint64_t elf_access_unsigned(struct elf_binary *elf, const void *ptr,
|
||||
uint64_t offset, size_t size);
|
||||
-int64_t elf_access_signed(struct elf_binary *elf, const void *ptr,
|
||||
- uint64_t offset, size_t size);
|
||||
|
||||
uint64_t elf_round_up(struct elf_binary *elf, uint64_t addr);
|
||||
|
||||
--
|
||||
1.7.2.5
|
||||
#From 682a04488e7b3bd6c3448ab60599566eb7c6177a Mon Sep 17 00:00:00 2001
|
||||
#From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
#Date: Fri, 14 Jun 2013 16:43:16 +0100
|
||||
#Subject: [PATCH 06/23] libelf: move include of <asm/guest_access.h> to top of file
|
||||
#
|
||||
#libelf-loader.c #includes <asm/guest_access.h>, when being compiled
|
||||
#for Xen. Currently it does this in the middle of the file.
|
||||
#
|
||||
#Move this #include to the top of the file, before libelf-private.h.
|
||||
#This is necessary because in forthcoming patches we will introduce
|
||||
#private #defines of memcpy etc. which would interfere with definitions
|
||||
#in headers #included from guest_access.h.
|
||||
#
|
||||
#No semantic or functional change in this patch.
|
||||
#
|
||||
#This is part of the fix to a security issue, XSA-55.
|
||||
#
|
||||
#Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
#Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
#Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
|
||||
#---
|
||||
# xen/common/libelf/libelf-loader.c | 5 ++++-
|
||||
# 1 files changed, 4 insertions(+), 1 deletions(-)
|
||||
#
|
||||
diff --git a/xen/common/libelf/libelf-loader.c b/xen/common/libelf/libelf-loader.c
|
||||
index 0559d88..ec0706b 100644
|
||||
--- a/xen/common/libelf/libelf-loader.c
|
||||
+++ b/xen/common/libelf/libelf-loader.c
|
||||
@@ -16,6 +16,10 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
+#ifdef __XEN__
|
||||
+#include <asm/guest_access.h>
|
||||
+#endif
|
||||
+
|
||||
#include "libelf-private.h"
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
@@ -116,7 +120,6 @@ static int elf_load_image(struct elf_binary *elf,
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
-#include <asm/guest_access.h>
|
||||
|
||||
void elf_set_verbose(struct elf_binary *elf)
|
||||
{
|
||||
--
|
||||
1.7.2.5
|
||||
#From de9089b449d2508b1ba05590905c7ebaee00c8c4 Mon Sep 17 00:00:00 2001
|
||||
#From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
#Date: Fri, 14 Jun 2013 16:43:16 +0100
|
||||
#Subject: [PATCH 07/23] libelf/xc_dom_load_elf_symtab: Do not use "syms" uninitialised
|
||||
#
|
||||
#xc_dom_load_elf_symtab (with load==0) calls elf_round_up, but it
|
||||
#mistakenly used the uninitialised variable "syms" when calculating
|
||||
#dom->bsd_symtab_start. This should be a reference to "elf".
|
||||
#
|
||||
#This change might have the effect of rounding the value differently.
|
||||
#Previously if the uninitialised value (a single byte on the stack) was
|
||||
#ELFCLASS64 (ie, 2), the alignment would be to 8 bytes, otherwise to 4.
|
||||
#
|
||||
#However, the value is calculated from dom->kernel_seg.vend so this
|
||||
#could only make a difference if that value wasn't already aligned to 8
|
||||
#bytes.
|
||||
#
|
||||
#This is part of the fix to a security issue, XSA-55.
|
||||
#
|
||||
#Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
#Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
#---
|
||||
# tools/libxc/xc_dom_elfloader.c | 2 +-
|
||||
# 1 files changed, 1 insertions(+), 1 deletions(-)
|
||||
#
|
||||
diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c
|
||||
index 031b5b6..e82f6e9 100644
|
||||
--- a/tools/libxc/xc_dom_elfloader.c
|
||||
+++ b/tools/libxc/xc_dom_elfloader.c
|
||||
@@ -144,7 +144,7 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
hdr = xc_dom_malloc(dom, size);
|
||||
if ( hdr == NULL )
|
||||
return 0;
|
||||
- dom->bsd_symtab_start = elf_round_up(&syms, dom->kernel_seg.vend);
|
||||
+ dom->bsd_symtab_start = elf_round_up(elf, dom->kernel_seg.vend);
|
||||
}
|
||||
|
||||
memcpy(hdr + sizeof(int),
|
||||
--
|
||||
1.7.2.5
|
@ -0,0 +1,252 @@
|
||||
From 3fb6ccf2faccaf5e22e33a3155ccc72d732896d8 Mon Sep 17 00:00:00 2001
|
||||
From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Date: Fri, 14 Jun 2013 16:43:18 +0100
|
||||
Subject: [PATCH 14/23] libelf: use C99 bool for booleans
|
||||
|
||||
We want to remove uses of "int" because signed integers have
|
||||
undesirable undefined behaviours on overflow. Malicious compilers can
|
||||
turn apparently-correct code into code with security vulnerabilities
|
||||
etc.
|
||||
|
||||
In this patch we change all the booleans in libelf to C99 bool,
|
||||
from <stdbool.h>.
|
||||
|
||||
For the one visible libelf boolean in libxc's public interface we
|
||||
retain the use of int to avoid changing the ABI; libxc converts it to
|
||||
a bool for consumption by libelf.
|
||||
|
||||
It is OK to change all values only ever used as booleans to _Bool
|
||||
(bool) because conversion from any scalar type to a _Bool works the
|
||||
same as the boolean test in if() or ?: and is always defined (C99
|
||||
6.3.1.2). But we do need to check that all these variables really are
|
||||
only ever used that way. (It is theoretically possible that the old
|
||||
code truncated some 64-bit values to 32-bit ints which might become
|
||||
zero depending on the value, which would mean a behavioural change in
|
||||
this patch, but it seems implausible that treating 0x????????00000000
|
||||
as false could have been intended.)
|
||||
|
||||
This is part of the fix to a security issue, XSA-55.
|
||||
|
||||
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Acked-by: George Dunlap <george.dunlap@eu.citrix.com>
|
||||
---
|
||||
tools/libxc/xc_dom_elfloader.c | 8 ++++----
|
||||
xen/common/libelf/libelf-dominfo.c | 2 +-
|
||||
xen/common/libelf/libelf-loader.c | 4 ++--
|
||||
xen/common/libelf/libelf-private.h | 2 +-
|
||||
xen/common/libelf/libelf-tools.c | 10 +++++-----
|
||||
xen/include/xen/libelf.h | 18 ++++++++++--------
|
||||
6 files changed, 23 insertions(+), 21 deletions(-)
|
||||
|
||||
diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c
|
||||
index 4fb4da2..9ba64ae 100644
|
||||
--- a/tools/libxc/xc_dom_elfloader.c
|
||||
+++ b/tools/libxc/xc_dom_elfloader.c
|
||||
@@ -34,7 +34,7 @@
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
static void log_callback(struct elf_binary *elf, void *caller_data,
|
||||
- int iserr, const char *fmt, va_list al) {
|
||||
+ bool iserr, const char *fmt, va_list al) {
|
||||
xc_interface *xch = caller_data;
|
||||
|
||||
xc_reportv(xch,
|
||||
@@ -46,7 +46,7 @@ static void log_callback(struct elf_binary *elf, void *caller_data,
|
||||
|
||||
void xc_elf_set_logfile(xc_interface *xch, struct elf_binary *elf,
|
||||
int verbose) {
|
||||
- elf_set_log(elf, log_callback, xch, verbose);
|
||||
+ elf_set_log(elf, log_callback, xch, verbose /* convert to bool */);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
@@ -84,7 +84,7 @@ static char *xc_dom_guest_type(struct xc_dom_image *dom,
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* parse elf binary */
|
||||
|
||||
-static int check_elf_kernel(struct xc_dom_image *dom, int verbose)
|
||||
+static int check_elf_kernel(struct xc_dom_image *dom, bool verbose)
|
||||
{
|
||||
if ( dom->kernel_blob == NULL )
|
||||
{
|
||||
@@ -112,7 +112,7 @@ static int xc_dom_probe_elf_kernel(struct xc_dom_image *dom)
|
||||
}
|
||||
|
||||
static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
- struct elf_binary *elf, int load)
|
||||
+ struct elf_binary *elf, bool load)
|
||||
{
|
||||
struct elf_binary syms;
|
||||
ELF_HANDLE_DECL_NONCONST(elf_shdr) shdr; ELF_HANDLE_DECL(elf_shdr) shdr2;
|
||||
diff --git a/xen/common/libelf/libelf-dominfo.c b/xen/common/libelf/libelf-dominfo.c
|
||||
index 98c80dc..12b6c2a 100644
|
||||
--- a/xen/common/libelf/libelf-dominfo.c
|
||||
+++ b/xen/common/libelf/libelf-dominfo.c
|
||||
@@ -101,7 +101,7 @@ int elf_xen_parse_note(struct elf_binary *elf,
|
||||
/* *INDENT-OFF* */
|
||||
static const struct {
|
||||
char *name;
|
||||
- int str;
|
||||
+ bool str;
|
||||
} note_desc[] = {
|
||||
[XEN_ELFNOTE_ENTRY] = { "ENTRY", 0},
|
||||
[XEN_ELFNOTE_HYPERCALL_PAGE] = { "HYPERCALL_PAGE", 0},
|
||||
diff --git a/xen/common/libelf/libelf-loader.c b/xen/common/libelf/libelf-loader.c
|
||||
index f8be635..0dccd4d 100644
|
||||
--- a/xen/common/libelf/libelf-loader.c
|
||||
+++ b/xen/common/libelf/libelf-loader.c
|
||||
@@ -92,7 +92,7 @@ int elf_init(struct elf_binary *elf, const char *image_input, size_t size)
|
||||
}
|
||||
|
||||
#ifndef __XEN__
|
||||
-void elf_call_log_callback(struct elf_binary *elf, int iserr,
|
||||
+void elf_call_log_callback(struct elf_binary *elf, bool iserr,
|
||||
const char *fmt,...) {
|
||||
va_list al;
|
||||
|
||||
@@ -107,7 +107,7 @@ void elf_call_log_callback(struct elf_binary *elf, int iserr,
|
||||
}
|
||||
|
||||
void elf_set_log(struct elf_binary *elf, elf_log_callback *log_callback,
|
||||
- void *log_caller_data, int verbose)
|
||||
+ void *log_caller_data, bool verbose)
|
||||
{
|
||||
elf->log_callback = log_callback;
|
||||
elf->log_caller_data = log_caller_data;
|
||||
diff --git a/xen/common/libelf/libelf-private.h b/xen/common/libelf/libelf-private.h
|
||||
index 280dfd1..277be04 100644
|
||||
--- a/xen/common/libelf/libelf-private.h
|
||||
+++ b/xen/common/libelf/libelf-private.h
|
||||
@@ -77,7 +77,7 @@
|
||||
#define elf_err(elf, fmt, args ... ) \
|
||||
elf_call_log_callback(elf, 1, fmt , ## args );
|
||||
|
||||
-void elf_call_log_callback(struct elf_binary*, int iserr, const char *fmt,...);
|
||||
+void elf_call_log_callback(struct elf_binary*, bool iserr, const char *fmt,...);
|
||||
|
||||
#define safe_strcpy(d,s) \
|
||||
do { strncpy((d),(s),sizeof((d))-1); \
|
||||
diff --git a/xen/common/libelf/libelf-tools.c b/xen/common/libelf/libelf-tools.c
|
||||
index 744027e..fa58f76 100644
|
||||
--- a/xen/common/libelf/libelf-tools.c
|
||||
+++ b/xen/common/libelf/libelf-tools.c
|
||||
@@ -31,7 +31,7 @@ const char *elf_check_broken(const struct elf_binary *elf)
|
||||
return elf->broken;
|
||||
}
|
||||
|
||||
-static int elf_ptrval_in_range(elf_ptrval ptrval, uint64_t size,
|
||||
+static bool elf_ptrval_in_range(elf_ptrval ptrval, uint64_t size,
|
||||
const void *region, uint64_t regionsize)
|
||||
/*
|
||||
* Returns true if the putative memory area [ptrval,ptrval+size>
|
||||
@@ -53,7 +53,7 @@ static int elf_ptrval_in_range(elf_ptrval ptrval, uint64_t size,
|
||||
return 1;
|
||||
}
|
||||
|
||||
-int elf_access_ok(struct elf_binary * elf,
|
||||
+bool elf_access_ok(struct elf_binary * elf,
|
||||
uint64_t ptrval, size_t size)
|
||||
{
|
||||
if ( elf_ptrval_in_range(ptrval, size, elf->image_base, elf->size) )
|
||||
@@ -92,7 +92,7 @@ uint64_t elf_access_unsigned(struct elf_binary * elf, elf_ptrval base,
|
||||
uint64_t moreoffset, size_t size)
|
||||
{
|
||||
elf_ptrval ptrval = base + moreoffset;
|
||||
- int need_swap = elf_swap(elf);
|
||||
+ bool need_swap = elf_swap(elf);
|
||||
const uint8_t *u8;
|
||||
const uint16_t *u16;
|
||||
const uint32_t *u32;
|
||||
@@ -332,7 +332,7 @@ ELF_HANDLE_DECL(elf_note) elf_note_next(struct elf_binary *elf, ELF_HANDLE_DECL(
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
-int elf_is_elfbinary(const void *image_start, size_t image_size)
|
||||
+bool elf_is_elfbinary(const void *image_start, size_t image_size)
|
||||
{
|
||||
const Elf32_Ehdr *ehdr = image_start;
|
||||
|
||||
@@ -342,7 +342,7 @@ int elf_is_elfbinary(const void *image_start, size_t image_size)
|
||||
return IS_ELF(*ehdr);
|
||||
}
|
||||
|
||||
-int elf_phdr_is_loadable(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr)
|
||||
+bool elf_phdr_is_loadable(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr)
|
||||
{
|
||||
uint64_t p_type = elf_uval(elf, phdr, p_type);
|
||||
uint64_t p_flags = elf_uval(elf, phdr, p_flags);
|
||||
diff --git a/xen/include/xen/libelf.h b/xen/include/xen/libelf.h
|
||||
index ac93858..951430f 100644
|
||||
--- a/xen/include/xen/libelf.h
|
||||
+++ b/xen/include/xen/libelf.h
|
||||
@@ -29,6 +29,8 @@
|
||||
#error define architectural endianness
|
||||
#endif
|
||||
|
||||
+#include <stdbool.h>
|
||||
+
|
||||
#undef ELFSIZE
|
||||
#include "elfstructs.h"
|
||||
#ifdef __XEN__
|
||||
@@ -42,7 +44,7 @@
|
||||
|
||||
struct elf_binary;
|
||||
typedef void elf_log_callback(struct elf_binary*, void *caller_data,
|
||||
- int iserr, const char *fmt, va_list al);
|
||||
+ bool iserr, const char *fmt, va_list al);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -237,7 +239,7 @@ struct elf_binary {
|
||||
elf_log_callback *log_callback;
|
||||
void *log_caller_data;
|
||||
#endif
|
||||
- int verbose;
|
||||
+ bool verbose;
|
||||
const char *broken;
|
||||
};
|
||||
|
||||
@@ -301,8 +303,8 @@ void elf_memset_safe(struct elf_binary*, elf_ptrval dst, int c, size_t);
|
||||
* outside permitted areas.
|
||||
*/
|
||||
|
||||
-int elf_access_ok(struct elf_binary * elf,
|
||||
- uint64_t ptrval, size_t size);
|
||||
+bool elf_access_ok(struct elf_binary * elf,
|
||||
+ uint64_t ptrval, size_t size);
|
||||
|
||||
#define elf_store_val(elf, type, ptr, val) \
|
||||
({ \
|
||||
@@ -351,9 +353,9 @@ uint64_t elf_note_numeric_array(struct elf_binary *, ELF_HANDLE_DECL(elf_note),
|
||||
ELF_HANDLE_DECL(elf_note) elf_note_next(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
|
||||
|
||||
/* (Only) checks that the image has the right magic number. */
|
||||
-int elf_is_elfbinary(const void *image_start, size_t image_size);
|
||||
+bool elf_is_elfbinary(const void *image_start, size_t image_size);
|
||||
|
||||
-int elf_phdr_is_loadable(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr);
|
||||
+bool elf_phdr_is_loadable(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr);
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* xc_libelf_loader.c */
|
||||
@@ -367,7 +369,7 @@ int elf_init(struct elf_binary *elf, const char *image, size_t size);
|
||||
void elf_set_verbose(struct elf_binary *elf);
|
||||
#else
|
||||
void elf_set_log(struct elf_binary *elf, elf_log_callback*,
|
||||
- void *log_caller_pointer, int verbose);
|
||||
+ void *log_caller_pointer, bool verbose);
|
||||
#endif
|
||||
|
||||
void elf_parse_binary(struct elf_binary *elf);
|
||||
@@ -419,7 +421,7 @@ struct elf_dom_parms {
|
||||
char xen_ver[16];
|
||||
char loader[16];
|
||||
int pae;
|
||||
- int bsd_symtab;
|
||||
+ bool bsd_symtab;
|
||||
uint64_t virt_base;
|
||||
uint64_t virt_entry;
|
||||
uint64_t virt_hypercall;
|
||||
--
|
||||
1.7.2.5
|
||||
|
@ -0,0 +1,382 @@
|
||||
From 77c0829fa751f052f7b8ec08287aef6e7ba97bc5 Mon Sep 17 00:00:00 2001
|
||||
From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Date: Fri, 14 Jun 2013 16:43:19 +0100
|
||||
Subject: [PATCH 19/23] libxc: check failure of xc_dom_*_to_ptr, xc_map_foreign_range
|
||||
|
||||
The return values from xc_dom_*_to_ptr and xc_map_foreign_range are
|
||||
sometimes dereferenced, or subjected to pointer arithmetic, without
|
||||
checking whether the relevant function failed and returned NULL.
|
||||
|
||||
Add an appropriate error check at every call site.
|
||||
|
||||
Changes in the 4.2 backport of this series:
|
||||
* Fix tools/libxc/xc_dom_x86.c:setup_pgtables_x86_32.
|
||||
* Fix tools/libxc/xc_dom_ia64.c:start_info_ia64.
|
||||
* Fix tools/libxc/ia64/xc_ia64_dom_fwloader.c:xc_dom_load_fw_kernel.
|
||||
|
||||
This is part of the fix to a security issue, XSA-55.
|
||||
|
||||
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
---
|
||||
tools/libxc/ia64/xc_ia64_dom_fwloader.c | 2 +
|
||||
tools/libxc/xc_dom_binloader.c | 6 +++
|
||||
tools/libxc/xc_dom_core.c | 6 +++
|
||||
tools/libxc/xc_dom_elfloader.c | 13 +++++++
|
||||
tools/libxc/xc_dom_ia64.c | 6 +++
|
||||
tools/libxc/xc_dom_x86.c | 55 +++++++++++++++++++++++++++++++
|
||||
tools/libxc/xc_domain_restore.c | 27 +++++++++++++++
|
||||
tools/libxc/xc_offline_page.c | 5 +++
|
||||
8 files changed, 120 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/tools/libxc/ia64/xc_ia64_dom_fwloader.c b/tools/libxc/ia64/xc_ia64_dom_fwloader.c
|
||||
index cdf3333..dbd3349 100644
|
||||
--- a/tools/libxc/ia64/xc_ia64_dom_fwloader.c
|
||||
+++ b/tools/libxc/ia64/xc_ia64_dom_fwloader.c
|
||||
@@ -60,6 +60,8 @@ static int xc_dom_load_fw_kernel(struct xc_dom_image *dom)
|
||||
unsigned long i;
|
||||
|
||||
dest = xc_dom_vaddr_to_ptr(dom, dom->kernel_seg.vstart);
|
||||
+ if ( dest == NULL )
|
||||
+ return -1;
|
||||
memcpy(dest, dom->kernel_blob, FW_SIZE);
|
||||
|
||||
/* Synchronize cache. */
|
||||
diff --git a/tools/libxc/xc_dom_binloader.c b/tools/libxc/xc_dom_binloader.c
|
||||
index 8596a28..553b366 100644
|
||||
--- a/tools/libxc/xc_dom_binloader.c
|
||||
+++ b/tools/libxc/xc_dom_binloader.c
|
||||
@@ -277,6 +277,12 @@ static int xc_dom_load_bin_kernel(struct xc_dom_image *dom)
|
||||
DOMPRINTF(" bss_size: 0x%" PRIx32 "", bss_size);
|
||||
|
||||
dest = xc_dom_vaddr_to_ptr(dom, dom->kernel_seg.vstart, &dest_size);
|
||||
+ if ( dest == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: xc_dom_vaddr_to_ptr(dom, dom->kernel_seg.vstart)"
|
||||
+ " => NULL", __FUNCTION__);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
|
||||
if ( dest_size < text_size ||
|
||||
dest_size - text_size < bss_size )
|
||||
diff --git a/tools/libxc/xc_dom_core.c b/tools/libxc/xc_dom_core.c
|
||||
index 8913e41..a54ddae 100644
|
||||
--- a/tools/libxc/xc_dom_core.c
|
||||
+++ b/tools/libxc/xc_dom_core.c
|
||||
@@ -868,6 +868,12 @@ int xc_dom_build_image(struct xc_dom_image *dom)
|
||||
ramdisklen) != 0 )
|
||||
goto err;
|
||||
ramdiskmap = xc_dom_seg_to_ptr(dom, &dom->ramdisk_seg);
|
||||
+ if ( ramdiskmap == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: xc_dom_seg_to_ptr(dom, &dom->ramdisk_seg) => NULL",
|
||||
+ __FUNCTION__);
|
||||
+ goto err;
|
||||
+ }
|
||||
if ( unziplen )
|
||||
{
|
||||
if ( xc_dom_do_gunzip(dom->xch,
|
||||
diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c
|
||||
index 9fc4b94..61b5798 100644
|
||||
--- a/tools/libxc/xc_dom_elfloader.c
|
||||
+++ b/tools/libxc/xc_dom_elfloader.c
|
||||
@@ -139,6 +139,12 @@ static elf_errorstatus xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
return 0;
|
||||
size = dom->kernel_seg.vend - dom->bsd_symtab_start;
|
||||
hdr_ptr = xc_dom_vaddr_to_ptr(dom, dom->bsd_symtab_start, &allow_size);
|
||||
+ if ( hdr_ptr == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s/load: xc_dom_vaddr_to_ptr(dom,dom->bsd_symtab_start"
|
||||
+ " => NULL", __FUNCTION__);
|
||||
+ return -1;
|
||||
+ }
|
||||
elf->caller_xdest_base = hdr_ptr;
|
||||
elf->caller_xdest_size = allow_size;
|
||||
hdr = ELF_REALPTR2PTRVAL(hdr_ptr);
|
||||
@@ -384,7 +390,14 @@ static elf_errorstatus xc_dom_load_elf_kernel(struct xc_dom_image *dom)
|
||||
xen_pfn_t pages;
|
||||
|
||||
elf->dest_base = xc_dom_seg_to_ptr_pages(dom, &dom->kernel_seg, &pages);
|
||||
+ if ( elf->dest_base == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: xc_dom_vaddr_to_ptr(dom,dom->kernel_seg)"
|
||||
+ " => NULL", __FUNCTION__);
|
||||
+ return -1;
|
||||
+ }
|
||||
elf->dest_size = pages * XC_DOM_PAGE_SIZE(dom);
|
||||
+
|
||||
rc = elf_load_binary(elf);
|
||||
if ( rc < 0 )
|
||||
{
|
||||
diff --git a/tools/libxc/xc_dom_ia64.c b/tools/libxc/xc_dom_ia64.c
|
||||
index dcd1523..7c0eff1 100644
|
||||
--- a/tools/libxc/xc_dom_ia64.c
|
||||
+++ b/tools/libxc/xc_dom_ia64.c
|
||||
@@ -60,6 +60,12 @@ int start_info_ia64(struct xc_dom_image *dom)
|
||||
|
||||
DOMPRINTF_CALLED(dom->xch);
|
||||
|
||||
+ if ( start_info == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: xc_dom_pfn_to_ptr failed on start_info", __FUNCTION__);
|
||||
+ return -1; /* our caller throws away our return value :-/ */
|
||||
+ }
|
||||
+
|
||||
memset(start_info, 0, sizeof(*start_info));
|
||||
sprintf(start_info->magic, dom->guest_type);
|
||||
start_info->flags = dom->flags;
|
||||
diff --git a/tools/libxc/xc_dom_x86.c b/tools/libxc/xc_dom_x86.c
|
||||
index 0cf1687..75d6b83 100644
|
||||
--- a/tools/libxc/xc_dom_x86.c
|
||||
+++ b/tools/libxc/xc_dom_x86.c
|
||||
@@ -144,6 +144,9 @@ static int setup_pgtables_x86_32(struct xc_dom_image *dom)
|
||||
xen_vaddr_t addr;
|
||||
xen_pfn_t pgpfn;
|
||||
|
||||
+ if ( l2tab == NULL )
|
||||
+ goto pfn_error;
|
||||
+
|
||||
for ( addr = dom->parms.virt_base; addr < dom->virt_pgtab_end;
|
||||
addr += PAGE_SIZE_X86 )
|
||||
{
|
||||
@@ -151,6 +154,8 @@ static int setup_pgtables_x86_32(struct xc_dom_image *dom)
|
||||
{
|
||||
/* get L1 tab, make L2 entry */
|
||||
l1tab = xc_dom_pfn_to_ptr(dom, l1pfn, 1);
|
||||
+ if ( l1tab == NULL )
|
||||
+ goto pfn_error;
|
||||
l2off = l2_table_offset_i386(addr);
|
||||
l2tab[l2off] =
|
||||
pfn_to_paddr(xc_dom_p2m_guest(dom, l1pfn)) | L2_PROT;
|
||||
@@ -169,6 +174,11 @@ static int setup_pgtables_x86_32(struct xc_dom_image *dom)
|
||||
l1tab = NULL;
|
||||
}
|
||||
return 0;
|
||||
+
|
||||
+pfn_error:
|
||||
+ xc_dom_panic(dom->xch, XC_INTERNAL_ERROR,
|
||||
+ "%s: xc_dom_pfn_to_ptr failed", __FUNCTION__);
|
||||
+ return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -219,6 +229,12 @@ static xen_pfn_t move_l3_below_4G(struct xc_dom_image *dom,
|
||||
goto out;
|
||||
|
||||
l3tab = xc_dom_pfn_to_ptr(dom, l3pfn, 1);
|
||||
+ if ( l3tab == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: xc_dom_pfn_to_ptr(dom, l3pfn, 1) => NULL",
|
||||
+ __FUNCTION__);
|
||||
+ return l3mfn; /* our one call site will call xc_dom_panic and fail */
|
||||
+ }
|
||||
memset(l3tab, 0, XC_DOM_PAGE_SIZE(dom));
|
||||
|
||||
DOMPRINTF("%s: successfully relocated L3 below 4G. "
|
||||
@@ -262,6 +278,8 @@ static int setup_pgtables_x86_32_pae(struct xc_dom_image *dom)
|
||||
}
|
||||
|
||||
l3tab = xc_dom_pfn_to_ptr(dom, l3pfn, 1);
|
||||
+ if ( l3tab == NULL )
|
||||
+ goto pfn_error;
|
||||
|
||||
for ( addr = dom->parms.virt_base; addr < dom->virt_pgtab_end;
|
||||
addr += PAGE_SIZE_X86 )
|
||||
@@ -270,6 +288,8 @@ static int setup_pgtables_x86_32_pae(struct xc_dom_image *dom)
|
||||
{
|
||||
/* get L2 tab, make L3 entry */
|
||||
l2tab = xc_dom_pfn_to_ptr(dom, l2pfn, 1);
|
||||
+ if ( l2tab == NULL )
|
||||
+ goto pfn_error;
|
||||
l3off = l3_table_offset_pae(addr);
|
||||
l3tab[l3off] =
|
||||
pfn_to_paddr(xc_dom_p2m_guest(dom, l2pfn)) | L3_PROT;
|
||||
@@ -280,6 +300,8 @@ static int setup_pgtables_x86_32_pae(struct xc_dom_image *dom)
|
||||
{
|
||||
/* get L1 tab, make L2 entry */
|
||||
l1tab = xc_dom_pfn_to_ptr(dom, l1pfn, 1);
|
||||
+ if ( l1tab == NULL )
|
||||
+ goto pfn_error;
|
||||
l2off = l2_table_offset_pae(addr);
|
||||
l2tab[l2off] =
|
||||
pfn_to_paddr(xc_dom_p2m_guest(dom, l1pfn)) | L2_PROT;
|
||||
@@ -306,6 +328,11 @@ static int setup_pgtables_x86_32_pae(struct xc_dom_image *dom)
|
||||
l3tab[3] = pfn_to_paddr(xc_dom_p2m_guest(dom, l2pfn)) | L3_PROT;
|
||||
}
|
||||
return 0;
|
||||
+
|
||||
+pfn_error:
|
||||
+ xc_dom_panic(dom->xch, XC_INTERNAL_ERROR,
|
||||
+ "%s: xc_dom_pfn_to_ptr failed", __FUNCTION__);
|
||||
+ return -EINVAL;
|
||||
}
|
||||
|
||||
#undef L1_PROT
|
||||
@@ -344,6 +371,9 @@ static int setup_pgtables_x86_64(struct xc_dom_image *dom)
|
||||
uint64_t addr;
|
||||
xen_pfn_t pgpfn;
|
||||
|
||||
+ if ( l4tab == NULL )
|
||||
+ goto pfn_error;
|
||||
+
|
||||
for ( addr = dom->parms.virt_base; addr < dom->virt_pgtab_end;
|
||||
addr += PAGE_SIZE_X86 )
|
||||
{
|
||||
@@ -351,6 +381,8 @@ static int setup_pgtables_x86_64(struct xc_dom_image *dom)
|
||||
{
|
||||
/* get L3 tab, make L4 entry */
|
||||
l3tab = xc_dom_pfn_to_ptr(dom, l3pfn, 1);
|
||||
+ if ( l3tab == NULL )
|
||||
+ goto pfn_error;
|
||||
l4off = l4_table_offset_x86_64(addr);
|
||||
l4tab[l4off] =
|
||||
pfn_to_paddr(xc_dom_p2m_guest(dom, l3pfn)) | L4_PROT;
|
||||
@@ -361,6 +393,8 @@ static int setup_pgtables_x86_64(struct xc_dom_image *dom)
|
||||
{
|
||||
/* get L2 tab, make L3 entry */
|
||||
l2tab = xc_dom_pfn_to_ptr(dom, l2pfn, 1);
|
||||
+ if ( l2tab == NULL )
|
||||
+ goto pfn_error;
|
||||
l3off = l3_table_offset_x86_64(addr);
|
||||
l3tab[l3off] =
|
||||
pfn_to_paddr(xc_dom_p2m_guest(dom, l2pfn)) | L3_PROT;
|
||||
@@ -373,6 +407,8 @@ static int setup_pgtables_x86_64(struct xc_dom_image *dom)
|
||||
{
|
||||
/* get L1 tab, make L2 entry */
|
||||
l1tab = xc_dom_pfn_to_ptr(dom, l1pfn, 1);
|
||||
+ if ( l1tab == NULL )
|
||||
+ goto pfn_error;
|
||||
l2off = l2_table_offset_x86_64(addr);
|
||||
l2tab[l2off] =
|
||||
pfn_to_paddr(xc_dom_p2m_guest(dom, l1pfn)) | L2_PROT;
|
||||
@@ -393,6 +429,11 @@ static int setup_pgtables_x86_64(struct xc_dom_image *dom)
|
||||
l1tab = NULL;
|
||||
}
|
||||
return 0;
|
||||
+
|
||||
+pfn_error:
|
||||
+ xc_dom_panic(dom->xch, XC_INTERNAL_ERROR,
|
||||
+ "%s: xc_dom_pfn_to_ptr failed", __FUNCTION__);
|
||||
+ return -EINVAL;
|
||||
}
|
||||
|
||||
#undef L1_PROT
|
||||
@@ -410,6 +451,8 @@ static int alloc_magic_pages(struct xc_dom_image *dom)
|
||||
if ( xc_dom_alloc_segment(dom, &dom->p2m_seg, "phys2mach", 0, p2m_size) )
|
||||
return -1;
|
||||
dom->p2m_guest = xc_dom_seg_to_ptr(dom, &dom->p2m_seg);
|
||||
+ if ( dom->p2m_guest == NULL )
|
||||
+ return -1;
|
||||
|
||||
/* allocate special pages */
|
||||
dom->start_info_pfn = xc_dom_alloc_page(dom, "start info");
|
||||
@@ -434,6 +477,12 @@ static int start_info_x86_32(struct xc_dom_image *dom)
|
||||
|
||||
DOMPRINTF_CALLED(dom->xch);
|
||||
|
||||
+ if ( start_info == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: xc_dom_pfn_to_ptr failed on start_info", __FUNCTION__);
|
||||
+ return -1; /* our caller throws away our return value :-/ */
|
||||
+ }
|
||||
+
|
||||
memset(start_info, 0, sizeof(*start_info));
|
||||
strncpy(start_info->magic, dom->guest_type, sizeof(start_info->magic));
|
||||
start_info->magic[sizeof(start_info->magic) - 1] = '\0';
|
||||
@@ -474,6 +523,12 @@ static int start_info_x86_64(struct xc_dom_image *dom)
|
||||
|
||||
DOMPRINTF_CALLED(dom->xch);
|
||||
|
||||
+ if ( start_info == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: xc_dom_pfn_to_ptr failed on start_info", __FUNCTION__);
|
||||
+ return -1; /* our caller throws away our return value :-/ */
|
||||
+ }
|
||||
+
|
||||
memset(start_info, 0, sizeof(*start_info));
|
||||
strncpy(start_info->magic, dom->guest_type, sizeof(start_info->magic));
|
||||
start_info->magic[sizeof(start_info->magic) - 1] = '\0';
|
||||
diff --git a/tools/libxc/xc_domain_restore.c b/tools/libxc/xc_domain_restore.c
|
||||
index b4c0b10..3994f8f 100644
|
||||
--- a/tools/libxc/xc_domain_restore.c
|
||||
+++ b/tools/libxc/xc_domain_restore.c
|
||||
@@ -1556,6 +1556,12 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
|
||||
mfn = ctx->p2m[pfn];
|
||||
buf = xc_map_foreign_range(xch, dom, PAGE_SIZE,
|
||||
PROT_READ | PROT_WRITE, mfn);
|
||||
+ if ( buf == NULL )
|
||||
+ {
|
||||
+ ERROR("xc_map_foreign_range for generation id"
|
||||
+ " buffer failed");
|
||||
+ goto out;
|
||||
+ }
|
||||
|
||||
generationid = *(unsigned long long *)(buf + offset);
|
||||
*(unsigned long long *)(buf + offset) = generationid + 1;
|
||||
@@ -1713,6 +1719,11 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
|
||||
l3tab = (uint64_t *)
|
||||
xc_map_foreign_range(xch, dom, PAGE_SIZE,
|
||||
PROT_READ, ctx->p2m[i]);
|
||||
+ if ( l3tab == NULL )
|
||||
+ {
|
||||
+ PERROR("xc_map_foreign_range failed (for l3tab)");
|
||||
+ goto out;
|
||||
+ }
|
||||
|
||||
for ( j = 0; j < 4; j++ )
|
||||
l3ptes[j] = l3tab[j];
|
||||
@@ -1739,6 +1750,11 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
|
||||
l3tab = (uint64_t *)
|
||||
xc_map_foreign_range(xch, dom, PAGE_SIZE,
|
||||
PROT_READ | PROT_WRITE, ctx->p2m[i]);
|
||||
+ if ( l3tab == NULL )
|
||||
+ {
|
||||
+ PERROR("xc_map_foreign_range failed (for l3tab, 2nd)");
|
||||
+ goto out;
|
||||
+ }
|
||||
|
||||
for ( j = 0; j < 4; j++ )
|
||||
l3tab[j] = l3ptes[j];
|
||||
@@ -1909,6 +1925,12 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
|
||||
SET_FIELD(ctxt, user_regs.edx, mfn);
|
||||
start_info = xc_map_foreign_range(
|
||||
xch, dom, PAGE_SIZE, PROT_READ | PROT_WRITE, mfn);
|
||||
+ if ( start_info == NULL )
|
||||
+ {
|
||||
+ PERROR("xc_map_foreign_range failed (for start_info)");
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
SET_FIELD(start_info, nr_pages, dinfo->p2m_size);
|
||||
SET_FIELD(start_info, shared_info, shared_info_frame<<PAGE_SHIFT);
|
||||
SET_FIELD(start_info, flags, 0);
|
||||
@@ -2056,6 +2078,11 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
|
||||
/* Restore contents of shared-info page. No checking needed. */
|
||||
new_shared_info = xc_map_foreign_range(
|
||||
xch, dom, PAGE_SIZE, PROT_WRITE, shared_info_frame);
|
||||
+ if ( new_shared_info == NULL )
|
||||
+ {
|
||||
+ PERROR("xc_map_foreign_range failed (for new_shared_info)");
|
||||
+ goto out;
|
||||
+ }
|
||||
|
||||
/* restore saved vcpu_info and arch specific info */
|
||||
MEMCPY_FIELD(new_shared_info, old_shared_info, vcpu_info);
|
||||
diff --git a/tools/libxc/xc_offline_page.c b/tools/libxc/xc_offline_page.c
|
||||
index 089a361..36b9812 100644
|
||||
--- a/tools/libxc/xc_offline_page.c
|
||||
+++ b/tools/libxc/xc_offline_page.c
|
||||
@@ -714,6 +714,11 @@ int xc_exchange_page(xc_interface *xch, int domid, xen_pfn_t mfn)
|
||||
|
||||
new_p = xc_map_foreign_range(xch, domid, PAGE_SIZE,
|
||||
PROT_READ|PROT_WRITE, new_mfn);
|
||||
+ if ( new_p == NULL )
|
||||
+ {
|
||||
+ ERROR("failed to map new_p for copy, guest may be broken?");
|
||||
+ goto failed;
|
||||
+ }
|
||||
memcpy(new_p, backup, PAGE_SIZE);
|
||||
munmap(new_p, PAGE_SIZE);
|
||||
mops.arg1.mfn = new_mfn;
|
||||
--
|
||||
1.7.2.5
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,261 @@
|
||||
From 59f66d58180832af6b99a9e4489031b5c2f627ab Mon Sep 17 00:00:00 2001
|
||||
From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Date: Fri, 14 Jun 2013 16:43:17 +0100
|
||||
Subject: [PATCH 09/23] tools/xcutils/readnotes: adjust print_l1_mfn_valid_note
|
||||
|
||||
Use the new PTRVAL macros and elf_access_unsigned in
|
||||
print_l1_mfn_valid_note.
|
||||
|
||||
No functional change unless the input is wrong, or we are reading a
|
||||
file for a different endianness.
|
||||
|
||||
Separated out from the previous patch because this change does produce
|
||||
a difference in the generated code.
|
||||
|
||||
This is part of the fix to a security issue, XSA-55.
|
||||
|
||||
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
---
|
||||
tools/xcutils/readnotes.c | 11 ++++++-----
|
||||
1 files changed, 6 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/tools/xcutils/readnotes.c b/tools/xcutils/readnotes.c
|
||||
index 2af047d..7ff2530 100644
|
||||
--- a/tools/xcutils/readnotes.c
|
||||
+++ b/tools/xcutils/readnotes.c
|
||||
@@ -77,22 +77,23 @@ static void print_numeric_note(const char *prefix, struct elf_binary *elf,
|
||||
}
|
||||
|
||||
static void print_l1_mfn_valid_note(const char *prefix, struct elf_binary *elf,
|
||||
- const elf_note *note)
|
||||
+ ELF_HANDLE_DECL(elf_note) note)
|
||||
{
|
||||
int descsz = elf_uval(elf, note, descsz);
|
||||
- const uint32_t *desc32 = elf_note_desc(elf, note);
|
||||
- const uint64_t *desc64 = elf_note_desc(elf, note);
|
||||
+ ELF_PTRVAL_CONST_VOID desc = elf_note_desc(elf, note);
|
||||
|
||||
/* XXX should be able to cope with a list of values. */
|
||||
switch ( descsz / 2 )
|
||||
{
|
||||
case 8:
|
||||
printf("%s: mask=%#"PRIx64" value=%#"PRIx64"\n", prefix,
|
||||
- desc64[0], desc64[1]);
|
||||
+ elf_access_unsigned(elf, desc, 0, 8),
|
||||
+ elf_access_unsigned(elf, desc, 8, 8));
|
||||
break;
|
||||
case 4:
|
||||
printf("%s: mask=%#"PRIx32" value=%#"PRIx32"\n", prefix,
|
||||
- desc32[0],desc32[1]);
|
||||
+ (uint32_t)elf_access_unsigned(elf, desc, 0, 4),
|
||||
+ (uint32_t)elf_access_unsigned(elf, desc, 4, 4));
|
||||
break;
|
||||
}
|
||||
|
||||
--
|
||||
1.7.2.5
|
||||
#From db14d5bd9b6508adfcd2b910f454fae12fa4ba00 Mon Sep 17 00:00:00 2001
|
||||
#From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
#Date: Fri, 14 Jun 2013 16:43:17 +0100
|
||||
#Subject: [PATCH 10/23] libelf: check nul-terminated strings properly
|
||||
#
|
||||
#It is not safe to simply take pointers into the ELF and use them as C
|
||||
#pointers. They might not be properly nul-terminated (and the pointers
|
||||
#might be wild).
|
||||
#
|
||||
#So we are going to introduce a new function elf_strval for safely
|
||||
#getting strings. This will check that the addresses are in range and
|
||||
#that there is a proper nul-terminated string. Of course it might
|
||||
#discover that there isn't. In that case, it will be made to fail.
|
||||
#This means that elf_note_name might fail, too.
|
||||
#
|
||||
#For the benefit of call sites which are just going to pass the value
|
||||
#to a printf-like function, we provide elf_strfmt which returns
|
||||
#"(invalid)" on failure rather than NULL.
|
||||
#
|
||||
#In this patch we introduce dummy definitions of these functions. We
|
||||
#introduce calls to elf_strval and elf_strfmt everywhere, and update
|
||||
#all the call sites with appropriate error checking.
|
||||
#
|
||||
#There is not yet any semantic change, since before this patch all the
|
||||
#places where we introduce elf_strval dereferenced the value anyway, so
|
||||
#it mustn't have been NULL.
|
||||
#
|
||||
#In future patches, when elf_strval is made able return NULL, when it
|
||||
#does so it will mark the elf "broken" so that an appropriate
|
||||
#diagnostic can be printed.
|
||||
#
|
||||
#This is part of the fix to a security issue, XSA-55.
|
||||
#
|
||||
#Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
#Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
#Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
|
||||
#---
|
||||
# tools/xcutils/readnotes.c | 11 ++++++++---
|
||||
# xen/common/libelf/libelf-dominfo.c | 13 ++++++++++---
|
||||
# xen/common/libelf/libelf-tools.c | 10 +++++++---
|
||||
# xen/include/xen/libelf.h | 7 +++++--
|
||||
# 4 files changed, 30 insertions(+), 11 deletions(-)
|
||||
#
|
||||
diff --git a/tools/xcutils/readnotes.c b/tools/xcutils/readnotes.c
|
||||
index 7ff2530..cfae994 100644
|
||||
--- a/tools/xcutils/readnotes.c
|
||||
+++ b/tools/xcutils/readnotes.c
|
||||
@@ -63,7 +63,7 @@ struct setup_header {
|
||||
static void print_string_note(const char *prefix, struct elf_binary *elf,
|
||||
ELF_HANDLE_DECL(elf_note) note)
|
||||
{
|
||||
- printf("%s: %s\n", prefix, (char*)elf_note_desc(elf, note));
|
||||
+ printf("%s: %s\n", prefix, elf_strfmt(elf, elf_note_desc(elf, note)));
|
||||
}
|
||||
|
||||
static void print_numeric_note(const char *prefix, struct elf_binary *elf,
|
||||
@@ -103,10 +103,14 @@ static int print_notes(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) start,
|
||||
{
|
||||
ELF_HANDLE_DECL(elf_note) note;
|
||||
int notes_found = 0;
|
||||
+ const char *this_note_name;
|
||||
|
||||
for ( note = start; ELF_HANDLE_PTRVAL(note) < ELF_HANDLE_PTRVAL(end); note = elf_note_next(elf, note) )
|
||||
{
|
||||
- if (0 != strcmp(elf_note_name(elf, note), "Xen"))
|
||||
+ this_note_name = elf_note_name(elf, note);
|
||||
+ if (NULL == this_note_name)
|
||||
+ continue;
|
||||
+ if (0 != strcmp(this_note_name, "Xen"))
|
||||
continue;
|
||||
|
||||
notes_found++;
|
||||
@@ -294,7 +298,8 @@ int main(int argc, char **argv)
|
||||
|
||||
shdr = elf_shdr_by_name(&elf, "__xen_guest");
|
||||
if (ELF_HANDLE_VALID(shdr))
|
||||
- printf("__xen_guest: %s\n", (char*)elf_section_start(&elf, shdr));
|
||||
+ printf("__xen_guest: %s\n",
|
||||
+ elf_strfmt(&elf, elf_section_start(&elf, shdr)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
diff --git a/xen/common/libelf/libelf-dominfo.c b/xen/common/libelf/libelf-dominfo.c
|
||||
index 7140d59..b217f8f 100644
|
||||
--- a/xen/common/libelf/libelf-dominfo.c
|
||||
+++ b/xen/common/libelf/libelf-dominfo.c
|
||||
@@ -137,7 +137,10 @@ int elf_xen_parse_note(struct elf_binary *elf,
|
||||
|
||||
if ( note_desc[type].str )
|
||||
{
|
||||
- str = elf_note_desc(elf, note);
|
||||
+ str = elf_strval(elf, elf_note_desc(elf, note));
|
||||
+ if (str == NULL)
|
||||
+ /* elf_strval will mark elf broken if it fails so no need to log */
|
||||
+ return 0;
|
||||
elf_msg(elf, "%s: %s = \"%s\"\n", __FUNCTION__,
|
||||
note_desc[type].name, str);
|
||||
parms->elf_notes[type].type = XEN_ENT_STR;
|
||||
@@ -220,6 +223,7 @@ static int elf_xen_parse_notes(struct elf_binary *elf,
|
||||
{
|
||||
int xen_elfnotes = 0;
|
||||
ELF_HANDLE_DECL(elf_note) note;
|
||||
+ const char *note_name;
|
||||
|
||||
parms->elf_note_start = start;
|
||||
parms->elf_note_end = end;
|
||||
@@ -227,7 +231,10 @@ static int elf_xen_parse_notes(struct elf_binary *elf,
|
||||
ELF_HANDLE_PTRVAL(note) < parms->elf_note_end;
|
||||
note = elf_note_next(elf, note) )
|
||||
{
|
||||
- if ( strcmp(elf_note_name(elf, note), "Xen") )
|
||||
+ note_name = elf_note_name(elf, note);
|
||||
+ if ( note_name == NULL )
|
||||
+ continue;
|
||||
+ if ( strcmp(note_name, "Xen") )
|
||||
continue;
|
||||
if ( elf_xen_parse_note(elf, parms, note) )
|
||||
return -1;
|
||||
@@ -541,7 +548,7 @@ int elf_xen_parse(struct elf_binary *elf,
|
||||
parms->elf_note_start = ELF_INVALID_PTRVAL;
|
||||
parms->elf_note_end = ELF_INVALID_PTRVAL;
|
||||
elf_msg(elf, "%s: __xen_guest: \"%s\"\n", __FUNCTION__,
|
||||
- parms->guest_info);
|
||||
+ elf_strfmt(elf, parms->guest_info));
|
||||
elf_xen_parse_guest_info(elf, parms);
|
||||
break;
|
||||
}
|
||||
diff --git a/xen/common/libelf/libelf-tools.c b/xen/common/libelf/libelf-tools.c
|
||||
index f1fd886..3a0cde1 100644
|
||||
--- a/xen/common/libelf/libelf-tools.c
|
||||
+++ b/xen/common/libelf/libelf-tools.c
|
||||
@@ -119,7 +119,7 @@ const char *elf_section_name(struct elf_binary *elf,
|
||||
if ( ELF_PTRVAL_INVALID(elf->sec_strtab) )
|
||||
return "unknown";
|
||||
|
||||
- return elf->sec_strtab + elf_uval(elf, shdr, sh_name);
|
||||
+ return elf_strval(elf, elf->sec_strtab + elf_uval(elf, shdr, sh_name));
|
||||
}
|
||||
|
||||
ELF_PTRVAL_CONST_VOID elf_section_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr)
|
||||
@@ -151,6 +151,7 @@ ELF_HANDLE_DECL(elf_sym) elf_sym_by_name(struct elf_binary *elf, const char *sym
|
||||
ELF_PTRVAL_CONST_VOID end = elf_section_end(elf, elf->sym_tab);
|
||||
ELF_HANDLE_DECL(elf_sym) sym;
|
||||
uint64_t info, name;
|
||||
+ const char *sym_name;
|
||||
|
||||
for ( ; ptr < end; ptr += elf_size(elf, sym) )
|
||||
{
|
||||
@@ -159,7 +160,10 @@ ELF_HANDLE_DECL(elf_sym) elf_sym_by_name(struct elf_binary *elf, const char *sym
|
||||
name = elf_uval(elf, sym, st_name);
|
||||
if ( ELF32_ST_BIND(info) != STB_GLOBAL )
|
||||
continue;
|
||||
- if ( strcmp(elf->sym_strtab + name, symbol) )
|
||||
+ sym_name = elf_strval(elf, elf->sym_strtab + name);
|
||||
+ if ( sym_name == NULL ) /* out of range, oops */
|
||||
+ return ELF_INVALID_HANDLE(elf_sym);
|
||||
+ if ( strcmp(sym_name, symbol) )
|
||||
continue;
|
||||
return sym;
|
||||
}
|
||||
@@ -177,7 +181,7 @@ ELF_HANDLE_DECL(elf_sym) elf_sym_by_index(struct elf_binary *elf, int index)
|
||||
|
||||
const char *elf_note_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note)
|
||||
{
|
||||
- return ELF_HANDLE_PTRVAL(note) + elf_size(elf, note);
|
||||
+ return elf_strval(elf, ELF_HANDLE_PTRVAL(note) + elf_size(elf, note));
|
||||
}
|
||||
|
||||
ELF_PTRVAL_CONST_VOID elf_note_desc(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note)
|
||||
diff --git a/xen/include/xen/libelf.h b/xen/include/xen/libelf.h
|
||||
index cefd3d3..af5b5c5 100644
|
||||
--- a/xen/include/xen/libelf.h
|
||||
+++ b/xen/include/xen/libelf.h
|
||||
@@ -252,6 +252,9 @@ uint64_t elf_access_unsigned(struct elf_binary *elf, ELF_PTRVAL_CONST_VOID ptr,
|
||||
uint64_t elf_round_up(struct elf_binary *elf, uint64_t addr);
|
||||
|
||||
|
||||
+#define elf_strval(elf,x) ((const char*)(x)) /* may return NULL in the future */
|
||||
+#define elf_strfmt(elf,x) ((const char*)(x)) /* will return (invalid) instead */
|
||||
+
|
||||
#define elf_memcpy_safe(elf, dst, src, sz) memcpy((dst),(src),(sz))
|
||||
#define elf_memset_safe(elf, dst, c, sz) memset((dst),(c),(sz))
|
||||
/*
|
||||
@@ -279,7 +282,7 @@ ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_name(struct elf_binary *elf, const char *n
|
||||
ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_index(struct elf_binary *elf, int index);
|
||||
ELF_HANDLE_DECL(elf_phdr) elf_phdr_by_index(struct elf_binary *elf, int index);
|
||||
|
||||
-const char *elf_section_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr);
|
||||
+const char *elf_section_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr); /* might return NULL if inputs are invalid */
|
||||
ELF_PTRVAL_CONST_VOID elf_section_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr);
|
||||
ELF_PTRVAL_CONST_VOID elf_section_end(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr);
|
||||
|
||||
@@ -289,7 +292,7 @@ ELF_PTRVAL_CONST_VOID elf_segment_end(struct elf_binary *elf, ELF_HANDLE_DECL(el
|
||||
ELF_HANDLE_DECL(elf_sym) elf_sym_by_name(struct elf_binary *elf, const char *symbol);
|
||||
ELF_HANDLE_DECL(elf_sym) elf_sym_by_index(struct elf_binary *elf, int index);
|
||||
|
||||
-const char *elf_note_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
|
||||
+const char *elf_note_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note); /* may return NULL */
|
||||
ELF_PTRVAL_CONST_VOID elf_note_desc(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
|
||||
uint64_t elf_note_numeric(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
|
||||
uint64_t elf_note_numeric_array(struct elf_binary *, ELF_HANDLE_DECL(elf_note),
|
||||
--
|
||||
1.7.2.5
|
||||
|
@ -1,116 +0,0 @@
|
||||
# Patch Makefile to patch insource newlib,
|
||||
# Prevent internal downloading of external packages
|
||||
diff -ur xen-4.2.0.orig/stubdom/Makefile xen-4.2.0/stubdom/Makefile
|
||||
--- stubdom/Makefile 2012-09-17 18:21:17.000000000 +0800
|
||||
+++ stubdom/Makefile 2012-12-05 14:01:10.694260256 +0800
|
||||
@@ -8,30 +8,30 @@
|
||||
include $(XEN_ROOT)/Config.mk
|
||||
|
||||
#ZLIB_URL?=http://www.zlib.net
|
||||
-ZLIB_URL=$(XEN_EXTFILES_URL)
|
||||
+ZLIB_URL=/mnt/gen2/TmpDir/portage/app-emulation/xen-pvgrub-4.2.0/distdir
|
||||
ZLIB_VERSION=1.2.3
|
||||
|
||||
#LIBPCI_URL?=http://www.kernel.org/pub/software/utils/pciutils
|
||||
-LIBPCI_URL?=$(XEN_EXTFILES_URL)
|
||||
+LIBPCI_URL?=/mnt/gen2/TmpDir/portage/app-emulation/xen-pvgrub-4.2.0/distdir
|
||||
LIBPCI_VERSION=2.2.9
|
||||
|
||||
#NEWLIB_URL?=ftp://sources.redhat.com/pub/newlib
|
||||
-NEWLIB_URL?=$(XEN_EXTFILES_URL)
|
||||
+NEWLIB_URL?=/mnt/gen2/TmpDir/portage/app-emulation/xen-pvgrub-4.2.0/distdir
|
||||
NEWLIB_VERSION=1.16.0
|
||||
|
||||
#LWIP_URL?=http://download.savannah.gnu.org/releases/lwip
|
||||
-LWIP_URL?=$(XEN_EXTFILES_URL)
|
||||
+LWIP_URL?=/mnt/gen2/TmpDir/portage/app-emulation/xen-pvgrub-4.2.0/distdir
|
||||
LWIP_VERSION=1.3.0
|
||||
|
||||
#GRUB_URL?=http://alpha.gnu.org/gnu/grub
|
||||
-GRUB_URL?=$(XEN_EXTFILES_URL)
|
||||
+GRUB_URL?=/mnt/gen2/TmpDir/portage/app-emulation/xen-pvgrub-4.2.0/distdir
|
||||
GRUB_VERSION=0.97
|
||||
|
||||
-#OCAML_URL?=$(XEN_EXTFILES_URL)
|
||||
+#OCAML_URL?=/mnt/gen2/TmpDir/portage/app-emulation/xen-pvgrub-4.2.0/distdir
|
||||
OCAML_URL?=http://caml.inria.fr/pub/distrib/ocaml-3.11
|
||||
OCAML_VERSION=3.11.0
|
||||
|
||||
-WGET=wget -c
|
||||
+WGET=cp -t .
|
||||
|
||||
GNU_TARGET_ARCH:=$(XEN_TARGET_ARCH)
|
||||
ifeq ($(XEN_TARGET_ARCH),x86_32)
|
||||
@@ -95,12 +95,12 @@
|
||||
##############
|
||||
|
||||
newlib-$(NEWLIB_VERSION).tar.gz:
|
||||
- $(WGET) $(NEWLIB_URL)/$@
|
||||
|
||||
newlib-$(NEWLIB_VERSION): newlib-$(NEWLIB_VERSION).tar.gz
|
||||
tar xzf $<
|
||||
patch -d $@ -p0 < newlib.patch
|
||||
patch -d $@ -p0 < newlib-chk.patch
|
||||
+ patch -d $@ -p0 < newlib-implicits.patch
|
||||
patch -d $@ -p1 < newlib-stdint-size_max-fix-from-1.17.0.patch
|
||||
find $@ -type f | xargs perl -i.bak \
|
||||
-pe 's/\b_(tzname|daylight|timezone)\b/$$1/g'
|
||||
@@ -112,7 +112,7 @@
|
||||
$(NEWLIB_STAMPFILE): mk-headers-$(XEN_TARGET_ARCH) newlib-$(NEWLIB_VERSION)
|
||||
mkdir -p newlib-$(XEN_TARGET_ARCH)
|
||||
( cd newlib-$(XEN_TARGET_ARCH) && \
|
||||
- CC_FOR_TARGET="$(CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(NEWLIB_CFLAGS)" AR_FOR_TARGET=$(AR) LD_FOR_TARGET=$(LD) RANLIB_FOR_TARGET=$(RANLIB) ../newlib-$(NEWLIB_VERSION)/configure --prefix=$(CROSS_PREFIX) --verbose --target=$(GNU_TARGET_ARCH)-xen-elf --enable-newlib-io-long-long --disable-multilib && \
|
||||
+ CC_FOR_TARGET="$(CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(NEWLIB_CFLAGS)" AR_FOR_TARGET=$(AR) LD_FOR_TARGET=$(LD) LDFLAGS= RANLIB_FOR_TARGET=$(RANLIB) ../newlib-$(NEWLIB_VERSION)/configure --prefix=$(CROSS_PREFIX) --verbose --target=$(GNU_TARGET_ARCH)-xen-elf --enable-newlib-io-long-long --disable-multilib && \
|
||||
$(CROSS_MAKE) && \
|
||||
$(CROSS_MAKE) install )
|
||||
|
||||
@@ -121,7 +121,6 @@
|
||||
############
|
||||
|
||||
zlib-$(ZLIB_VERSION).tar.gz:
|
||||
- $(WGET) $(ZLIB_URL)/$@
|
||||
|
||||
zlib-$(XEN_TARGET_ARCH): zlib-$(ZLIB_VERSION).tar.gz
|
||||
tar xzf $<
|
||||
@@ -132,7 +132,7 @@
|
||||
cross-zlib: $(ZLIB_STAMPFILE)
|
||||
$(ZLIB_STAMPFILE): zlib-$(XEN_TARGET_ARCH) $(NEWLIB_STAMPFILE)
|
||||
( cd $< && \
|
||||
- CFLAGS="$(TARGET_CPPFLAGS) $(TARGET_CFLAGS)" CC=$(CC) ./configure --prefix=$(CROSS_PREFIX)/$(GNU_TARGET_ARCH)-xen-elf && \
|
||||
+ CFLAGS="$(TARGET_CPPFLAGS) $(TARGET_CFLAGS)" CC="$(CC)" ./configure --prefix=$(CROSS_PREFIX)/$(GNU_TARGET_ARCH)-xen-elf && \
|
||||
$(CROSS_MAKE) libz.a && \
|
||||
$(CROSS_MAKE) install )
|
||||
|
||||
@@ -141,7 +142,6 @@
|
||||
##############
|
||||
|
||||
pciutils-$(LIBPCI_VERSION).tar.bz2:
|
||||
- $(WGET) $(LIBPCI_URL)/$@
|
||||
|
||||
pciutils-$(XEN_TARGET_ARCH): pciutils-$(LIBPCI_VERSION).tar.bz2
|
||||
tar xjf $<
|
||||
@@ -169,7 +170,6 @@
|
||||
######
|
||||
|
||||
lwip-$(LWIP_VERSION).tar.gz:
|
||||
- $(WGET) $(LWIP_URL)/$@
|
||||
|
||||
lwip-$(XEN_TARGET_ARCH): lwip-$(LWIP_VERSION).tar.gz
|
||||
tar xzf $<
|
||||
@@ -325,7 +326,6 @@
|
||||
######
|
||||
|
||||
grub-$(GRUB_VERSION).tar.gz:
|
||||
- $(WGET) $(GRUB_URL)/$@
|
||||
|
||||
grub-upstream: grub-$(GRUB_VERSION).tar.gz
|
||||
tar xzf $<
|
||||
@@ -392,7 +393,7 @@
|
||||
$(INSTALL_DIR) "$(DESTDIR)$(XENFIRMWAREDIR)"
|
||||
$(INSTALL_DATA) mini-os-$(XEN_TARGET_ARCH)-ioemu/mini-os.gz "$(DESTDIR)$(XENFIRMWAREDIR)/ioemu-stubdom.gz"
|
||||
|
||||
-install-grub: pv-grub
|
||||
+install-grub:
|
||||
$(INSTALL_DIR) "$(DESTDIR)$(XENFIRMWAREDIR)"
|
||||
$(INSTALL_DATA) mini-os-$(XEN_TARGET_ARCH)-grub/mini-os.gz "$(DESTDIR)$(XENFIRMWAREDIR)/pv-grub-$(XEN_TARGET_ARCH).gz"
|
||||
|
@ -1,113 +0,0 @@
|
||||
# Copyright 1999-2013 Gentoo Foundation
|
||||
# Distributed under the terms of the GNU General Public License v2
|
||||
# $Header: /var/cvsroot/gentoo-x86/app-emulation/xen-pvgrub/xen-pvgrub-4.2.1.ebuild,v 1.2 2013/01/30 14:12:30 idella4 Exp $
|
||||
|
||||
EAPI="4"
|
||||
|
||||
inherit flag-o-matic eutils multilib toolchain-funcs
|
||||
|
||||
XEN_EXTFILES_URL="http://xenbits.xensource.com/xen-extfiles"
|
||||
LIBPCI_URL=ftp://atrey.karlin.mff.cuni.cz/pub/linux/pci
|
||||
GRUB_URL=mirror://gnu-alpha/grub
|
||||
SRC_URI="
|
||||
http://bits.xensource.com/oss-xen/release/${PV}/xen-${PV}.tar.gz
|
||||
$GRUB_URL/grub-0.97.tar.gz
|
||||
$XEN_EXTFILES_URL/zlib-1.2.3.tar.gz
|
||||
$LIBPCI_URL/pciutils-2.2.9.tar.bz2
|
||||
$XEN_EXTFILES_URL/lwip-1.3.0.tar.gz
|
||||
$XEN_EXTFILES_URL/newlib/newlib-1.16.0.tar.gz"
|
||||
|
||||
S="${WORKDIR}/xen-${PV}"
|
||||
|
||||
DESCRIPTION="allows to boot Xen domU kernels from a menu.lst laying inside guest filesystem"
|
||||
HOMEPAGE="http://xen.org/"
|
||||
LICENSE="GPL-2"
|
||||
SLOT="0"
|
||||
KEYWORDS="~amd64 ~x86"
|
||||
IUSE="custom-cflags"
|
||||
|
||||
DEPEND="sys-devel/gettext
|
||||
sys-devel/gcc"
|
||||
|
||||
RDEPEND=">=app-emulation/xen-4.2.1"
|
||||
|
||||
src_prepare() {
|
||||
|
||||
# if the user *really* wants to use their own custom-cflags, let them
|
||||
if use custom-cflags; then
|
||||
einfo "User wants their own CFLAGS - removing defaults"
|
||||
# try and remove all the default custom-cflags
|
||||
find "${S}" -name Makefile -o -name Rules.mk -o -name Config.mk -exec sed \
|
||||
-e 's/CFLAGS\(.*\)=\(.*\)-O3\(.*\)/CFLAGS\1=\2\3/' \
|
||||
-e 's/CFLAGS\(.*\)=\(.*\)-march=i686\(.*\)/CFLAGS\1=\2\3/' \
|
||||
-e 's/CFLAGS\(.*\)=\(.*\)-fomit-frame-pointer\(.*\)/CFLAGS\1=\2\3/' \
|
||||
-e 's/CFLAGS\(.*\)=\(.*\)-g3*\s\(.*\)/CFLAGS\1=\2 \3/' \
|
||||
-e 's/CFLAGS\(.*\)=\(.*\)-O2\(.*\)/CFLAGS\1=\2\3/' \
|
||||
-i {} \;
|
||||
fi
|
||||
|
||||
#Substitute for internal downloading
|
||||
cp $DISTDIR/zlib-1.2.3.tar.gz \
|
||||
$DISTDIR/pciutils-2.2.9.tar.bz2 \
|
||||
$DISTDIR/lwip-1.3.0.tar.gz \
|
||||
$DISTDIR/newlib-1.16.0.tar.gz \
|
||||
$DISTDIR/grub-0.97.tar.gz \
|
||||
./stubdom/ || die "files not coped to stubdom"
|
||||
# Note: tip to patch grub gentoo style, for review soon. This is around 1/3.
|
||||
# cp "${WORKDIR}"/patch/{00[3-6]_all_grub*,010_all_grub*,01[3-9]_all_grub*,0[6-7]0_all_grub*} \
|
||||
# "${WORKDIR}"/patch/{110_all_grub*,300_all_grub*} \
|
||||
# stubdom/grub.patches/ || die
|
||||
einfo "files copied to stubdom"
|
||||
|
||||
# Patch the unmergeable newlib, fix most of the leftover gcc QA issues
|
||||
cp "${FILESDIR}"/newlib-implicits.patch stubdom || die
|
||||
|
||||
# Patch stubdom/Makefile to patch insource newlib & prevent internal downloading
|
||||
epatch "${FILESDIR}"/${P/-pvgrub/}-externals.patch
|
||||
|
||||
# Drop .config and Fix gcc-4.6
|
||||
epatch "${FILESDIR}"/${PN/-pvgrub/}-4-fix_dotconfig-gcc.patch
|
||||
|
||||
# fix jobserver in Makefile
|
||||
epatch "${FILESDIR}"/${PN/-pvgrub/}-4.2.0-jserver.patch
|
||||
}
|
||||
|
||||
src_compile() {
|
||||
use custom-cflags || unset CFLAGS
|
||||
if test-flag-CC -fno-strict-overflow; then
|
||||
append-flags -fno-strict-overflow
|
||||
fi
|
||||
|
||||
emake CC="$(tc-getCC)" LD="$(tc-getLD)" -C tools/include
|
||||
|
||||
# TODO; fix those -j1
|
||||
if use x86; then
|
||||
emake CC="$(tc-getCC)" LD="$(tc-getLD)" \
|
||||
XEN_TARGET_ARCH="x86_32" -C stubdom pv-grub
|
||||
elif use amd64; then
|
||||
emake CC="$(tc-getCC)" LD="$(tc-getLD)" \
|
||||
XEN_TARGET_ARCH="x86_64" -C stubdom pv-grub
|
||||
if use multilib; then
|
||||
multilib_toolchain_setup x86
|
||||
emake XEN_TARGET_ARCH="x86_32" -C stubdom pv-grub
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
src_install() {
|
||||
if use x86; then
|
||||
emake XEN_TARGET_ARCH="x86_32" DESTDIR="${D}" -C stubdom install-grub
|
||||
fi
|
||||
if use amd64; then
|
||||
emake XEN_TARGET_ARCH="x86_64" DESTDIR="${D}" -C stubdom install-grub
|
||||
if use multilib; then
|
||||
emake XEN_TARGET_ARCH="x86_32" DESTDIR="${D}" -C stubdom install-grub
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
pkg_postinst() {
|
||||
elog "Official Xen Guide and the unoffical wiki page:"
|
||||
elog " http://www.gentoo.org/doc/en/xen-guide.xml"
|
||||
elog " http://en.gentoo-wiki.com/wiki/Xen/"
|
||||
}
|
@ -1,369 +0,0 @@
|
||||
|
||||
# HG changeset patch
|
||||
# User Ian Jackson <Ian.Jackson@eu.citrix.com>
|
||||
# Date 1351264255 -3600
|
||||
# Node ID 537776f51f79c5789d06f97b363596a197c3e71c
|
||||
# Parent 40ccbee890e1fc053de3046bbc3d13b8ff6f5d63
|
||||
libxc: builder: limit maximum size of kernel/ramdisk.
|
||||
|
||||
Allowing user supplied kernels of arbitrary sizes, especially during
|
||||
decompression, can swallow up dom0 memory leading to either virtual
|
||||
address space exhaustion in the builder process or allocation
|
||||
failures/OOM killing of both toolstack and unrelated processes.
|
||||
|
||||
We disable these checks when building in a stub domain for pvgrub
|
||||
since this uses the guest's own memory and is isolated.
|
||||
|
||||
Decompression of gzip compressed kernels and ramdisks has been safe
|
||||
since 14954:58205257517d (Xen 3.1.0 onwards).
|
||||
|
||||
This is XSA-25 / CVE-2012-4544.
|
||||
|
||||
Also make explicit checks for buffer overflows in various
|
||||
decompression routines. These were already ruled out due to other
|
||||
properties of the code but check them as a belt-and-braces measure.
|
||||
|
||||
Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
|
||||
diff -r 40ccbee890e1 -r 537776f51f79 stubdom/grub/kexec.c
|
||||
--- stubdom/grub/kexec.c Thu Oct 25 15:36:32 2012 +0200
|
||||
+++ stubdom/grub/kexec.c Fri Oct 26 16:10:55 2012 +0100
|
||||
@@ -137,6 +137,10 @@ void kexec(void *kernel, long kernel_siz
|
||||
dom = xc_dom_allocate(xc_handle, cmdline, features);
|
||||
dom->allocate = kexec_allocate;
|
||||
|
||||
+ /* We are using guest owned memory, therefore no limits. */
|
||||
+ xc_dom_kernel_max_size(dom, 0);
|
||||
+ xc_dom_ramdisk_max_size(dom, 0);
|
||||
+
|
||||
dom->kernel_blob = kernel;
|
||||
dom->kernel_size = kernel_size;
|
||||
|
||||
diff -r 40ccbee890e1 -r 537776f51f79 tools/libxc/xc_dom.h
|
||||
--- tools/libxc/xc_dom.h Thu Oct 25 15:36:32 2012 +0200
|
||||
+++ tools/libxc/xc_dom.h Fri Oct 26 16:10:55 2012 +0100
|
||||
@@ -55,6 +55,9 @@ struct xc_dom_image {
|
||||
void *ramdisk_blob;
|
||||
size_t ramdisk_size;
|
||||
|
||||
+ size_t max_kernel_size;
|
||||
+ size_t max_ramdisk_size;
|
||||
+
|
||||
/* arguments and parameters */
|
||||
char *cmdline;
|
||||
uint32_t f_requested[XENFEAT_NR_SUBMAPS];
|
||||
@@ -180,6 +183,23 @@ void xc_dom_release_phys(struct xc_dom_i
|
||||
void xc_dom_release(struct xc_dom_image *dom);
|
||||
int xc_dom_mem_init(struct xc_dom_image *dom, unsigned int mem_mb);
|
||||
|
||||
+/* Set this larger if you have enormous ramdisks/kernels. Note that
|
||||
+ * you should trust all kernels not to be maliciously large (e.g. to
|
||||
+ * exhaust all dom0 memory) if you do this (see CVE-2012-4544 /
|
||||
+ * XSA-25). You can also set the default independently for
|
||||
+ * ramdisks/kernels in xc_dom_allocate() or call
|
||||
+ * xc_dom_{kernel,ramdisk}_max_size.
|
||||
+ */
|
||||
+#ifndef XC_DOM_DECOMPRESS_MAX
|
||||
+#define XC_DOM_DECOMPRESS_MAX (1024*1024*1024) /* 1GB */
|
||||
+#endif
|
||||
+
|
||||
+int xc_dom_kernel_check_size(struct xc_dom_image *dom, size_t sz);
|
||||
+int xc_dom_kernel_max_size(struct xc_dom_image *dom, size_t sz);
|
||||
+
|
||||
+int xc_dom_ramdisk_check_size(struct xc_dom_image *dom, size_t sz);
|
||||
+int xc_dom_ramdisk_max_size(struct xc_dom_image *dom, size_t sz);
|
||||
+
|
||||
size_t xc_dom_check_gzip(xc_interface *xch,
|
||||
void *blob, size_t ziplen);
|
||||
int xc_dom_do_gunzip(xc_interface *xch,
|
||||
@@ -240,7 +260,8 @@ void xc_dom_log_memory_footprint(struct
|
||||
void *xc_dom_malloc(struct xc_dom_image *dom, size_t size);
|
||||
void *xc_dom_malloc_page_aligned(struct xc_dom_image *dom, size_t size);
|
||||
void *xc_dom_malloc_filemap(struct xc_dom_image *dom,
|
||||
- const char *filename, size_t * size);
|
||||
+ const char *filename, size_t * size,
|
||||
+ const size_t max_size);
|
||||
char *xc_dom_strdup(struct xc_dom_image *dom, const char *str);
|
||||
|
||||
/* --- alloc memory pool ------------------------------------------- */
|
||||
diff -r 40ccbee890e1 -r 537776f51f79 tools/libxc/xc_dom_bzimageloader.c
|
||||
--- tools/libxc/xc_dom_bzimageloader.c Thu Oct 25 15:36:32 2012 +0200
|
||||
+++ tools/libxc/xc_dom_bzimageloader.c Fri Oct 26 16:10:55 2012 +0100
|
||||
@@ -47,13 +47,19 @@ static int xc_try_bzip2_decode(
|
||||
char *out_buf;
|
||||
char *tmp_buf;
|
||||
int retval = -1;
|
||||
- int outsize;
|
||||
+ unsigned int outsize;
|
||||
uint64_t total;
|
||||
|
||||
stream.bzalloc = NULL;
|
||||
stream.bzfree = NULL;
|
||||
stream.opaque = NULL;
|
||||
|
||||
+ if ( dom->kernel_size == 0)
|
||||
+ {
|
||||
+ DOMPRINTF("BZIP2: Input is 0 size");
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
ret = BZ2_bzDecompressInit(&stream, 0, 0);
|
||||
if ( ret != BZ_OK )
|
||||
{
|
||||
@@ -66,6 +72,17 @@ static int xc_try_bzip2_decode(
|
||||
* the input buffer to start, and we'll realloc as needed.
|
||||
*/
|
||||
outsize = dom->kernel_size;
|
||||
+
|
||||
+ /*
|
||||
+ * stream.avail_in and outsize are unsigned int, while kernel_size
|
||||
+ * is a size_t. Check we aren't overflowing.
|
||||
+ */
|
||||
+ if ( outsize != dom->kernel_size )
|
||||
+ {
|
||||
+ DOMPRINTF("BZIP2: Input too large");
|
||||
+ goto bzip2_cleanup;
|
||||
+ }
|
||||
+
|
||||
out_buf = malloc(outsize);
|
||||
if ( out_buf == NULL )
|
||||
{
|
||||
@@ -98,13 +115,20 @@ static int xc_try_bzip2_decode(
|
||||
if ( stream.avail_out == 0 )
|
||||
{
|
||||
/* Protect against output buffer overflow */
|
||||
- if ( outsize > INT_MAX / 2 )
|
||||
+ if ( outsize > UINT_MAX / 2 )
|
||||
{
|
||||
DOMPRINTF("BZIP2: output buffer overflow");
|
||||
free(out_buf);
|
||||
goto bzip2_cleanup;
|
||||
}
|
||||
|
||||
+ if ( xc_dom_kernel_check_size(dom, outsize * 2) )
|
||||
+ {
|
||||
+ DOMPRINTF("BZIP2: output too large");
|
||||
+ free(out_buf);
|
||||
+ goto bzip2_cleanup;
|
||||
+ }
|
||||
+
|
||||
tmp_buf = realloc(out_buf, outsize * 2);
|
||||
if ( tmp_buf == NULL )
|
||||
{
|
||||
@@ -172,9 +196,15 @@ static int _xc_try_lzma_decode(
|
||||
unsigned char *out_buf;
|
||||
unsigned char *tmp_buf;
|
||||
int retval = -1;
|
||||
- int outsize;
|
||||
+ size_t outsize;
|
||||
const char *msg;
|
||||
|
||||
+ if ( dom->kernel_size == 0)
|
||||
+ {
|
||||
+ DOMPRINTF("%s: Input is 0 size", what);
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
/* sigh. We don't know up-front how much memory we are going to need
|
||||
* for the output buffer. Allocate the output buffer to be equal
|
||||
* the input buffer to start, and we'll realloc as needed.
|
||||
@@ -244,13 +274,20 @@ static int _xc_try_lzma_decode(
|
||||
if ( stream->avail_out == 0 )
|
||||
{
|
||||
/* Protect against output buffer overflow */
|
||||
- if ( outsize > INT_MAX / 2 )
|
||||
+ if ( outsize > SIZE_MAX / 2 )
|
||||
{
|
||||
DOMPRINTF("%s: output buffer overflow", what);
|
||||
free(out_buf);
|
||||
goto lzma_cleanup;
|
||||
}
|
||||
|
||||
+ if ( xc_dom_kernel_check_size(dom, outsize * 2) )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: output too large", what);
|
||||
+ free(out_buf);
|
||||
+ goto lzma_cleanup;
|
||||
+ }
|
||||
+
|
||||
tmp_buf = realloc(out_buf, outsize * 2);
|
||||
if ( tmp_buf == NULL )
|
||||
{
|
||||
@@ -359,6 +396,12 @@ static int xc_try_lzo1x_decode(
|
||||
0x89, 0x4c, 0x5a, 0x4f, 0x00, 0x0d, 0x0a, 0x1a, 0x0a
|
||||
};
|
||||
|
||||
+ /*
|
||||
+ * lzo_uint should match size_t. Check that this is the case to be
|
||||
+ * sure we won't overflow various lzo_uint fields.
|
||||
+ */
|
||||
+ XC_BUILD_BUG_ON(sizeof(lzo_uint) != sizeof(size_t));
|
||||
+
|
||||
ret = lzo_init();
|
||||
if ( ret != LZO_E_OK )
|
||||
{
|
||||
@@ -438,6 +481,14 @@ static int xc_try_lzo1x_decode(
|
||||
if ( src_len <= 0 || src_len > dst_len || src_len > left )
|
||||
break;
|
||||
|
||||
+ msg = "Output buffer overflow";
|
||||
+ if ( *size > SIZE_MAX - dst_len )
|
||||
+ break;
|
||||
+
|
||||
+ msg = "Decompressed image too large";
|
||||
+ if ( xc_dom_kernel_check_size(dom, *size + dst_len) )
|
||||
+ break;
|
||||
+
|
||||
msg = "Failed to (re)alloc memory";
|
||||
tmp_buf = realloc(out_buf, *size + dst_len);
|
||||
if ( tmp_buf == NULL )
|
||||
diff -r 40ccbee890e1 -r 537776f51f79 tools/libxc/xc_dom_core.c
|
||||
--- tools/libxc/xc_dom_core.c Thu Oct 25 15:36:32 2012 +0200
|
||||
+++ tools/libxc/xc_dom_core.c Fri Oct 26 16:10:55 2012 +0100
|
||||
@@ -159,7 +159,8 @@ void *xc_dom_malloc_page_aligned(struct
|
||||
}
|
||||
|
||||
void *xc_dom_malloc_filemap(struct xc_dom_image *dom,
|
||||
- const char *filename, size_t * size)
|
||||
+ const char *filename, size_t * size,
|
||||
+ const size_t max_size)
|
||||
{
|
||||
struct xc_dom_mem *block = NULL;
|
||||
int fd = -1;
|
||||
@@ -171,6 +172,13 @@ void *xc_dom_malloc_filemap(struct xc_do
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
*size = lseek(fd, 0, SEEK_END);
|
||||
|
||||
+ if ( max_size && *size > max_size )
|
||||
+ {
|
||||
+ xc_dom_panic(dom->xch, XC_OUT_OF_MEMORY,
|
||||
+ "tried to map file which is too large");
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
block = malloc(sizeof(*block));
|
||||
if ( block == NULL )
|
||||
goto err;
|
||||
@@ -222,6 +230,40 @@ char *xc_dom_strdup(struct xc_dom_image
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
+/* decompression buffer sizing */
|
||||
+int xc_dom_kernel_check_size(struct xc_dom_image *dom, size_t sz)
|
||||
+{
|
||||
+ /* No limit */
|
||||
+ if ( !dom->max_kernel_size )
|
||||
+ return 0;
|
||||
+
|
||||
+ if ( sz > dom->max_kernel_size )
|
||||
+ {
|
||||
+ xc_dom_panic(dom->xch, XC_INVALID_KERNEL,
|
||||
+ "kernel image too large");
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int xc_dom_ramdisk_check_size(struct xc_dom_image *dom, size_t sz)
|
||||
+{
|
||||
+ /* No limit */
|
||||
+ if ( !dom->max_ramdisk_size )
|
||||
+ return 0;
|
||||
+
|
||||
+ if ( sz > dom->max_ramdisk_size )
|
||||
+ {
|
||||
+ xc_dom_panic(dom->xch, XC_INVALID_KERNEL,
|
||||
+ "ramdisk image too large");
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/* ------------------------------------------------------------------------ */
|
||||
/* read files, copy memory blocks, with transparent gunzip */
|
||||
|
||||
size_t xc_dom_check_gzip(xc_interface *xch, void *blob, size_t ziplen)
|
||||
@@ -235,7 +277,7 @@ size_t xc_dom_check_gzip(xc_interface *x
|
||||
|
||||
gzlen = blob + ziplen - 4;
|
||||
unziplen = gzlen[3] << 24 | gzlen[2] << 16 | gzlen[1] << 8 | gzlen[0];
|
||||
- if ( (unziplen < 0) || (unziplen > (1024*1024*1024)) ) /* 1GB limit */
|
||||
+ if ( (unziplen < 0) || (unziplen > XC_DOM_DECOMPRESS_MAX) )
|
||||
{
|
||||
xc_dom_printf
|
||||
(xch,
|
||||
@@ -288,6 +330,9 @@ int xc_dom_try_gunzip(struct xc_dom_imag
|
||||
if ( unziplen == 0 )
|
||||
return 0;
|
||||
|
||||
+ if ( xc_dom_kernel_check_size(dom, unziplen) )
|
||||
+ return 0;
|
||||
+
|
||||
unzip = xc_dom_malloc(dom, unziplen);
|
||||
if ( unzip == NULL )
|
||||
return -1;
|
||||
@@ -588,6 +633,9 @@ struct xc_dom_image *xc_dom_allocate(xc_
|
||||
memset(dom, 0, sizeof(*dom));
|
||||
dom->xch = xch;
|
||||
|
||||
+ dom->max_kernel_size = XC_DOM_DECOMPRESS_MAX;
|
||||
+ dom->max_ramdisk_size = XC_DOM_DECOMPRESS_MAX;
|
||||
+
|
||||
if ( cmdline )
|
||||
dom->cmdline = xc_dom_strdup(dom, cmdline);
|
||||
if ( features )
|
||||
@@ -608,10 +656,25 @@ struct xc_dom_image *xc_dom_allocate(xc_
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+int xc_dom_kernel_max_size(struct xc_dom_image *dom, size_t sz)
|
||||
+{
|
||||
+ DOMPRINTF("%s: kernel_max_size=%zx", __FUNCTION__, sz);
|
||||
+ dom->max_kernel_size = sz;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int xc_dom_ramdisk_max_size(struct xc_dom_image *dom, size_t sz)
|
||||
+{
|
||||
+ DOMPRINTF("%s: ramdisk_max_size=%zx", __FUNCTION__, sz);
|
||||
+ dom->max_ramdisk_size = sz;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
int xc_dom_kernel_file(struct xc_dom_image *dom, const char *filename)
|
||||
{
|
||||
DOMPRINTF("%s: filename=\"%s\"", __FUNCTION__, filename);
|
||||
- dom->kernel_blob = xc_dom_malloc_filemap(dom, filename, &dom->kernel_size);
|
||||
+ dom->kernel_blob = xc_dom_malloc_filemap(dom, filename, &dom->kernel_size,
|
||||
+ dom->max_kernel_size);
|
||||
if ( dom->kernel_blob == NULL )
|
||||
return -1;
|
||||
return xc_dom_try_gunzip(dom, &dom->kernel_blob, &dom->kernel_size);
|
||||
@@ -621,7 +684,9 @@ int xc_dom_ramdisk_file(struct xc_dom_im
|
||||
{
|
||||
DOMPRINTF("%s: filename=\"%s\"", __FUNCTION__, filename);
|
||||
dom->ramdisk_blob =
|
||||
- xc_dom_malloc_filemap(dom, filename, &dom->ramdisk_size);
|
||||
+ xc_dom_malloc_filemap(dom, filename, &dom->ramdisk_size,
|
||||
+ dom->max_ramdisk_size);
|
||||
+
|
||||
if ( dom->ramdisk_blob == NULL )
|
||||
return -1;
|
||||
// return xc_dom_try_gunzip(dom, &dom->ramdisk_blob, &dom->ramdisk_size);
|
||||
@@ -781,7 +846,11 @@ int xc_dom_build_image(struct xc_dom_ima
|
||||
void *ramdiskmap;
|
||||
|
||||
unziplen = xc_dom_check_gzip(dom->xch, dom->ramdisk_blob, dom->ramdisk_size);
|
||||
+ if ( xc_dom_ramdisk_check_size(dom, unziplen) != 0 )
|
||||
+ unziplen = 0;
|
||||
+
|
||||
ramdisklen = unziplen ? unziplen : dom->ramdisk_size;
|
||||
+
|
||||
if ( xc_dom_alloc_segment(dom, &dom->ramdisk_seg, "ramdisk", 0,
|
||||
ramdisklen) != 0 )
|
||||
goto err;
|
||||
|
||||
|
@ -0,0 +1,417 @@
|
||||
From 9737484becab4a25159f1e985700eaee89690d34 Mon Sep 17 00:00:00 2001
|
||||
From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Date: Fri, 14 Jun 2013 16:43:15 +0100
|
||||
Subject: [PATCH 01/23] libelf: abolish libelf-relocate.c
|
||||
|
||||
This file is not actually used. It's not built in Xen's instance of
|
||||
libelf; in libxc's it's built but nothing in it is called. Do not
|
||||
compile it in libxc, and delete it.
|
||||
|
||||
This reduces the amount of work we need to do in forthcoming patches
|
||||
to libelf (particularly since as libelf-relocate.c is not used it is
|
||||
probably full of bugs).
|
||||
|
||||
This is part of the fix to a security issue, XSA-55.
|
||||
|
||||
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
---
|
||||
tools/libxc/Makefile | 2 +-
|
||||
xen/common/libelf/libelf-relocate.c | 372 -----------------------------------
|
||||
2 files changed, 1 insertions(+), 373 deletions(-)
|
||||
delete mode 100644 xen/common/libelf/libelf-relocate.c
|
||||
|
||||
diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile
|
||||
index ca38cbd..d8c6a60 100644
|
||||
--- a/tools/libxc/Makefile
|
||||
+++ b/tools/libxc/Makefile
|
||||
@@ -53,7 +53,7 @@ vpath %.c ../../xen/common/libelf
|
||||
CFLAGS += -I../../xen/common/libelf
|
||||
|
||||
GUEST_SRCS-y += libelf-tools.c libelf-loader.c
|
||||
-GUEST_SRCS-y += libelf-dominfo.c libelf-relocate.c
|
||||
+GUEST_SRCS-y += libelf-dominfo.c
|
||||
|
||||
# new domain builder
|
||||
GUEST_SRCS-y += xc_dom_core.c xc_dom_boot.c
|
||||
diff --git a/xen/common/libelf/libelf-relocate.c b/xen/common/libelf/libelf-relocate.c
|
||||
#deleted file mode 100644
|
||||
index 7ef4b01..0000000
|
||||
--- a/xen/common/libelf/libelf-relocate.c
|
||||
+++ /dev/null
|
||||
@@ -1,372 +0,0 @@
|
||||
-/*
|
||||
- * ELF relocation code (not used by xen kernel right now).
|
||||
- *
|
||||
- * This 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;
|
||||
- * version 2.1 of the License.
|
||||
- *
|
||||
- * This 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 this library; if not, write to the Free Software
|
||||
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
- */
|
||||
-
|
||||
-#include "libelf-private.h"
|
||||
-
|
||||
-/* ------------------------------------------------------------------------ */
|
||||
-
|
||||
-static const char *rel_names_i386[] = {
|
||||
- "R_386_NONE",
|
||||
- "R_386_32",
|
||||
- "R_386_PC32",
|
||||
- "R_386_GOT32",
|
||||
- "R_386_PLT32",
|
||||
- "R_386_COPY",
|
||||
- "R_386_GLOB_DAT",
|
||||
- "R_386_JMP_SLOT",
|
||||
- "R_386_RELATIVE",
|
||||
- "R_386_GOTOFF",
|
||||
- "R_386_GOTPC",
|
||||
- "R_386_32PLT",
|
||||
- "R_386_TLS_TPOFF",
|
||||
- "R_386_TLS_IE",
|
||||
- "R_386_TLS_GOTIE",
|
||||
- "R_386_TLS_LE",
|
||||
- "R_386_TLS_GD",
|
||||
- "R_386_TLS_LDM",
|
||||
- "R_386_16",
|
||||
- "R_386_PC16",
|
||||
- "R_386_8",
|
||||
- "R_386_PC8",
|
||||
- "R_386_TLS_GD_32",
|
||||
- "R_386_TLS_GD_PUSH",
|
||||
- "R_386_TLS_GD_CALL",
|
||||
- "R_386_TLS_GD_POP",
|
||||
- "R_386_TLS_LDM_32",
|
||||
- "R_386_TLS_LDM_PUSH",
|
||||
- "R_386_TLS_LDM_CALL",
|
||||
- "R_386_TLS_LDM_POP",
|
||||
- "R_386_TLS_LDO_32",
|
||||
- "R_386_TLS_IE_32",
|
||||
- "R_386_TLS_LE_32",
|
||||
- "R_386_TLS_DTPMOD32",
|
||||
- "R_386_TLS_DTPOFF32",
|
||||
- "R_386_TLS_TPOFF32",
|
||||
-};
|
||||
-
|
||||
-static int elf_reloc_i386(struct elf_binary *elf, int type,
|
||||
- uint64_t addr, uint64_t value)
|
||||
-{
|
||||
- void *ptr = elf_get_ptr(elf, addr);
|
||||
- uint32_t *u32;
|
||||
-
|
||||
- switch ( type )
|
||||
- {
|
||||
- case 1 /* R_386_32 */ :
|
||||
- u32 = ptr;
|
||||
- *u32 += elf->reloc_offset;
|
||||
- break;
|
||||
- case 2 /* R_386_PC32 */ :
|
||||
- /* nothing */
|
||||
- break;
|
||||
- default:
|
||||
- return -1;
|
||||
- }
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-/* ------------------------------------------------------------------------ */
|
||||
-
|
||||
-static const char *rel_names_x86_64[] = {
|
||||
- "R_X86_64_NONE",
|
||||
- "R_X86_64_64",
|
||||
- "R_X86_64_PC32",
|
||||
- "R_X86_64_GOT32",
|
||||
- "R_X86_64_PLT32",
|
||||
- "R_X86_64_COPY",
|
||||
- "R_X86_64_GLOB_DAT",
|
||||
- "R_X86_64_JUMP_SLOT",
|
||||
- "R_X86_64_RELATIVE",
|
||||
- "R_X86_64_GOTPCREL",
|
||||
- "R_X86_64_32",
|
||||
- "R_X86_64_32S",
|
||||
- "R_X86_64_16",
|
||||
- "R_X86_64_PC16",
|
||||
- "R_X86_64_8",
|
||||
- "R_X86_64_PC8",
|
||||
- "R_X86_64_DTPMOD64",
|
||||
- "R_X86_64_DTPOFF64",
|
||||
- "R_X86_64_TPOFF64",
|
||||
- "R_X86_64_TLSGD",
|
||||
- "R_X86_64_TLSLD",
|
||||
- "R_X86_64_DTPOFF32",
|
||||
- "R_X86_64_GOTTPOFF",
|
||||
- "R_X86_64_TPOFF32",
|
||||
-};
|
||||
-
|
||||
-static int elf_reloc_x86_64(struct elf_binary *elf, int type,
|
||||
- uint64_t addr, uint64_t value)
|
||||
-{
|
||||
- void *ptr = elf_get_ptr(elf, addr);
|
||||
- uint64_t *u64;
|
||||
- uint32_t *u32;
|
||||
- int32_t *s32;
|
||||
-
|
||||
- switch ( type )
|
||||
- {
|
||||
- case 1 /* R_X86_64_64 */ :
|
||||
- u64 = ptr;
|
||||
- value += elf->reloc_offset;
|
||||
- *u64 = value;
|
||||
- break;
|
||||
- case 2 /* R_X86_64_PC32 */ :
|
||||
- u32 = ptr;
|
||||
- *u32 = value - addr;
|
||||
- if ( *u32 != (uint32_t)(value - addr) )
|
||||
- {
|
||||
- elf_err(elf, "R_X86_64_PC32 overflow: 0x%" PRIx32
|
||||
- " != 0x%" PRIx32 "\n",
|
||||
- *u32, (uint32_t) (value - addr));
|
||||
- return -1;
|
||||
- }
|
||||
- break;
|
||||
- case 10 /* R_X86_64_32 */ :
|
||||
- u32 = ptr;
|
||||
- value += elf->reloc_offset;
|
||||
- *u32 = value;
|
||||
- if ( *u32 != value )
|
||||
- {
|
||||
- elf_err(elf, "R_X86_64_32 overflow: 0x%" PRIx32
|
||||
- " != 0x%" PRIx64 "\n",
|
||||
- *u32, value);
|
||||
- return -1;
|
||||
- }
|
||||
- break;
|
||||
- case 11 /* R_X86_64_32S */ :
|
||||
- s32 = ptr;
|
||||
- value += elf->reloc_offset;
|
||||
- *s32 = value;
|
||||
- if ( *s32 != (int64_t) value )
|
||||
- {
|
||||
- elf_err(elf, "R_X86_64_32S overflow: 0x%" PRIx32
|
||||
- " != 0x%" PRIx64 "\n",
|
||||
- *s32, (int64_t) value);
|
||||
- return -1;
|
||||
- }
|
||||
- break;
|
||||
- default:
|
||||
- return -1;
|
||||
- }
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-/* ------------------------------------------------------------------------ */
|
||||
-
|
||||
-static struct relocs {
|
||||
- const char **names;
|
||||
- int count;
|
||||
- int (*func) (struct elf_binary * elf, int type, uint64_t addr,
|
||||
- uint64_t value);
|
||||
-} relocs[] =
|
||||
-/* *INDENT-OFF* */
|
||||
-{
|
||||
- [EM_386] = {
|
||||
- .names = rel_names_i386,
|
||||
- .count = sizeof(rel_names_i386) / sizeof(rel_names_i386[0]),
|
||||
- .func = elf_reloc_i386,
|
||||
- },
|
||||
- [EM_X86_64] = {
|
||||
- .names = rel_names_x86_64,
|
||||
- .count = sizeof(rel_names_x86_64) / sizeof(rel_names_x86_64[0]),
|
||||
- .func = elf_reloc_x86_64,
|
||||
- }
|
||||
-};
|
||||
-/* *INDENT-ON* */
|
||||
-
|
||||
-/* ------------------------------------------------------------------------ */
|
||||
-
|
||||
-static const char *rela_name(int machine, int type)
|
||||
-{
|
||||
- if ( machine > sizeof(relocs) / sizeof(relocs[0]) )
|
||||
- return "unknown mach";
|
||||
- if ( !relocs[machine].names )
|
||||
- return "unknown mach";
|
||||
- if ( type > relocs[machine].count )
|
||||
- return "unknown rela";
|
||||
- return relocs[machine].names[type];
|
||||
-}
|
||||
-
|
||||
-static int elf_reloc_section(struct elf_binary *elf,
|
||||
- const elf_shdr * rels,
|
||||
- const elf_shdr * sect, const elf_shdr * syms)
|
||||
-{
|
||||
- const void *ptr, *end;
|
||||
- const elf_shdr *shdr;
|
||||
- const elf_rela *rela;
|
||||
- const elf_rel *rel;
|
||||
- const elf_sym *sym;
|
||||
- uint64_t s_type;
|
||||
- uint64_t r_offset;
|
||||
- uint64_t r_info;
|
||||
- uint64_t r_addend;
|
||||
- int r_type, r_sym;
|
||||
- size_t rsize;
|
||||
- uint64_t shndx, sbase, addr, value;
|
||||
- const char *sname;
|
||||
- int machine;
|
||||
-
|
||||
- machine = elf_uval(elf, elf->ehdr, e_machine);
|
||||
- if ( (machine >= (sizeof(relocs) / sizeof(relocs[0]))) ||
|
||||
- (relocs[machine].func == NULL) )
|
||||
- {
|
||||
- elf_err(elf, "%s: can't handle machine %d\n",
|
||||
- __FUNCTION__, machine);
|
||||
- return -1;
|
||||
- }
|
||||
- if ( elf_swap(elf) )
|
||||
- {
|
||||
- elf_err(elf, "%s: non-native byte order, relocation not supported\n",
|
||||
- __FUNCTION__);
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
- s_type = elf_uval(elf, rels, sh_type);
|
||||
- rsize = (SHT_REL == s_type) ? elf_size(elf, rel) : elf_size(elf, rela);
|
||||
- ptr = elf_section_start(elf, rels);
|
||||
- end = elf_section_end(elf, rels);
|
||||
-
|
||||
- for ( ; ptr < end; ptr += rsize )
|
||||
- {
|
||||
- switch ( s_type )
|
||||
- {
|
||||
- case SHT_REL:
|
||||
- rel = ptr;
|
||||
- r_offset = elf_uval(elf, rel, r_offset);
|
||||
- r_info = elf_uval(elf, rel, r_info);
|
||||
- r_addend = 0;
|
||||
- break;
|
||||
- case SHT_RELA:
|
||||
- rela = ptr;
|
||||
- r_offset = elf_uval(elf, rela, r_offset);
|
||||
- r_info = elf_uval(elf, rela, r_info);
|
||||
- r_addend = elf_uval(elf, rela, r_addend);
|
||||
- break;
|
||||
- default:
|
||||
- /* can't happen */
|
||||
- return -1;
|
||||
- }
|
||||
- if ( elf_64bit(elf) )
|
||||
- {
|
||||
- r_type = ELF64_R_TYPE(r_info);
|
||||
- r_sym = ELF64_R_SYM(r_info);
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- r_type = ELF32_R_TYPE(r_info);
|
||||
- r_sym = ELF32_R_SYM(r_info);
|
||||
- }
|
||||
-
|
||||
- sym = elf_sym_by_index(elf, r_sym);
|
||||
- shndx = elf_uval(elf, sym, st_shndx);
|
||||
- switch ( shndx )
|
||||
- {
|
||||
- case SHN_UNDEF:
|
||||
- sname = "*UNDEF*";
|
||||
- sbase = 0;
|
||||
- break;
|
||||
- case SHN_COMMON:
|
||||
- elf_err(elf, "%s: invalid section: %" PRId64 "\n",
|
||||
- __FUNCTION__, shndx);
|
||||
- return -1;
|
||||
- case SHN_ABS:
|
||||
- sname = "*ABS*";
|
||||
- sbase = 0;
|
||||
- break;
|
||||
- default:
|
||||
- shdr = elf_shdr_by_index(elf, shndx);
|
||||
- if ( shdr == NULL )
|
||||
- {
|
||||
- elf_err(elf, "%s: invalid section: %" PRId64 "\n",
|
||||
- __FUNCTION__, shndx);
|
||||
- return -1;
|
||||
- }
|
||||
- sname = elf_section_name(elf, shdr);
|
||||
- sbase = elf_uval(elf, shdr, sh_addr);
|
||||
- }
|
||||
-
|
||||
- addr = r_offset;
|
||||
- value = elf_uval(elf, sym, st_value);
|
||||
- value += r_addend;
|
||||
-
|
||||
- if ( elf->log_callback && (elf->verbose > 1) )
|
||||
- {
|
||||
- uint64_t st_name = elf_uval(elf, sym, st_name);
|
||||
- const char *name = st_name ? elf->sym_strtab + st_name : "*NONE*";
|
||||
-
|
||||
- elf_msg(elf,
|
||||
- "%s: type %s [%d], off 0x%" PRIx64 ", add 0x%" PRIx64 ","
|
||||
- " sym %s [0x%" PRIx64 "], sec %s [0x%" PRIx64 "]"
|
||||
- " -> addr 0x%" PRIx64 " value 0x%" PRIx64 "\n",
|
||||
- __FUNCTION__, rela_name(machine, r_type), r_type, r_offset,
|
||||
- r_addend, name, elf_uval(elf, sym, st_value), sname, sbase,
|
||||
- addr, value);
|
||||
- }
|
||||
-
|
||||
- if ( relocs[machine].func(elf, r_type, addr, value) == -1 )
|
||||
- {
|
||||
- elf_err(elf, "%s: unknown/unsupported reloc type %s [%d]\n",
|
||||
- __FUNCTION__, rela_name(machine, r_type), r_type);
|
||||
- return -1;
|
||||
- }
|
||||
- }
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-int elf_reloc(struct elf_binary *elf)
|
||||
-{
|
||||
- const elf_shdr *rels, *sect, *syms;
|
||||
- uint64_t i, count, type;
|
||||
-
|
||||
- count = elf_shdr_count(elf);
|
||||
- for ( i = 0; i < count; i++ )
|
||||
- {
|
||||
- rels = elf_shdr_by_index(elf, i);
|
||||
- type = elf_uval(elf, rels, sh_type);
|
||||
- if ( (type != SHT_REL) && (type != SHT_RELA) )
|
||||
- continue;
|
||||
-
|
||||
- sect = elf_shdr_by_index(elf, elf_uval(elf, rels, sh_info));
|
||||
- syms = elf_shdr_by_index(elf, elf_uval(elf, rels, sh_link));
|
||||
- if ( NULL == sect || NULL == syms )
|
||||
- continue;
|
||||
-
|
||||
- if ( !(elf_uval(elf, sect, sh_flags) & SHF_ALLOC) )
|
||||
- {
|
||||
- elf_msg(elf, "%s: relocations for %s, skipping\n",
|
||||
- __FUNCTION__, elf_section_name(elf, sect));
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- elf_msg(elf, "%s: relocations for %s @ 0x%" PRIx64 "\n",
|
||||
- __FUNCTION__, elf_section_name(elf, sect),
|
||||
- elf_uval(elf, sect, sh_addr));
|
||||
- if ( elf_reloc_section(elf, rels, sect, syms) != 0 )
|
||||
- return -1;
|
||||
- }
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-/*
|
||||
- * Local variables:
|
||||
- * mode: C
|
||||
- * c-set-style: "BSD"
|
||||
- * c-basic-offset: 4
|
||||
- * tab-width: 4
|
||||
- * indent-tabs-mode: nil
|
||||
- * End:
|
||||
- */
|
||||
--
|
||||
#1.7.2.5
|
||||
|
@ -0,0 +1,788 @@
|
||||
From cc8761371aac432318530c2ddfe2c8234bc0621f Mon Sep 17 00:00:00 2001
|
||||
From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Date: Fri, 14 Jun 2013 16:43:17 +0100
|
||||
Subject: [PATCH 11/23] libelf: check all pointer accesses
|
||||
|
||||
We change the ELF_PTRVAL and ELF_HANDLE types and associated macros:
|
||||
|
||||
* PTRVAL becomes a uintptr_t, for which we provide a typedef
|
||||
elf_ptrval. This means no arithmetic done on it can overflow so
|
||||
the compiler cannot do any malicious invalid pointer arithmetic
|
||||
"optimisations". It also means that any places where we
|
||||
dereference one of these pointers without using the appropriate
|
||||
macros or functions become a compilation error.
|
||||
|
||||
So we can be sure that we won't miss any memory accesses.
|
||||
|
||||
All the PTRVAL variables were previously void* or char*, so
|
||||
the actual address calculations are unchanged.
|
||||
|
||||
* ELF_HANDLE becomes a union, one half of which keeps the pointer
|
||||
value and the other half of which is just there to record the
|
||||
type.
|
||||
|
||||
The new type is not a pointer type so there can be no address
|
||||
calculations on it whose meaning would change. Every assignment or
|
||||
access has to go through one of our macros.
|
||||
|
||||
* The distinction between const and non-const pointers and char*s
|
||||
and void*s in libelf goes away. This was not important (and
|
||||
anyway libelf tended to cast away const in various places).
|
||||
|
||||
* The fields elf->image and elf->dest are renamed. That proves
|
||||
that we haven't missed any unchecked uses of these actual
|
||||
pointer values.
|
||||
|
||||
* The caller may fill in elf->caller_xdest_base and _size to
|
||||
specify another range of memory which is safe for libelf to
|
||||
access, besides the input and output images.
|
||||
|
||||
* When accesses fail due to being out of range, we mark the elf
|
||||
"broken". This will be checked and used for diagnostics in
|
||||
a following patch.
|
||||
|
||||
We do not check for write accesses to the input image. This is
|
||||
because libelf actually does this in a number of places. So we
|
||||
simply permit that.
|
||||
|
||||
* Each caller of libelf which used to set dest now sets
|
||||
dest_base and dest_size.
|
||||
|
||||
* In xc_dom_load_elf_symtab we provide a new actual-pointer
|
||||
value hdr_ptr which we get from mapping the guest's kernel
|
||||
area and use (checking carefully) as the caller_xdest area.
|
||||
|
||||
* The STAR(h) macro in libelf-dominfo.c now uses elf_access_unsigned.
|
||||
|
||||
* elf-init uses the new elf_uval_3264 accessor to access the 32-bit
|
||||
fields, rather than an unchecked field access (ie, unchecked
|
||||
pointer access).
|
||||
|
||||
* elf_uval has been reworked to use elf_uval_3264. Both of these
|
||||
macros are essentially new in this patch (although they are derived
|
||||
from the old elf_uval) and need careful review.
|
||||
|
||||
* ELF_ADVANCE_DEST is now safe in the sense that you can use it to
|
||||
chop parts off the front of the dest area but if you chop more than
|
||||
is available, the dest area is simply set to be empty, preventing
|
||||
future accesses.
|
||||
|
||||
* We introduce some #defines for memcpy, memset, memmove and strcpy:
|
||||
- We provide elf_memcpy_safe and elf_memset_safe which take
|
||||
PTRVALs and do checking on the supplied pointers.
|
||||
- Users inside libelf must all be changed to either
|
||||
elf_mem*_unchecked (which are just like mem*), or
|
||||
elf_mem*_safe (which take PTRVALs) and are checked. Any
|
||||
unchanged call sites become compilation errors.
|
||||
|
||||
* We do _not_ at this time fix elf_access_unsigned so that it doesn't
|
||||
make unaligned accesses. We hope that unaligned accesses are OK on
|
||||
every supported architecture. But it does check the supplied
|
||||
pointer for validity.
|
||||
|
||||
This is part of the fix to a security issue, XSA-55.
|
||||
|
||||
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
---
|
||||
tools/libxc/xc_dom_elfloader.c | 49 ++++++++--
|
||||
tools/libxc/xc_hvm_build_x86.c | 10 +-
|
||||
xen/arch/x86/domain_build.c | 3 +-
|
||||
xen/common/libelf/libelf-dominfo.c | 2 +-
|
||||
xen/common/libelf/libelf-loader.c | 16 ++--
|
||||
xen/common/libelf/libelf-private.h | 13 +++
|
||||
xen/common/libelf/libelf-tools.c | 106 ++++++++++++++++++-
|
||||
xen/include/xen/libelf.h | 198 +++++++++++++++++++++++++-----------
|
||||
8 files changed, 312 insertions(+), 85 deletions(-)
|
||||
|
||||
diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c
|
||||
index cc0f206..b82a08c 100644
|
||||
--- a/tools/libxc/xc_dom_elfloader.c
|
||||
+++ b/tools/libxc/xc_dom_elfloader.c
|
||||
@@ -130,20 +130,30 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
|
||||
if ( load )
|
||||
{
|
||||
- size_t allow_size; /* will be used in a forthcoming XSA-55 patch */
|
||||
+ char *hdr_ptr;
|
||||
+ size_t allow_size;
|
||||
+
|
||||
if ( !dom->bsd_symtab_start )
|
||||
return 0;
|
||||
size = dom->kernel_seg.vend - dom->bsd_symtab_start;
|
||||
- hdr = xc_dom_vaddr_to_ptr(dom, dom->bsd_symtab_start, &allow_size);
|
||||
- *(int *)hdr = size - sizeof(int);
|
||||
+ hdr_ptr = xc_dom_vaddr_to_ptr(dom, dom->bsd_symtab_start, &allow_size);
|
||||
+ elf->caller_xdest_base = hdr_ptr;
|
||||
+ elf->caller_xdest_size = allow_size;
|
||||
+ hdr = ELF_REALPTR2PTRVAL(hdr_ptr);
|
||||
+ elf_store_val(elf, int, hdr, size - sizeof(int));
|
||||
}
|
||||
else
|
||||
{
|
||||
+ char *hdr_ptr;
|
||||
+
|
||||
size = sizeof(int) + elf_size(elf, elf->ehdr) +
|
||||
elf_shdr_count(elf) * elf_size(elf, shdr);
|
||||
- hdr = xc_dom_malloc(dom, size);
|
||||
- if ( hdr == NULL )
|
||||
+ hdr_ptr = xc_dom_malloc(dom, size);
|
||||
+ if ( hdr_ptr == NULL )
|
||||
return 0;
|
||||
+ elf->caller_xdest_base = hdr_ptr;
|
||||
+ elf->caller_xdest_size = size;
|
||||
+ hdr = ELF_REALPTR2PTRVAL(hdr_ptr);
|
||||
dom->bsd_symtab_start = elf_round_up(elf, dom->kernel_seg.vend);
|
||||
}
|
||||
|
||||
@@ -171,9 +181,32 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
ehdr->e_shoff = elf_size(elf, elf->ehdr);
|
||||
ehdr->e_shstrndx = SHN_UNDEF;
|
||||
}
|
||||
- if ( elf_init(&syms, hdr + sizeof(int), size - sizeof(int)) )
|
||||
+ if ( elf->caller_xdest_size < sizeof(int) )
|
||||
+ {
|
||||
+ DOMPRINTF("%s/%s: header size %"PRIx64" too small",
|
||||
+ __FUNCTION__, load ? "load" : "parse",
|
||||
+ (uint64_t)elf->caller_xdest_size);
|
||||
+ return -1;
|
||||
+ }
|
||||
+ if ( elf_init(&syms, elf->caller_xdest_base + sizeof(int),
|
||||
+ elf->caller_xdest_size - sizeof(int)) )
|
||||
return -1;
|
||||
|
||||
+ /*
|
||||
+ * The caller_xdest_{base,size} and dest_{base,size} need to
|
||||
+ * remain valid so long as each struct elf_image does. The
|
||||
+ * principle we adopt is that these values are set when the
|
||||
+ * memory is allocated or mapped, and cleared when (and if)
|
||||
+ * they are unmapped.
|
||||
+ *
|
||||
+ * Mappings of the guest are normally undone by xc_dom_unmap_all
|
||||
+ * (directly or via xc_dom_release). We do not explicitly clear
|
||||
+ * these because in fact that happens only at the end of
|
||||
+ * xc_dom_boot_image, at which time all of these ELF loading
|
||||
+ * functions have returned. No relevant struct elf_binary*
|
||||
+ * escapes this file.
|
||||
+ */
|
||||
+
|
||||
xc_elf_set_logfile(dom->xch, &syms, 1);
|
||||
|
||||
symtab = dom->bsd_symtab_start + sizeof(int);
|
||||
@@ -312,8 +345,10 @@ static int xc_dom_load_elf_kernel(struct xc_dom_image *dom)
|
||||
{
|
||||
struct elf_binary *elf = dom->private_loader;
|
||||
int rc;
|
||||
+ xen_pfn_t pages;
|
||||
|
||||
- elf->dest = xc_dom_seg_to_ptr(dom, &dom->kernel_seg);
|
||||
+ elf->dest_base = xc_dom_seg_to_ptr_pages(dom, &dom->kernel_seg, &pages);
|
||||
+ elf->dest_size = pages * XC_DOM_PAGE_SIZE(dom);
|
||||
rc = elf_load_binary(elf);
|
||||
if ( rc < 0 )
|
||||
{
|
||||
diff --git a/tools/libxc/xc_hvm_build_x86.c b/tools/libxc/xc_hvm_build_x86.c
|
||||
index 15b603d..ccfd8b5 100644
|
||||
--- a/tools/libxc/xc_hvm_build_x86.c
|
||||
+++ b/tools/libxc/xc_hvm_build_x86.c
|
||||
@@ -104,11 +104,12 @@ static int loadelfimage(
|
||||
for ( i = 0; i < pages; i++ )
|
||||
entries[i].mfn = parray[(elf->pstart >> PAGE_SHIFT) + i];
|
||||
|
||||
- elf->dest = xc_map_foreign_ranges(
|
||||
+ elf->dest_base = xc_map_foreign_ranges(
|
||||
xch, dom, pages << PAGE_SHIFT, PROT_READ | PROT_WRITE, 1 << PAGE_SHIFT,
|
||||
entries, pages);
|
||||
- if ( elf->dest == NULL )
|
||||
+ if ( elf->dest_base == NULL )
|
||||
goto err;
|
||||
+ elf->dest_size = pages * PAGE_SIZE;
|
||||
|
||||
ELF_ADVANCE_DEST(elf, elf->pstart & (PAGE_SIZE - 1));
|
||||
|
||||
@@ -117,8 +118,9 @@ static int loadelfimage(
|
||||
if ( rc < 0 )
|
||||
PERROR("Failed to load elf binary\n");
|
||||
|
||||
- munmap(elf->dest, pages << PAGE_SHIFT);
|
||||
- elf->dest = NULL;
|
||||
+ munmap(elf->dest_base, pages << PAGE_SHIFT);
|
||||
+ elf->dest_base = NULL;
|
||||
+ elf->dest_size = 0;
|
||||
|
||||
err:
|
||||
free(entries);
|
||||
diff --git a/xen/arch/x86/domain_build.c b/xen/arch/x86/domain_build.c
|
||||
index 469d363..a655b21 100644
|
||||
--- a/xen/arch/x86/domain_build.c
|
||||
+++ b/xen/arch/x86/domain_build.c
|
||||
@@ -908,7 +908,8 @@ int __init construct_dom0(
|
||||
write_ptbase(v);
|
||||
|
||||
/* Copy the OS image and free temporary buffer. */
|
||||
- elf.dest = (void*)vkern_start;
|
||||
+ elf.dest_base = (void*)vkern_start;
|
||||
+ elf.dest_size = vkern_end - vkern_start;
|
||||
rc = elf_load_binary(&elf);
|
||||
if ( rc < 0 )
|
||||
{
|
||||
diff --git a/xen/common/libelf/libelf-dominfo.c b/xen/common/libelf/libelf-dominfo.c
|
||||
index b217f8f..98c80dc 100644
|
||||
--- a/xen/common/libelf/libelf-dominfo.c
|
||||
+++ b/xen/common/libelf/libelf-dominfo.c
|
||||
@@ -254,7 +254,7 @@ int elf_xen_parse_guest_info(struct elf_binary *elf,
|
||||
int len;
|
||||
|
||||
h = parms->guest_info;
|
||||
-#define STAR(h) (*(h))
|
||||
+#define STAR(h) (elf_access_unsigned(elf, (h), 0, 1))
|
||||
while ( STAR(h) )
|
||||
{
|
||||
elf_memset_unchecked(name, 0, sizeof(name));
|
||||
diff --git a/xen/common/libelf/libelf-loader.c b/xen/common/libelf/libelf-loader.c
|
||||
index 0fef84c..a3310e7 100644
|
||||
--- a/xen/common/libelf/libelf-loader.c
|
||||
+++ b/xen/common/libelf/libelf-loader.c
|
||||
@@ -24,23 +24,25 @@
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
-int elf_init(struct elf_binary *elf, const char *image, size_t size)
|
||||
+int elf_init(struct elf_binary *elf, const char *image_input, size_t size)
|
||||
{
|
||||
ELF_HANDLE_DECL(elf_shdr) shdr;
|
||||
uint64_t i, count, section, offset;
|
||||
|
||||
- if ( !elf_is_elfbinary(image) )
|
||||
+ if ( !elf_is_elfbinary(image_input) )
|
||||
{
|
||||
elf_err(elf, "%s: not an ELF binary\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
elf_memset_unchecked(elf, 0, sizeof(*elf));
|
||||
- elf->image = image;
|
||||
+ elf->image_base = image_input;
|
||||
elf->size = size;
|
||||
- elf->ehdr = (elf_ehdr *)image;
|
||||
- elf->class = elf->ehdr->e32.e_ident[EI_CLASS];
|
||||
- elf->data = elf->ehdr->e32.e_ident[EI_DATA];
|
||||
+ elf->ehdr = ELF_MAKE_HANDLE(elf_ehdr, (elf_ptrval)image_input);
|
||||
+ elf->class = elf_uval_3264(elf, elf->ehdr, e32.e_ident[EI_CLASS]);
|
||||
+ elf->data = elf_uval_3264(elf, elf->ehdr, e32.e_ident[EI_DATA]);
|
||||
+ elf->caller_xdest_base = NULL;
|
||||
+ elf->caller_xdest_size = 0;
|
||||
|
||||
/* Sanity check phdr. */
|
||||
offset = elf_uval(elf, elf->ehdr, e_phoff) +
|
||||
@@ -300,7 +302,7 @@ int elf_load_binary(struct elf_binary *elf)
|
||||
|
||||
ELF_PTRVAL_VOID elf_get_ptr(struct elf_binary *elf, unsigned long addr)
|
||||
{
|
||||
- return elf->dest + addr - elf->pstart;
|
||||
+ return ELF_REALPTR2PTRVAL(elf->dest_base) + addr - elf->pstart;
|
||||
}
|
||||
|
||||
uint64_t elf_lookup_addr(struct elf_binary * elf, const char *symbol)
|
||||
diff --git a/xen/common/libelf/libelf-private.h b/xen/common/libelf/libelf-private.h
|
||||
index 3ef753c..280dfd1 100644
|
||||
--- a/xen/common/libelf/libelf-private.h
|
||||
+++ b/xen/common/libelf/libelf-private.h
|
||||
@@ -86,6 +86,19 @@ do { strncpy((d),(s),sizeof((d))-1); \
|
||||
|
||||
#endif
|
||||
|
||||
+#undef memcpy
|
||||
+#undef memset
|
||||
+#undef memmove
|
||||
+#undef strcpy
|
||||
+
|
||||
+#define memcpy MISTAKE_unspecified_memcpy
|
||||
+#define memset MISTAKE_unspecified_memset
|
||||
+#define memmove MISTAKE_unspecified_memmove
|
||||
+#define strcpy MISTAKE_unspecified_strcpy
|
||||
+ /* This prevents libelf from using these undecorated versions
|
||||
+ * of memcpy, memset, memmove and strcpy. Every call site
|
||||
+ * must either use elf_mem*_unchecked, or elf_mem*_safe. */
|
||||
+
|
||||
#endif /* __LIBELF_PRIVATE_H_ */
|
||||
|
||||
/*
|
||||
diff --git a/xen/common/libelf/libelf-tools.c b/xen/common/libelf/libelf-tools.c
|
||||
index 3a0cde1..46ca553 100644
|
||||
--- a/xen/common/libelf/libelf-tools.c
|
||||
+++ b/xen/common/libelf/libelf-tools.c
|
||||
@@ -20,28 +20,100 @@
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
-uint64_t elf_access_unsigned(struct elf_binary * elf, const void *ptr,
|
||||
- uint64_t offset, size_t size)
|
||||
+void elf_mark_broken(struct elf_binary *elf, const char *msg)
|
||||
{
|
||||
+ if ( elf->broken == NULL )
|
||||
+ elf->broken = msg;
|
||||
+}
|
||||
+
|
||||
+const char *elf_check_broken(const struct elf_binary *elf)
|
||||
+{
|
||||
+ return elf->broken;
|
||||
+}
|
||||
+
|
||||
+static int elf_ptrval_in_range(elf_ptrval ptrval, uint64_t size,
|
||||
+ const void *region, uint64_t regionsize)
|
||||
+ /*
|
||||
+ * Returns true if the putative memory area [ptrval,ptrval+size>
|
||||
+ * is completely inside the region [region,region+regionsize>.
|
||||
+ *
|
||||
+ * ptrval and size are the untrusted inputs to be checked.
|
||||
+ * region and regionsize are trusted and must be correct and valid,
|
||||
+ * although it is OK for region to perhaps be maliciously NULL
|
||||
+ * (but not some other malicious value).
|
||||
+ */
|
||||
+{
|
||||
+ elf_ptrval regionp = (elf_ptrval)region;
|
||||
+
|
||||
+ if ( (region == NULL) ||
|
||||
+ (ptrval < regionp) || /* start is before region */
|
||||
+ (ptrval > regionp + regionsize) || /* start is after region */
|
||||
+ (size > regionsize - (ptrval - regionp)) ) /* too big */
|
||||
+ return 0;
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+int elf_access_ok(struct elf_binary * elf,
|
||||
+ uint64_t ptrval, size_t size)
|
||||
+{
|
||||
+ if ( elf_ptrval_in_range(ptrval, size, elf->image_base, elf->size) )
|
||||
+ return 1;
|
||||
+ if ( elf_ptrval_in_range(ptrval, size, elf->dest_base, elf->dest_size) )
|
||||
+ return 1;
|
||||
+ if ( elf_ptrval_in_range(ptrval, size,
|
||||
+ elf->caller_xdest_base, elf->caller_xdest_size) )
|
||||
+ return 1;
|
||||
+ elf_mark_broken(elf, "out of range access");
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+void elf_memcpy_safe(struct elf_binary *elf, elf_ptrval dst,
|
||||
+ elf_ptrval src, size_t size)
|
||||
+{
|
||||
+ if ( elf_access_ok(elf, dst, size) &&
|
||||
+ elf_access_ok(elf, src, size) )
|
||||
+ {
|
||||
+ /* use memmove because these checks do not prove that the
|
||||
+ * regions don't overlap and overlapping regions grant
|
||||
+ * permission for compiler malice */
|
||||
+ elf_memmove_unchecked(ELF_UNSAFE_PTR(dst), ELF_UNSAFE_PTR(src), size);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+void elf_memset_safe(struct elf_binary *elf, elf_ptrval dst, int c, size_t size)
|
||||
+{
|
||||
+ if ( elf_access_ok(elf, dst, size) )
|
||||
+ {
|
||||
+ elf_memset_unchecked(ELF_UNSAFE_PTR(dst), c, size);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+uint64_t elf_access_unsigned(struct elf_binary * elf, elf_ptrval base,
|
||||
+ uint64_t moreoffset, size_t size)
|
||||
+{
|
||||
+ elf_ptrval ptrval = base + moreoffset;
|
||||
int need_swap = elf_swap(elf);
|
||||
const uint8_t *u8;
|
||||
const uint16_t *u16;
|
||||
const uint32_t *u32;
|
||||
const uint64_t *u64;
|
||||
|
||||
+ if ( !elf_access_ok(elf, ptrval, size) )
|
||||
+ return 0;
|
||||
+
|
||||
switch ( size )
|
||||
{
|
||||
case 1:
|
||||
- u8 = ptr + offset;
|
||||
+ u8 = (const void*)ptrval;
|
||||
return *u8;
|
||||
case 2:
|
||||
- u16 = ptr + offset;
|
||||
+ u16 = (const void*)ptrval;
|
||||
return need_swap ? bswap_16(*u16) : *u16;
|
||||
case 4:
|
||||
- u32 = ptr + offset;
|
||||
+ u32 = (const void*)ptrval;
|
||||
return need_swap ? bswap_32(*u32) : *u32;
|
||||
case 8:
|
||||
- u64 = ptr + offset;
|
||||
+ u64 = (const void*)ptrval;
|
||||
return need_swap ? bswap_64(*u64) : *u64;
|
||||
default:
|
||||
return 0;
|
||||
@@ -122,6 +194,28 @@ const char *elf_section_name(struct elf_binary *elf,
|
||||
return elf_strval(elf, elf->sec_strtab + elf_uval(elf, shdr, sh_name));
|
||||
}
|
||||
|
||||
+const char *elf_strval(struct elf_binary *elf, elf_ptrval start)
|
||||
+{
|
||||
+ uint64_t length;
|
||||
+
|
||||
+ for ( length = 0; ; length++ ) {
|
||||
+ if ( !elf_access_ok(elf, start + length, 1) )
|
||||
+ return NULL;
|
||||
+ if ( !elf_access_unsigned(elf, start, length, 1) )
|
||||
+ /* ok */
|
||||
+ return ELF_UNSAFE_PTR(start);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+const char *elf_strfmt(struct elf_binary *elf, elf_ptrval start)
|
||||
+{
|
||||
+ const char *str = elf_strval(elf, start);
|
||||
+
|
||||
+ if ( str == NULL )
|
||||
+ return "(invalid)";
|
||||
+ return str;
|
||||
+}
|
||||
+
|
||||
ELF_PTRVAL_CONST_VOID elf_section_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr)
|
||||
{
|
||||
return ELF_IMAGE_BASE(elf) + elf_uval(elf, shdr, sh_offset);
|
||||
diff --git a/xen/include/xen/libelf.h b/xen/include/xen/libelf.h
|
||||
index af5b5c5..ddc3ed7 100644
|
||||
--- a/xen/include/xen/libelf.h
|
||||
+++ b/xen/include/xen/libelf.h
|
||||
@@ -57,8 +57,9 @@ typedef void elf_log_callback(struct elf_binary*, void *caller_data,
|
||||
* on this.
|
||||
* This replaces variables which were char*,void*
|
||||
* and their const versions, so we provide four
|
||||
- * different declaration macros:
|
||||
+ * different obsolete declaration macros:
|
||||
* ELF_PTRVAL_{,CONST}{VOID,CHAR}
|
||||
+ * New code can simply use the elf_ptrval typedef.
|
||||
* HANDLE A pointer to a struct. There is one of these types
|
||||
* for each pointer type - that is, for each "structname".
|
||||
* In the arguments to the various HANDLE macros, structname
|
||||
@@ -67,54 +68,66 @@ typedef void elf_log_callback(struct elf_binary*, void *caller_data,
|
||||
* pointers. In the current code attempts to do so will
|
||||
* compile, but in the next patch this will become a
|
||||
* compile error.
|
||||
- * We provide two declaration macros for const and
|
||||
- * non-const pointers.
|
||||
+ * We also provide a second declaration macro for
|
||||
+ * pointers which were to const; this is obsolete.
|
||||
*/
|
||||
|
||||
-#define ELF_REALPTR2PTRVAL(realpointer) (realpointer)
|
||||
+typedef uintptr_t elf_ptrval;
|
||||
+
|
||||
+#define ELF_REALPTR2PTRVAL(realpointer) ((elf_ptrval)(realpointer))
|
||||
/* Converts an actual C pointer into a PTRVAL */
|
||||
|
||||
-#define ELF_HANDLE_DECL_NONCONST(structname) structname *
|
||||
-#define ELF_HANDLE_DECL(structname) const structname *
|
||||
+#define ELF_HANDLE_DECL_NONCONST(structname) structname##_handle /*obsolete*/
|
||||
+#define ELF_HANDLE_DECL(structname) structname##_handle
|
||||
/* Provides a type declaration for a HANDLE. */
|
||||
- /* May only be used to declare ONE variable at a time */
|
||||
|
||||
-#define ELF_PTRVAL_VOID void *
|
||||
-#define ELF_PTRVAL_CHAR char *
|
||||
-#define ELF_PTRVAL_CONST_VOID const void *
|
||||
-#define ELF_PTRVAL_CONST_CHAR const char *
|
||||
- /* Provides a type declaration for a PTRVAL. */
|
||||
- /* May only be used to declare ONE variable at a time */
|
||||
+#define ELF_PTRVAL_VOID elf_ptrval /*obsolete*/
|
||||
+#define ELF_PTRVAL_CHAR elf_ptrval /*obsolete*/
|
||||
+#define ELF_PTRVAL_CONST_VOID elf_ptrval /*obsolete*/
|
||||
+#define ELF_PTRVAL_CONST_CHAR elf_ptrval /*obsolete*/
|
||||
+
|
||||
+#ifdef __XEN__
|
||||
+# define ELF_PRPTRVAL "lu"
|
||||
+ /*
|
||||
+ * PRIuPTR is misdefined in xen/include/xen/inttypes.h, on 32-bit,
|
||||
+ * to "u", when in fact uintptr_t is an unsigned long.
|
||||
+ */
|
||||
+#else
|
||||
+# define ELF_PRPTRVAL PRIuPTR
|
||||
+#endif
|
||||
+ /* printf format a la PRId... for a PTRVAL */
|
||||
|
||||
-#define ELF_DEFINE_HANDLE(structname) /* empty */
|
||||
+#define ELF_DEFINE_HANDLE(structname) \
|
||||
+ typedef union { \
|
||||
+ elf_ptrval ptrval; \
|
||||
+ const structname *typeonly; /* for sizeof, offsetof, &c only */ \
|
||||
+ } structname##_handle;
|
||||
/*
|
||||
* This must be invoked for each HANDLE type to define
|
||||
* the actual C type used for that kind of HANDLE.
|
||||
*/
|
||||
|
||||
-#define ELF_PRPTRVAL "p"
|
||||
- /* printf format a la PRId... for a PTRVAL */
|
||||
-
|
||||
-#define ELF_MAKE_HANDLE(structname, ptrval) (ptrval)
|
||||
+#define ELF_MAKE_HANDLE(structname, ptrval) ((structname##_handle){ ptrval })
|
||||
/* Converts a PTRVAL to a HANDLE */
|
||||
|
||||
-#define ELF_IMAGE_BASE(elf) ((elf)->image)
|
||||
+#define ELF_IMAGE_BASE(elf) ((elf_ptrval)(elf)->image_base)
|
||||
/* Returns the base of the image as a PTRVAL. */
|
||||
|
||||
-#define ELF_HANDLE_PTRVAL(handleval) ((void*)(handleval))
|
||||
+#define ELF_HANDLE_PTRVAL(handleval) ((handleval).ptrval)
|
||||
/* Converts a HANDLE to a PTRVAL. */
|
||||
|
||||
-#define ELF_OBSOLETE_VOIDP_CAST (void*)(uintptr_t)
|
||||
+#define ELF_OBSOLETE_VOIDP_CAST /*empty*/
|
||||
/*
|
||||
- * In some places the existing code needs to
|
||||
+ * In some places the old code used to need to
|
||||
* - cast away const (the existing code uses const a fair
|
||||
* bit but actually sometimes wants to write to its input)
|
||||
* from a PTRVAL.
|
||||
* - convert an integer representing a pointer to a PTRVAL
|
||||
- * This macro provides a suitable cast.
|
||||
+ * Nowadays all of these re uintptr_ts so there is no const problem
|
||||
+ * and no need for any casting.
|
||||
*/
|
||||
|
||||
-#define ELF_UNSAFE_PTR(ptrval) ((void*)(uintptr_t)(ptrval))
|
||||
+#define ELF_UNSAFE_PTR(ptrval) ((void*)(elf_ptrval)(ptrval))
|
||||
/*
|
||||
* Turns a PTRVAL into an actual C pointer. Before this is done
|
||||
* the caller must have ensured that the PTRVAL does in fact point
|
||||
@@ -122,18 +135,21 @@ typedef void elf_log_callback(struct elf_binary*, void *caller_data,
|
||||
*/
|
||||
|
||||
/* PTRVALs can be INVALID (ie, NULL). */
|
||||
-#define ELF_INVALID_PTRVAL (NULL) /* returns NULL PTRVAL */
|
||||
+#define ELF_INVALID_PTRVAL ((elf_ptrval)0) /* returns NULL PTRVAL */
|
||||
#define ELF_INVALID_HANDLE(structname) /* returns NULL handle */ \
|
||||
ELF_MAKE_HANDLE(structname, ELF_INVALID_PTRVAL)
|
||||
-#define ELF_PTRVAL_VALID(ptrval) (ptrval) /* } */
|
||||
-#define ELF_HANDLE_VALID(handleval) (handleval) /* } predicates */
|
||||
-#define ELF_PTRVAL_INVALID(ptrval) ((ptrval) == NULL) /* } */
|
||||
+#define ELF_PTRVAL_VALID(ptrval) (!!(ptrval)) /* } */
|
||||
+#define ELF_HANDLE_VALID(handleval) (!!(handleval).ptrval) /* } predicates */
|
||||
+#define ELF_PTRVAL_INVALID(ptrval) (!ELF_PTRVAL_VALID((ptrval))) /* } */
|
||||
+
|
||||
+#define ELF_MAX_PTRVAL (~(elf_ptrval)0)
|
||||
+ /* PTRVAL value guaranteed to compare > to any valid PTRVAL */
|
||||
|
||||
/* For internal use by other macros here */
|
||||
#define ELF__HANDLE_FIELD_TYPE(handleval, elm) \
|
||||
- typeof((handleval)->elm)
|
||||
+ typeof((handleval).typeonly->elm)
|
||||
#define ELF__HANDLE_FIELD_OFFSET(handleval, elm) \
|
||||
- offsetof(typeof(*(handleval)),elm)
|
||||
+ offsetof(typeof(*(handleval).typeonly),elm)
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
@@ -182,7 +198,7 @@ ELF_DEFINE_HANDLE(elf_note)
|
||||
|
||||
struct elf_binary {
|
||||
/* elf binary */
|
||||
- const char *image;
|
||||
+ const void *image_base;
|
||||
size_t size;
|
||||
char class;
|
||||
char data;
|
||||
@@ -190,10 +206,16 @@ struct elf_binary {
|
||||
ELF_HANDLE_DECL(elf_ehdr) ehdr;
|
||||
ELF_PTRVAL_CONST_CHAR sec_strtab;
|
||||
ELF_HANDLE_DECL(elf_shdr) sym_tab;
|
||||
- ELF_PTRVAL_CONST_CHAR sym_strtab;
|
||||
+ uint64_t sym_strtab;
|
||||
|
||||
/* loaded to */
|
||||
- char *dest;
|
||||
+ /*
|
||||
+ * dest_base and dest_size are trusted and must be correct;
|
||||
+ * whenever dest_size is not 0, both of these must be valid
|
||||
+ * so long as the struct elf_binary is in use.
|
||||
+ */
|
||||
+ char *dest_base;
|
||||
+ size_t dest_size;
|
||||
uint64_t pstart;
|
||||
uint64_t pend;
|
||||
uint64_t reloc_offset;
|
||||
@@ -201,12 +223,22 @@ struct elf_binary {
|
||||
uint64_t bsd_symtab_pstart;
|
||||
uint64_t bsd_symtab_pend;
|
||||
|
||||
+ /*
|
||||
+ * caller's other acceptable destination
|
||||
+ *
|
||||
+ * Again, these are trusted and must be valid (or 0) so long
|
||||
+ * as the struct elf_binary is in use.
|
||||
+ */
|
||||
+ void *caller_xdest_base;
|
||||
+ uint64_t caller_xdest_size;
|
||||
+
|
||||
#ifndef __XEN__
|
||||
/* misc */
|
||||
elf_log_callback *log_callback;
|
||||
void *log_caller_data;
|
||||
#endif
|
||||
int verbose;
|
||||
+ const char *broken;
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
@@ -224,22 +256,27 @@ struct elf_binary {
|
||||
#define elf_lsb(elf) (ELFDATA2LSB == (elf)->data)
|
||||
#define elf_swap(elf) (NATIVE_ELFDATA != (elf)->data)
|
||||
|
||||
-#define elf_uval(elf, str, elem) \
|
||||
- ((ELFCLASS64 == (elf)->class) \
|
||||
- ? elf_access_unsigned((elf), (str), \
|
||||
- offsetof(typeof(*(str)),e64.elem), \
|
||||
- sizeof((str)->e64.elem)) \
|
||||
- : elf_access_unsigned((elf), (str), \
|
||||
- offsetof(typeof(*(str)),e32.elem), \
|
||||
- sizeof((str)->e32.elem)))
|
||||
+#define elf_uval_3264(elf, handle, elem) \
|
||||
+ elf_access_unsigned((elf), (handle).ptrval, \
|
||||
+ offsetof(typeof(*(handle).typeonly),elem), \
|
||||
+ sizeof((handle).typeonly->elem))
|
||||
+
|
||||
+#define elf_uval(elf, handle, elem) \
|
||||
+ ((ELFCLASS64 == (elf)->class) \
|
||||
+ ? elf_uval_3264(elf, handle, e64.elem) \
|
||||
+ : elf_uval_3264(elf, handle, e32.elem))
|
||||
/*
|
||||
* Reads an unsigned field in a header structure in the ELF.
|
||||
* str is a HANDLE, and elem is the field name in it.
|
||||
*/
|
||||
|
||||
-#define elf_size(elf, str) \
|
||||
+
|
||||
+#define elf_size(elf, handle_or_handletype) ({ \
|
||||
+ typeof(handle_or_handletype) elf_size__dummy; \
|
||||
((ELFCLASS64 == (elf)->class) \
|
||||
- ? sizeof((str)->e64) : sizeof((str)->e32))
|
||||
+ ? sizeof(elf_size__dummy.typeonly->e64) \
|
||||
+ : sizeof(elf_size__dummy.typeonly->e32)); \
|
||||
+})
|
||||
/*
|
||||
* Returns the size of the substructure for the appropriate 32/64-bitness.
|
||||
* str should be a HANDLE.
|
||||
@@ -251,23 +288,37 @@ uint64_t elf_access_unsigned(struct elf_binary *elf, ELF_PTRVAL_CONST_VOID ptr,
|
||||
|
||||
uint64_t elf_round_up(struct elf_binary *elf, uint64_t addr);
|
||||
|
||||
+const char *elf_strval(struct elf_binary *elf, elf_ptrval start);
|
||||
+ /* may return NULL if the string is out of range etc. */
|
||||
|
||||
-#define elf_strval(elf,x) ((const char*)(x)) /* may return NULL in the future */
|
||||
-#define elf_strfmt(elf,x) ((const char*)(x)) /* will return (invalid) instead */
|
||||
+const char *elf_strfmt(struct elf_binary *elf, elf_ptrval start);
|
||||
+ /* like elf_strval but returns "(invalid)" instead of NULL */
|
||||
|
||||
-#define elf_memcpy_safe(elf, dst, src, sz) memcpy((dst),(src),(sz))
|
||||
-#define elf_memset_safe(elf, dst, c, sz) memset((dst),(c),(sz))
|
||||
+void elf_memcpy_safe(struct elf_binary*, elf_ptrval dst, elf_ptrval src, size_t);
|
||||
+void elf_memset_safe(struct elf_binary*, elf_ptrval dst, int c, size_t);
|
||||
/*
|
||||
- * Versions of memcpy and memset which will (in the next patch)
|
||||
- * arrange never to write outside permitted areas.
|
||||
+ * Versions of memcpy and memset which arrange never to write
|
||||
+ * outside permitted areas.
|
||||
*/
|
||||
|
||||
-#define elf_store_val(elf, type, ptr, val) (*(type*)(ptr) = (val))
|
||||
+int elf_access_ok(struct elf_binary * elf,
|
||||
+ uint64_t ptrval, size_t size);
|
||||
+
|
||||
+#define elf_store_val(elf, type, ptr, val) \
|
||||
+ ({ \
|
||||
+ typeof(type) elf_store__val = (val); \
|
||||
+ elf_ptrval elf_store__targ = ptr; \
|
||||
+ if (elf_access_ok((elf), elf_store__targ, \
|
||||
+ sizeof(elf_store__val))) { \
|
||||
+ elf_memcpy_unchecked((void*)elf_store__targ, &elf_store__val, \
|
||||
+ sizeof(elf_store__val)); \
|
||||
+ } \
|
||||
+ }) \
|
||||
/* Stores a value at a particular PTRVAL. */
|
||||
|
||||
-#define elf_store_field(elf, hdr, elm, val) \
|
||||
- (elf_store_val((elf), ELF__HANDLE_FIELD_TYPE(hdr, elm), \
|
||||
- &((hdr)->elm), \
|
||||
+#define elf_store_field(elf, hdr, elm, val) \
|
||||
+ (elf_store_val((elf), ELF__HANDLE_FIELD_TYPE(hdr, elm), \
|
||||
+ ELF_HANDLE_PTRVAL(hdr) + ELF__HANDLE_FIELD_OFFSET(hdr, elm), \
|
||||
(val)))
|
||||
/* Stores a 32/64-bit field. hdr is a HANDLE and elm is the field name. */
|
||||
|
||||
@@ -306,6 +357,10 @@ int elf_phdr_is_loadable(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr)
|
||||
/* xc_libelf_loader.c */
|
||||
|
||||
int elf_init(struct elf_binary *elf, const char *image, size_t size);
|
||||
+ /*
|
||||
+ * image and size must be correct. They will be recorded in
|
||||
+ * *elf, and must remain valid while the elf is in use.
|
||||
+ */
|
||||
#ifdef __XEN__
|
||||
void elf_set_verbose(struct elf_binary *elf);
|
||||
#else
|
||||
@@ -321,6 +376,9 @@ uint64_t elf_lookup_addr(struct elf_binary *elf, const char *symbol);
|
||||
|
||||
void elf_parse_bsdsyms(struct elf_binary *elf, uint64_t pstart); /* private */
|
||||
|
||||
+void elf_mark_broken(struct elf_binary *elf, const char *msg);
|
||||
+const char *elf_check_broken(const struct elf_binary *elf); /* NULL means OK */
|
||||
+
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* xc_libelf_relocate.c */
|
||||
|
||||
@@ -395,16 +453,38 @@ int elf_xen_parse_guest_info(struct elf_binary *elf,
|
||||
int elf_xen_parse(struct elf_binary *elf,
|
||||
struct elf_dom_parms *parms);
|
||||
|
||||
-#define elf_memcpy_unchecked memcpy
|
||||
-#define elf_memset_unchecked memset
|
||||
+static inline void *elf_memcpy_unchecked(void *dest, const void *src, size_t n)
|
||||
+ { return memcpy(dest, src, n); }
|
||||
+static inline void *elf_memmove_unchecked(void *dest, const void *src, size_t n)
|
||||
+ { return memmove(dest, src, n); }
|
||||
+static inline void *elf_memset_unchecked(void *s, int c, size_t n)
|
||||
+ { return memset(s, c, n); }
|
||||
/*
|
||||
- * Unsafe versions of memcpy and memset which take actual C
|
||||
- * pointers. These are just like real memcpy and memset.
|
||||
+ * Unsafe versions of memcpy, memmove memset which take actual C
|
||||
+ * pointers. These are just like the real functions.
|
||||
+ * We provide these so that in libelf-private.h we can #define
|
||||
+ * memcpy, memset and memmove to undefined MISTAKE things.
|
||||
*/
|
||||
|
||||
|
||||
-#define ELF_ADVANCE_DEST(elf, amount) elf->dest += (amount)
|
||||
- /* Advances past amount bytes of the current destination area. */
|
||||
+/* Advances past amount bytes of the current destination area. */
|
||||
+static inline void ELF_ADVANCE_DEST(struct elf_binary *elf, uint64_t amount)
|
||||
+{
|
||||
+ if ( elf->dest_base == NULL )
|
||||
+ {
|
||||
+ elf_mark_broken(elf, "advancing in null image");
|
||||
+ }
|
||||
+ else if ( elf->dest_size >= amount )
|
||||
+ {
|
||||
+ elf->dest_base += amount;
|
||||
+ elf->dest_size -= amount;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ elf->dest_size = 0;
|
||||
+ elf_mark_broken(elf, "advancing past end (image very short?)");
|
||||
+ }
|
||||
+}
|
||||
|
||||
|
||||
#endif /* __XEN_LIBELF_H__ */
|
||||
--
|
||||
1.7.2.5
|
||||
|
@ -0,0 +1,371 @@
|
||||
From d0790bdad7496e720416b2d4a04563c4c27e7b95 Mon Sep 17 00:00:00 2001
|
||||
From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Date: Fri, 14 Jun 2013 16:43:17 +0100
|
||||
Subject: [PATCH 12/23] libelf: Check pointer references in elf_is_elfbinary
|
||||
|
||||
elf_is_elfbinary didn't take a length parameter and could potentially
|
||||
access out of range when provided with a very short image.
|
||||
|
||||
We only need to check the size is enough for the actual dereference in
|
||||
elf_is_elfbinary; callers are just using it to check the magic number
|
||||
and do their own checks (usually via the new elf_ptrval system) before
|
||||
dereferencing other parts of the header.
|
||||
|
||||
This is part of the fix to a security issue, XSA-55.
|
||||
|
||||
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
|
||||
---
|
||||
tools/libxc/xc_dom_elfloader.c | 2 +-
|
||||
xen/arch/x86/bzimage.c | 4 ++--
|
||||
xen/common/libelf/libelf-loader.c | 2 +-
|
||||
xen/common/libelf/libelf-tools.c | 9 ++++++---
|
||||
xen/include/xen/libelf.h | 4 +++-
|
||||
5 files changed, 13 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c
|
||||
index b82a08c..ea45886 100644
|
||||
--- a/tools/libxc/xc_dom_elfloader.c
|
||||
+++ b/tools/libxc/xc_dom_elfloader.c
|
||||
@@ -95,7 +95,7 @@ static int check_elf_kernel(struct xc_dom_image *dom, int verbose)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
- if ( !elf_is_elfbinary(dom->kernel_blob) )
|
||||
+ if ( !elf_is_elfbinary(dom->kernel_blob, dom->kernel_size) )
|
||||
{
|
||||
if ( verbose )
|
||||
xc_dom_panic(dom->xch,
|
||||
diff --git a/xen/arch/x86/bzimage.c b/xen/arch/x86/bzimage.c
|
||||
index 5adc223..3600dca 100644
|
||||
--- a/xen/arch/x86/bzimage.c
|
||||
+++ b/xen/arch/x86/bzimage.c
|
||||
@@ -220,7 +220,7 @@ unsigned long __init bzimage_headroom(char *image_start,
|
||||
image_length = hdr->payload_length;
|
||||
}
|
||||
|
||||
- if ( elf_is_elfbinary(image_start) )
|
||||
+ if ( elf_is_elfbinary(image_start, image_length) )
|
||||
return 0;
|
||||
|
||||
orig_image_len = image_length;
|
||||
@@ -251,7 +251,7 @@ int __init bzimage_parse(char *image_base, char **image_start, unsigned long *im
|
||||
*image_len = hdr->payload_length;
|
||||
}
|
||||
|
||||
- if ( elf_is_elfbinary(*image_start) )
|
||||
+ if ( elf_is_elfbinary(*image_start, *image_len) )
|
||||
return 0;
|
||||
|
||||
BUG_ON(!(image_base < *image_start));
|
||||
diff --git a/xen/common/libelf/libelf-loader.c b/xen/common/libelf/libelf-loader.c
|
||||
index a3310e7..f8be635 100644
|
||||
--- a/xen/common/libelf/libelf-loader.c
|
||||
+++ b/xen/common/libelf/libelf-loader.c
|
||||
@@ -29,7 +29,7 @@ int elf_init(struct elf_binary *elf, const char *image_input, size_t size)
|
||||
ELF_HANDLE_DECL(elf_shdr) shdr;
|
||||
uint64_t i, count, section, offset;
|
||||
|
||||
- if ( !elf_is_elfbinary(image_input) )
|
||||
+ if ( !elf_is_elfbinary(image_input, size) )
|
||||
{
|
||||
elf_err(elf, "%s: not an ELF binary\n", __FUNCTION__);
|
||||
return -1;
|
||||
diff --git a/xen/common/libelf/libelf-tools.c b/xen/common/libelf/libelf-tools.c
|
||||
index 46ca553..744027e 100644
|
||||
--- a/xen/common/libelf/libelf-tools.c
|
||||
+++ b/xen/common/libelf/libelf-tools.c
|
||||
@@ -332,11 +332,14 @@ ELF_HANDLE_DECL(elf_note) elf_note_next(struct elf_binary *elf, ELF_HANDLE_DECL(
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
-int elf_is_elfbinary(const void *image)
|
||||
+int elf_is_elfbinary(const void *image_start, size_t image_size)
|
||||
{
|
||||
- const Elf32_Ehdr *ehdr = image;
|
||||
+ const Elf32_Ehdr *ehdr = image_start;
|
||||
|
||||
- return IS_ELF(*ehdr); /* fixme unchecked */
|
||||
+ if ( image_size < sizeof(*ehdr) )
|
||||
+ return 0;
|
||||
+
|
||||
+ return IS_ELF(*ehdr);
|
||||
}
|
||||
|
||||
int elf_phdr_is_loadable(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr)
|
||||
diff --git a/xen/include/xen/libelf.h b/xen/include/xen/libelf.h
|
||||
index ddc3ed7..ac93858 100644
|
||||
--- a/xen/include/xen/libelf.h
|
||||
+++ b/xen/include/xen/libelf.h
|
||||
@@ -350,7 +350,9 @@ uint64_t elf_note_numeric_array(struct elf_binary *, ELF_HANDLE_DECL(elf_note),
|
||||
unsigned int unitsz, unsigned int idx);
|
||||
ELF_HANDLE_DECL(elf_note) elf_note_next(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
|
||||
|
||||
-int elf_is_elfbinary(const void *image);
|
||||
+/* (Only) checks that the image has the right magic number. */
|
||||
+int elf_is_elfbinary(const void *image_start, size_t image_size);
|
||||
+
|
||||
int elf_phdr_is_loadable(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr);
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
--
|
||||
1.7.2.5
|
||||
#From a965b8f80388603d439ae2b8ee7b9b018a079f90 Mon Sep 17 00:00:00 2001
|
||||
#From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
#Date: Fri, 14 Jun 2013 16:43:17 +0100
|
||||
#Subject: [PATCH 13/23] libelf: Make all callers call elf_check_broken
|
||||
#
|
||||
#This arranges that if the new pointer reference error checking
|
||||
#tripped, we actually get a message about it. In this patch these
|
||||
#messages do not change the actual return values from the various
|
||||
#functions: so pointer reference errors do not prevent loading. This
|
||||
#is for fear that some existing kernels might cause the code to make
|
||||
#these wild references, which would then break, which is not a good
|
||||
#thing in a security patch.
|
||||
#
|
||||
#In xen/arch/x86/domain_build.c we have to introduce an "out" label and
|
||||
#change all of the "return rc" beyond the relevant point into "goto
|
||||
#out".
|
||||
#
|
||||
#Difference in the 4.2 series, compared to unstable:
|
||||
#
|
||||
#* tools/libxc/xc_hvm_build_x86.c:setup_guest and
|
||||
# xen/arch/arm/kernel.c:kernel_try_elf_prepare have different
|
||||
# error handling in 4.2 to unstable; patch adjusted accordingly.
|
||||
#
|
||||
#This is part of the fix to a security issue, XSA-55.
|
||||
#
|
||||
#Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
#
|
||||
#xen-unstable version Reviewed-by: George Dunlap <george.dunlap@eu.citrix.com>
|
||||
#---
|
||||
# tools/libxc/xc_dom_elfloader.c | 25 +++++++++++++++++++++----
|
||||
# tools/libxc/xc_hvm_build_x86.c | 5 +++++
|
||||
# tools/xcutils/readnotes.c | 3 +++
|
||||
# xen/arch/arm/kernel.c | 15 ++++++++++++++-
|
||||
# xen/arch/x86/domain_build.c | 28 +++++++++++++++++++++-------
|
||||
# 5 files changed, 64 insertions(+), 12 deletions(-)
|
||||
#
|
||||
diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c
|
||||
index ea45886..4fb4da2 100644
|
||||
--- a/tools/libxc/xc_dom_elfloader.c
|
||||
+++ b/tools/libxc/xc_dom_elfloader.c
|
||||
@@ -276,6 +276,13 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
elf_store_field(elf, shdr, e32.sh_name, 0);
|
||||
}
|
||||
|
||||
+ if ( elf_check_broken(&syms) )
|
||||
+ DOMPRINTF("%s: symbols ELF broken: %s", __FUNCTION__,
|
||||
+ elf_check_broken(&syms));
|
||||
+ if ( elf_check_broken(elf) )
|
||||
+ DOMPRINTF("%s: ELF broken: %s", __FUNCTION__,
|
||||
+ elf_check_broken(elf));
|
||||
+
|
||||
if ( tables == 0 )
|
||||
{
|
||||
DOMPRINTF("%s: no symbol table present", __FUNCTION__);
|
||||
@@ -312,19 +319,23 @@ static int xc_dom_parse_elf_kernel(struct xc_dom_image *dom)
|
||||
{
|
||||
xc_dom_panic(dom->xch, XC_INVALID_KERNEL, "%s: ELF image"
|
||||
" has no shstrtab", __FUNCTION__);
|
||||
- return -EINVAL;
|
||||
+ rc = -EINVAL;
|
||||
+ goto out;
|
||||
}
|
||||
|
||||
/* parse binary and get xen meta info */
|
||||
elf_parse_binary(elf);
|
||||
if ( (rc = elf_xen_parse(elf, &dom->parms)) != 0 )
|
||||
- return rc;
|
||||
+ {
|
||||
+ goto out;
|
||||
+ }
|
||||
|
||||
if ( elf_xen_feature_get(XENFEAT_dom0, dom->parms.f_required) )
|
||||
{
|
||||
xc_dom_panic(dom->xch, XC_INVALID_KERNEL, "%s: Kernel does not"
|
||||
" support unprivileged (DomU) operation", __FUNCTION__);
|
||||
- return -EINVAL;
|
||||
+ rc = -EINVAL;
|
||||
+ goto out;
|
||||
}
|
||||
|
||||
/* find kernel segment */
|
||||
@@ -338,7 +349,13 @@ static int xc_dom_parse_elf_kernel(struct xc_dom_image *dom)
|
||||
DOMPRINTF("%s: %s: 0x%" PRIx64 " -> 0x%" PRIx64 "",
|
||||
__FUNCTION__, dom->guest_type,
|
||||
dom->kernel_seg.vstart, dom->kernel_seg.vend);
|
||||
- return 0;
|
||||
+ rc = 0;
|
||||
+out:
|
||||
+ if ( elf_check_broken(elf) )
|
||||
+ DOMPRINTF("%s: ELF broken: %s", __FUNCTION__,
|
||||
+ elf_check_broken(elf));
|
||||
+
|
||||
+ return rc;
|
||||
}
|
||||
|
||||
static int xc_dom_load_elf_kernel(struct xc_dom_image *dom)
|
||||
diff --git a/tools/libxc/xc_hvm_build_x86.c b/tools/libxc/xc_hvm_build_x86.c
|
||||
index ccfd8b5..8165287 100644
|
||||
--- a/tools/libxc/xc_hvm_build_x86.c
|
||||
+++ b/tools/libxc/xc_hvm_build_x86.c
|
||||
@@ -403,11 +403,16 @@ static int setup_guest(xc_interface *xch,
|
||||
munmap(page0, PAGE_SIZE);
|
||||
}
|
||||
|
||||
+ if ( elf_check_broken(&elf) )
|
||||
+ ERROR("HVM ELF broken: %s", elf_check_broken(&elf));
|
||||
+
|
||||
free(page_array);
|
||||
return 0;
|
||||
|
||||
error_out:
|
||||
free(page_array);
|
||||
+ if ( elf_check_broken(&elf) )
|
||||
+ ERROR("HVM ELF broken, failing: %s", elf_check_broken(&elf));
|
||||
return -1;
|
||||
}
|
||||
|
||||
diff --git a/tools/xcutils/readnotes.c b/tools/xcutils/readnotes.c
|
||||
index cfae994..d1f7a30 100644
|
||||
--- a/tools/xcutils/readnotes.c
|
||||
+++ b/tools/xcutils/readnotes.c
|
||||
@@ -301,6 +301,9 @@ int main(int argc, char **argv)
|
||||
printf("__xen_guest: %s\n",
|
||||
elf_strfmt(&elf, elf_section_start(&elf, shdr)));
|
||||
|
||||
+ if (elf_check_broken(&elf))
|
||||
+ printf("warning: broken ELF: %s\n", elf_check_broken(&elf));
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
diff --git a/xen/arch/arm/kernel.c b/xen/arch/arm/kernel.c
|
||||
index 2d56130..dec0519 100644
|
||||
--- a/xen/arch/arm/kernel.c
|
||||
+++ b/xen/arch/arm/kernel.c
|
||||
@@ -146,6 +146,8 @@ static int kernel_try_elf_prepare(struct kernel_info *info)
|
||||
{
|
||||
int rc;
|
||||
|
||||
+ memset(&info->elf.elf, 0, sizeof(info->elf.elf));
|
||||
+
|
||||
info->kernel_order = get_order_from_bytes(KERNEL_FLASH_SIZE);
|
||||
info->kernel_img = alloc_xenheap_pages(info->kernel_order, 0);
|
||||
if ( info->kernel_img == NULL )
|
||||
@@ -160,7 +162,7 @@ static int kernel_try_elf_prepare(struct kernel_info *info)
|
||||
#endif
|
||||
elf_parse_binary(&info->elf.elf);
|
||||
if ( (rc = elf_xen_parse(&info->elf.elf, &info->elf.parms)) != 0 )
|
||||
- return rc;
|
||||
+ goto err;
|
||||
|
||||
/*
|
||||
* TODO: can the ELF header be used to find the physical address
|
||||
@@ -169,7 +171,18 @@ static int kernel_try_elf_prepare(struct kernel_info *info)
|
||||
info->entry = info->elf.parms.virt_entry;
|
||||
info->load = kernel_elf_load;
|
||||
|
||||
+ if ( elf_check_broken(&info->elf.elf) )
|
||||
+ printk("Xen: warning: ELF kernel broken: %s\n",
|
||||
+ elf_check_broken(&info->elf.elf));
|
||||
+
|
||||
return 0;
|
||||
+
|
||||
+err:
|
||||
+ if ( elf_check_broken(&info->elf.elf) )
|
||||
+ printk("Xen: ELF kernel broken: %s\n",
|
||||
+ elf_check_broken(&info->elf.elf));
|
||||
+
|
||||
+ return rc;
|
||||
}
|
||||
|
||||
int kernel_prepare(struct kernel_info *info)
|
||||
diff --git a/xen/arch/x86/domain_build.c b/xen/arch/x86/domain_build.c
|
||||
index a655b21..0dbec96 100644
|
||||
--- a/xen/arch/x86/domain_build.c
|
||||
+++ b/xen/arch/x86/domain_build.c
|
||||
@@ -374,7 +374,7 @@ int __init construct_dom0(
|
||||
#endif
|
||||
elf_parse_binary(&elf);
|
||||
if ( (rc = elf_xen_parse(&elf, &parms)) != 0 )
|
||||
- return rc;
|
||||
+ goto out;
|
||||
|
||||
/* compatibility check */
|
||||
compatible = 0;
|
||||
@@ -413,14 +413,16 @@ int __init construct_dom0(
|
||||
if ( !compatible )
|
||||
{
|
||||
printk("Mismatch between Xen and DOM0 kernel\n");
|
||||
- return -EINVAL;
|
||||
+ rc = -EINVAL;
|
||||
+ goto out;
|
||||
}
|
||||
|
||||
if ( parms.elf_notes[XEN_ELFNOTE_SUPPORTED_FEATURES].type != XEN_ENT_NONE &&
|
||||
!test_bit(XENFEAT_dom0, parms.f_supported) )
|
||||
{
|
||||
printk("Kernel does not support Dom0 operation\n");
|
||||
- return -EINVAL;
|
||||
+ rc = -EINVAL;
|
||||
+ goto out;
|
||||
}
|
||||
|
||||
#if defined(__x86_64__)
|
||||
@@ -734,7 +736,8 @@ int __init construct_dom0(
|
||||
(v_end > HYPERVISOR_COMPAT_VIRT_START(d)) )
|
||||
{
|
||||
printk("DOM0 image overlaps with Xen private area.\n");
|
||||
- return -EINVAL;
|
||||
+ rc = -EINVAL;
|
||||
+ goto out;
|
||||
}
|
||||
|
||||
if ( is_pv_32on64_domain(d) )
|
||||
@@ -914,7 +917,7 @@ int __init construct_dom0(
|
||||
if ( rc < 0 )
|
||||
{
|
||||
printk("Failed to load the kernel binary\n");
|
||||
- return rc;
|
||||
+ goto out;
|
||||
}
|
||||
bootstrap_map(NULL);
|
||||
|
||||
@@ -925,7 +928,8 @@ int __init construct_dom0(
|
||||
{
|
||||
write_ptbase(current);
|
||||
printk("Invalid HYPERCALL_PAGE field in ELF notes.\n");
|
||||
- return -1;
|
||||
+ rc = -1;
|
||||
+ goto out;
|
||||
}
|
||||
hypercall_page_initialise(
|
||||
d, (void *)(unsigned long)parms.virt_hypercall);
|
||||
@@ -1272,9 +1276,19 @@ int __init construct_dom0(
|
||||
|
||||
BUG_ON(rc != 0);
|
||||
|
||||
- iommu_dom0_init(dom0);
|
||||
+ if ( elf_check_broken(&elf) )
|
||||
+ printk(" Xen warning: dom0 kernel broken ELF: %s\n",
|
||||
+ elf_check_broken(&elf));
|
||||
|
||||
+ iommu_dom0_init(dom0);
|
||||
return 0;
|
||||
+
|
||||
+out:
|
||||
+ if ( elf_check_broken(&elf) )
|
||||
+ printk(" Xen dom0 kernel broken ELF: %s\n",
|
||||
+ elf_check_broken(&elf));
|
||||
+
|
||||
+ return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
--
|
||||
1.7.2.5
|
||||
|
||||
|
@ -0,0 +1,252 @@
|
||||
From 3fb6ccf2faccaf5e22e33a3155ccc72d732896d8 Mon Sep 17 00:00:00 2001
|
||||
From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Date: Fri, 14 Jun 2013 16:43:18 +0100
|
||||
Subject: [PATCH 14/23] libelf: use C99 bool for booleans
|
||||
|
||||
We want to remove uses of "int" because signed integers have
|
||||
undesirable undefined behaviours on overflow. Malicious compilers can
|
||||
turn apparently-correct code into code with security vulnerabilities
|
||||
etc.
|
||||
|
||||
In this patch we change all the booleans in libelf to C99 bool,
|
||||
from <stdbool.h>.
|
||||
|
||||
For the one visible libelf boolean in libxc's public interface we
|
||||
retain the use of int to avoid changing the ABI; libxc converts it to
|
||||
a bool for consumption by libelf.
|
||||
|
||||
It is OK to change all values only ever used as booleans to _Bool
|
||||
(bool) because conversion from any scalar type to a _Bool works the
|
||||
same as the boolean test in if() or ?: and is always defined (C99
|
||||
6.3.1.2). But we do need to check that all these variables really are
|
||||
only ever used that way. (It is theoretically possible that the old
|
||||
code truncated some 64-bit values to 32-bit ints which might become
|
||||
zero depending on the value, which would mean a behavioural change in
|
||||
this patch, but it seems implausible that treating 0x????????00000000
|
||||
as false could have been intended.)
|
||||
|
||||
This is part of the fix to a security issue, XSA-55.
|
||||
|
||||
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Acked-by: George Dunlap <george.dunlap@eu.citrix.com>
|
||||
---
|
||||
tools/libxc/xc_dom_elfloader.c | 8 ++++----
|
||||
xen/common/libelf/libelf-dominfo.c | 2 +-
|
||||
xen/common/libelf/libelf-loader.c | 4 ++--
|
||||
xen/common/libelf/libelf-private.h | 2 +-
|
||||
xen/common/libelf/libelf-tools.c | 10 +++++-----
|
||||
xen/include/xen/libelf.h | 18 ++++++++++--------
|
||||
6 files changed, 23 insertions(+), 21 deletions(-)
|
||||
|
||||
diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c
|
||||
index 4fb4da2..9ba64ae 100644
|
||||
--- a/tools/libxc/xc_dom_elfloader.c
|
||||
+++ b/tools/libxc/xc_dom_elfloader.c
|
||||
@@ -34,7 +34,7 @@
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
static void log_callback(struct elf_binary *elf, void *caller_data,
|
||||
- int iserr, const char *fmt, va_list al) {
|
||||
+ bool iserr, const char *fmt, va_list al) {
|
||||
xc_interface *xch = caller_data;
|
||||
|
||||
xc_reportv(xch,
|
||||
@@ -46,7 +46,7 @@ static void log_callback(struct elf_binary *elf, void *caller_data,
|
||||
|
||||
void xc_elf_set_logfile(xc_interface *xch, struct elf_binary *elf,
|
||||
int verbose) {
|
||||
- elf_set_log(elf, log_callback, xch, verbose);
|
||||
+ elf_set_log(elf, log_callback, xch, verbose /* convert to bool */);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
@@ -84,7 +84,7 @@ static char *xc_dom_guest_type(struct xc_dom_image *dom,
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* parse elf binary */
|
||||
|
||||
-static int check_elf_kernel(struct xc_dom_image *dom, int verbose)
|
||||
+static int check_elf_kernel(struct xc_dom_image *dom, bool verbose)
|
||||
{
|
||||
if ( dom->kernel_blob == NULL )
|
||||
{
|
||||
@@ -112,7 +112,7 @@ static int xc_dom_probe_elf_kernel(struct xc_dom_image *dom)
|
||||
}
|
||||
|
||||
static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
- struct elf_binary *elf, int load)
|
||||
+ struct elf_binary *elf, bool load)
|
||||
{
|
||||
struct elf_binary syms;
|
||||
ELF_HANDLE_DECL_NONCONST(elf_shdr) shdr; ELF_HANDLE_DECL(elf_shdr) shdr2;
|
||||
diff --git a/xen/common/libelf/libelf-dominfo.c b/xen/common/libelf/libelf-dominfo.c
|
||||
index 98c80dc..12b6c2a 100644
|
||||
--- a/xen/common/libelf/libelf-dominfo.c
|
||||
+++ b/xen/common/libelf/libelf-dominfo.c
|
||||
@@ -101,7 +101,7 @@ int elf_xen_parse_note(struct elf_binary *elf,
|
||||
/* *INDENT-OFF* */
|
||||
static const struct {
|
||||
char *name;
|
||||
- int str;
|
||||
+ bool str;
|
||||
} note_desc[] = {
|
||||
[XEN_ELFNOTE_ENTRY] = { "ENTRY", 0},
|
||||
[XEN_ELFNOTE_HYPERCALL_PAGE] = { "HYPERCALL_PAGE", 0},
|
||||
diff --git a/xen/common/libelf/libelf-loader.c b/xen/common/libelf/libelf-loader.c
|
||||
index f8be635..0dccd4d 100644
|
||||
--- a/xen/common/libelf/libelf-loader.c
|
||||
+++ b/xen/common/libelf/libelf-loader.c
|
||||
@@ -92,7 +92,7 @@ int elf_init(struct elf_binary *elf, const char *image_input, size_t size)
|
||||
}
|
||||
|
||||
#ifndef __XEN__
|
||||
-void elf_call_log_callback(struct elf_binary *elf, int iserr,
|
||||
+void elf_call_log_callback(struct elf_binary *elf, bool iserr,
|
||||
const char *fmt,...) {
|
||||
va_list al;
|
||||
|
||||
@@ -107,7 +107,7 @@ void elf_call_log_callback(struct elf_binary *elf, int iserr,
|
||||
}
|
||||
|
||||
void elf_set_log(struct elf_binary *elf, elf_log_callback *log_callback,
|
||||
- void *log_caller_data, int verbose)
|
||||
+ void *log_caller_data, bool verbose)
|
||||
{
|
||||
elf->log_callback = log_callback;
|
||||
elf->log_caller_data = log_caller_data;
|
||||
diff --git a/xen/common/libelf/libelf-private.h b/xen/common/libelf/libelf-private.h
|
||||
index 280dfd1..277be04 100644
|
||||
--- a/xen/common/libelf/libelf-private.h
|
||||
+++ b/xen/common/libelf/libelf-private.h
|
||||
@@ -77,7 +77,7 @@
|
||||
#define elf_err(elf, fmt, args ... ) \
|
||||
elf_call_log_callback(elf, 1, fmt , ## args );
|
||||
|
||||
-void elf_call_log_callback(struct elf_binary*, int iserr, const char *fmt,...);
|
||||
+void elf_call_log_callback(struct elf_binary*, bool iserr, const char *fmt,...);
|
||||
|
||||
#define safe_strcpy(d,s) \
|
||||
do { strncpy((d),(s),sizeof((d))-1); \
|
||||
diff --git a/xen/common/libelf/libelf-tools.c b/xen/common/libelf/libelf-tools.c
|
||||
index 744027e..fa58f76 100644
|
||||
--- a/xen/common/libelf/libelf-tools.c
|
||||
+++ b/xen/common/libelf/libelf-tools.c
|
||||
@@ -31,7 +31,7 @@ const char *elf_check_broken(const struct elf_binary *elf)
|
||||
return elf->broken;
|
||||
}
|
||||
|
||||
-static int elf_ptrval_in_range(elf_ptrval ptrval, uint64_t size,
|
||||
+static bool elf_ptrval_in_range(elf_ptrval ptrval, uint64_t size,
|
||||
const void *region, uint64_t regionsize)
|
||||
/*
|
||||
* Returns true if the putative memory area [ptrval,ptrval+size>
|
||||
@@ -53,7 +53,7 @@ static int elf_ptrval_in_range(elf_ptrval ptrval, uint64_t size,
|
||||
return 1;
|
||||
}
|
||||
|
||||
-int elf_access_ok(struct elf_binary * elf,
|
||||
+bool elf_access_ok(struct elf_binary * elf,
|
||||
uint64_t ptrval, size_t size)
|
||||
{
|
||||
if ( elf_ptrval_in_range(ptrval, size, elf->image_base, elf->size) )
|
||||
@@ -92,7 +92,7 @@ uint64_t elf_access_unsigned(struct elf_binary * elf, elf_ptrval base,
|
||||
uint64_t moreoffset, size_t size)
|
||||
{
|
||||
elf_ptrval ptrval = base + moreoffset;
|
||||
- int need_swap = elf_swap(elf);
|
||||
+ bool need_swap = elf_swap(elf);
|
||||
const uint8_t *u8;
|
||||
const uint16_t *u16;
|
||||
const uint32_t *u32;
|
||||
@@ -332,7 +332,7 @@ ELF_HANDLE_DECL(elf_note) elf_note_next(struct elf_binary *elf, ELF_HANDLE_DECL(
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
-int elf_is_elfbinary(const void *image_start, size_t image_size)
|
||||
+bool elf_is_elfbinary(const void *image_start, size_t image_size)
|
||||
{
|
||||
const Elf32_Ehdr *ehdr = image_start;
|
||||
|
||||
@@ -342,7 +342,7 @@ int elf_is_elfbinary(const void *image_start, size_t image_size)
|
||||
return IS_ELF(*ehdr);
|
||||
}
|
||||
|
||||
-int elf_phdr_is_loadable(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr)
|
||||
+bool elf_phdr_is_loadable(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr)
|
||||
{
|
||||
uint64_t p_type = elf_uval(elf, phdr, p_type);
|
||||
uint64_t p_flags = elf_uval(elf, phdr, p_flags);
|
||||
diff --git a/xen/include/xen/libelf.h b/xen/include/xen/libelf.h
|
||||
index ac93858..951430f 100644
|
||||
--- a/xen/include/xen/libelf.h
|
||||
+++ b/xen/include/xen/libelf.h
|
||||
@@ -29,6 +29,8 @@
|
||||
#error define architectural endianness
|
||||
#endif
|
||||
|
||||
+#include <stdbool.h>
|
||||
+
|
||||
#undef ELFSIZE
|
||||
#include "elfstructs.h"
|
||||
#ifdef __XEN__
|
||||
@@ -42,7 +44,7 @@
|
||||
|
||||
struct elf_binary;
|
||||
typedef void elf_log_callback(struct elf_binary*, void *caller_data,
|
||||
- int iserr, const char *fmt, va_list al);
|
||||
+ bool iserr, const char *fmt, va_list al);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -237,7 +239,7 @@ struct elf_binary {
|
||||
elf_log_callback *log_callback;
|
||||
void *log_caller_data;
|
||||
#endif
|
||||
- int verbose;
|
||||
+ bool verbose;
|
||||
const char *broken;
|
||||
};
|
||||
|
||||
@@ -301,8 +303,8 @@ void elf_memset_safe(struct elf_binary*, elf_ptrval dst, int c, size_t);
|
||||
* outside permitted areas.
|
||||
*/
|
||||
|
||||
-int elf_access_ok(struct elf_binary * elf,
|
||||
- uint64_t ptrval, size_t size);
|
||||
+bool elf_access_ok(struct elf_binary * elf,
|
||||
+ uint64_t ptrval, size_t size);
|
||||
|
||||
#define elf_store_val(elf, type, ptr, val) \
|
||||
({ \
|
||||
@@ -351,9 +353,9 @@ uint64_t elf_note_numeric_array(struct elf_binary *, ELF_HANDLE_DECL(elf_note),
|
||||
ELF_HANDLE_DECL(elf_note) elf_note_next(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
|
||||
|
||||
/* (Only) checks that the image has the right magic number. */
|
||||
-int elf_is_elfbinary(const void *image_start, size_t image_size);
|
||||
+bool elf_is_elfbinary(const void *image_start, size_t image_size);
|
||||
|
||||
-int elf_phdr_is_loadable(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr);
|
||||
+bool elf_phdr_is_loadable(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr);
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* xc_libelf_loader.c */
|
||||
@@ -367,7 +369,7 @@ int elf_init(struct elf_binary *elf, const char *image, size_t size);
|
||||
void elf_set_verbose(struct elf_binary *elf);
|
||||
#else
|
||||
void elf_set_log(struct elf_binary *elf, elf_log_callback*,
|
||||
- void *log_caller_pointer, int verbose);
|
||||
+ void *log_caller_pointer, bool verbose);
|
||||
#endif
|
||||
|
||||
void elf_parse_binary(struct elf_binary *elf);
|
||||
@@ -419,7 +421,7 @@ struct elf_dom_parms {
|
||||
char xen_ver[16];
|
||||
char loader[16];
|
||||
int pae;
|
||||
- int bsd_symtab;
|
||||
+ bool bsd_symtab;
|
||||
uint64_t virt_base;
|
||||
uint64_t virt_entry;
|
||||
uint64_t virt_hypercall;
|
||||
--
|
||||
1.7.2.5
|
||||
|
@ -0,0 +1,759 @@
|
||||
From e673ca50127b6c1263727aa31de0b8bb966ca7a2 Mon Sep 17 00:00:00 2001
|
||||
From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Date: Fri, 14 Jun 2013 16:43:18 +0100
|
||||
Subject: [PATCH 15/23] libelf: use only unsigned integers
|
||||
|
||||
Signed integers have undesirable undefined behaviours on overflow.
|
||||
Malicious compilers can turn apparently-correct code into code with
|
||||
security vulnerabilities etc.
|
||||
|
||||
So use only unsigned integers. Exceptions are booleans (which we have
|
||||
already changed) and error codes.
|
||||
|
||||
We _do_ change all the chars which aren't fixed constants from our own
|
||||
text segment, but not the char*s. This is because it is safe to
|
||||
access an arbitrary byte through a char*, but not necessarily safe to
|
||||
convert an arbitrary value to a char.
|
||||
|
||||
As a consequence we need to compile libelf with -Wno-pointer-sign.
|
||||
|
||||
It is OK to change all the signed integers to unsigned because all the
|
||||
inequalities in libelf are in contexts where we don't "expect"
|
||||
negative numbers.
|
||||
|
||||
In libelf-dominfo.c:elf_xen_parse we rename a variable "rc" to
|
||||
"more_notes" as it actually contains a note count derived from the
|
||||
input image. The "error" return value from elf_xen_parse_notes is
|
||||
changed from -1 to ~0U.
|
||||
|
||||
grepping shows only one occurrence of "PRId" or "%d" or "%ld" in
|
||||
libelf and xc_dom_elfloader.c (a "%d" which becomes "%u").
|
||||
|
||||
This is part of the fix to a security issue, XSA-55.
|
||||
|
||||
For those concerned about unintentional functional changes, the
|
||||
following rune produces a version of the patch which is much smaller
|
||||
and eliminates only non-functional changes:
|
||||
|
||||
GIT_EXTERNAL_DIFF=.../unsigned-differ git-diff <before>..<after>
|
||||
|
||||
where <before> and <after> are git refs for the code before and after
|
||||
this patch, and unsigned-differ is this shell script:
|
||||
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
seddery () {
|
||||
perl -pe 's/\b(?:elf_errorstatus|elf_negerrnoval)\b/int/g'
|
||||
}
|
||||
|
||||
path="$1"
|
||||
in="$2"
|
||||
out="$5"
|
||||
|
||||
set +e
|
||||
diff -pu --label "$path~" <(seddery <"$in") --label "$path" <(seddery <"$out")
|
||||
rc=$?
|
||||
set -e
|
||||
if [ $rc = 1 ]; then rc=0; fi
|
||||
exit $rc
|
||||
|
||||
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
---
|
||||
tools/libxc/Makefile | 9 +++++-
|
||||
tools/libxc/xc_dom.h | 7 +++--
|
||||
tools/libxc/xc_dom_elfloader.c | 42 ++++++++++++++++-------------
|
||||
tools/xcutils/readnotes.c | 15 +++++-----
|
||||
xen/common/libelf/Makefile | 2 +
|
||||
xen/common/libelf/libelf-dominfo.c | 52 ++++++++++++++++++-----------------
|
||||
xen/common/libelf/libelf-loader.c | 20 +++++++-------
|
||||
xen/common/libelf/libelf-tools.c | 24 ++++++++--------
|
||||
xen/include/xen/libelf.h | 21 ++++++++------
|
||||
9 files changed, 105 insertions(+), 87 deletions(-)
|
||||
|
||||
diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile
|
||||
index d8c6a60..a3fd90c 100644
|
||||
--- a/tools/libxc/Makefile
|
||||
+++ b/tools/libxc/Makefile
|
||||
@@ -52,8 +52,13 @@ endif
|
||||
vpath %.c ../../xen/common/libelf
|
||||
CFLAGS += -I../../xen/common/libelf
|
||||
|
||||
-GUEST_SRCS-y += libelf-tools.c libelf-loader.c
|
||||
-GUEST_SRCS-y += libelf-dominfo.c
|
||||
+ELF_SRCS-y += libelf-tools.c libelf-loader.c
|
||||
+ELF_SRCS-y += libelf-dominfo.c
|
||||
+
|
||||
+GUEST_SRCS-y += $(ELF_SRCS-y)
|
||||
+
|
||||
+$(patsubst %.c,%.o,$(ELF_SRCS-y)): CFLAGS += -Wno-pointer-sign
|
||||
+$(patsubst %.c,%.opic,$(ELF_SRCS-y)): CFLAGS += -Wno-pointer-sign
|
||||
|
||||
# new domain builder
|
||||
GUEST_SRCS-y += xc_dom_core.c xc_dom_boot.c
|
||||
diff --git a/tools/libxc/xc_dom.h b/tools/libxc/xc_dom.h
|
||||
index 9f8037e..0161459 100644
|
||||
--- a/tools/libxc/xc_dom.h
|
||||
+++ b/tools/libxc/xc_dom.h
|
||||
@@ -140,9 +140,10 @@ struct xc_dom_image {
|
||||
|
||||
struct xc_dom_loader {
|
||||
char *name;
|
||||
- int (*probe) (struct xc_dom_image * dom);
|
||||
- int (*parser) (struct xc_dom_image * dom);
|
||||
- int (*loader) (struct xc_dom_image * dom);
|
||||
+ /* Sadly the error returns from these functions are not consistent: */
|
||||
+ elf_negerrnoval (*probe) (struct xc_dom_image * dom);
|
||||
+ elf_negerrnoval (*parser) (struct xc_dom_image * dom);
|
||||
+ elf_errorstatus (*loader) (struct xc_dom_image * dom);
|
||||
|
||||
struct xc_dom_loader *next;
|
||||
};
|
||||
diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c
|
||||
index 9ba64ae..62a0d3b 100644
|
||||
--- a/tools/libxc/xc_dom_elfloader.c
|
||||
+++ b/tools/libxc/xc_dom_elfloader.c
|
||||
@@ -84,7 +84,7 @@ static char *xc_dom_guest_type(struct xc_dom_image *dom,
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* parse elf binary */
|
||||
|
||||
-static int check_elf_kernel(struct xc_dom_image *dom, bool verbose)
|
||||
+static elf_negerrnoval check_elf_kernel(struct xc_dom_image *dom, bool verbose)
|
||||
{
|
||||
if ( dom->kernel_blob == NULL )
|
||||
{
|
||||
@@ -106,12 +106,12 @@ static int check_elf_kernel(struct xc_dom_image *dom, bool verbose)
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int xc_dom_probe_elf_kernel(struct xc_dom_image *dom)
|
||||
+static elf_negerrnoval xc_dom_probe_elf_kernel(struct xc_dom_image *dom)
|
||||
{
|
||||
return check_elf_kernel(dom, 0);
|
||||
}
|
||||
|
||||
-static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
+static elf_errorstatus xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
struct elf_binary *elf, bool load)
|
||||
{
|
||||
struct elf_binary syms;
|
||||
@@ -119,7 +119,7 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
xen_vaddr_t symtab, maxaddr;
|
||||
ELF_PTRVAL_CHAR hdr;
|
||||
size_t size;
|
||||
- int h, count, type, i, tables = 0;
|
||||
+ unsigned h, count, type, i, tables = 0;
|
||||
|
||||
if ( elf_swap(elf) )
|
||||
{
|
||||
@@ -140,13 +140,13 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
elf->caller_xdest_base = hdr_ptr;
|
||||
elf->caller_xdest_size = allow_size;
|
||||
hdr = ELF_REALPTR2PTRVAL(hdr_ptr);
|
||||
- elf_store_val(elf, int, hdr, size - sizeof(int));
|
||||
+ elf_store_val(elf, unsigned, hdr, size - sizeof(unsigned));
|
||||
}
|
||||
else
|
||||
{
|
||||
char *hdr_ptr;
|
||||
|
||||
- size = sizeof(int) + elf_size(elf, elf->ehdr) +
|
||||
+ size = sizeof(unsigned) + elf_size(elf, elf->ehdr) +
|
||||
elf_shdr_count(elf) * elf_size(elf, shdr);
|
||||
hdr_ptr = xc_dom_malloc(dom, size);
|
||||
if ( hdr_ptr == NULL )
|
||||
@@ -157,15 +157,15 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
dom->bsd_symtab_start = elf_round_up(elf, dom->kernel_seg.vend);
|
||||
}
|
||||
|
||||
- elf_memcpy_safe(elf, hdr + sizeof(int),
|
||||
+ elf_memcpy_safe(elf, hdr + sizeof(unsigned),
|
||||
ELF_IMAGE_BASE(elf),
|
||||
elf_size(elf, elf->ehdr));
|
||||
- elf_memcpy_safe(elf, hdr + sizeof(int) + elf_size(elf, elf->ehdr),
|
||||
+ elf_memcpy_safe(elf, hdr + sizeof(unsigned) + elf_size(elf, elf->ehdr),
|
||||
ELF_IMAGE_BASE(elf) + elf_uval(elf, elf->ehdr, e_shoff),
|
||||
elf_shdr_count(elf) * elf_size(elf, shdr));
|
||||
if ( elf_64bit(elf) )
|
||||
{
|
||||
- Elf64_Ehdr *ehdr = (Elf64_Ehdr *)(hdr + sizeof(int));
|
||||
+ Elf64_Ehdr *ehdr = (Elf64_Ehdr *)(hdr + sizeof(unsigned));
|
||||
ehdr->e_phoff = 0;
|
||||
ehdr->e_phentsize = 0;
|
||||
ehdr->e_phnum = 0;
|
||||
@@ -174,22 +174,22 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
}
|
||||
else
|
||||
{
|
||||
- Elf32_Ehdr *ehdr = (Elf32_Ehdr *)(hdr + sizeof(int));
|
||||
+ Elf32_Ehdr *ehdr = (Elf32_Ehdr *)(hdr + sizeof(unsigned));
|
||||
ehdr->e_phoff = 0;
|
||||
ehdr->e_phentsize = 0;
|
||||
ehdr->e_phnum = 0;
|
||||
ehdr->e_shoff = elf_size(elf, elf->ehdr);
|
||||
ehdr->e_shstrndx = SHN_UNDEF;
|
||||
}
|
||||
- if ( elf->caller_xdest_size < sizeof(int) )
|
||||
+ if ( elf->caller_xdest_size < sizeof(unsigned) )
|
||||
{
|
||||
DOMPRINTF("%s/%s: header size %"PRIx64" too small",
|
||||
__FUNCTION__, load ? "load" : "parse",
|
||||
(uint64_t)elf->caller_xdest_size);
|
||||
return -1;
|
||||
}
|
||||
- if ( elf_init(&syms, elf->caller_xdest_base + sizeof(int),
|
||||
- elf->caller_xdest_size - sizeof(int)) )
|
||||
+ if ( elf_init(&syms, elf->caller_xdest_base + sizeof(unsigned),
|
||||
+ elf->caller_xdest_size - sizeof(unsigned)) )
|
||||
return -1;
|
||||
|
||||
/*
|
||||
@@ -209,7 +209,7 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
|
||||
xc_elf_set_logfile(dom->xch, &syms, 1);
|
||||
|
||||
- symtab = dom->bsd_symtab_start + sizeof(int);
|
||||
+ symtab = dom->bsd_symtab_start + sizeof(unsigned);
|
||||
maxaddr = elf_round_up(&syms, symtab + elf_size(&syms, syms.ehdr) +
|
||||
elf_shdr_count(&syms) * elf_size(&syms, shdr));
|
||||
|
||||
@@ -255,7 +255,7 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
size = elf_uval(&syms, shdr, sh_size);
|
||||
maxaddr = elf_round_up(&syms, maxaddr + size);
|
||||
tables++;
|
||||
- DOMPRINTF("%s: h=%d %s, size=0x%zx, maxaddr=0x%" PRIx64 "",
|
||||
+ DOMPRINTF("%s: h=%u %s, size=0x%zx, maxaddr=0x%" PRIx64 "",
|
||||
__FUNCTION__, h,
|
||||
type == SHT_SYMTAB ? "symtab" : "strtab",
|
||||
size, maxaddr);
|
||||
@@ -294,10 +294,14 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int xc_dom_parse_elf_kernel(struct xc_dom_image *dom)
|
||||
+static elf_errorstatus xc_dom_parse_elf_kernel(struct xc_dom_image *dom)
|
||||
+ /*
|
||||
+ * This function sometimes returns -1 for error and sometimes
|
||||
+ * an errno value. ?!?!
|
||||
+ */
|
||||
{
|
||||
struct elf_binary *elf;
|
||||
- int rc;
|
||||
+ elf_errorstatus rc;
|
||||
|
||||
rc = check_elf_kernel(dom, 1);
|
||||
if ( rc != 0 )
|
||||
@@ -358,10 +362,10 @@ out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
-static int xc_dom_load_elf_kernel(struct xc_dom_image *dom)
|
||||
+static elf_errorstatus xc_dom_load_elf_kernel(struct xc_dom_image *dom)
|
||||
{
|
||||
struct elf_binary *elf = dom->private_loader;
|
||||
- int rc;
|
||||
+ elf_errorstatus rc;
|
||||
xen_pfn_t pages;
|
||||
|
||||
elf->dest_base = xc_dom_seg_to_ptr_pages(dom, &dom->kernel_seg, &pages);
|
||||
diff --git a/tools/xcutils/readnotes.c b/tools/xcutils/readnotes.c
|
||||
index d1f7a30..2ca7732 100644
|
||||
--- a/tools/xcutils/readnotes.c
|
||||
+++ b/tools/xcutils/readnotes.c
|
||||
@@ -70,7 +70,7 @@ static void print_numeric_note(const char *prefix, struct elf_binary *elf,
|
||||
ELF_HANDLE_DECL(elf_note) note)
|
||||
{
|
||||
uint64_t value = elf_note_numeric(elf, note);
|
||||
- int descsz = elf_uval(elf, note, descsz);
|
||||
+ unsigned descsz = elf_uval(elf, note, descsz);
|
||||
|
||||
printf("%s: %#*" PRIx64 " (%d bytes)\n",
|
||||
prefix, 2+2*descsz, value, descsz);
|
||||
@@ -79,7 +79,7 @@ static void print_numeric_note(const char *prefix, struct elf_binary *elf,
|
||||
static void print_l1_mfn_valid_note(const char *prefix, struct elf_binary *elf,
|
||||
ELF_HANDLE_DECL(elf_note) note)
|
||||
{
|
||||
- int descsz = elf_uval(elf, note, descsz);
|
||||
+ unsigned descsz = elf_uval(elf, note, descsz);
|
||||
ELF_PTRVAL_CONST_VOID desc = elf_note_desc(elf, note);
|
||||
|
||||
/* XXX should be able to cope with a list of values. */
|
||||
@@ -99,10 +99,10 @@ static void print_l1_mfn_valid_note(const char *prefix, struct elf_binary *elf,
|
||||
|
||||
}
|
||||
|
||||
-static int print_notes(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) start, ELF_HANDLE_DECL(elf_note) end)
|
||||
+static unsigned print_notes(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) start, ELF_HANDLE_DECL(elf_note) end)
|
||||
{
|
||||
ELF_HANDLE_DECL(elf_note) note;
|
||||
- int notes_found = 0;
|
||||
+ unsigned notes_found = 0;
|
||||
const char *this_note_name;
|
||||
|
||||
for ( note = start; ELF_HANDLE_PTRVAL(note) < ELF_HANDLE_PTRVAL(end); note = elf_note_next(elf, note) )
|
||||
@@ -161,7 +161,7 @@ static int print_notes(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) start,
|
||||
break;
|
||||
default:
|
||||
printf("unknown note type %#x\n",
|
||||
- (int)elf_uval(elf, note, type));
|
||||
+ (unsigned)elf_uval(elf, note, type));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -171,12 +171,13 @@ static int print_notes(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) start,
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char *f;
|
||||
- int fd,h,size,usize,count;
|
||||
+ int fd;
|
||||
+ unsigned h,size,usize,count;
|
||||
void *image,*tmp;
|
||||
struct stat st;
|
||||
struct elf_binary elf;
|
||||
ELF_HANDLE_DECL(elf_shdr) shdr;
|
||||
- int notes_found = 0;
|
||||
+ unsigned notes_found = 0;
|
||||
|
||||
struct setup_header *hdr;
|
||||
uint64_t payload_offset, payload_length;
|
||||
diff --git a/xen/common/libelf/Makefile b/xen/common/libelf/Makefile
|
||||
index 18dc8e2..5bf8f76 100644
|
||||
--- a/xen/common/libelf/Makefile
|
||||
+++ b/xen/common/libelf/Makefile
|
||||
@@ -2,6 +2,8 @@ obj-bin-y := libelf.o
|
||||
|
||||
SECTIONS := text data $(SPECIAL_DATA_SECTIONS)
|
||||
|
||||
+CFLAGS += -Wno-pointer-sign
|
||||
+
|
||||
libelf.o: libelf-temp.o Makefile
|
||||
$(OBJCOPY) $(foreach s,$(SECTIONS),--rename-section .$(s)=.init.$(s)) $< $@
|
||||
|
||||
diff --git a/xen/common/libelf/libelf-dominfo.c b/xen/common/libelf/libelf-dominfo.c
|
||||
index 12b6c2a..cdd0d31 100644
|
||||
--- a/xen/common/libelf/libelf-dominfo.c
|
||||
+++ b/xen/common/libelf/libelf-dominfo.c
|
||||
@@ -29,15 +29,15 @@ static const char *const elf_xen_feature_names[] = {
|
||||
[XENFEAT_pae_pgdir_above_4gb] = "pae_pgdir_above_4gb",
|
||||
[XENFEAT_dom0] = "dom0"
|
||||
};
|
||||
-static const int elf_xen_features =
|
||||
+static const unsigned elf_xen_features =
|
||||
sizeof(elf_xen_feature_names) / sizeof(elf_xen_feature_names[0]);
|
||||
|
||||
-int elf_xen_parse_features(const char *features,
|
||||
+elf_errorstatus elf_xen_parse_features(const char *features,
|
||||
uint32_t *supported,
|
||||
uint32_t *required)
|
||||
{
|
||||
- char feature[64];
|
||||
- int pos, len, i;
|
||||
+ unsigned char feature[64];
|
||||
+ unsigned pos, len, i;
|
||||
|
||||
if ( features == NULL )
|
||||
return 0;
|
||||
@@ -94,7 +94,7 @@ int elf_xen_parse_features(const char *features,
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* xen elf notes */
|
||||
|
||||
-int elf_xen_parse_note(struct elf_binary *elf,
|
||||
+elf_errorstatus elf_xen_parse_note(struct elf_binary *elf,
|
||||
struct elf_dom_parms *parms,
|
||||
ELF_HANDLE_DECL(elf_note) note)
|
||||
{
|
||||
@@ -125,7 +125,7 @@ int elf_xen_parse_note(struct elf_binary *elf,
|
||||
const char *str = NULL;
|
||||
uint64_t val = 0;
|
||||
unsigned int i;
|
||||
- int type = elf_uval(elf, note, type);
|
||||
+ unsigned type = elf_uval(elf, note, type);
|
||||
|
||||
if ( (type >= sizeof(note_desc) / sizeof(note_desc[0])) ||
|
||||
(note_desc[type].name == NULL) )
|
||||
@@ -216,12 +216,14 @@ int elf_xen_parse_note(struct elf_binary *elf,
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int elf_xen_parse_notes(struct elf_binary *elf,
|
||||
+#define ELF_NOTE_INVALID (~0U)
|
||||
+
|
||||
+static unsigned elf_xen_parse_notes(struct elf_binary *elf,
|
||||
struct elf_dom_parms *parms,
|
||||
ELF_PTRVAL_CONST_VOID start,
|
||||
ELF_PTRVAL_CONST_VOID end)
|
||||
{
|
||||
- int xen_elfnotes = 0;
|
||||
+ unsigned xen_elfnotes = 0;
|
||||
ELF_HANDLE_DECL(elf_note) note;
|
||||
const char *note_name;
|
||||
|
||||
@@ -237,7 +239,7 @@ static int elf_xen_parse_notes(struct elf_binary *elf,
|
||||
if ( strcmp(note_name, "Xen") )
|
||||
continue;
|
||||
if ( elf_xen_parse_note(elf, parms, note) )
|
||||
- return -1;
|
||||
+ return ELF_NOTE_INVALID;
|
||||
xen_elfnotes++;
|
||||
}
|
||||
return xen_elfnotes;
|
||||
@@ -246,12 +248,12 @@ static int elf_xen_parse_notes(struct elf_binary *elf,
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* __xen_guest section */
|
||||
|
||||
-int elf_xen_parse_guest_info(struct elf_binary *elf,
|
||||
+elf_errorstatus elf_xen_parse_guest_info(struct elf_binary *elf,
|
||||
struct elf_dom_parms *parms)
|
||||
{
|
||||
ELF_PTRVAL_CONST_CHAR h;
|
||||
- char name[32], value[128];
|
||||
- int len;
|
||||
+ unsigned char name[32], value[128];
|
||||
+ unsigned len;
|
||||
|
||||
h = parms->guest_info;
|
||||
#define STAR(h) (elf_access_unsigned(elf, (h), 0, 1))
|
||||
@@ -334,13 +336,13 @@ int elf_xen_parse_guest_info(struct elf_binary *elf,
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* sanity checks */
|
||||
|
||||
-static int elf_xen_note_check(struct elf_binary *elf,
|
||||
+static elf_errorstatus elf_xen_note_check(struct elf_binary *elf,
|
||||
struct elf_dom_parms *parms)
|
||||
{
|
||||
if ( (ELF_PTRVAL_INVALID(parms->elf_note_start)) &&
|
||||
(ELF_PTRVAL_INVALID(parms->guest_info)) )
|
||||
{
|
||||
- int machine = elf_uval(elf, elf->ehdr, e_machine);
|
||||
+ unsigned machine = elf_uval(elf, elf->ehdr, e_machine);
|
||||
if ( (machine == EM_386) || (machine == EM_X86_64) )
|
||||
{
|
||||
elf_err(elf, "%s: ERROR: Not a Xen-ELF image: "
|
||||
@@ -378,7 +380,7 @@ static int elf_xen_note_check(struct elf_binary *elf,
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int elf_xen_addr_calc_check(struct elf_binary *elf,
|
||||
+static elf_errorstatus elf_xen_addr_calc_check(struct elf_binary *elf,
|
||||
struct elf_dom_parms *parms)
|
||||
{
|
||||
if ( (parms->elf_paddr_offset != UNSET_ADDR) &&
|
||||
@@ -464,13 +466,13 @@ static int elf_xen_addr_calc_check(struct elf_binary *elf,
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* glue it all together ... */
|
||||
|
||||
-int elf_xen_parse(struct elf_binary *elf,
|
||||
+elf_errorstatus elf_xen_parse(struct elf_binary *elf,
|
||||
struct elf_dom_parms *parms)
|
||||
{
|
||||
ELF_HANDLE_DECL(elf_shdr) shdr;
|
||||
ELF_HANDLE_DECL(elf_phdr) phdr;
|
||||
- int xen_elfnotes = 0;
|
||||
- int i, count, rc;
|
||||
+ unsigned xen_elfnotes = 0;
|
||||
+ unsigned i, count, more_notes;
|
||||
|
||||
elf_memset_unchecked(parms, 0, sizeof(*parms));
|
||||
parms->virt_base = UNSET_ADDR;
|
||||
@@ -495,13 +497,13 @@ int elf_xen_parse(struct elf_binary *elf,
|
||||
if (elf_uval(elf, phdr, p_offset) == 0)
|
||||
continue;
|
||||
|
||||
- rc = elf_xen_parse_notes(elf, parms,
|
||||
+ more_notes = elf_xen_parse_notes(elf, parms,
|
||||
elf_segment_start(elf, phdr),
|
||||
elf_segment_end(elf, phdr));
|
||||
- if ( rc == -1 )
|
||||
+ if ( more_notes == ELF_NOTE_INVALID )
|
||||
return -1;
|
||||
|
||||
- xen_elfnotes += rc;
|
||||
+ xen_elfnotes += more_notes;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -518,17 +520,17 @@ int elf_xen_parse(struct elf_binary *elf,
|
||||
if ( elf_uval(elf, shdr, sh_type) != SHT_NOTE )
|
||||
continue;
|
||||
|
||||
- rc = elf_xen_parse_notes(elf, parms,
|
||||
+ more_notes = elf_xen_parse_notes(elf, parms,
|
||||
elf_section_start(elf, shdr),
|
||||
elf_section_end(elf, shdr));
|
||||
|
||||
- if ( rc == -1 )
|
||||
+ if ( more_notes == ELF_NOTE_INVALID )
|
||||
return -1;
|
||||
|
||||
- if ( xen_elfnotes == 0 && rc > 0 )
|
||||
+ if ( xen_elfnotes == 0 && more_notes > 0 )
|
||||
elf_msg(elf, "%s: using notes from SHT_NOTE section\n", __FUNCTION__);
|
||||
|
||||
- xen_elfnotes += rc;
|
||||
+ xen_elfnotes += more_notes;
|
||||
}
|
||||
|
||||
}
|
||||
diff --git a/xen/common/libelf/libelf-loader.c b/xen/common/libelf/libelf-loader.c
|
||||
index 0dccd4d..c3a9e51 100644
|
||||
--- a/xen/common/libelf/libelf-loader.c
|
||||
+++ b/xen/common/libelf/libelf-loader.c
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
-int elf_init(struct elf_binary *elf, const char *image_input, size_t size)
|
||||
+elf_errorstatus elf_init(struct elf_binary *elf, const char *image_input, size_t size)
|
||||
{
|
||||
ELF_HANDLE_DECL(elf_shdr) shdr;
|
||||
uint64_t i, count, section, offset;
|
||||
@@ -114,7 +114,7 @@ void elf_set_log(struct elf_binary *elf, elf_log_callback *log_callback,
|
||||
elf->verbose = verbose;
|
||||
}
|
||||
|
||||
-static int elf_load_image(struct elf_binary *elf,
|
||||
+static elf_errorstatus elf_load_image(struct elf_binary *elf,
|
||||
ELF_PTRVAL_VOID dst, ELF_PTRVAL_CONST_VOID src,
|
||||
uint64_t filesz, uint64_t memsz)
|
||||
{
|
||||
@@ -129,9 +129,9 @@ void elf_set_verbose(struct elf_binary *elf)
|
||||
elf->verbose = 1;
|
||||
}
|
||||
|
||||
-static int elf_load_image(struct elf_binary *elf, ELF_PTRVAL_VOID dst, ELF_PTRVAL_CONST_VOID src, uint64_t filesz, uint64_t memsz)
|
||||
+static elf_errorstatus elf_load_image(struct elf_binary *elf, ELF_PTRVAL_VOID dst, ELF_PTRVAL_CONST_VOID src, uint64_t filesz, uint64_t memsz)
|
||||
{
|
||||
- int rc;
|
||||
+ elf_errorstatus rc;
|
||||
if ( filesz > ULONG_MAX || memsz > ULONG_MAX )
|
||||
return -1;
|
||||
/* We trust the dom0 kernel image completely, so we don't care
|
||||
@@ -151,7 +151,7 @@ void elf_parse_bsdsyms(struct elf_binary *elf, uint64_t pstart)
|
||||
{
|
||||
uint64_t sz;
|
||||
ELF_HANDLE_DECL(elf_shdr) shdr;
|
||||
- int i, type;
|
||||
+ unsigned i, type;
|
||||
|
||||
if ( !ELF_HANDLE_VALID(elf->sym_tab) )
|
||||
return;
|
||||
@@ -187,7 +187,7 @@ static void elf_load_bsdsyms(struct elf_binary *elf)
|
||||
ELF_PTRVAL_VOID symbase;
|
||||
ELF_PTRVAL_VOID symtab_addr;
|
||||
ELF_HANDLE_DECL_NONCONST(elf_shdr) shdr;
|
||||
- int i, type;
|
||||
+ unsigned i, type;
|
||||
|
||||
if ( !elf->bsd_symtab_pstart )
|
||||
return;
|
||||
@@ -220,7 +220,7 @@ do { \
|
||||
elf_memcpy_safe(elf, ELF_HANDLE_PTRVAL(shdr),
|
||||
ELF_IMAGE_BASE(elf) + elf_uval(elf, elf->ehdr, e_shoff),
|
||||
sz);
|
||||
- maxva = ELF_OBSOLETE_VOIDP_CAST elf_round_up(elf, (long)maxva + sz);
|
||||
+ maxva = ELF_OBSOLETE_VOIDP_CAST elf_round_up(elf, (unsigned long)maxva + sz);
|
||||
|
||||
for ( i = 0; i < elf_shdr_count(elf); i++ )
|
||||
{
|
||||
@@ -233,10 +233,10 @@ do { \
|
||||
elf_memcpy_safe(elf, maxva, elf_section_start(elf, shdr), sz);
|
||||
/* Mangled to be based on ELF header location. */
|
||||
elf_hdr_elm(elf, shdr, sh_offset, maxva - symtab_addr);
|
||||
- maxva = ELF_OBSOLETE_VOIDP_CAST elf_round_up(elf, (long)maxva + sz);
|
||||
+ maxva = ELF_OBSOLETE_VOIDP_CAST elf_round_up(elf, (unsigned long)maxva + sz);
|
||||
}
|
||||
shdr = ELF_MAKE_HANDLE(elf_shdr, ELF_HANDLE_PTRVAL(shdr) +
|
||||
- (long)elf_uval(elf, elf->ehdr, e_shentsize));
|
||||
+ (unsigned long)elf_uval(elf, elf->ehdr, e_shentsize));
|
||||
}
|
||||
|
||||
/* Write down the actual sym size. */
|
||||
@@ -273,7 +273,7 @@ void elf_parse_binary(struct elf_binary *elf)
|
||||
__FUNCTION__, elf->pstart, elf->pend);
|
||||
}
|
||||
|
||||
-int elf_load_binary(struct elf_binary *elf)
|
||||
+elf_errorstatus elf_load_binary(struct elf_binary *elf)
|
||||
{
|
||||
ELF_HANDLE_DECL(elf_phdr) phdr;
|
||||
uint64_t i, count, paddr, offset, filesz, memsz;
|
||||
diff --git a/xen/common/libelf/libelf-tools.c b/xen/common/libelf/libelf-tools.c
|
||||
index fa58f76..46d4ab1 100644
|
||||
--- a/xen/common/libelf/libelf-tools.c
|
||||
+++ b/xen/common/libelf/libelf-tools.c
|
||||
@@ -122,19 +122,19 @@ uint64_t elf_access_unsigned(struct elf_binary * elf, elf_ptrval base,
|
||||
|
||||
uint64_t elf_round_up(struct elf_binary *elf, uint64_t addr)
|
||||
{
|
||||
- int elf_round = (elf_64bit(elf) ? 8 : 4) - 1;
|
||||
+ uint64_t elf_round = (elf_64bit(elf) ? 8 : 4) - 1;
|
||||
|
||||
return (addr + elf_round) & ~elf_round;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
-int elf_shdr_count(struct elf_binary *elf)
|
||||
+unsigned elf_shdr_count(struct elf_binary *elf)
|
||||
{
|
||||
return elf_uval(elf, elf->ehdr, e_shnum);
|
||||
}
|
||||
|
||||
-int elf_phdr_count(struct elf_binary *elf)
|
||||
+unsigned elf_phdr_count(struct elf_binary *elf)
|
||||
{
|
||||
return elf_uval(elf, elf->ehdr, e_phnum);
|
||||
}
|
||||
@@ -144,7 +144,7 @@ ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_name(struct elf_binary *elf, const char *n
|
||||
uint64_t count = elf_shdr_count(elf);
|
||||
ELF_HANDLE_DECL(elf_shdr) shdr;
|
||||
const char *sname;
|
||||
- int i;
|
||||
+ unsigned i;
|
||||
|
||||
for ( i = 0; i < count; i++ )
|
||||
{
|
||||
@@ -156,7 +156,7 @@ ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_name(struct elf_binary *elf, const char *n
|
||||
return ELF_INVALID_HANDLE(elf_shdr);
|
||||
}
|
||||
|
||||
-ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_index(struct elf_binary *elf, int index)
|
||||
+ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_index(struct elf_binary *elf, unsigned index)
|
||||
{
|
||||
uint64_t count = elf_shdr_count(elf);
|
||||
ELF_PTRVAL_CONST_VOID ptr;
|
||||
@@ -170,7 +170,7 @@ ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_index(struct elf_binary *elf, int index)
|
||||
return ELF_MAKE_HANDLE(elf_shdr, ptr);
|
||||
}
|
||||
|
||||
-ELF_HANDLE_DECL(elf_phdr) elf_phdr_by_index(struct elf_binary *elf, int index)
|
||||
+ELF_HANDLE_DECL(elf_phdr) elf_phdr_by_index(struct elf_binary *elf, unsigned index)
|
||||
{
|
||||
uint64_t count = elf_uval(elf, elf->ehdr, e_phnum);
|
||||
ELF_PTRVAL_CONST_VOID ptr;
|
||||
@@ -264,7 +264,7 @@ ELF_HANDLE_DECL(elf_sym) elf_sym_by_name(struct elf_binary *elf, const char *sym
|
||||
return ELF_INVALID_HANDLE(elf_sym);
|
||||
}
|
||||
|
||||
-ELF_HANDLE_DECL(elf_sym) elf_sym_by_index(struct elf_binary *elf, int index)
|
||||
+ELF_HANDLE_DECL(elf_sym) elf_sym_by_index(struct elf_binary *elf, unsigned index)
|
||||
{
|
||||
ELF_PTRVAL_CONST_VOID ptr = elf_section_start(elf, elf->sym_tab);
|
||||
ELF_HANDLE_DECL(elf_sym) sym;
|
||||
@@ -280,7 +280,7 @@ const char *elf_note_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note
|
||||
|
||||
ELF_PTRVAL_CONST_VOID elf_note_desc(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note)
|
||||
{
|
||||
- int namesz = (elf_uval(elf, note, namesz) + 3) & ~3;
|
||||
+ unsigned namesz = (elf_uval(elf, note, namesz) + 3) & ~3;
|
||||
|
||||
return ELF_HANDLE_PTRVAL(note) + elf_size(elf, note) + namesz;
|
||||
}
|
||||
@@ -288,7 +288,7 @@ ELF_PTRVAL_CONST_VOID elf_note_desc(struct elf_binary *elf, ELF_HANDLE_DECL(elf_
|
||||
uint64_t elf_note_numeric(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note)
|
||||
{
|
||||
ELF_PTRVAL_CONST_VOID desc = elf_note_desc(elf, note);
|
||||
- int descsz = elf_uval(elf, note, descsz);
|
||||
+ unsigned descsz = elf_uval(elf, note, descsz);
|
||||
|
||||
switch (descsz)
|
||||
{
|
||||
@@ -306,7 +306,7 @@ uint64_t elf_note_numeric_array(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note
|
||||
unsigned int unitsz, unsigned int idx)
|
||||
{
|
||||
ELF_PTRVAL_CONST_VOID desc = elf_note_desc(elf, note);
|
||||
- int descsz = elf_uval(elf, note, descsz);
|
||||
+ unsigned descsz = elf_uval(elf, note, descsz);
|
||||
|
||||
if ( descsz % unitsz || idx >= descsz / unitsz )
|
||||
return 0;
|
||||
@@ -324,8 +324,8 @@ uint64_t elf_note_numeric_array(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note
|
||||
|
||||
ELF_HANDLE_DECL(elf_note) elf_note_next(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note)
|
||||
{
|
||||
- int namesz = (elf_uval(elf, note, namesz) + 3) & ~3;
|
||||
- int descsz = (elf_uval(elf, note, descsz) + 3) & ~3;
|
||||
+ unsigned namesz = (elf_uval(elf, note, namesz) + 3) & ~3;
|
||||
+ unsigned descsz = (elf_uval(elf, note, descsz) + 3) & ~3;
|
||||
|
||||
return ELF_MAKE_HANDLE(elf_note, ELF_HANDLE_PTRVAL(note) + elf_size(elf, note) + namesz + descsz);
|
||||
}
|
||||
diff --git a/xen/include/xen/libelf.h b/xen/include/xen/libelf.h
|
||||
index 951430f..87e126a 100644
|
||||
--- a/xen/include/xen/libelf.h
|
||||
+++ b/xen/include/xen/libelf.h
|
||||
@@ -31,6 +31,9 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
+typedef int elf_errorstatus; /* 0: ok; -ve (normally -1): error */
|
||||
+typedef int elf_negerrnoval; /* 0: ok; -EFOO: error */
|
||||
+
|
||||
#undef ELFSIZE
|
||||
#include "elfstructs.h"
|
||||
#ifdef __XEN__
|
||||
@@ -328,12 +331,12 @@ bool elf_access_ok(struct elf_binary * elf,
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* xc_libelf_tools.c */
|
||||
|
||||
-int elf_shdr_count(struct elf_binary *elf);
|
||||
-int elf_phdr_count(struct elf_binary *elf);
|
||||
+unsigned elf_shdr_count(struct elf_binary *elf);
|
||||
+unsigned elf_phdr_count(struct elf_binary *elf);
|
||||
|
||||
ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_name(struct elf_binary *elf, const char *name);
|
||||
-ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_index(struct elf_binary *elf, int index);
|
||||
-ELF_HANDLE_DECL(elf_phdr) elf_phdr_by_index(struct elf_binary *elf, int index);
|
||||
+ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_index(struct elf_binary *elf, unsigned index);
|
||||
+ELF_HANDLE_DECL(elf_phdr) elf_phdr_by_index(struct elf_binary *elf, unsigned index);
|
||||
|
||||
const char *elf_section_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr); /* might return NULL if inputs are invalid */
|
||||
ELF_PTRVAL_CONST_VOID elf_section_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr);
|
||||
@@ -343,7 +346,7 @@ ELF_PTRVAL_CONST_VOID elf_segment_start(struct elf_binary *elf, ELF_HANDLE_DECL(
|
||||
ELF_PTRVAL_CONST_VOID elf_segment_end(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr);
|
||||
|
||||
ELF_HANDLE_DECL(elf_sym) elf_sym_by_name(struct elf_binary *elf, const char *symbol);
|
||||
-ELF_HANDLE_DECL(elf_sym) elf_sym_by_index(struct elf_binary *elf, int index);
|
||||
+ELF_HANDLE_DECL(elf_sym) elf_sym_by_index(struct elf_binary *elf, unsigned index);
|
||||
|
||||
const char *elf_note_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note); /* may return NULL */
|
||||
ELF_PTRVAL_CONST_VOID elf_note_desc(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
|
||||
@@ -360,7 +363,7 @@ bool elf_phdr_is_loadable(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* xc_libelf_loader.c */
|
||||
|
||||
-int elf_init(struct elf_binary *elf, const char *image, size_t size);
|
||||
+elf_errorstatus elf_init(struct elf_binary *elf, const char *image, size_t size);
|
||||
/*
|
||||
* image and size must be correct. They will be recorded in
|
||||
* *elf, and must remain valid while the elf is in use.
|
||||
@@ -373,7 +376,7 @@ void elf_set_log(struct elf_binary *elf, elf_log_callback*,
|
||||
#endif
|
||||
|
||||
void elf_parse_binary(struct elf_binary *elf);
|
||||
-int elf_load_binary(struct elf_binary *elf);
|
||||
+elf_errorstatus elf_load_binary(struct elf_binary *elf);
|
||||
|
||||
ELF_PTRVAL_VOID elf_get_ptr(struct elf_binary *elf, unsigned long addr);
|
||||
uint64_t elf_lookup_addr(struct elf_binary *elf, const char *symbol);
|
||||
@@ -386,7 +389,7 @@ const char *elf_check_broken(const struct elf_binary *elf); /* NULL means OK */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* xc_libelf_relocate.c */
|
||||
|
||||
-int elf_reloc(struct elf_binary *elf);
|
||||
+elf_errorstatus elf_reloc(struct elf_binary *elf);
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* xc_libelf_dominfo.c */
|
||||
@@ -420,7 +423,7 @@ struct elf_dom_parms {
|
||||
char guest_ver[16];
|
||||
char xen_ver[16];
|
||||
char loader[16];
|
||||
- int pae;
|
||||
+ int pae; /* some kind of enum apparently */
|
||||
bool bsd_symtab;
|
||||
uint64_t virt_base;
|
||||
uint64_t virt_entry;
|
||||
--
|
||||
1.7.2.5
|
||||
|
@ -0,0 +1,409 @@
|
||||
From 52d8cc2dd3bb3e0f6d51e00280da934e8d91653a Mon Sep 17 00:00:00 2001
|
||||
From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Date: Fri, 14 Jun 2013 16:43:18 +0100
|
||||
Subject: [PATCH 16/23] libelf: check loops for running away
|
||||
|
||||
Ensure that libelf does not have any loops which can run away
|
||||
indefinitely even if the input is bogus. (Grepped for \bfor, \bwhile
|
||||
and \bgoto in libelf and xc_dom_*loader*.c.)
|
||||
|
||||
Changes needed:
|
||||
* elf_note_next uses the note's unchecked alleged length, which might
|
||||
wrap round. If it does, return ELF_MAX_PTRVAL (0xfff..fff) instead,
|
||||
which will be beyond the end of the section and so terminate the
|
||||
caller's loop. Also check that the returned psuedopointer is sane.
|
||||
* In various loops over section and program headers, check that the
|
||||
calculated header pointer is still within the image, and quit the
|
||||
loop if it isn't.
|
||||
* Some fixed limits to avoid potentially O(image_size^2) loops:
|
||||
- maximum length of strings: 4K (longer ones ignored totally)
|
||||
- maximum total number of ELF notes: 65536 (any more are ignored)
|
||||
* Check that the total program contents (text, data) we copy or
|
||||
initialise doesn't exceed twice the output image area size.
|
||||
* Remove an entirely useless loop from elf_xen_parse (!)
|
||||
* Replace a nested search loop in in xc_dom_load_elf_symtab in
|
||||
xc_dom_elfloader.c by a precomputation of a bitmap of referenced
|
||||
symtabs.
|
||||
|
||||
We have not changed loops which might, in principle, iterate over the
|
||||
whole image - even if they might do so one byte at a time with a
|
||||
nontrivial access check function in the middle.
|
||||
|
||||
This is part of the fix to a security issue, XSA-55.
|
||||
|
||||
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
---
|
||||
tools/libxc/xc_dom_elfloader.c | 33 ++++++++++++++++++-------
|
||||
xen/common/libelf/libelf-dominfo.c | 43 ++++++++++++++++++++------------
|
||||
xen/common/libelf/libelf-loader.c | 47 ++++++++++++++++++++++++++++++++++-
|
||||
xen/common/libelf/libelf-tools.c | 28 ++++++++++++++++++++-
|
||||
xen/include/xen/libelf.h | 13 ++++++++++
|
||||
5 files changed, 135 insertions(+), 29 deletions(-)
|
||||
|
||||
diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c
|
||||
index 62a0d3b..c5014d2 100644
|
||||
--- a/tools/libxc/xc_dom_elfloader.c
|
||||
+++ b/tools/libxc/xc_dom_elfloader.c
|
||||
@@ -28,6 +28,7 @@
|
||||
|
||||
#include "xg_private.h"
|
||||
#include "xc_dom.h"
|
||||
+#include "xc_bitops.h"
|
||||
|
||||
#define XEN_VER "xen-3.0"
|
||||
|
||||
@@ -120,6 +121,7 @@ static elf_errorstatus xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
ELF_PTRVAL_CHAR hdr;
|
||||
size_t size;
|
||||
unsigned h, count, type, i, tables = 0;
|
||||
+ unsigned long *strtab_referenced = NULL;
|
||||
|
||||
if ( elf_swap(elf) )
|
||||
{
|
||||
@@ -220,22 +222,35 @@ static elf_errorstatus xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
symtab, maxaddr);
|
||||
|
||||
count = elf_shdr_count(&syms);
|
||||
+ /* elf_shdr_count guarantees that count is reasonable */
|
||||
+
|
||||
+ strtab_referenced = xc_dom_malloc(dom, bitmap_size(count));
|
||||
+ if ( strtab_referenced == NULL )
|
||||
+ return -1;
|
||||
+ bitmap_clear(strtab_referenced, count);
|
||||
+ /* Note the symtabs @h linked to by any strtab @i. */
|
||||
+ for ( i = 0; i < count; i++ )
|
||||
+ {
|
||||
+ shdr2 = elf_shdr_by_index(&syms, i);
|
||||
+ if ( elf_uval(&syms, shdr2, sh_type) == SHT_SYMTAB )
|
||||
+ {
|
||||
+ h = elf_uval(&syms, shdr2, sh_link);
|
||||
+ if (h < count)
|
||||
+ set_bit(h, strtab_referenced);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
for ( h = 0; h < count; h++ )
|
||||
{
|
||||
shdr = ELF_OBSOLETE_VOIDP_CAST elf_shdr_by_index(&syms, h);
|
||||
+ if ( !elf_access_ok(elf, ELF_HANDLE_PTRVAL(shdr), 1) )
|
||||
+ /* input has an insane section header count field */
|
||||
+ break;
|
||||
type = elf_uval(&syms, shdr, sh_type);
|
||||
if ( type == SHT_STRTAB )
|
||||
{
|
||||
- /* Look for a strtab @i linked to symtab @h. */
|
||||
- for ( i = 0; i < count; i++ )
|
||||
- {
|
||||
- shdr2 = elf_shdr_by_index(&syms, i);
|
||||
- if ( (elf_uval(&syms, shdr2, sh_type) == SHT_SYMTAB) &&
|
||||
- (elf_uval(&syms, shdr2, sh_link) == h) )
|
||||
- break;
|
||||
- }
|
||||
/* Skip symtab @h if we found no corresponding strtab @i. */
|
||||
- if ( i == count )
|
||||
+ if ( !test_bit(h, strtab_referenced) )
|
||||
{
|
||||
if ( elf_64bit(&syms) )
|
||||
elf_store_field(elf, shdr, e64.sh_offset, 0);
|
||||
diff --git a/xen/common/libelf/libelf-dominfo.c b/xen/common/libelf/libelf-dominfo.c
|
||||
index cdd0d31..25a10d7 100644
|
||||
--- a/xen/common/libelf/libelf-dominfo.c
|
||||
+++ b/xen/common/libelf/libelf-dominfo.c
|
||||
@@ -221,7 +221,8 @@ elf_errorstatus elf_xen_parse_note(struct elf_binary *elf,
|
||||
static unsigned elf_xen_parse_notes(struct elf_binary *elf,
|
||||
struct elf_dom_parms *parms,
|
||||
ELF_PTRVAL_CONST_VOID start,
|
||||
- ELF_PTRVAL_CONST_VOID end)
|
||||
+ ELF_PTRVAL_CONST_VOID end,
|
||||
+ unsigned *total_note_count)
|
||||
{
|
||||
unsigned xen_elfnotes = 0;
|
||||
ELF_HANDLE_DECL(elf_note) note;
|
||||
@@ -233,6 +234,12 @@ static unsigned elf_xen_parse_notes(struct elf_binary *elf,
|
||||
ELF_HANDLE_PTRVAL(note) < parms->elf_note_end;
|
||||
note = elf_note_next(elf, note) )
|
||||
{
|
||||
+ if ( *total_note_count >= ELF_MAX_TOTAL_NOTE_COUNT )
|
||||
+ {
|
||||
+ elf_mark_broken(elf, "too many ELF notes");
|
||||
+ break;
|
||||
+ }
|
||||
+ (*total_note_count)++;
|
||||
note_name = elf_note_name(elf, note);
|
||||
if ( note_name == NULL )
|
||||
continue;
|
||||
@@ -473,6 +480,7 @@ elf_errorstatus elf_xen_parse(struct elf_binary *elf,
|
||||
ELF_HANDLE_DECL(elf_phdr) phdr;
|
||||
unsigned xen_elfnotes = 0;
|
||||
unsigned i, count, more_notes;
|
||||
+ unsigned total_note_count = 0;
|
||||
|
||||
elf_memset_unchecked(parms, 0, sizeof(*parms));
|
||||
parms->virt_base = UNSET_ADDR;
|
||||
@@ -487,6 +495,9 @@ elf_errorstatus elf_xen_parse(struct elf_binary *elf,
|
||||
for ( i = 0; i < count; i++ )
|
||||
{
|
||||
phdr = elf_phdr_by_index(elf, i);
|
||||
+ if ( !elf_access_ok(elf, ELF_HANDLE_PTRVAL(phdr), 1) )
|
||||
+ /* input has an insane program header count field */
|
||||
+ break;
|
||||
if ( elf_uval(elf, phdr, p_type) != PT_NOTE )
|
||||
continue;
|
||||
|
||||
@@ -499,7 +510,8 @@ elf_errorstatus elf_xen_parse(struct elf_binary *elf,
|
||||
|
||||
more_notes = elf_xen_parse_notes(elf, parms,
|
||||
elf_segment_start(elf, phdr),
|
||||
- elf_segment_end(elf, phdr));
|
||||
+ elf_segment_end(elf, phdr),
|
||||
+ &total_note_count);
|
||||
if ( more_notes == ELF_NOTE_INVALID )
|
||||
return -1;
|
||||
|
||||
@@ -516,13 +528,17 @@ elf_errorstatus elf_xen_parse(struct elf_binary *elf,
|
||||
for ( i = 0; i < count; i++ )
|
||||
{
|
||||
shdr = elf_shdr_by_index(elf, i);
|
||||
+ if ( !elf_access_ok(elf, ELF_HANDLE_PTRVAL(shdr), 1) )
|
||||
+ /* input has an insane section header count field */
|
||||
+ break;
|
||||
|
||||
if ( elf_uval(elf, shdr, sh_type) != SHT_NOTE )
|
||||
continue;
|
||||
|
||||
more_notes = elf_xen_parse_notes(elf, parms,
|
||||
elf_section_start(elf, shdr),
|
||||
- elf_section_end(elf, shdr));
|
||||
+ elf_section_end(elf, shdr),
|
||||
+ &total_note_count);
|
||||
|
||||
if ( more_notes == ELF_NOTE_INVALID )
|
||||
return -1;
|
||||
@@ -540,20 +556,15 @@ elf_errorstatus elf_xen_parse(struct elf_binary *elf,
|
||||
*/
|
||||
if ( xen_elfnotes == 0 )
|
||||
{
|
||||
- count = elf_shdr_count(elf);
|
||||
- for ( i = 0; i < count; i++ )
|
||||
+ shdr = elf_shdr_by_name(elf, "__xen_guest");
|
||||
+ if ( ELF_HANDLE_VALID(shdr) )
|
||||
{
|
||||
- shdr = elf_shdr_by_name(elf, "__xen_guest");
|
||||
- if ( ELF_HANDLE_VALID(shdr) )
|
||||
- {
|
||||
- parms->guest_info = elf_section_start(elf, shdr);
|
||||
- parms->elf_note_start = ELF_INVALID_PTRVAL;
|
||||
- parms->elf_note_end = ELF_INVALID_PTRVAL;
|
||||
- elf_msg(elf, "%s: __xen_guest: \"%s\"\n", __FUNCTION__,
|
||||
- elf_strfmt(elf, parms->guest_info));
|
||||
- elf_xen_parse_guest_info(elf, parms);
|
||||
- break;
|
||||
- }
|
||||
+ parms->guest_info = elf_section_start(elf, shdr);
|
||||
+ parms->elf_note_start = ELF_INVALID_PTRVAL;
|
||||
+ parms->elf_note_end = ELF_INVALID_PTRVAL;
|
||||
+ elf_msg(elf, "%s: __xen_guest: \"%s\"\n", __FUNCTION__,
|
||||
+ elf_strfmt(elf, parms->guest_info));
|
||||
+ elf_xen_parse_guest_info(elf, parms);
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/xen/common/libelf/libelf-loader.c b/xen/common/libelf/libelf-loader.c
|
||||
index c3a9e51..06799af 100644
|
||||
--- a/xen/common/libelf/libelf-loader.c
|
||||
+++ b/xen/common/libelf/libelf-loader.c
|
||||
@@ -75,6 +75,9 @@ elf_errorstatus elf_init(struct elf_binary *elf, const char *image_input, size_t
|
||||
for ( i = 0; i < count; i++ )
|
||||
{
|
||||
shdr = elf_shdr_by_index(elf, i);
|
||||
+ if ( !elf_access_ok(elf, ELF_HANDLE_PTRVAL(shdr), 1) )
|
||||
+ /* input has an insane section header count field */
|
||||
+ break;
|
||||
if ( elf_uval(elf, shdr, sh_type) != SHT_SYMTAB )
|
||||
continue;
|
||||
elf->sym_tab = shdr;
|
||||
@@ -170,6 +173,9 @@ void elf_parse_bsdsyms(struct elf_binary *elf, uint64_t pstart)
|
||||
for ( i = 0; i < elf_shdr_count(elf); i++ )
|
||||
{
|
||||
shdr = elf_shdr_by_index(elf, i);
|
||||
+ if ( !elf_access_ok(elf, ELF_HANDLE_PTRVAL(shdr), 1) )
|
||||
+ /* input has an insane section header count field */
|
||||
+ break;
|
||||
type = elf_uval(elf, shdr, sh_type);
|
||||
if ( (type == SHT_STRTAB) || (type == SHT_SYMTAB) )
|
||||
sz = elf_round_up(elf, sz + elf_uval(elf, shdr, sh_size));
|
||||
@@ -224,6 +230,9 @@ do { \
|
||||
|
||||
for ( i = 0; i < elf_shdr_count(elf); i++ )
|
||||
{
|
||||
+ elf_ptrval old_shdr_p;
|
||||
+ elf_ptrval new_shdr_p;
|
||||
+
|
||||
type = elf_uval(elf, shdr, sh_type);
|
||||
if ( (type == SHT_STRTAB) || (type == SHT_SYMTAB) )
|
||||
{
|
||||
@@ -235,8 +244,16 @@ do { \
|
||||
elf_hdr_elm(elf, shdr, sh_offset, maxva - symtab_addr);
|
||||
maxva = ELF_OBSOLETE_VOIDP_CAST elf_round_up(elf, (unsigned long)maxva + sz);
|
||||
}
|
||||
- shdr = ELF_MAKE_HANDLE(elf_shdr, ELF_HANDLE_PTRVAL(shdr) +
|
||||
- (unsigned long)elf_uval(elf, elf->ehdr, e_shentsize));
|
||||
+ old_shdr_p = ELF_HANDLE_PTRVAL(shdr);
|
||||
+ new_shdr_p = old_shdr_p + elf_uval(elf, elf->ehdr, e_shentsize);
|
||||
+ if ( new_shdr_p <= old_shdr_p ) /* wrapped or stuck */
|
||||
+ {
|
||||
+ elf_mark_broken(elf, "bad section header length");
|
||||
+ break;
|
||||
+ }
|
||||
+ if ( !elf_access_ok(elf, new_shdr_p, 1) ) /* outside image */
|
||||
+ break;
|
||||
+ shdr = ELF_MAKE_HANDLE(elf_shdr, new_shdr_p);
|
||||
}
|
||||
|
||||
/* Write down the actual sym size. */
|
||||
@@ -256,6 +273,9 @@ void elf_parse_binary(struct elf_binary *elf)
|
||||
for ( i = 0; i < count; i++ )
|
||||
{
|
||||
phdr = elf_phdr_by_index(elf, i);
|
||||
+ if ( !elf_access_ok(elf, ELF_HANDLE_PTRVAL(phdr), 1) )
|
||||
+ /* input has an insane program header count field */
|
||||
+ break;
|
||||
if ( !elf_phdr_is_loadable(elf, phdr) )
|
||||
continue;
|
||||
paddr = elf_uval(elf, phdr, p_paddr);
|
||||
@@ -278,11 +298,20 @@ elf_errorstatus elf_load_binary(struct elf_binary *elf)
|
||||
ELF_HANDLE_DECL(elf_phdr) phdr;
|
||||
uint64_t i, count, paddr, offset, filesz, memsz;
|
||||
ELF_PTRVAL_VOID dest;
|
||||
+ /*
|
||||
+ * Let bizarre ELFs write the output image up to twice; this
|
||||
+ * calculation is just to ensure our copying loop is no worse than
|
||||
+ * O(domain_size).
|
||||
+ */
|
||||
+ uint64_t remain_allow_copy = (uint64_t)elf->dest_size * 2;
|
||||
|
||||
count = elf_uval(elf, elf->ehdr, e_phnum);
|
||||
for ( i = 0; i < count; i++ )
|
||||
{
|
||||
phdr = elf_phdr_by_index(elf, i);
|
||||
+ if ( !elf_access_ok(elf, ELF_HANDLE_PTRVAL(phdr), 1) )
|
||||
+ /* input has an insane program header count field */
|
||||
+ break;
|
||||
if ( !elf_phdr_is_loadable(elf, phdr) )
|
||||
continue;
|
||||
paddr = elf_uval(elf, phdr, p_paddr);
|
||||
@@ -290,6 +319,20 @@ elf_errorstatus elf_load_binary(struct elf_binary *elf)
|
||||
filesz = elf_uval(elf, phdr, p_filesz);
|
||||
memsz = elf_uval(elf, phdr, p_memsz);
|
||||
dest = elf_get_ptr(elf, paddr);
|
||||
+
|
||||
+ /*
|
||||
+ * We need to check that the input image doesn't have us copy
|
||||
+ * the whole image zillions of times, as that could lead to
|
||||
+ * O(n^2) time behaviour and possible DoS by a malicous ELF.
|
||||
+ */
|
||||
+ if ( remain_allow_copy < memsz )
|
||||
+ {
|
||||
+ elf_mark_broken(elf, "program segments total to more"
|
||||
+ " than the input image size");
|
||||
+ break;
|
||||
+ }
|
||||
+ remain_allow_copy -= memsz;
|
||||
+
|
||||
elf_msg(elf, "%s: phdr %" PRIu64 " at 0x%"ELF_PRPTRVAL" -> 0x%"ELF_PRPTRVAL"\n",
|
||||
__func__, i, dest, (ELF_PTRVAL_VOID)(dest + filesz));
|
||||
if ( elf_load_image(elf, dest, ELF_IMAGE_BASE(elf) + offset, filesz, memsz) != 0 )
|
||||
diff --git a/xen/common/libelf/libelf-tools.c b/xen/common/libelf/libelf-tools.c
|
||||
index 46d4ab1..4a83133 100644
|
||||
--- a/xen/common/libelf/libelf-tools.c
|
||||
+++ b/xen/common/libelf/libelf-tools.c
|
||||
@@ -131,7 +131,16 @@ uint64_t elf_round_up(struct elf_binary *elf, uint64_t addr)
|
||||
|
||||
unsigned elf_shdr_count(struct elf_binary *elf)
|
||||
{
|
||||
- return elf_uval(elf, elf->ehdr, e_shnum);
|
||||
+ unsigned count = elf_uval(elf, elf->ehdr, e_shnum);
|
||||
+ uint64_t max = elf->size / sizeof(Elf32_Shdr);
|
||||
+ if (max > ~(unsigned)0)
|
||||
+ max = ~(unsigned)0; /* Xen doesn't have limits.h :-/ */
|
||||
+ if (count > max)
|
||||
+ {
|
||||
+ elf_mark_broken(elf, "far too many section headers");
|
||||
+ count = max;
|
||||
+ }
|
||||
+ return count;
|
||||
}
|
||||
|
||||
unsigned elf_phdr_count(struct elf_binary *elf)
|
||||
@@ -149,6 +158,9 @@ ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_name(struct elf_binary *elf, const char *n
|
||||
for ( i = 0; i < count; i++ )
|
||||
{
|
||||
shdr = elf_shdr_by_index(elf, i);
|
||||
+ if ( !elf_access_ok(elf, ELF_HANDLE_PTRVAL(shdr), 1) )
|
||||
+ /* input has an insane section header count field */
|
||||
+ break;
|
||||
sname = elf_section_name(elf, shdr);
|
||||
if ( sname && !strcmp(sname, name) )
|
||||
return shdr;
|
||||
@@ -204,6 +216,11 @@ const char *elf_strval(struct elf_binary *elf, elf_ptrval start)
|
||||
if ( !elf_access_unsigned(elf, start, length, 1) )
|
||||
/* ok */
|
||||
return ELF_UNSAFE_PTR(start);
|
||||
+ if ( length >= ELF_MAX_STRING_LENGTH )
|
||||
+ {
|
||||
+ elf_mark_broken(elf, "excessively long string");
|
||||
+ return NULL;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -327,7 +344,14 @@ ELF_HANDLE_DECL(elf_note) elf_note_next(struct elf_binary *elf, ELF_HANDLE_DECL(
|
||||
unsigned namesz = (elf_uval(elf, note, namesz) + 3) & ~3;
|
||||
unsigned descsz = (elf_uval(elf, note, descsz) + 3) & ~3;
|
||||
|
||||
- return ELF_MAKE_HANDLE(elf_note, ELF_HANDLE_PTRVAL(note) + elf_size(elf, note) + namesz + descsz);
|
||||
+ elf_ptrval ptrval = ELF_HANDLE_PTRVAL(note)
|
||||
+ + elf_size(elf, note) + namesz + descsz;
|
||||
+
|
||||
+ if ( ( ptrval <= ELF_HANDLE_PTRVAL(note) || /* wrapped or stuck */
|
||||
+ !elf_access_ok(elf, ELF_HANDLE_PTRVAL(note), 1) ) )
|
||||
+ ptrval = ELF_MAX_PTRVAL; /* terminate caller's loop */
|
||||
+
|
||||
+ return ELF_MAKE_HANDLE(elf_note, ptrval);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
diff --git a/xen/include/xen/libelf.h b/xen/include/xen/libelf.h
|
||||
index 87e126a..f95fe88 100644
|
||||
--- a/xen/include/xen/libelf.h
|
||||
+++ b/xen/include/xen/libelf.h
|
||||
@@ -51,6 +51,9 @@ typedef void elf_log_callback(struct elf_binary*, void *caller_data,
|
||||
|
||||
#endif
|
||||
|
||||
+#define ELF_MAX_STRING_LENGTH 4096
|
||||
+#define ELF_MAX_TOTAL_NOTE_COUNT 65536
|
||||
+
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
/* Macros for accessing the input image and output area. */
|
||||
@@ -353,6 +356,16 @@ ELF_PTRVAL_CONST_VOID elf_note_desc(struct elf_binary *elf, ELF_HANDLE_DECL(elf_
|
||||
uint64_t elf_note_numeric(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
|
||||
uint64_t elf_note_numeric_array(struct elf_binary *, ELF_HANDLE_DECL(elf_note),
|
||||
unsigned int unitsz, unsigned int idx);
|
||||
+
|
||||
+/*
|
||||
+ * If you use elf_note_next in a loop, you must put a nontrivial upper
|
||||
+ * bound on the returned value as part of your loop condition. In
|
||||
+ * some cases elf_note_next will substitute ELF_PTRVAL_MAX as return
|
||||
+ * value to indicate that the iteration isn't going well (for example,
|
||||
+ * the putative "next" value would be earlier in memory). In this
|
||||
+ * case the caller's loop must terminate. Checking against the
|
||||
+ * end of the notes segment with a strict inequality is sufficient.
|
||||
+ */
|
||||
ELF_HANDLE_DECL(elf_note) elf_note_next(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
|
||||
|
||||
/* (Only) checks that the image has the right magic number. */
|
||||
--
|
||||
1.7.2.5
|
||||
|
@ -0,0 +1,406 @@
|
||||
From 3baaa4ffcd3e7dd6227f9bdf817f90e5b75aeda2 Mon Sep 17 00:00:00 2001
|
||||
From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Date: Fri, 14 Jun 2013 16:43:19 +0100
|
||||
Subject: [PATCH 17/23] libelf: abolish obsolete macros
|
||||
|
||||
Abolish ELF_PTRVAL_[CONST_]{CHAR,VOID}; change uses to elf_ptrval.
|
||||
Abolish ELF_HANDLE_DECL_NONCONST; change uses to ELF_HANDLE_DECL.
|
||||
Abolish ELF_OBSOLETE_VOIDP_CAST; simply remove all uses.
|
||||
|
||||
No functional change. (Verified by diffing assembler output.)
|
||||
|
||||
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
|
||||
v2: New patch.
|
||||
---
|
||||
tools/libxc/xc_dom_elfloader.c | 8 +++---
|
||||
tools/xcutils/readnotes.c | 2 +-
|
||||
xen/common/libelf/libelf-dominfo.c | 6 ++--
|
||||
xen/common/libelf/libelf-loader.c | 24 +++++++++---------
|
||||
xen/common/libelf/libelf-tools.c | 24 +++++++++---------
|
||||
xen/include/xen/libelf.h | 48 +++++++++---------------------------
|
||||
6 files changed, 44 insertions(+), 68 deletions(-)
|
||||
|
||||
diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c
|
||||
index c5014d2..9fc4b94 100644
|
||||
--- a/tools/libxc/xc_dom_elfloader.c
|
||||
+++ b/tools/libxc/xc_dom_elfloader.c
|
||||
@@ -116,9 +116,9 @@ static elf_errorstatus xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
struct elf_binary *elf, bool load)
|
||||
{
|
||||
struct elf_binary syms;
|
||||
- ELF_HANDLE_DECL_NONCONST(elf_shdr) shdr; ELF_HANDLE_DECL(elf_shdr) shdr2;
|
||||
+ ELF_HANDLE_DECL(elf_shdr) shdr; ELF_HANDLE_DECL(elf_shdr) shdr2;
|
||||
xen_vaddr_t symtab, maxaddr;
|
||||
- ELF_PTRVAL_CHAR hdr;
|
||||
+ elf_ptrval hdr;
|
||||
size_t size;
|
||||
unsigned h, count, type, i, tables = 0;
|
||||
unsigned long *strtab_referenced = NULL;
|
||||
@@ -242,7 +242,7 @@ static elf_errorstatus xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
|
||||
for ( h = 0; h < count; h++ )
|
||||
{
|
||||
- shdr = ELF_OBSOLETE_VOIDP_CAST elf_shdr_by_index(&syms, h);
|
||||
+ shdr = elf_shdr_by_index(&syms, h);
|
||||
if ( !elf_access_ok(elf, ELF_HANDLE_PTRVAL(shdr), 1) )
|
||||
/* input has an insane section header count field */
|
||||
break;
|
||||
@@ -278,7 +278,7 @@ static elf_errorstatus xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
if ( load )
|
||||
{
|
||||
shdr2 = elf_shdr_by_index(elf, h);
|
||||
- elf_memcpy_safe(elf, ELF_OBSOLETE_VOIDP_CAST elf_section_start(&syms, shdr),
|
||||
+ elf_memcpy_safe(elf, elf_section_start(&syms, shdr),
|
||||
elf_section_start(elf, shdr2),
|
||||
size);
|
||||
}
|
||||
diff --git a/tools/xcutils/readnotes.c b/tools/xcutils/readnotes.c
|
||||
index 2ca7732..5fa445e 100644
|
||||
--- a/tools/xcutils/readnotes.c
|
||||
+++ b/tools/xcutils/readnotes.c
|
||||
@@ -80,7 +80,7 @@ static void print_l1_mfn_valid_note(const char *prefix, struct elf_binary *elf,
|
||||
ELF_HANDLE_DECL(elf_note) note)
|
||||
{
|
||||
unsigned descsz = elf_uval(elf, note, descsz);
|
||||
- ELF_PTRVAL_CONST_VOID desc = elf_note_desc(elf, note);
|
||||
+ elf_ptrval desc = elf_note_desc(elf, note);
|
||||
|
||||
/* XXX should be able to cope with a list of values. */
|
||||
switch ( descsz / 2 )
|
||||
diff --git a/xen/common/libelf/libelf-dominfo.c b/xen/common/libelf/libelf-dominfo.c
|
||||
index 25a10d7..412ea70 100644
|
||||
--- a/xen/common/libelf/libelf-dominfo.c
|
||||
+++ b/xen/common/libelf/libelf-dominfo.c
|
||||
@@ -220,8 +220,8 @@ elf_errorstatus elf_xen_parse_note(struct elf_binary *elf,
|
||||
|
||||
static unsigned elf_xen_parse_notes(struct elf_binary *elf,
|
||||
struct elf_dom_parms *parms,
|
||||
- ELF_PTRVAL_CONST_VOID start,
|
||||
- ELF_PTRVAL_CONST_VOID end,
|
||||
+ elf_ptrval start,
|
||||
+ elf_ptrval end,
|
||||
unsigned *total_note_count)
|
||||
{
|
||||
unsigned xen_elfnotes = 0;
|
||||
@@ -258,7 +258,7 @@ static unsigned elf_xen_parse_notes(struct elf_binary *elf,
|
||||
elf_errorstatus elf_xen_parse_guest_info(struct elf_binary *elf,
|
||||
struct elf_dom_parms *parms)
|
||||
{
|
||||
- ELF_PTRVAL_CONST_CHAR h;
|
||||
+ elf_ptrval h;
|
||||
unsigned char name[32], value[128];
|
||||
unsigned len;
|
||||
|
||||
diff --git a/xen/common/libelf/libelf-loader.c b/xen/common/libelf/libelf-loader.c
|
||||
index 06799af..e2e75af 100644
|
||||
--- a/xen/common/libelf/libelf-loader.c
|
||||
+++ b/xen/common/libelf/libelf-loader.c
|
||||
@@ -118,7 +118,7 @@ void elf_set_log(struct elf_binary *elf, elf_log_callback *log_callback,
|
||||
}
|
||||
|
||||
static elf_errorstatus elf_load_image(struct elf_binary *elf,
|
||||
- ELF_PTRVAL_VOID dst, ELF_PTRVAL_CONST_VOID src,
|
||||
+ elf_ptrval dst, elf_ptrval src,
|
||||
uint64_t filesz, uint64_t memsz)
|
||||
{
|
||||
elf_memcpy_safe(elf, dst, src, filesz);
|
||||
@@ -132,7 +132,7 @@ void elf_set_verbose(struct elf_binary *elf)
|
||||
elf->verbose = 1;
|
||||
}
|
||||
|
||||
-static elf_errorstatus elf_load_image(struct elf_binary *elf, ELF_PTRVAL_VOID dst, ELF_PTRVAL_CONST_VOID src, uint64_t filesz, uint64_t memsz)
|
||||
+static elf_errorstatus elf_load_image(struct elf_binary *elf, elf_ptrval dst, elf_ptrval src, uint64_t filesz, uint64_t memsz)
|
||||
{
|
||||
elf_errorstatus rc;
|
||||
if ( filesz > ULONG_MAX || memsz > ULONG_MAX )
|
||||
@@ -187,12 +187,12 @@ void elf_parse_bsdsyms(struct elf_binary *elf, uint64_t pstart)
|
||||
|
||||
static void elf_load_bsdsyms(struct elf_binary *elf)
|
||||
{
|
||||
- ELF_HANDLE_DECL_NONCONST(elf_ehdr) sym_ehdr;
|
||||
+ ELF_HANDLE_DECL(elf_ehdr) sym_ehdr;
|
||||
unsigned long sz;
|
||||
- ELF_PTRVAL_VOID maxva;
|
||||
- ELF_PTRVAL_VOID symbase;
|
||||
- ELF_PTRVAL_VOID symtab_addr;
|
||||
- ELF_HANDLE_DECL_NONCONST(elf_shdr) shdr;
|
||||
+ elf_ptrval maxva;
|
||||
+ elf_ptrval symbase;
|
||||
+ elf_ptrval symtab_addr;
|
||||
+ ELF_HANDLE_DECL(elf_shdr) shdr;
|
||||
unsigned i, type;
|
||||
|
||||
if ( !elf->bsd_symtab_pstart )
|
||||
@@ -226,7 +226,7 @@ do { \
|
||||
elf_memcpy_safe(elf, ELF_HANDLE_PTRVAL(shdr),
|
||||
ELF_IMAGE_BASE(elf) + elf_uval(elf, elf->ehdr, e_shoff),
|
||||
sz);
|
||||
- maxva = ELF_OBSOLETE_VOIDP_CAST elf_round_up(elf, (unsigned long)maxva + sz);
|
||||
+ maxva = elf_round_up(elf, (unsigned long)maxva + sz);
|
||||
|
||||
for ( i = 0; i < elf_shdr_count(elf); i++ )
|
||||
{
|
||||
@@ -242,7 +242,7 @@ do { \
|
||||
elf_memcpy_safe(elf, maxva, elf_section_start(elf, shdr), sz);
|
||||
/* Mangled to be based on ELF header location. */
|
||||
elf_hdr_elm(elf, shdr, sh_offset, maxva - symtab_addr);
|
||||
- maxva = ELF_OBSOLETE_VOIDP_CAST elf_round_up(elf, (unsigned long)maxva + sz);
|
||||
+ maxva = elf_round_up(elf, (unsigned long)maxva + sz);
|
||||
}
|
||||
old_shdr_p = ELF_HANDLE_PTRVAL(shdr);
|
||||
new_shdr_p = old_shdr_p + elf_uval(elf, elf->ehdr, e_shentsize);
|
||||
@@ -297,7 +297,7 @@ elf_errorstatus elf_load_binary(struct elf_binary *elf)
|
||||
{
|
||||
ELF_HANDLE_DECL(elf_phdr) phdr;
|
||||
uint64_t i, count, paddr, offset, filesz, memsz;
|
||||
- ELF_PTRVAL_VOID dest;
|
||||
+ elf_ptrval dest;
|
||||
/*
|
||||
* Let bizarre ELFs write the output image up to twice; this
|
||||
* calculation is just to ensure our copying loop is no worse than
|
||||
@@ -334,7 +334,7 @@ elf_errorstatus elf_load_binary(struct elf_binary *elf)
|
||||
remain_allow_copy -= memsz;
|
||||
|
||||
elf_msg(elf, "%s: phdr %" PRIu64 " at 0x%"ELF_PRPTRVAL" -> 0x%"ELF_PRPTRVAL"\n",
|
||||
- __func__, i, dest, (ELF_PTRVAL_VOID)(dest + filesz));
|
||||
+ __func__, i, dest, (elf_ptrval)(dest + filesz));
|
||||
if ( elf_load_image(elf, dest, ELF_IMAGE_BASE(elf) + offset, filesz, memsz) != 0 )
|
||||
return -1;
|
||||
}
|
||||
@@ -343,7 +343,7 @@ elf_errorstatus elf_load_binary(struct elf_binary *elf)
|
||||
return 0;
|
||||
}
|
||||
|
||||
-ELF_PTRVAL_VOID elf_get_ptr(struct elf_binary *elf, unsigned long addr)
|
||||
+elf_ptrval elf_get_ptr(struct elf_binary *elf, unsigned long addr)
|
||||
{
|
||||
return ELF_REALPTR2PTRVAL(elf->dest_base) + addr - elf->pstart;
|
||||
}
|
||||
diff --git a/xen/common/libelf/libelf-tools.c b/xen/common/libelf/libelf-tools.c
|
||||
index 4a83133..e202249 100644
|
||||
--- a/xen/common/libelf/libelf-tools.c
|
||||
+++ b/xen/common/libelf/libelf-tools.c
|
||||
@@ -171,7 +171,7 @@ ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_name(struct elf_binary *elf, const char *n
|
||||
ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_index(struct elf_binary *elf, unsigned index)
|
||||
{
|
||||
uint64_t count = elf_shdr_count(elf);
|
||||
- ELF_PTRVAL_CONST_VOID ptr;
|
||||
+ elf_ptrval ptr;
|
||||
|
||||
if ( index >= count )
|
||||
return ELF_INVALID_HANDLE(elf_shdr);
|
||||
@@ -185,7 +185,7 @@ ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_index(struct elf_binary *elf, unsigned ind
|
||||
ELF_HANDLE_DECL(elf_phdr) elf_phdr_by_index(struct elf_binary *elf, unsigned index)
|
||||
{
|
||||
uint64_t count = elf_uval(elf, elf->ehdr, e_phnum);
|
||||
- ELF_PTRVAL_CONST_VOID ptr;
|
||||
+ elf_ptrval ptr;
|
||||
|
||||
if ( index >= count )
|
||||
return ELF_INVALID_HANDLE(elf_phdr);
|
||||
@@ -233,24 +233,24 @@ const char *elf_strfmt(struct elf_binary *elf, elf_ptrval start)
|
||||
return str;
|
||||
}
|
||||
|
||||
-ELF_PTRVAL_CONST_VOID elf_section_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr)
|
||||
+elf_ptrval elf_section_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr)
|
||||
{
|
||||
return ELF_IMAGE_BASE(elf) + elf_uval(elf, shdr, sh_offset);
|
||||
}
|
||||
|
||||
-ELF_PTRVAL_CONST_VOID elf_section_end(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr)
|
||||
+elf_ptrval elf_section_end(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr)
|
||||
{
|
||||
return ELF_IMAGE_BASE(elf)
|
||||
+ elf_uval(elf, shdr, sh_offset) + elf_uval(elf, shdr, sh_size);
|
||||
}
|
||||
|
||||
-ELF_PTRVAL_CONST_VOID elf_segment_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr)
|
||||
+elf_ptrval elf_segment_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr)
|
||||
{
|
||||
return ELF_IMAGE_BASE(elf)
|
||||
+ elf_uval(elf, phdr, p_offset);
|
||||
}
|
||||
|
||||
-ELF_PTRVAL_CONST_VOID elf_segment_end(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr)
|
||||
+elf_ptrval elf_segment_end(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr)
|
||||
{
|
||||
return ELF_IMAGE_BASE(elf)
|
||||
+ elf_uval(elf, phdr, p_offset) + elf_uval(elf, phdr, p_filesz);
|
||||
@@ -258,8 +258,8 @@ ELF_PTRVAL_CONST_VOID elf_segment_end(struct elf_binary *elf, ELF_HANDLE_DECL(el
|
||||
|
||||
ELF_HANDLE_DECL(elf_sym) elf_sym_by_name(struct elf_binary *elf, const char *symbol)
|
||||
{
|
||||
- ELF_PTRVAL_CONST_VOID ptr = elf_section_start(elf, elf->sym_tab);
|
||||
- ELF_PTRVAL_CONST_VOID end = elf_section_end(elf, elf->sym_tab);
|
||||
+ elf_ptrval ptr = elf_section_start(elf, elf->sym_tab);
|
||||
+ elf_ptrval end = elf_section_end(elf, elf->sym_tab);
|
||||
ELF_HANDLE_DECL(elf_sym) sym;
|
||||
uint64_t info, name;
|
||||
const char *sym_name;
|
||||
@@ -283,7 +283,7 @@ ELF_HANDLE_DECL(elf_sym) elf_sym_by_name(struct elf_binary *elf, const char *sym
|
||||
|
||||
ELF_HANDLE_DECL(elf_sym) elf_sym_by_index(struct elf_binary *elf, unsigned index)
|
||||
{
|
||||
- ELF_PTRVAL_CONST_VOID ptr = elf_section_start(elf, elf->sym_tab);
|
||||
+ elf_ptrval ptr = elf_section_start(elf, elf->sym_tab);
|
||||
ELF_HANDLE_DECL(elf_sym) sym;
|
||||
|
||||
sym = ELF_MAKE_HANDLE(elf_sym, ptr + index * elf_size(elf, sym));
|
||||
@@ -295,7 +295,7 @@ const char *elf_note_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note
|
||||
return elf_strval(elf, ELF_HANDLE_PTRVAL(note) + elf_size(elf, note));
|
||||
}
|
||||
|
||||
-ELF_PTRVAL_CONST_VOID elf_note_desc(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note)
|
||||
+elf_ptrval elf_note_desc(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note)
|
||||
{
|
||||
unsigned namesz = (elf_uval(elf, note, namesz) + 3) & ~3;
|
||||
|
||||
@@ -304,7 +304,7 @@ ELF_PTRVAL_CONST_VOID elf_note_desc(struct elf_binary *elf, ELF_HANDLE_DECL(elf_
|
||||
|
||||
uint64_t elf_note_numeric(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note)
|
||||
{
|
||||
- ELF_PTRVAL_CONST_VOID desc = elf_note_desc(elf, note);
|
||||
+ elf_ptrval desc = elf_note_desc(elf, note);
|
||||
unsigned descsz = elf_uval(elf, note, descsz);
|
||||
|
||||
switch (descsz)
|
||||
@@ -322,7 +322,7 @@ uint64_t elf_note_numeric(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note
|
||||
uint64_t elf_note_numeric_array(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note,
|
||||
unsigned int unitsz, unsigned int idx)
|
||||
{
|
||||
- ELF_PTRVAL_CONST_VOID desc = elf_note_desc(elf, note);
|
||||
+ elf_ptrval desc = elf_note_desc(elf, note);
|
||||
unsigned descsz = elf_uval(elf, note, descsz);
|
||||
|
||||
if ( descsz % unitsz || idx >= descsz / unitsz )
|
||||
diff --git a/xen/include/xen/libelf.h b/xen/include/xen/libelf.h
|
||||
index f95fe88..174f8da 100644
|
||||
--- a/xen/include/xen/libelf.h
|
||||
+++ b/xen/include/xen/libelf.h
|
||||
@@ -61,13 +61,8 @@ typedef void elf_log_callback(struct elf_binary*, void *caller_data,
|
||||
/*
|
||||
* We abstract away the pointerness of these pointers, replacing
|
||||
* various void*, char* and struct* with the following:
|
||||
- * PTRVAL A pointer to a byte; one can do pointer arithmetic
|
||||
+ * elf_ptrval A pointer to a byte; one can do pointer arithmetic
|
||||
* on this.
|
||||
- * This replaces variables which were char*,void*
|
||||
- * and their const versions, so we provide four
|
||||
- * different obsolete declaration macros:
|
||||
- * ELF_PTRVAL_{,CONST}{VOID,CHAR}
|
||||
- * New code can simply use the elf_ptrval typedef.
|
||||
* HANDLE A pointer to a struct. There is one of these types
|
||||
* for each pointer type - that is, for each "structname".
|
||||
* In the arguments to the various HANDLE macros, structname
|
||||
@@ -76,8 +71,6 @@ typedef void elf_log_callback(struct elf_binary*, void *caller_data,
|
||||
* pointers. In the current code attempts to do so will
|
||||
* compile, but in the next patch this will become a
|
||||
* compile error.
|
||||
- * We also provide a second declaration macro for
|
||||
- * pointers which were to const; this is obsolete.
|
||||
*/
|
||||
|
||||
typedef uintptr_t elf_ptrval;
|
||||
@@ -85,15 +78,9 @@ typedef uintptr_t elf_ptrval;
|
||||
#define ELF_REALPTR2PTRVAL(realpointer) ((elf_ptrval)(realpointer))
|
||||
/* Converts an actual C pointer into a PTRVAL */
|
||||
|
||||
-#define ELF_HANDLE_DECL_NONCONST(structname) structname##_handle /*obsolete*/
|
||||
#define ELF_HANDLE_DECL(structname) structname##_handle
|
||||
/* Provides a type declaration for a HANDLE. */
|
||||
|
||||
-#define ELF_PTRVAL_VOID elf_ptrval /*obsolete*/
|
||||
-#define ELF_PTRVAL_CHAR elf_ptrval /*obsolete*/
|
||||
-#define ELF_PTRVAL_CONST_VOID elf_ptrval /*obsolete*/
|
||||
-#define ELF_PTRVAL_CONST_CHAR elf_ptrval /*obsolete*/
|
||||
-
|
||||
#ifdef __XEN__
|
||||
# define ELF_PRPTRVAL "lu"
|
||||
/*
|
||||
@@ -124,17 +111,6 @@ typedef uintptr_t elf_ptrval;
|
||||
#define ELF_HANDLE_PTRVAL(handleval) ((handleval).ptrval)
|
||||
/* Converts a HANDLE to a PTRVAL. */
|
||||
|
||||
-#define ELF_OBSOLETE_VOIDP_CAST /*empty*/
|
||||
- /*
|
||||
- * In some places the old code used to need to
|
||||
- * - cast away const (the existing code uses const a fair
|
||||
- * bit but actually sometimes wants to write to its input)
|
||||
- * from a PTRVAL.
|
||||
- * - convert an integer representing a pointer to a PTRVAL
|
||||
- * Nowadays all of these re uintptr_ts so there is no const problem
|
||||
- * and no need for any casting.
|
||||
- */
|
||||
-
|
||||
#define ELF_UNSAFE_PTR(ptrval) ((void*)(elf_ptrval)(ptrval))
|
||||
/*
|
||||
* Turns a PTRVAL into an actual C pointer. Before this is done
|
||||
@@ -212,7 +188,7 @@ struct elf_binary {
|
||||
char data;
|
||||
|
||||
ELF_HANDLE_DECL(elf_ehdr) ehdr;
|
||||
- ELF_PTRVAL_CONST_CHAR sec_strtab;
|
||||
+ elf_ptrval sec_strtab;
|
||||
ELF_HANDLE_DECL(elf_shdr) sym_tab;
|
||||
uint64_t sym_strtab;
|
||||
|
||||
@@ -290,7 +266,7 @@ struct elf_binary {
|
||||
* str should be a HANDLE.
|
||||
*/
|
||||
|
||||
-uint64_t elf_access_unsigned(struct elf_binary *elf, ELF_PTRVAL_CONST_VOID ptr,
|
||||
+uint64_t elf_access_unsigned(struct elf_binary *elf, elf_ptrval ptr,
|
||||
uint64_t offset, size_t size);
|
||||
/* Reads a field at arbitrary offset and alignemnt */
|
||||
|
||||
@@ -342,17 +318,17 @@ ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_index(struct elf_binary *elf, unsigned ind
|
||||
ELF_HANDLE_DECL(elf_phdr) elf_phdr_by_index(struct elf_binary *elf, unsigned index);
|
||||
|
||||
const char *elf_section_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr); /* might return NULL if inputs are invalid */
|
||||
-ELF_PTRVAL_CONST_VOID elf_section_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr);
|
||||
-ELF_PTRVAL_CONST_VOID elf_section_end(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr);
|
||||
+elf_ptrval elf_section_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr);
|
||||
+elf_ptrval elf_section_end(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr);
|
||||
|
||||
-ELF_PTRVAL_CONST_VOID elf_segment_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr);
|
||||
-ELF_PTRVAL_CONST_VOID elf_segment_end(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr);
|
||||
+elf_ptrval elf_segment_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr);
|
||||
+elf_ptrval elf_segment_end(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr);
|
||||
|
||||
ELF_HANDLE_DECL(elf_sym) elf_sym_by_name(struct elf_binary *elf, const char *symbol);
|
||||
ELF_HANDLE_DECL(elf_sym) elf_sym_by_index(struct elf_binary *elf, unsigned index);
|
||||
|
||||
const char *elf_note_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note); /* may return NULL */
|
||||
-ELF_PTRVAL_CONST_VOID elf_note_desc(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
|
||||
+elf_ptrval elf_note_desc(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
|
||||
uint64_t elf_note_numeric(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
|
||||
uint64_t elf_note_numeric_array(struct elf_binary *, ELF_HANDLE_DECL(elf_note),
|
||||
unsigned int unitsz, unsigned int idx);
|
||||
@@ -391,7 +367,7 @@ void elf_set_log(struct elf_binary *elf, elf_log_callback*,
|
||||
void elf_parse_binary(struct elf_binary *elf);
|
||||
elf_errorstatus elf_load_binary(struct elf_binary *elf);
|
||||
|
||||
-ELF_PTRVAL_VOID elf_get_ptr(struct elf_binary *elf, unsigned long addr);
|
||||
+elf_ptrval elf_get_ptr(struct elf_binary *elf, unsigned long addr);
|
||||
uint64_t elf_lookup_addr(struct elf_binary *elf, const char *symbol);
|
||||
|
||||
void elf_parse_bsdsyms(struct elf_binary *elf, uint64_t pstart); /* private */
|
||||
@@ -426,9 +402,9 @@ struct xen_elfnote {
|
||||
|
||||
struct elf_dom_parms {
|
||||
/* raw */
|
||||
- ELF_PTRVAL_CONST_CHAR guest_info;
|
||||
- ELF_PTRVAL_CONST_VOID elf_note_start;
|
||||
- ELF_PTRVAL_CONST_VOID elf_note_end;
|
||||
+ elf_ptrval guest_info;
|
||||
+ elf_ptrval elf_note_start;
|
||||
+ elf_ptrval elf_note_end;
|
||||
struct xen_elfnote elf_notes[XEN_ELFNOTE_MAX + 1];
|
||||
|
||||
/* parsed */
|
||||
--
|
||||
1.7.2.5
|
||||
|
@ -0,0 +1,450 @@
|
||||
From b06e277b1fc08c7da3befeb3ac3950e1d941585d Mon Sep 17 00:00:00 2001
|
||||
From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Date: Fri, 14 Jun 2013 16:43:19 +0100
|
||||
Subject: [PATCH 18/23] libxc: Add range checking to xc_dom_binloader
|
||||
|
||||
This is a simple binary image loader with its own metadata format.
|
||||
However, it is too careless with image-supplied values.
|
||||
|
||||
Add the following checks:
|
||||
|
||||
* That the image is bigger than the metadata table; otherwise the
|
||||
pointer arithmetic to calculate the metadata table location may
|
||||
yield undefined and dangerous values.
|
||||
|
||||
* When clamping the end of the region to search, that we do not
|
||||
calculate pointers beyond the end of the image. The C
|
||||
specification does not permit this and compilers are becoming ever
|
||||
more determined to miscompile code when they can "prove" various
|
||||
falsehoods based on assertions from the C spec.
|
||||
|
||||
* That the supplied image is big enough for the text we are allegedly
|
||||
copying from it. Otherwise we might have a read overrun and copy
|
||||
the results (perhaps a lot of secret data) into the guest.
|
||||
|
||||
This is part of the fix to a security issue, XSA-55.
|
||||
|
||||
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
---
|
||||
tools/libxc/xc_dom_binloader.c | 15 +++++++++++++--
|
||||
1 files changed, 13 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/tools/libxc/xc_dom_binloader.c b/tools/libxc/xc_dom_binloader.c
|
||||
index bde93f7..8596a28 100644
|
||||
--- a/tools/libxc/xc_dom_binloader.c
|
||||
+++ b/tools/libxc/xc_dom_binloader.c
|
||||
@@ -123,10 +123,13 @@ static struct xen_bin_image_table *find_table(struct xc_dom_image *dom)
|
||||
uint32_t *probe_ptr;
|
||||
uint32_t *probe_end;
|
||||
|
||||
+ if ( dom->kernel_size < sizeof(*table) )
|
||||
+ return NULL;
|
||||
probe_ptr = dom->kernel_blob;
|
||||
- probe_end = dom->kernel_blob + dom->kernel_size - sizeof(*table);
|
||||
- if ( (void*)probe_end > (dom->kernel_blob + 8192) )
|
||||
+ if ( dom->kernel_size > (8192 + sizeof(*table)) )
|
||||
probe_end = dom->kernel_blob + 8192;
|
||||
+ else
|
||||
+ probe_end = dom->kernel_blob + dom->kernel_size - sizeof(*table);
|
||||
|
||||
for ( table = NULL; probe_ptr < probe_end; probe_ptr++ )
|
||||
{
|
||||
@@ -282,6 +285,14 @@ static int xc_dom_load_bin_kernel(struct xc_dom_image *dom)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
+ if ( image_size < skip ||
|
||||
+ image_size - skip < text_size )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: image is too small for declared text size",
|
||||
+ __FUNCTION__);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
memcpy(dest, image + skip, text_size);
|
||||
memset(dest + text_size, 0, bss_size);
|
||||
|
||||
--
|
||||
1.7.2.5
|
||||
#From 77c0829fa751f052f7b8ec08287aef6e7ba97bc5 Mon Sep 17 00:00:00 2001
|
||||
#From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
#Date: Fri, 14 Jun 2013 16:43:19 +0100
|
||||
#Subject: [PATCH 19/23] libxc: check failure of xc_dom_*_to_ptr, xc_map_foreign_range
|
||||
#
|
||||
#The return values from xc_dom_*_to_ptr and xc_map_foreign_range are
|
||||
#sometimes dereferenced, or subjected to pointer arithmetic, without
|
||||
#checking whether the relevant function failed and returned NULL.
|
||||
#
|
||||
#Add an appropriate error check at every call site.
|
||||
#
|
||||
#Changes in the 4.2 backport of this series:
|
||||
#* Fix tools/libxc/xc_dom_x86.c:setup_pgtables_x86_32.
|
||||
#* Fix tools/libxc/xc_dom_ia64.c:start_info_ia64.
|
||||
#* Fix tools/libxc/ia64/xc_ia64_dom_fwloader.c:xc_dom_load_fw_kernel.
|
||||
#
|
||||
#This is part of the fix to a security issue, XSA-55.
|
||||
#
|
||||
#Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
#---
|
||||
# tools/libxc/ia64/xc_ia64_dom_fwloader.c | 2 +
|
||||
# tools/libxc/xc_dom_binloader.c | 6 +++
|
||||
# tools/libxc/xc_dom_core.c | 6 +++
|
||||
# tools/libxc/xc_dom_elfloader.c | 13 +++++++
|
||||
# tools/libxc/xc_dom_ia64.c | 6 +++
|
||||
# tools/libxc/xc_dom_x86.c | 55 +++++++++++++++++++++++++++++++
|
||||
# tools/libxc/xc_domain_restore.c | 27 +++++++++++++++
|
||||
# tools/libxc/xc_offline_page.c | 5 +++
|
||||
# 8 files changed, 120 insertions(+), 0 deletions(-)
|
||||
#
|
||||
diff --git a/tools/libxc/ia64/xc_ia64_dom_fwloader.c b/tools/libxc/ia64/xc_ia64_dom_fwloader.c
|
||||
index cdf3333..dbd3349 100644
|
||||
--- a/tools/libxc/ia64/xc_ia64_dom_fwloader.c
|
||||
+++ b/tools/libxc/ia64/xc_ia64_dom_fwloader.c
|
||||
@@ -60,6 +60,8 @@ static int xc_dom_load_fw_kernel(struct xc_dom_image *dom)
|
||||
unsigned long i;
|
||||
|
||||
dest = xc_dom_vaddr_to_ptr(dom, dom->kernel_seg.vstart);
|
||||
+ if ( dest == NULL )
|
||||
+ return -1;
|
||||
memcpy(dest, dom->kernel_blob, FW_SIZE);
|
||||
|
||||
/* Synchronize cache. */
|
||||
diff --git a/tools/libxc/xc_dom_binloader.c b/tools/libxc/xc_dom_binloader.c
|
||||
index 8596a28..553b366 100644
|
||||
--- a/tools/libxc/xc_dom_binloader.c
|
||||
+++ b/tools/libxc/xc_dom_binloader.c
|
||||
@@ -277,6 +277,12 @@ static int xc_dom_load_bin_kernel(struct xc_dom_image *dom)
|
||||
DOMPRINTF(" bss_size: 0x%" PRIx32 "", bss_size);
|
||||
|
||||
dest = xc_dom_vaddr_to_ptr(dom, dom->kernel_seg.vstart, &dest_size);
|
||||
+ if ( dest == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: xc_dom_vaddr_to_ptr(dom, dom->kernel_seg.vstart)"
|
||||
+ " => NULL", __FUNCTION__);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
|
||||
if ( dest_size < text_size ||
|
||||
dest_size - text_size < bss_size )
|
||||
diff --git a/tools/libxc/xc_dom_core.c b/tools/libxc/xc_dom_core.c
|
||||
index 8913e41..a54ddae 100644
|
||||
--- a/tools/libxc/xc_dom_core.c
|
||||
+++ b/tools/libxc/xc_dom_core.c
|
||||
@@ -868,6 +868,12 @@ int xc_dom_build_image(struct xc_dom_image *dom)
|
||||
ramdisklen) != 0 )
|
||||
goto err;
|
||||
ramdiskmap = xc_dom_seg_to_ptr(dom, &dom->ramdisk_seg);
|
||||
+ if ( ramdiskmap == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: xc_dom_seg_to_ptr(dom, &dom->ramdisk_seg) => NULL",
|
||||
+ __FUNCTION__);
|
||||
+ goto err;
|
||||
+ }
|
||||
if ( unziplen )
|
||||
{
|
||||
if ( xc_dom_do_gunzip(dom->xch,
|
||||
diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c
|
||||
index 9fc4b94..61b5798 100644
|
||||
--- a/tools/libxc/xc_dom_elfloader.c
|
||||
+++ b/tools/libxc/xc_dom_elfloader.c
|
||||
@@ -139,6 +139,12 @@ static elf_errorstatus xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
return 0;
|
||||
size = dom->kernel_seg.vend - dom->bsd_symtab_start;
|
||||
hdr_ptr = xc_dom_vaddr_to_ptr(dom, dom->bsd_symtab_start, &allow_size);
|
||||
+ if ( hdr_ptr == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s/load: xc_dom_vaddr_to_ptr(dom,dom->bsd_symtab_start"
|
||||
+ " => NULL", __FUNCTION__);
|
||||
+ return -1;
|
||||
+ }
|
||||
elf->caller_xdest_base = hdr_ptr;
|
||||
elf->caller_xdest_size = allow_size;
|
||||
hdr = ELF_REALPTR2PTRVAL(hdr_ptr);
|
||||
@@ -384,7 +390,14 @@ static elf_errorstatus xc_dom_load_elf_kernel(struct xc_dom_image *dom)
|
||||
xen_pfn_t pages;
|
||||
|
||||
elf->dest_base = xc_dom_seg_to_ptr_pages(dom, &dom->kernel_seg, &pages);
|
||||
+ if ( elf->dest_base == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: xc_dom_vaddr_to_ptr(dom,dom->kernel_seg)"
|
||||
+ " => NULL", __FUNCTION__);
|
||||
+ return -1;
|
||||
+ }
|
||||
elf->dest_size = pages * XC_DOM_PAGE_SIZE(dom);
|
||||
+
|
||||
rc = elf_load_binary(elf);
|
||||
if ( rc < 0 )
|
||||
{
|
||||
diff --git a/tools/libxc/xc_dom_ia64.c b/tools/libxc/xc_dom_ia64.c
|
||||
index dcd1523..7c0eff1 100644
|
||||
--- a/tools/libxc/xc_dom_ia64.c
|
||||
+++ b/tools/libxc/xc_dom_ia64.c
|
||||
@@ -60,6 +60,12 @@ int start_info_ia64(struct xc_dom_image *dom)
|
||||
|
||||
DOMPRINTF_CALLED(dom->xch);
|
||||
|
||||
+ if ( start_info == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: xc_dom_pfn_to_ptr failed on start_info", __FUNCTION__);
|
||||
+ return -1; /* our caller throws away our return value :-/ */
|
||||
+ }
|
||||
+
|
||||
memset(start_info, 0, sizeof(*start_info));
|
||||
sprintf(start_info->magic, dom->guest_type);
|
||||
start_info->flags = dom->flags;
|
||||
diff --git a/tools/libxc/xc_dom_x86.c b/tools/libxc/xc_dom_x86.c
|
||||
index 0cf1687..75d6b83 100644
|
||||
--- a/tools/libxc/xc_dom_x86.c
|
||||
+++ b/tools/libxc/xc_dom_x86.c
|
||||
@@ -144,6 +144,9 @@ static int setup_pgtables_x86_32(struct xc_dom_image *dom)
|
||||
xen_vaddr_t addr;
|
||||
xen_pfn_t pgpfn;
|
||||
|
||||
+ if ( l2tab == NULL )
|
||||
+ goto pfn_error;
|
||||
+
|
||||
for ( addr = dom->parms.virt_base; addr < dom->virt_pgtab_end;
|
||||
addr += PAGE_SIZE_X86 )
|
||||
{
|
||||
@@ -151,6 +154,8 @@ static int setup_pgtables_x86_32(struct xc_dom_image *dom)
|
||||
{
|
||||
/* get L1 tab, make L2 entry */
|
||||
l1tab = xc_dom_pfn_to_ptr(dom, l1pfn, 1);
|
||||
+ if ( l1tab == NULL )
|
||||
+ goto pfn_error;
|
||||
l2off = l2_table_offset_i386(addr);
|
||||
l2tab[l2off] =
|
||||
pfn_to_paddr(xc_dom_p2m_guest(dom, l1pfn)) | L2_PROT;
|
||||
@@ -169,6 +174,11 @@ static int setup_pgtables_x86_32(struct xc_dom_image *dom)
|
||||
l1tab = NULL;
|
||||
}
|
||||
return 0;
|
||||
+
|
||||
+pfn_error:
|
||||
+ xc_dom_panic(dom->xch, XC_INTERNAL_ERROR,
|
||||
+ "%s: xc_dom_pfn_to_ptr failed", __FUNCTION__);
|
||||
+ return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -219,6 +229,12 @@ static xen_pfn_t move_l3_below_4G(struct xc_dom_image *dom,
|
||||
goto out;
|
||||
|
||||
l3tab = xc_dom_pfn_to_ptr(dom, l3pfn, 1);
|
||||
+ if ( l3tab == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: xc_dom_pfn_to_ptr(dom, l3pfn, 1) => NULL",
|
||||
+ __FUNCTION__);
|
||||
+ return l3mfn; /* our one call site will call xc_dom_panic and fail */
|
||||
+ }
|
||||
memset(l3tab, 0, XC_DOM_PAGE_SIZE(dom));
|
||||
|
||||
DOMPRINTF("%s: successfully relocated L3 below 4G. "
|
||||
@@ -262,6 +278,8 @@ static int setup_pgtables_x86_32_pae(struct xc_dom_image *dom)
|
||||
}
|
||||
|
||||
l3tab = xc_dom_pfn_to_ptr(dom, l3pfn, 1);
|
||||
+ if ( l3tab == NULL )
|
||||
+ goto pfn_error;
|
||||
|
||||
for ( addr = dom->parms.virt_base; addr < dom->virt_pgtab_end;
|
||||
addr += PAGE_SIZE_X86 )
|
||||
@@ -270,6 +288,8 @@ static int setup_pgtables_x86_32_pae(struct xc_dom_image *dom)
|
||||
{
|
||||
/* get L2 tab, make L3 entry */
|
||||
l2tab = xc_dom_pfn_to_ptr(dom, l2pfn, 1);
|
||||
+ if ( l2tab == NULL )
|
||||
+ goto pfn_error;
|
||||
l3off = l3_table_offset_pae(addr);
|
||||
l3tab[l3off] =
|
||||
pfn_to_paddr(xc_dom_p2m_guest(dom, l2pfn)) | L3_PROT;
|
||||
@@ -280,6 +300,8 @@ static int setup_pgtables_x86_32_pae(struct xc_dom_image *dom)
|
||||
{
|
||||
/* get L1 tab, make L2 entry */
|
||||
l1tab = xc_dom_pfn_to_ptr(dom, l1pfn, 1);
|
||||
+ if ( l1tab == NULL )
|
||||
+ goto pfn_error;
|
||||
l2off = l2_table_offset_pae(addr);
|
||||
l2tab[l2off] =
|
||||
pfn_to_paddr(xc_dom_p2m_guest(dom, l1pfn)) | L2_PROT;
|
||||
@@ -306,6 +328,11 @@ static int setup_pgtables_x86_32_pae(struct xc_dom_image *dom)
|
||||
l3tab[3] = pfn_to_paddr(xc_dom_p2m_guest(dom, l2pfn)) | L3_PROT;
|
||||
}
|
||||
return 0;
|
||||
+
|
||||
+pfn_error:
|
||||
+ xc_dom_panic(dom->xch, XC_INTERNAL_ERROR,
|
||||
+ "%s: xc_dom_pfn_to_ptr failed", __FUNCTION__);
|
||||
+ return -EINVAL;
|
||||
}
|
||||
|
||||
#undef L1_PROT
|
||||
@@ -344,6 +371,9 @@ static int setup_pgtables_x86_64(struct xc_dom_image *dom)
|
||||
uint64_t addr;
|
||||
xen_pfn_t pgpfn;
|
||||
|
||||
+ if ( l4tab == NULL )
|
||||
+ goto pfn_error;
|
||||
+
|
||||
for ( addr = dom->parms.virt_base; addr < dom->virt_pgtab_end;
|
||||
addr += PAGE_SIZE_X86 )
|
||||
{
|
||||
@@ -351,6 +381,8 @@ static int setup_pgtables_x86_64(struct xc_dom_image *dom)
|
||||
{
|
||||
/* get L3 tab, make L4 entry */
|
||||
l3tab = xc_dom_pfn_to_ptr(dom, l3pfn, 1);
|
||||
+ if ( l3tab == NULL )
|
||||
+ goto pfn_error;
|
||||
l4off = l4_table_offset_x86_64(addr);
|
||||
l4tab[l4off] =
|
||||
pfn_to_paddr(xc_dom_p2m_guest(dom, l3pfn)) | L4_PROT;
|
||||
@@ -361,6 +393,8 @@ static int setup_pgtables_x86_64(struct xc_dom_image *dom)
|
||||
{
|
||||
/* get L2 tab, make L3 entry */
|
||||
l2tab = xc_dom_pfn_to_ptr(dom, l2pfn, 1);
|
||||
+ if ( l2tab == NULL )
|
||||
+ goto pfn_error;
|
||||
l3off = l3_table_offset_x86_64(addr);
|
||||
l3tab[l3off] =
|
||||
pfn_to_paddr(xc_dom_p2m_guest(dom, l2pfn)) | L3_PROT;
|
||||
@@ -373,6 +407,8 @@ static int setup_pgtables_x86_64(struct xc_dom_image *dom)
|
||||
{
|
||||
/* get L1 tab, make L2 entry */
|
||||
l1tab = xc_dom_pfn_to_ptr(dom, l1pfn, 1);
|
||||
+ if ( l1tab == NULL )
|
||||
+ goto pfn_error;
|
||||
l2off = l2_table_offset_x86_64(addr);
|
||||
l2tab[l2off] =
|
||||
pfn_to_paddr(xc_dom_p2m_guest(dom, l1pfn)) | L2_PROT;
|
||||
@@ -393,6 +429,11 @@ static int setup_pgtables_x86_64(struct xc_dom_image *dom)
|
||||
l1tab = NULL;
|
||||
}
|
||||
return 0;
|
||||
+
|
||||
+pfn_error:
|
||||
+ xc_dom_panic(dom->xch, XC_INTERNAL_ERROR,
|
||||
+ "%s: xc_dom_pfn_to_ptr failed", __FUNCTION__);
|
||||
+ return -EINVAL;
|
||||
}
|
||||
|
||||
#undef L1_PROT
|
||||
@@ -410,6 +451,8 @@ static int alloc_magic_pages(struct xc_dom_image *dom)
|
||||
if ( xc_dom_alloc_segment(dom, &dom->p2m_seg, "phys2mach", 0, p2m_size) )
|
||||
return -1;
|
||||
dom->p2m_guest = xc_dom_seg_to_ptr(dom, &dom->p2m_seg);
|
||||
+ if ( dom->p2m_guest == NULL )
|
||||
+ return -1;
|
||||
|
||||
/* allocate special pages */
|
||||
dom->start_info_pfn = xc_dom_alloc_page(dom, "start info");
|
||||
@@ -434,6 +477,12 @@ static int start_info_x86_32(struct xc_dom_image *dom)
|
||||
|
||||
DOMPRINTF_CALLED(dom->xch);
|
||||
|
||||
+ if ( start_info == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: xc_dom_pfn_to_ptr failed on start_info", __FUNCTION__);
|
||||
+ return -1; /* our caller throws away our return value :-/ */
|
||||
+ }
|
||||
+
|
||||
memset(start_info, 0, sizeof(*start_info));
|
||||
strncpy(start_info->magic, dom->guest_type, sizeof(start_info->magic));
|
||||
start_info->magic[sizeof(start_info->magic) - 1] = '\0';
|
||||
@@ -474,6 +523,12 @@ static int start_info_x86_64(struct xc_dom_image *dom)
|
||||
|
||||
DOMPRINTF_CALLED(dom->xch);
|
||||
|
||||
+ if ( start_info == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: xc_dom_pfn_to_ptr failed on start_info", __FUNCTION__);
|
||||
+ return -1; /* our caller throws away our return value :-/ */
|
||||
+ }
|
||||
+
|
||||
memset(start_info, 0, sizeof(*start_info));
|
||||
strncpy(start_info->magic, dom->guest_type, sizeof(start_info->magic));
|
||||
start_info->magic[sizeof(start_info->magic) - 1] = '\0';
|
||||
diff --git a/tools/libxc/xc_domain_restore.c b/tools/libxc/xc_domain_restore.c
|
||||
index b4c0b10..3994f8f 100644
|
||||
--- a/tools/libxc/xc_domain_restore.c
|
||||
+++ b/tools/libxc/xc_domain_restore.c
|
||||
@@ -1556,6 +1556,12 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
|
||||
mfn = ctx->p2m[pfn];
|
||||
buf = xc_map_foreign_range(xch, dom, PAGE_SIZE,
|
||||
PROT_READ | PROT_WRITE, mfn);
|
||||
+ if ( buf == NULL )
|
||||
+ {
|
||||
+ ERROR("xc_map_foreign_range for generation id"
|
||||
+ " buffer failed");
|
||||
+ goto out;
|
||||
+ }
|
||||
|
||||
generationid = *(unsigned long long *)(buf + offset);
|
||||
*(unsigned long long *)(buf + offset) = generationid + 1;
|
||||
@@ -1713,6 +1719,11 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
|
||||
l3tab = (uint64_t *)
|
||||
xc_map_foreign_range(xch, dom, PAGE_SIZE,
|
||||
PROT_READ, ctx->p2m[i]);
|
||||
+ if ( l3tab == NULL )
|
||||
+ {
|
||||
+ PERROR("xc_map_foreign_range failed (for l3tab)");
|
||||
+ goto out;
|
||||
+ }
|
||||
|
||||
for ( j = 0; j < 4; j++ )
|
||||
l3ptes[j] = l3tab[j];
|
||||
@@ -1739,6 +1750,11 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
|
||||
l3tab = (uint64_t *)
|
||||
xc_map_foreign_range(xch, dom, PAGE_SIZE,
|
||||
PROT_READ | PROT_WRITE, ctx->p2m[i]);
|
||||
+ if ( l3tab == NULL )
|
||||
+ {
|
||||
+ PERROR("xc_map_foreign_range failed (for l3tab, 2nd)");
|
||||
+ goto out;
|
||||
+ }
|
||||
|
||||
for ( j = 0; j < 4; j++ )
|
||||
l3tab[j] = l3ptes[j];
|
||||
@@ -1909,6 +1925,12 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
|
||||
SET_FIELD(ctxt, user_regs.edx, mfn);
|
||||
start_info = xc_map_foreign_range(
|
||||
xch, dom, PAGE_SIZE, PROT_READ | PROT_WRITE, mfn);
|
||||
+ if ( start_info == NULL )
|
||||
+ {
|
||||
+ PERROR("xc_map_foreign_range failed (for start_info)");
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
SET_FIELD(start_info, nr_pages, dinfo->p2m_size);
|
||||
SET_FIELD(start_info, shared_info, shared_info_frame<<PAGE_SHIFT);
|
||||
SET_FIELD(start_info, flags, 0);
|
||||
@@ -2056,6 +2078,11 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
|
||||
/* Restore contents of shared-info page. No checking needed. */
|
||||
new_shared_info = xc_map_foreign_range(
|
||||
xch, dom, PAGE_SIZE, PROT_WRITE, shared_info_frame);
|
||||
+ if ( new_shared_info == NULL )
|
||||
+ {
|
||||
+ PERROR("xc_map_foreign_range failed (for new_shared_info)");
|
||||
+ goto out;
|
||||
+ }
|
||||
|
||||
/* restore saved vcpu_info and arch specific info */
|
||||
MEMCPY_FIELD(new_shared_info, old_shared_info, vcpu_info);
|
||||
diff --git a/tools/libxc/xc_offline_page.c b/tools/libxc/xc_offline_page.c
|
||||
index 089a361..36b9812 100644
|
||||
--- a/tools/libxc/xc_offline_page.c
|
||||
+++ b/tools/libxc/xc_offline_page.c
|
||||
@@ -714,6 +714,11 @@ int xc_exchange_page(xc_interface *xch, int domid, xen_pfn_t mfn)
|
||||
|
||||
new_p = xc_map_foreign_range(xch, domid, PAGE_SIZE,
|
||||
PROT_READ|PROT_WRITE, new_mfn);
|
||||
+ if ( new_p == NULL )
|
||||
+ {
|
||||
+ ERROR("failed to map new_p for copy, guest may be broken?");
|
||||
+ goto failed;
|
||||
+ }
|
||||
memcpy(new_p, backup, PAGE_SIZE);
|
||||
munmap(new_p, PAGE_SIZE);
|
||||
mops.arg1.mfn = new_mfn;
|
||||
--
|
||||
1.7.2.5
|
||||
|
@ -0,0 +1,56 @@
|
||||
From a672da4b2d58ef12be9d7407160e9fb43cac75d9 Mon Sep 17 00:00:00 2001
|
||||
From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Date: Fri, 14 Jun 2013 16:43:16 +0100
|
||||
Subject: [PATCH 02/23] libxc: introduce xc_dom_seg_to_ptr_pages
|
||||
|
||||
Provide a version of xc_dom_seg_to_ptr which returns the number of
|
||||
guest pages it has actually mapped. This is useful for callers who
|
||||
want to do range checking; we will use this later in this series.
|
||||
|
||||
This is part of the fix to a security issue, XSA-55.
|
||||
|
||||
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
|
||||
---
|
||||
tools/libxc/xc_dom.h | 19 ++++++++++++++++---
|
||||
1 files changed, 16 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/tools/libxc/xc_dom.h b/tools/libxc/xc_dom.h
|
||||
index 6a72aa9..9af2195 100644
|
||||
--- a/tools/libxc/xc_dom.h
|
||||
+++ b/tools/libxc/xc_dom.h
|
||||
@@ -278,14 +278,27 @@ void *xc_dom_pfn_to_ptr(struct xc_dom_image *dom, xen_pfn_t first,
|
||||
void xc_dom_unmap_one(struct xc_dom_image *dom, xen_pfn_t pfn);
|
||||
void xc_dom_unmap_all(struct xc_dom_image *dom);
|
||||
|
||||
-static inline void *xc_dom_seg_to_ptr(struct xc_dom_image *dom,
|
||||
- struct xc_dom_seg *seg)
|
||||
+static inline void *xc_dom_seg_to_ptr_pages(struct xc_dom_image *dom,
|
||||
+ struct xc_dom_seg *seg,
|
||||
+ xen_pfn_t *pages_out)
|
||||
{
|
||||
xen_vaddr_t segsize = seg->vend - seg->vstart;
|
||||
unsigned int page_size = XC_DOM_PAGE_SIZE(dom);
|
||||
xen_pfn_t pages = (segsize + page_size - 1) / page_size;
|
||||
+ void *retval;
|
||||
+
|
||||
+ retval = xc_dom_pfn_to_ptr(dom, seg->pfn, pages);
|
||||
+
|
||||
+ *pages_out = retval ? pages : 0;
|
||||
+ return retval;
|
||||
+}
|
||||
+
|
||||
+static inline void *xc_dom_seg_to_ptr(struct xc_dom_image *dom,
|
||||
+ struct xc_dom_seg *seg)
|
||||
+{
|
||||
+ xen_pfn_t dummy;
|
||||
|
||||
- return xc_dom_pfn_to_ptr(dom, seg->pfn, pages);
|
||||
+ return xc_dom_seg_to_ptr_pages(dom, seg, &dummy);
|
||||
}
|
||||
|
||||
static inline void *xc_dom_vaddr_to_ptr(struct xc_dom_image *dom,
|
||||
--
|
||||
1.7.2.5
|
||||
|
@ -0,0 +1,381 @@
|
||||
From 8dc90d163650ce8aa36ae0b46debab83cc61edb6 Mon Sep 17 00:00:00 2001
|
||||
From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Date: Fri, 14 Jun 2013 16:43:19 +0100
|
||||
Subject: [PATCH 20/23] libxc: check return values from malloc
|
||||
|
||||
A sufficiently malformed input to libxc (such as a malformed input ELF
|
||||
or other guest-controlled data) might cause one of libxc's malloc() to
|
||||
fail. In this case we need to make sure we don't dereference or do
|
||||
pointer arithmetic on the result.
|
||||
|
||||
Search for all occurrences of \b(m|c|re)alloc in libxc, and all
|
||||
functions which call them, and add appropriate error checking where
|
||||
missing.
|
||||
|
||||
This includes the functions xc_dom_malloc*, which now print a message
|
||||
when they fail so that callers don't have to do so.
|
||||
|
||||
The function xc_cpuid_to_str wasn't provided with a sane return value
|
||||
and has a pretty strange API, which now becomes a little stranger.
|
||||
There are no in-tree callers.
|
||||
|
||||
Changes in the Xen 4.2 version of this series:
|
||||
* No need to fix code relating to ARM.
|
||||
* No need to fix code relating to superpage support.
|
||||
* Additionally fix `dom->p2m_host = xc_dom_malloc...' in xc_dom_ia64.c.
|
||||
|
||||
This is part of the fix to a security issue, XSA-55.
|
||||
|
||||
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
---
|
||||
tools/libxc/xc_cpuid_x86.c | 20 ++++++++++++++++++--
|
||||
tools/libxc/xc_dom_core.c | 13 +++++++++++++
|
||||
tools/libxc/xc_dom_elfloader.c | 2 ++
|
||||
tools/libxc/xc_dom_ia64.c | 6 ++++++
|
||||
tools/libxc/xc_dom_x86.c | 3 +++
|
||||
tools/libxc/xc_domain_restore.c | 5 +++++
|
||||
tools/libxc/xc_linux_osdep.c | 4 ++++
|
||||
tools/libxc/xc_private.c | 2 ++
|
||||
tools/libxc/xenctrl.h | 2 +-
|
||||
9 files changed, 54 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/tools/libxc/xc_cpuid_x86.c b/tools/libxc/xc_cpuid_x86.c
|
||||
index 0882ce6..da435ce 100644
|
||||
--- a/tools/libxc/xc_cpuid_x86.c
|
||||
+++ b/tools/libxc/xc_cpuid_x86.c
|
||||
@@ -589,6 +589,8 @@ static int xc_cpuid_do_domctl(
|
||||
static char *alloc_str(void)
|
||||
{
|
||||
char *s = malloc(33);
|
||||
+ if ( s == NULL )
|
||||
+ return s;
|
||||
memset(s, 0, 33);
|
||||
return s;
|
||||
}
|
||||
@@ -600,6 +602,8 @@ void xc_cpuid_to_str(const unsigned int *regs, char **strs)
|
||||
for ( i = 0; i < 4; i++ )
|
||||
{
|
||||
strs[i] = alloc_str();
|
||||
+ if ( strs[i] == NULL )
|
||||
+ continue;
|
||||
for ( j = 0; j < 32; j++ )
|
||||
strs[i][j] = !!((regs[i] & (1U << (31 - j)))) ? '1' : '0';
|
||||
}
|
||||
@@ -680,7 +684,7 @@ int xc_cpuid_check(
|
||||
const char **config,
|
||||
char **config_transformed)
|
||||
{
|
||||
- int i, j;
|
||||
+ int i, j, rc;
|
||||
unsigned int regs[4];
|
||||
|
||||
memset(config_transformed, 0, 4 * sizeof(*config_transformed));
|
||||
@@ -692,6 +696,11 @@ int xc_cpuid_check(
|
||||
if ( config[i] == NULL )
|
||||
continue;
|
||||
config_transformed[i] = alloc_str();
|
||||
+ if ( config_transformed[i] == NULL )
|
||||
+ {
|
||||
+ rc = -ENOMEM;
|
||||
+ goto fail_rc;
|
||||
+ }
|
||||
for ( j = 0; j < 32; j++ )
|
||||
{
|
||||
unsigned char val = !!((regs[i] & (1U << (31 - j))));
|
||||
@@ -708,12 +717,14 @@ int xc_cpuid_check(
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
+ rc = -EPERM;
|
||||
+ fail_rc:
|
||||
for ( i = 0; i < 4; i++ )
|
||||
{
|
||||
free(config_transformed[i]);
|
||||
config_transformed[i] = NULL;
|
||||
}
|
||||
- return -EPERM;
|
||||
+ return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -758,6 +769,11 @@ int xc_cpuid_set(
|
||||
}
|
||||
|
||||
config_transformed[i] = alloc_str();
|
||||
+ if ( config_transformed[i] == NULL )
|
||||
+ {
|
||||
+ rc = -ENOMEM;
|
||||
+ goto fail;
|
||||
+ }
|
||||
|
||||
for ( j = 0; j < 32; j++ )
|
||||
{
|
||||
diff --git a/tools/libxc/xc_dom_core.c b/tools/libxc/xc_dom_core.c
|
||||
index a54ddae..3cbf9f7 100644
|
||||
--- a/tools/libxc/xc_dom_core.c
|
||||
+++ b/tools/libxc/xc_dom_core.c
|
||||
@@ -120,9 +120,17 @@ void *xc_dom_malloc(struct xc_dom_image *dom, size_t size)
|
||||
{
|
||||
struct xc_dom_mem *block;
|
||||
|
||||
+ if ( size > SIZE_MAX - sizeof(*block) )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: unreasonable allocation size", __FUNCTION__);
|
||||
+ return NULL;
|
||||
+ }
|
||||
block = malloc(sizeof(*block) + size);
|
||||
if ( block == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: allocation failed", __FUNCTION__);
|
||||
return NULL;
|
||||
+ }
|
||||
memset(block, 0, sizeof(*block) + size);
|
||||
block->next = dom->memblocks;
|
||||
dom->memblocks = block;
|
||||
@@ -138,7 +146,10 @@ void *xc_dom_malloc_page_aligned(struct xc_dom_image *dom, size_t size)
|
||||
|
||||
block = malloc(sizeof(*block));
|
||||
if ( block == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: allocation failed", __FUNCTION__);
|
||||
return NULL;
|
||||
+ }
|
||||
memset(block, 0, sizeof(*block));
|
||||
block->mmap_len = size;
|
||||
block->mmap_ptr = mmap(NULL, block->mmap_len,
|
||||
@@ -146,6 +157,7 @@ void *xc_dom_malloc_page_aligned(struct xc_dom_image *dom, size_t size)
|
||||
-1, 0);
|
||||
if ( block->mmap_ptr == MAP_FAILED )
|
||||
{
|
||||
+ DOMPRINTF("%s: mmap failed", __FUNCTION__);
|
||||
free(block);
|
||||
return NULL;
|
||||
}
|
||||
@@ -202,6 +214,7 @@ void *xc_dom_malloc_filemap(struct xc_dom_image *dom,
|
||||
close(fd);
|
||||
if ( block != NULL )
|
||||
free(block);
|
||||
+ DOMPRINTF("%s: failed (on file `%s')", __FUNCTION__, filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c
|
||||
index 61b5798..be58276 100644
|
||||
--- a/tools/libxc/xc_dom_elfloader.c
|
||||
+++ b/tools/libxc/xc_dom_elfloader.c
|
||||
@@ -329,6 +329,8 @@ static elf_errorstatus xc_dom_parse_elf_kernel(struct xc_dom_image *dom)
|
||||
return rc;
|
||||
|
||||
elf = xc_dom_malloc(dom, sizeof(*elf));
|
||||
+ if ( elf == NULL )
|
||||
+ return -1;
|
||||
dom->private_loader = elf;
|
||||
rc = elf_init(elf, dom->kernel_blob, dom->kernel_size);
|
||||
xc_elf_set_logfile(dom->xch, elf, 1);
|
||||
diff --git a/tools/libxc/xc_dom_ia64.c b/tools/libxc/xc_dom_ia64.c
|
||||
index 7c0eff1..076821c 100644
|
||||
--- a/tools/libxc/xc_dom_ia64.c
|
||||
+++ b/tools/libxc/xc_dom_ia64.c
|
||||
@@ -188,6 +188,12 @@ int arch_setup_meminit(struct xc_dom_image *dom)
|
||||
|
||||
/* setup initial p2m */
|
||||
dom->p2m_host = xc_dom_malloc(dom, sizeof(xen_pfn_t) * nbr);
|
||||
+ if ( dom->p2m_host == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: xc_dom_malloc failed for p2m_host",
|
||||
+ __FUNCTION__);
|
||||
+ return -1;
|
||||
+ }
|
||||
for ( pfn = 0; pfn < nbr; pfn++ )
|
||||
dom->p2m_host[pfn] = start + pfn;
|
||||
|
||||
diff --git a/tools/libxc/xc_dom_x86.c b/tools/libxc/xc_dom_x86.c
|
||||
index 75d6b83..448d9a1 100644
|
||||
--- a/tools/libxc/xc_dom_x86.c
|
||||
+++ b/tools/libxc/xc_dom_x86.c
|
||||
@@ -780,6 +780,9 @@ int arch_setup_meminit(struct xc_dom_image *dom)
|
||||
}
|
||||
|
||||
dom->p2m_host = xc_dom_malloc(dom, sizeof(xen_pfn_t) * dom->total_pages);
|
||||
+ if ( dom->p2m_host == NULL )
|
||||
+ return -EINVAL;
|
||||
+
|
||||
if ( dom->superpages )
|
||||
{
|
||||
int count = dom->total_pages >> SUPERPAGE_PFN_SHIFT;
|
||||
diff --git a/tools/libxc/xc_domain_restore.c b/tools/libxc/xc_domain_restore.c
|
||||
index 3994f8f..f9ed6b2 100644
|
||||
--- a/tools/libxc/xc_domain_restore.c
|
||||
+++ b/tools/libxc/xc_domain_restore.c
|
||||
@@ -1180,6 +1180,11 @@ static int apply_batch(xc_interface *xch, uint32_t dom, struct restore_ctx *ctx,
|
||||
|
||||
/* Map relevant mfns */
|
||||
pfn_err = calloc(j, sizeof(*pfn_err));
|
||||
+ if ( pfn_err == NULL )
|
||||
+ {
|
||||
+ PERROR("allocation for pfn_err failed");
|
||||
+ return -1;
|
||||
+ }
|
||||
region_base = xc_map_foreign_bulk(
|
||||
xch, dom, PROT_WRITE, region_mfn, pfn_err, j);
|
||||
|
||||
diff --git a/tools/libxc/xc_linux_osdep.c b/tools/libxc/xc_linux_osdep.c
|
||||
index 787e742..98e041c 100644
|
||||
--- a/tools/libxc/xc_linux_osdep.c
|
||||
+++ b/tools/libxc/xc_linux_osdep.c
|
||||
@@ -378,6 +378,8 @@ static void *linux_privcmd_map_foreign_range(xc_interface *xch, xc_osdep_handle
|
||||
|
||||
num = (size + XC_PAGE_SIZE - 1) >> XC_PAGE_SHIFT;
|
||||
arr = calloc(num, sizeof(xen_pfn_t));
|
||||
+ if ( arr == NULL )
|
||||
+ return NULL;
|
||||
|
||||
for ( i = 0; i < num; i++ )
|
||||
arr[i] = mfn + i;
|
||||
@@ -402,6 +404,8 @@ static void *linux_privcmd_map_foreign_ranges(xc_interface *xch, xc_osdep_handle
|
||||
num_per_entry = chunksize >> XC_PAGE_SHIFT;
|
||||
num = num_per_entry * nentries;
|
||||
arr = calloc(num, sizeof(xen_pfn_t));
|
||||
+ if ( arr == NULL )
|
||||
+ return NULL;
|
||||
|
||||
for ( i = 0; i < nentries; i++ )
|
||||
for ( j = 0; j < num_per_entry; j++ )
|
||||
diff --git a/tools/libxc/xc_private.c b/tools/libxc/xc_private.c
|
||||
index 3e03a91..848ceed 100644
|
||||
--- a/tools/libxc/xc_private.c
|
||||
+++ b/tools/libxc/xc_private.c
|
||||
@@ -771,6 +771,8 @@ const char *xc_strerror(xc_interface *xch, int errcode)
|
||||
errbuf = pthread_getspecific(errbuf_pkey);
|
||||
if (errbuf == NULL) {
|
||||
errbuf = malloc(XS_BUFSIZE);
|
||||
+ if ( errbuf == NULL )
|
||||
+ return "(failed to allocate errbuf)";
|
||||
pthread_setspecific(errbuf_pkey, errbuf);
|
||||
}
|
||||
|
||||
diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h
|
||||
index b7741ca..8952048 100644
|
||||
--- a/tools/libxc/xenctrl.h
|
||||
+++ b/tools/libxc/xenctrl.h
|
||||
@@ -1778,7 +1778,7 @@ int xc_cpuid_set(xc_interface *xch,
|
||||
int xc_cpuid_apply_policy(xc_interface *xch,
|
||||
domid_t domid);
|
||||
void xc_cpuid_to_str(const unsigned int *regs,
|
||||
- char **strs);
|
||||
+ char **strs); /* some strs[] may be NULL if ENOMEM */
|
||||
int xc_mca_op(xc_interface *xch, struct xen_mc *mc);
|
||||
#endif
|
||||
|
||||
--
|
||||
1.7.2.5
|
||||
#From 052a689aa526ca51fd70528d4b0f83dfb2de99c1 Mon Sep 17 00:00:00 2001
|
||||
#From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
#Date: Fri, 14 Jun 2013 16:43:19 +0100
|
||||
#Subject: [PATCH 21/23] libxc: range checks in xc_dom_p2m_host and _guest
|
||||
#
|
||||
#These functions take guest pfns and look them up in the p2m. They did
|
||||
#no range checking.
|
||||
#
|
||||
#However, some callers, notably xc_dom_boot.c:setup_hypercall_page want
|
||||
#to pass untrusted guest-supplied value(s). It is most convenient to
|
||||
#detect this here and return INVALID_MFN.
|
||||
#
|
||||
#This is part of the fix to a security issue, XSA-55.
|
||||
#
|
||||
#Changes from Xen 4.2 version of this patch:
|
||||
#* 4.2 lacks dom->rambase_pfn, so don't add/subtract/check it.
|
||||
#
|
||||
#Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
#---
|
||||
# tools/libxc/xc_dom.h | 4 ++++
|
||||
# 1 files changed, 4 insertions(+), 0 deletions(-)
|
||||
#
|
||||
diff --git a/tools/libxc/xc_dom.h b/tools/libxc/xc_dom.h
|
||||
index 0161459..d801f66 100644
|
||||
--- a/tools/libxc/xc_dom.h
|
||||
+++ b/tools/libxc/xc_dom.h
|
||||
@@ -331,6 +331,8 @@ static inline xen_pfn_t xc_dom_p2m_host(struct xc_dom_image *dom, xen_pfn_t pfn)
|
||||
{
|
||||
if (dom->shadow_enabled)
|
||||
return pfn;
|
||||
+ if (pfn >= dom->total_pages)
|
||||
+ return INVALID_MFN;
|
||||
return dom->p2m_host[pfn];
|
||||
}
|
||||
|
||||
@@ -339,6 +341,8 @@ static inline xen_pfn_t xc_dom_p2m_guest(struct xc_dom_image *dom,
|
||||
{
|
||||
if (xc_dom_feature_translated(dom))
|
||||
return pfn;
|
||||
+ if (pfn >= dom->total_pages)
|
||||
+ return INVALID_MFN;
|
||||
return dom->p2m_host[pfn];
|
||||
}
|
||||
|
||||
--
|
||||
1.7.2.5
|
||||
#From 2a548e22915535ac13694eb38222903bca7245e3 Mon Sep 17 00:00:00 2001
|
||||
#From: Matthew Daley <mattjd@gmail.com>
|
||||
#Date: Fri, 14 Jun 2013 16:43:19 +0100
|
||||
#Subject: [PATCH 22/23] libxc: check blob size before proceeding in xc_dom_check_gzip
|
||||
#
|
||||
#This is part of the fix to a security issue, XSA-55.
|
||||
#
|
||||
#Signed-off-by: Matthew Daley <mattjd@gmail.com>
|
||||
#---
|
||||
# tools/libxc/xc_dom_core.c | 5 +++++
|
||||
# 1 files changed, 5 insertions(+), 0 deletions(-)
|
||||
#
|
||||
diff --git a/tools/libxc/xc_dom_core.c b/tools/libxc/xc_dom_core.c
|
||||
index 3cbf9f7..f8d1b08 100644
|
||||
--- a/tools/libxc/xc_dom_core.c
|
||||
+++ b/tools/libxc/xc_dom_core.c
|
||||
@@ -284,6 +284,11 @@ size_t xc_dom_check_gzip(xc_interface *xch, void *blob, size_t ziplen)
|
||||
unsigned char *gzlen;
|
||||
size_t unziplen;
|
||||
|
||||
+ if ( ziplen < 6 )
|
||||
+ /* Too small. We need (i.e. the subsequent code relies on)
|
||||
+ * 2 bytes for the magic number plus 4 bytes length. */
|
||||
+ return 0;
|
||||
+
|
||||
if ( strncmp(blob, "\037\213", 2) )
|
||||
/* not gzipped */
|
||||
return 0;
|
||||
--
|
||||
1.7.2.5
|
||||
#From d21d36e84354c04638b60a739a5f7c3d9f8adaf8 Mon Sep 17 00:00:00 2001
|
||||
#From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
#Date: Fri, 14 Jun 2013 16:43:19 +0100
|
||||
#Subject: [PATCH 23/23] libxc: Better range check in xc_dom_alloc_segment
|
||||
#
|
||||
#If seg->pfn is too large, the arithmetic in the range check might
|
||||
#overflow, defeating the range check.
|
||||
#
|
||||
#This is part of the fix to a security issue, XSA-55.
|
||||
#
|
||||
#Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
#Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
|
||||
#---
|
||||
# tools/libxc/xc_dom_core.c | 3 ++-
|
||||
# 1 files changed, 2 insertions(+), 1 deletions(-)
|
||||
#
|
||||
diff --git a/tools/libxc/xc_dom_core.c b/tools/libxc/xc_dom_core.c
|
||||
index f8d1b08..e79e38d 100644
|
||||
--- a/tools/libxc/xc_dom_core.c
|
||||
+++ b/tools/libxc/xc_dom_core.c
|
||||
@@ -509,7 +509,8 @@ int xc_dom_alloc_segment(struct xc_dom_image *dom,
|
||||
seg->vstart = start;
|
||||
seg->pfn = (seg->vstart - dom->parms.virt_base) / page_size;
|
||||
|
||||
- if ( pages > dom->total_pages || /* double test avoids overflow probs */
|
||||
+ if ( pages > dom->total_pages || /* multiple test avoids overflow probs */
|
||||
+ seg->pfn > dom->total_pages ||
|
||||
pages > dom->total_pages - seg->pfn)
|
||||
{
|
||||
xc_dom_panic(dom->xch, XC_OUT_OF_MEMORY,
|
||||
--
|
||||
1.7.2.5
|
||||
|
||||
|
@ -0,0 +1,156 @@
|
||||
From 8c738fa5c1f3cfcd935b6191b3526f7ac8b2a5bd Mon Sep 17 00:00:00 2001
|
||||
From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Date: Fri, 14 Jun 2013 16:43:16 +0100
|
||||
Subject: [PATCH 03/23] libxc: Fix range checking in xc_dom_pfn_to_ptr etc.
|
||||
|
||||
* Ensure that xc_dom_pfn_to_ptr (when called with count==0) does not
|
||||
return a previously-allocated block which is entirely before the
|
||||
requested pfn (!)
|
||||
|
||||
* Provide a version of xc_dom_pfn_to_ptr, xc_dom_pfn_to_ptr_retcount,
|
||||
which provides the length of the mapped region via an out parameter.
|
||||
|
||||
* Change xc_dom_vaddr_to_ptr to always provide the length of the
|
||||
mapped region and change the call site in xc_dom_binloader.c to
|
||||
check it. The call site in xc_dom_load_elf_symtab will be corrected
|
||||
in a forthcoming patch, and for now ignores the returned length.
|
||||
|
||||
This is part of the fix to a security issue, XSA-55.
|
||||
|
||||
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
---
|
||||
tools/libxc/xc_dom.h | 16 +++++++++++++---
|
||||
tools/libxc/xc_dom_binloader.c | 11 ++++++++++-
|
||||
tools/libxc/xc_dom_core.c | 13 +++++++++++++
|
||||
tools/libxc/xc_dom_elfloader.c | 3 ++-
|
||||
4 files changed, 38 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/tools/libxc/xc_dom.h b/tools/libxc/xc_dom.h
|
||||
index 9af2195..9f8037e 100644
|
||||
--- a/tools/libxc/xc_dom.h
|
||||
+++ b/tools/libxc/xc_dom.h
|
||||
@@ -275,6 +275,8 @@ int xc_dom_alloc_segment(struct xc_dom_image *dom,
|
||||
|
||||
void *xc_dom_pfn_to_ptr(struct xc_dom_image *dom, xen_pfn_t first,
|
||||
xen_pfn_t count);
|
||||
+void *xc_dom_pfn_to_ptr_retcount(struct xc_dom_image *dom, xen_pfn_t first,
|
||||
+ xen_pfn_t count, xen_pfn_t *count_out);
|
||||
void xc_dom_unmap_one(struct xc_dom_image *dom, xen_pfn_t pfn);
|
||||
void xc_dom_unmap_all(struct xc_dom_image *dom);
|
||||
|
||||
@@ -302,13 +304,21 @@ static inline void *xc_dom_seg_to_ptr(struct xc_dom_image *dom,
|
||||
}
|
||||
|
||||
static inline void *xc_dom_vaddr_to_ptr(struct xc_dom_image *dom,
|
||||
- xen_vaddr_t vaddr)
|
||||
+ xen_vaddr_t vaddr,
|
||||
+ size_t *safe_region_out)
|
||||
{
|
||||
unsigned int page_size = XC_DOM_PAGE_SIZE(dom);
|
||||
xen_pfn_t page = (vaddr - dom->parms.virt_base) / page_size;
|
||||
unsigned int offset = (vaddr - dom->parms.virt_base) % page_size;
|
||||
- void *ptr = xc_dom_pfn_to_ptr(dom, page, 0);
|
||||
- return (ptr ? (ptr + offset) : NULL);
|
||||
+ xen_pfn_t safe_region_count;
|
||||
+ void *ptr;
|
||||
+
|
||||
+ *safe_region_out = 0;
|
||||
+ ptr = xc_dom_pfn_to_ptr_retcount(dom, page, 0, &safe_region_count);
|
||||
+ if ( ptr == NULL )
|
||||
+ return ptr;
|
||||
+ *safe_region_out = (safe_region_count << XC_DOM_PAGE_SHIFT(dom)) - offset;
|
||||
+ return ptr;
|
||||
}
|
||||
|
||||
static inline int xc_dom_feature_translated(struct xc_dom_image *dom)
|
||||
diff --git a/tools/libxc/xc_dom_binloader.c b/tools/libxc/xc_dom_binloader.c
|
||||
index 769e97d..bde93f7 100644
|
||||
--- a/tools/libxc/xc_dom_binloader.c
|
||||
+++ b/tools/libxc/xc_dom_binloader.c
|
||||
@@ -249,6 +249,7 @@ static int xc_dom_load_bin_kernel(struct xc_dom_image *dom)
|
||||
char *image = dom->kernel_blob;
|
||||
char *dest;
|
||||
size_t image_size = dom->kernel_size;
|
||||
+ size_t dest_size;
|
||||
uint32_t start_addr;
|
||||
uint32_t load_end_addr;
|
||||
uint32_t bss_end_addr;
|
||||
@@ -272,7 +273,15 @@ static int xc_dom_load_bin_kernel(struct xc_dom_image *dom)
|
||||
DOMPRINTF(" text_size: 0x%" PRIx32 "", text_size);
|
||||
DOMPRINTF(" bss_size: 0x%" PRIx32 "", bss_size);
|
||||
|
||||
- dest = xc_dom_vaddr_to_ptr(dom, dom->kernel_seg.vstart);
|
||||
+ dest = xc_dom_vaddr_to_ptr(dom, dom->kernel_seg.vstart, &dest_size);
|
||||
+
|
||||
+ if ( dest_size < text_size ||
|
||||
+ dest_size - text_size < bss_size )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: mapped region is too small for image", __FUNCTION__);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
memcpy(dest, image + skip, text_size);
|
||||
memset(dest + text_size, 0, bss_size);
|
||||
|
||||
diff --git a/tools/libxc/xc_dom_core.c b/tools/libxc/xc_dom_core.c
|
||||
index 2a01d7c..8913e41 100644
|
||||
--- a/tools/libxc/xc_dom_core.c
|
||||
+++ b/tools/libxc/xc_dom_core.c
|
||||
@@ -351,10 +351,19 @@ int xc_dom_try_gunzip(struct xc_dom_image *dom, void **blob, size_t * size)
|
||||
void *xc_dom_pfn_to_ptr(struct xc_dom_image *dom, xen_pfn_t pfn,
|
||||
xen_pfn_t count)
|
||||
{
|
||||
+ xen_pfn_t count_out_dummy;
|
||||
+ return xc_dom_pfn_to_ptr_retcount(dom, pfn, count, &count_out_dummy);
|
||||
+}
|
||||
+
|
||||
+void *xc_dom_pfn_to_ptr_retcount(struct xc_dom_image *dom, xen_pfn_t pfn,
|
||||
+ xen_pfn_t count, xen_pfn_t *count_out)
|
||||
+{
|
||||
struct xc_dom_phys *phys;
|
||||
unsigned int page_shift = XC_DOM_PAGE_SHIFT(dom);
|
||||
char *mode = "unset";
|
||||
|
||||
+ *count_out = 0;
|
||||
+
|
||||
if ( pfn > dom->total_pages || /* multiple checks to avoid overflows */
|
||||
count > dom->total_pages ||
|
||||
pfn > dom->total_pages - count )
|
||||
@@ -384,6 +393,7 @@ void *xc_dom_pfn_to_ptr(struct xc_dom_image *dom, xen_pfn_t pfn,
|
||||
phys->count);
|
||||
return NULL;
|
||||
}
|
||||
+ *count_out = count;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -391,6 +401,9 @@ void *xc_dom_pfn_to_ptr(struct xc_dom_image *dom, xen_pfn_t pfn,
|
||||
just hand out a pointer to it */
|
||||
if ( pfn < phys->first )
|
||||
continue;
|
||||
+ if ( pfn >= phys->first + phys->count )
|
||||
+ continue;
|
||||
+ *count_out = phys->count - (pfn - phys->first);
|
||||
}
|
||||
return phys->ptr + ((pfn - phys->first) << page_shift);
|
||||
}
|
||||
diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c
|
||||
index 2e69559..031b5b6 100644
|
||||
--- a/tools/libxc/xc_dom_elfloader.c
|
||||
+++ b/tools/libxc/xc_dom_elfloader.c
|
||||
@@ -130,10 +130,11 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
|
||||
if ( load )
|
||||
{
|
||||
+ size_t allow_size; /* will be used in a forthcoming XSA-55 patch */
|
||||
if ( !dom->bsd_symtab_start )
|
||||
return 0;
|
||||
size = dom->kernel_seg.vend - dom->bsd_symtab_start;
|
||||
- hdr = xc_dom_vaddr_to_ptr(dom, dom->bsd_symtab_start);
|
||||
+ hdr = xc_dom_vaddr_to_ptr(dom, dom->bsd_symtab_start, &allow_size);
|
||||
*(int *)hdr = size - sizeof(int);
|
||||
}
|
||||
else
|
||||
--
|
||||
1.7.2.5
|
||||
|
@ -0,0 +1,55 @@
|
||||
From 035634047d10c678cbb8801c4263747bdaf4e5b1 Mon Sep 17 00:00:00 2001
|
||||
From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Date: Fri, 14 Jun 2013 16:43:16 +0100
|
||||
Subject: [PATCH 04/23] libelf: add `struct elf_binary*' parameter to elf_load_image
|
||||
|
||||
The meat of this function is going to need a copy of the elf pointer,
|
||||
in forthcoming patches.
|
||||
|
||||
No functional change in this patch.
|
||||
|
||||
This is part of the fix to a security issue, XSA-55.
|
||||
|
||||
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
|
||||
---
|
||||
xen/common/libelf/libelf-loader.c | 8 +++++---
|
||||
1 files changed, 5 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/xen/common/libelf/libelf-loader.c b/xen/common/libelf/libelf-loader.c
|
||||
index ab58b8b..0559d88 100644
|
||||
--- a/xen/common/libelf/libelf-loader.c
|
||||
+++ b/xen/common/libelf/libelf-loader.c
|
||||
@@ -108,7 +108,8 @@ void elf_set_log(struct elf_binary *elf, elf_log_callback *log_callback,
|
||||
elf->verbose = verbose;
|
||||
}
|
||||
|
||||
-static int elf_load_image(void *dst, const void *src, uint64_t filesz, uint64_t memsz)
|
||||
+static int elf_load_image(struct elf_binary *elf,
|
||||
+ void *dst, const void *src, uint64_t filesz, uint64_t memsz)
|
||||
{
|
||||
memcpy(dst, src, filesz);
|
||||
memset(dst + filesz, 0, memsz - filesz);
|
||||
@@ -122,7 +123,8 @@ void elf_set_verbose(struct elf_binary *elf)
|
||||
elf->verbose = 1;
|
||||
}
|
||||
|
||||
-static int elf_load_image(void *dst, const void *src, uint64_t filesz, uint64_t memsz)
|
||||
+static int elf_load_image(struct elf_binary *elf,
|
||||
+ void *dst, const void *src, uint64_t filesz, uint64_t memsz)
|
||||
{
|
||||
int rc;
|
||||
if ( filesz > ULONG_MAX || memsz > ULONG_MAX )
|
||||
@@ -279,7 +281,7 @@ int elf_load_binary(struct elf_binary *elf)
|
||||
dest = elf_get_ptr(elf, paddr);
|
||||
elf_msg(elf, "%s: phdr %" PRIu64 " at 0x%p -> 0x%p\n",
|
||||
__func__, i, dest, dest + filesz);
|
||||
- if ( elf_load_image(dest, elf->image + offset, filesz, memsz) != 0 )
|
||||
+ if ( elf_load_image(elf, dest, elf->image + offset, filesz, memsz) != 0 )
|
||||
return -1;
|
||||
}
|
||||
|
||||
--
|
||||
1.7.2.5
|
||||
|
@ -0,0 +1,174 @@
|
||||
From 83ec905922b496e1a5756e3a88405eb6c2c6ba88 Mon Sep 17 00:00:00 2001
|
||||
From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Date: Fri, 14 Jun 2013 16:43:16 +0100
|
||||
Subject: [PATCH 05/23] libelf: abolish elf_sval and elf_access_signed
|
||||
|
||||
These are not used anywhere.
|
||||
|
||||
This is part of the fix to a security issue, XSA-55.
|
||||
|
||||
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
---
|
||||
xen/common/libelf/libelf-tools.c | 28 ----------------------------
|
||||
xen/include/xen/libelf.h | 11 -----------
|
||||
2 files changed, 0 insertions(+), 39 deletions(-)
|
||||
|
||||
diff --git a/xen/common/libelf/libelf-tools.c b/xen/common/libelf/libelf-tools.c
|
||||
index cb97908..2f54142 100644
|
||||
--- a/xen/common/libelf/libelf-tools.c
|
||||
+++ b/xen/common/libelf/libelf-tools.c
|
||||
@@ -48,34 +48,6 @@ uint64_t elf_access_unsigned(struct elf_binary * elf, const void *ptr,
|
||||
}
|
||||
}
|
||||
|
||||
-int64_t elf_access_signed(struct elf_binary *elf, const void *ptr,
|
||||
- uint64_t offset, size_t size)
|
||||
-{
|
||||
- int need_swap = elf_swap(elf);
|
||||
- const int8_t *s8;
|
||||
- const int16_t *s16;
|
||||
- const int32_t *s32;
|
||||
- const int64_t *s64;
|
||||
-
|
||||
- switch ( size )
|
||||
- {
|
||||
- case 1:
|
||||
- s8 = ptr + offset;
|
||||
- return *s8;
|
||||
- case 2:
|
||||
- s16 = ptr + offset;
|
||||
- return need_swap ? bswap_16(*s16) : *s16;
|
||||
- case 4:
|
||||
- s32 = ptr + offset;
|
||||
- return need_swap ? bswap_32(*s32) : *s32;
|
||||
- case 8:
|
||||
- s64 = ptr + offset;
|
||||
- return need_swap ? bswap_64(*s64) : *s64;
|
||||
- default:
|
||||
- return 0;
|
||||
- }
|
||||
-}
|
||||
-
|
||||
uint64_t elf_round_up(struct elf_binary *elf, uint64_t addr)
|
||||
{
|
||||
int elf_round = (elf_64bit(elf) ? 8 : 4) - 1;
|
||||
diff --git a/xen/include/xen/libelf.h b/xen/include/xen/libelf.h
|
||||
index e8f6508..38e490c 100644
|
||||
--- a/xen/include/xen/libelf.h
|
||||
+++ b/xen/include/xen/libelf.h
|
||||
@@ -136,23 +136,12 @@ struct elf_binary {
|
||||
offsetof(typeof(*(str)),e32.elem), \
|
||||
sizeof((str)->e32.elem)))
|
||||
|
||||
-#define elf_sval(elf, str, elem) \
|
||||
- ((ELFCLASS64 == (elf)->class) \
|
||||
- ? elf_access_signed((elf), (str), \
|
||||
- offsetof(typeof(*(str)),e64.elem), \
|
||||
- sizeof((str)->e64.elem)) \
|
||||
- : elf_access_signed((elf), (str), \
|
||||
- offsetof(typeof(*(str)),e32.elem), \
|
||||
- sizeof((str)->e32.elem)))
|
||||
-
|
||||
#define elf_size(elf, str) \
|
||||
((ELFCLASS64 == (elf)->class) \
|
||||
? sizeof((str)->e64) : sizeof((str)->e32))
|
||||
|
||||
uint64_t elf_access_unsigned(struct elf_binary *elf, const void *ptr,
|
||||
uint64_t offset, size_t size);
|
||||
-int64_t elf_access_signed(struct elf_binary *elf, const void *ptr,
|
||||
- uint64_t offset, size_t size);
|
||||
|
||||
uint64_t elf_round_up(struct elf_binary *elf, uint64_t addr);
|
||||
|
||||
--
|
||||
1.7.2.5
|
||||
#From 682a04488e7b3bd6c3448ab60599566eb7c6177a Mon Sep 17 00:00:00 2001
|
||||
#From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
#Date: Fri, 14 Jun 2013 16:43:16 +0100
|
||||
#Subject: [PATCH 06/23] libelf: move include of <asm/guest_access.h> to top of file
|
||||
#
|
||||
#libelf-loader.c #includes <asm/guest_access.h>, when being compiled
|
||||
#for Xen. Currently it does this in the middle of the file.
|
||||
#
|
||||
#Move this #include to the top of the file, before libelf-private.h.
|
||||
#This is necessary because in forthcoming patches we will introduce
|
||||
#private #defines of memcpy etc. which would interfere with definitions
|
||||
#in headers #included from guest_access.h.
|
||||
#
|
||||
#No semantic or functional change in this patch.
|
||||
#
|
||||
#This is part of the fix to a security issue, XSA-55.
|
||||
#
|
||||
#Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
#Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
#Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
|
||||
#---
|
||||
# xen/common/libelf/libelf-loader.c | 5 ++++-
|
||||
# 1 files changed, 4 insertions(+), 1 deletions(-)
|
||||
#
|
||||
diff --git a/xen/common/libelf/libelf-loader.c b/xen/common/libelf/libelf-loader.c
|
||||
index 0559d88..ec0706b 100644
|
||||
--- a/xen/common/libelf/libelf-loader.c
|
||||
+++ b/xen/common/libelf/libelf-loader.c
|
||||
@@ -16,6 +16,10 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
+#ifdef __XEN__
|
||||
+#include <asm/guest_access.h>
|
||||
+#endif
|
||||
+
|
||||
#include "libelf-private.h"
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
@@ -116,7 +120,6 @@ static int elf_load_image(struct elf_binary *elf,
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
-#include <asm/guest_access.h>
|
||||
|
||||
void elf_set_verbose(struct elf_binary *elf)
|
||||
{
|
||||
--
|
||||
1.7.2.5
|
||||
#From de9089b449d2508b1ba05590905c7ebaee00c8c4 Mon Sep 17 00:00:00 2001
|
||||
#From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
#Date: Fri, 14 Jun 2013 16:43:16 +0100
|
||||
#Subject: [PATCH 07/23] libelf/xc_dom_load_elf_symtab: Do not use "syms" uninitialised
|
||||
#
|
||||
#xc_dom_load_elf_symtab (with load==0) calls elf_round_up, but it
|
||||
#mistakenly used the uninitialised variable "syms" when calculating
|
||||
#dom->bsd_symtab_start. This should be a reference to "elf".
|
||||
#
|
||||
#This change might have the effect of rounding the value differently.
|
||||
#Previously if the uninitialised value (a single byte on the stack) was
|
||||
#ELFCLASS64 (ie, 2), the alignment would be to 8 bytes, otherwise to 4.
|
||||
#
|
||||
#However, the value is calculated from dom->kernel_seg.vend so this
|
||||
#could only make a difference if that value wasn't already aligned to 8
|
||||
#bytes.
|
||||
#
|
||||
#This is part of the fix to a security issue, XSA-55.
|
||||
#
|
||||
#Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
#Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
#---
|
||||
# tools/libxc/xc_dom_elfloader.c | 2 +-
|
||||
# 1 files changed, 1 insertions(+), 1 deletions(-)
|
||||
#
|
||||
diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c
|
||||
index 031b5b6..e82f6e9 100644
|
||||
--- a/tools/libxc/xc_dom_elfloader.c
|
||||
+++ b/tools/libxc/xc_dom_elfloader.c
|
||||
@@ -144,7 +144,7 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
hdr = xc_dom_malloc(dom, size);
|
||||
if ( hdr == NULL )
|
||||
return 0;
|
||||
- dom->bsd_symtab_start = elf_round_up(&syms, dom->kernel_seg.vend);
|
||||
+ dom->bsd_symtab_start = elf_round_up(elf, dom->kernel_seg.vend);
|
||||
}
|
||||
|
||||
memcpy(hdr + sizeof(int),
|
||||
--
|
||||
1.7.2.5
|
@ -0,0 +1,252 @@
|
||||
From 3fb6ccf2faccaf5e22e33a3155ccc72d732896d8 Mon Sep 17 00:00:00 2001
|
||||
From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Date: Fri, 14 Jun 2013 16:43:18 +0100
|
||||
Subject: [PATCH 14/23] libelf: use C99 bool for booleans
|
||||
|
||||
We want to remove uses of "int" because signed integers have
|
||||
undesirable undefined behaviours on overflow. Malicious compilers can
|
||||
turn apparently-correct code into code with security vulnerabilities
|
||||
etc.
|
||||
|
||||
In this patch we change all the booleans in libelf to C99 bool,
|
||||
from <stdbool.h>.
|
||||
|
||||
For the one visible libelf boolean in libxc's public interface we
|
||||
retain the use of int to avoid changing the ABI; libxc converts it to
|
||||
a bool for consumption by libelf.
|
||||
|
||||
It is OK to change all values only ever used as booleans to _Bool
|
||||
(bool) because conversion from any scalar type to a _Bool works the
|
||||
same as the boolean test in if() or ?: and is always defined (C99
|
||||
6.3.1.2). But we do need to check that all these variables really are
|
||||
only ever used that way. (It is theoretically possible that the old
|
||||
code truncated some 64-bit values to 32-bit ints which might become
|
||||
zero depending on the value, which would mean a behavioural change in
|
||||
this patch, but it seems implausible that treating 0x????????00000000
|
||||
as false could have been intended.)
|
||||
|
||||
This is part of the fix to a security issue, XSA-55.
|
||||
|
||||
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Acked-by: George Dunlap <george.dunlap@eu.citrix.com>
|
||||
---
|
||||
tools/libxc/xc_dom_elfloader.c | 8 ++++----
|
||||
xen/common/libelf/libelf-dominfo.c | 2 +-
|
||||
xen/common/libelf/libelf-loader.c | 4 ++--
|
||||
xen/common/libelf/libelf-private.h | 2 +-
|
||||
xen/common/libelf/libelf-tools.c | 10 +++++-----
|
||||
xen/include/xen/libelf.h | 18 ++++++++++--------
|
||||
6 files changed, 23 insertions(+), 21 deletions(-)
|
||||
|
||||
diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c
|
||||
index 4fb4da2..9ba64ae 100644
|
||||
--- a/tools/libxc/xc_dom_elfloader.c
|
||||
+++ b/tools/libxc/xc_dom_elfloader.c
|
||||
@@ -34,7 +34,7 @@
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
static void log_callback(struct elf_binary *elf, void *caller_data,
|
||||
- int iserr, const char *fmt, va_list al) {
|
||||
+ bool iserr, const char *fmt, va_list al) {
|
||||
xc_interface *xch = caller_data;
|
||||
|
||||
xc_reportv(xch,
|
||||
@@ -46,7 +46,7 @@ static void log_callback(struct elf_binary *elf, void *caller_data,
|
||||
|
||||
void xc_elf_set_logfile(xc_interface *xch, struct elf_binary *elf,
|
||||
int verbose) {
|
||||
- elf_set_log(elf, log_callback, xch, verbose);
|
||||
+ elf_set_log(elf, log_callback, xch, verbose /* convert to bool */);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
@@ -84,7 +84,7 @@ static char *xc_dom_guest_type(struct xc_dom_image *dom,
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* parse elf binary */
|
||||
|
||||
-static int check_elf_kernel(struct xc_dom_image *dom, int verbose)
|
||||
+static int check_elf_kernel(struct xc_dom_image *dom, bool verbose)
|
||||
{
|
||||
if ( dom->kernel_blob == NULL )
|
||||
{
|
||||
@@ -112,7 +112,7 @@ static int xc_dom_probe_elf_kernel(struct xc_dom_image *dom)
|
||||
}
|
||||
|
||||
static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
- struct elf_binary *elf, int load)
|
||||
+ struct elf_binary *elf, bool load)
|
||||
{
|
||||
struct elf_binary syms;
|
||||
ELF_HANDLE_DECL_NONCONST(elf_shdr) shdr; ELF_HANDLE_DECL(elf_shdr) shdr2;
|
||||
diff --git a/xen/common/libelf/libelf-dominfo.c b/xen/common/libelf/libelf-dominfo.c
|
||||
index 98c80dc..12b6c2a 100644
|
||||
--- a/xen/common/libelf/libelf-dominfo.c
|
||||
+++ b/xen/common/libelf/libelf-dominfo.c
|
||||
@@ -101,7 +101,7 @@ int elf_xen_parse_note(struct elf_binary *elf,
|
||||
/* *INDENT-OFF* */
|
||||
static const struct {
|
||||
char *name;
|
||||
- int str;
|
||||
+ bool str;
|
||||
} note_desc[] = {
|
||||
[XEN_ELFNOTE_ENTRY] = { "ENTRY", 0},
|
||||
[XEN_ELFNOTE_HYPERCALL_PAGE] = { "HYPERCALL_PAGE", 0},
|
||||
diff --git a/xen/common/libelf/libelf-loader.c b/xen/common/libelf/libelf-loader.c
|
||||
index f8be635..0dccd4d 100644
|
||||
--- a/xen/common/libelf/libelf-loader.c
|
||||
+++ b/xen/common/libelf/libelf-loader.c
|
||||
@@ -92,7 +92,7 @@ int elf_init(struct elf_binary *elf, const char *image_input, size_t size)
|
||||
}
|
||||
|
||||
#ifndef __XEN__
|
||||
-void elf_call_log_callback(struct elf_binary *elf, int iserr,
|
||||
+void elf_call_log_callback(struct elf_binary *elf, bool iserr,
|
||||
const char *fmt,...) {
|
||||
va_list al;
|
||||
|
||||
@@ -107,7 +107,7 @@ void elf_call_log_callback(struct elf_binary *elf, int iserr,
|
||||
}
|
||||
|
||||
void elf_set_log(struct elf_binary *elf, elf_log_callback *log_callback,
|
||||
- void *log_caller_data, int verbose)
|
||||
+ void *log_caller_data, bool verbose)
|
||||
{
|
||||
elf->log_callback = log_callback;
|
||||
elf->log_caller_data = log_caller_data;
|
||||
diff --git a/xen/common/libelf/libelf-private.h b/xen/common/libelf/libelf-private.h
|
||||
index 280dfd1..277be04 100644
|
||||
--- a/xen/common/libelf/libelf-private.h
|
||||
+++ b/xen/common/libelf/libelf-private.h
|
||||
@@ -77,7 +77,7 @@
|
||||
#define elf_err(elf, fmt, args ... ) \
|
||||
elf_call_log_callback(elf, 1, fmt , ## args );
|
||||
|
||||
-void elf_call_log_callback(struct elf_binary*, int iserr, const char *fmt,...);
|
||||
+void elf_call_log_callback(struct elf_binary*, bool iserr, const char *fmt,...);
|
||||
|
||||
#define safe_strcpy(d,s) \
|
||||
do { strncpy((d),(s),sizeof((d))-1); \
|
||||
diff --git a/xen/common/libelf/libelf-tools.c b/xen/common/libelf/libelf-tools.c
|
||||
index 744027e..fa58f76 100644
|
||||
--- a/xen/common/libelf/libelf-tools.c
|
||||
+++ b/xen/common/libelf/libelf-tools.c
|
||||
@@ -31,7 +31,7 @@ const char *elf_check_broken(const struct elf_binary *elf)
|
||||
return elf->broken;
|
||||
}
|
||||
|
||||
-static int elf_ptrval_in_range(elf_ptrval ptrval, uint64_t size,
|
||||
+static bool elf_ptrval_in_range(elf_ptrval ptrval, uint64_t size,
|
||||
const void *region, uint64_t regionsize)
|
||||
/*
|
||||
* Returns true if the putative memory area [ptrval,ptrval+size>
|
||||
@@ -53,7 +53,7 @@ static int elf_ptrval_in_range(elf_ptrval ptrval, uint64_t size,
|
||||
return 1;
|
||||
}
|
||||
|
||||
-int elf_access_ok(struct elf_binary * elf,
|
||||
+bool elf_access_ok(struct elf_binary * elf,
|
||||
uint64_t ptrval, size_t size)
|
||||
{
|
||||
if ( elf_ptrval_in_range(ptrval, size, elf->image_base, elf->size) )
|
||||
@@ -92,7 +92,7 @@ uint64_t elf_access_unsigned(struct elf_binary * elf, elf_ptrval base,
|
||||
uint64_t moreoffset, size_t size)
|
||||
{
|
||||
elf_ptrval ptrval = base + moreoffset;
|
||||
- int need_swap = elf_swap(elf);
|
||||
+ bool need_swap = elf_swap(elf);
|
||||
const uint8_t *u8;
|
||||
const uint16_t *u16;
|
||||
const uint32_t *u32;
|
||||
@@ -332,7 +332,7 @@ ELF_HANDLE_DECL(elf_note) elf_note_next(struct elf_binary *elf, ELF_HANDLE_DECL(
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
-int elf_is_elfbinary(const void *image_start, size_t image_size)
|
||||
+bool elf_is_elfbinary(const void *image_start, size_t image_size)
|
||||
{
|
||||
const Elf32_Ehdr *ehdr = image_start;
|
||||
|
||||
@@ -342,7 +342,7 @@ int elf_is_elfbinary(const void *image_start, size_t image_size)
|
||||
return IS_ELF(*ehdr);
|
||||
}
|
||||
|
||||
-int elf_phdr_is_loadable(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr)
|
||||
+bool elf_phdr_is_loadable(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr)
|
||||
{
|
||||
uint64_t p_type = elf_uval(elf, phdr, p_type);
|
||||
uint64_t p_flags = elf_uval(elf, phdr, p_flags);
|
||||
diff --git a/xen/include/xen/libelf.h b/xen/include/xen/libelf.h
|
||||
index ac93858..951430f 100644
|
||||
--- a/xen/include/xen/libelf.h
|
||||
+++ b/xen/include/xen/libelf.h
|
||||
@@ -29,6 +29,8 @@
|
||||
#error define architectural endianness
|
||||
#endif
|
||||
|
||||
+#include <stdbool.h>
|
||||
+
|
||||
#undef ELFSIZE
|
||||
#include "elfstructs.h"
|
||||
#ifdef __XEN__
|
||||
@@ -42,7 +44,7 @@
|
||||
|
||||
struct elf_binary;
|
||||
typedef void elf_log_callback(struct elf_binary*, void *caller_data,
|
||||
- int iserr, const char *fmt, va_list al);
|
||||
+ bool iserr, const char *fmt, va_list al);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -237,7 +239,7 @@ struct elf_binary {
|
||||
elf_log_callback *log_callback;
|
||||
void *log_caller_data;
|
||||
#endif
|
||||
- int verbose;
|
||||
+ bool verbose;
|
||||
const char *broken;
|
||||
};
|
||||
|
||||
@@ -301,8 +303,8 @@ void elf_memset_safe(struct elf_binary*, elf_ptrval dst, int c, size_t);
|
||||
* outside permitted areas.
|
||||
*/
|
||||
|
||||
-int elf_access_ok(struct elf_binary * elf,
|
||||
- uint64_t ptrval, size_t size);
|
||||
+bool elf_access_ok(struct elf_binary * elf,
|
||||
+ uint64_t ptrval, size_t size);
|
||||
|
||||
#define elf_store_val(elf, type, ptr, val) \
|
||||
({ \
|
||||
@@ -351,9 +353,9 @@ uint64_t elf_note_numeric_array(struct elf_binary *, ELF_HANDLE_DECL(elf_note),
|
||||
ELF_HANDLE_DECL(elf_note) elf_note_next(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
|
||||
|
||||
/* (Only) checks that the image has the right magic number. */
|
||||
-int elf_is_elfbinary(const void *image_start, size_t image_size);
|
||||
+bool elf_is_elfbinary(const void *image_start, size_t image_size);
|
||||
|
||||
-int elf_phdr_is_loadable(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr);
|
||||
+bool elf_phdr_is_loadable(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr);
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* xc_libelf_loader.c */
|
||||
@@ -367,7 +369,7 @@ int elf_init(struct elf_binary *elf, const char *image, size_t size);
|
||||
void elf_set_verbose(struct elf_binary *elf);
|
||||
#else
|
||||
void elf_set_log(struct elf_binary *elf, elf_log_callback*,
|
||||
- void *log_caller_pointer, int verbose);
|
||||
+ void *log_caller_pointer, bool verbose);
|
||||
#endif
|
||||
|
||||
void elf_parse_binary(struct elf_binary *elf);
|
||||
@@ -419,7 +421,7 @@ struct elf_dom_parms {
|
||||
char xen_ver[16];
|
||||
char loader[16];
|
||||
int pae;
|
||||
- int bsd_symtab;
|
||||
+ bool bsd_symtab;
|
||||
uint64_t virt_base;
|
||||
uint64_t virt_entry;
|
||||
uint64_t virt_hypercall;
|
||||
--
|
||||
1.7.2.5
|
||||
|
@ -0,0 +1,382 @@
|
||||
From 77c0829fa751f052f7b8ec08287aef6e7ba97bc5 Mon Sep 17 00:00:00 2001
|
||||
From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Date: Fri, 14 Jun 2013 16:43:19 +0100
|
||||
Subject: [PATCH 19/23] libxc: check failure of xc_dom_*_to_ptr, xc_map_foreign_range
|
||||
|
||||
The return values from xc_dom_*_to_ptr and xc_map_foreign_range are
|
||||
sometimes dereferenced, or subjected to pointer arithmetic, without
|
||||
checking whether the relevant function failed and returned NULL.
|
||||
|
||||
Add an appropriate error check at every call site.
|
||||
|
||||
Changes in the 4.2 backport of this series:
|
||||
* Fix tools/libxc/xc_dom_x86.c:setup_pgtables_x86_32.
|
||||
* Fix tools/libxc/xc_dom_ia64.c:start_info_ia64.
|
||||
* Fix tools/libxc/ia64/xc_ia64_dom_fwloader.c:xc_dom_load_fw_kernel.
|
||||
|
||||
This is part of the fix to a security issue, XSA-55.
|
||||
|
||||
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
---
|
||||
tools/libxc/ia64/xc_ia64_dom_fwloader.c | 2 +
|
||||
tools/libxc/xc_dom_binloader.c | 6 +++
|
||||
tools/libxc/xc_dom_core.c | 6 +++
|
||||
tools/libxc/xc_dom_elfloader.c | 13 +++++++
|
||||
tools/libxc/xc_dom_ia64.c | 6 +++
|
||||
tools/libxc/xc_dom_x86.c | 55 +++++++++++++++++++++++++++++++
|
||||
tools/libxc/xc_domain_restore.c | 27 +++++++++++++++
|
||||
tools/libxc/xc_offline_page.c | 5 +++
|
||||
8 files changed, 120 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/tools/libxc/ia64/xc_ia64_dom_fwloader.c b/tools/libxc/ia64/xc_ia64_dom_fwloader.c
|
||||
index cdf3333..dbd3349 100644
|
||||
--- a/tools/libxc/ia64/xc_ia64_dom_fwloader.c
|
||||
+++ b/tools/libxc/ia64/xc_ia64_dom_fwloader.c
|
||||
@@ -60,6 +60,8 @@ static int xc_dom_load_fw_kernel(struct xc_dom_image *dom)
|
||||
unsigned long i;
|
||||
|
||||
dest = xc_dom_vaddr_to_ptr(dom, dom->kernel_seg.vstart);
|
||||
+ if ( dest == NULL )
|
||||
+ return -1;
|
||||
memcpy(dest, dom->kernel_blob, FW_SIZE);
|
||||
|
||||
/* Synchronize cache. */
|
||||
diff --git a/tools/libxc/xc_dom_binloader.c b/tools/libxc/xc_dom_binloader.c
|
||||
index 8596a28..553b366 100644
|
||||
--- a/tools/libxc/xc_dom_binloader.c
|
||||
+++ b/tools/libxc/xc_dom_binloader.c
|
||||
@@ -277,6 +277,12 @@ static int xc_dom_load_bin_kernel(struct xc_dom_image *dom)
|
||||
DOMPRINTF(" bss_size: 0x%" PRIx32 "", bss_size);
|
||||
|
||||
dest = xc_dom_vaddr_to_ptr(dom, dom->kernel_seg.vstart, &dest_size);
|
||||
+ if ( dest == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: xc_dom_vaddr_to_ptr(dom, dom->kernel_seg.vstart)"
|
||||
+ " => NULL", __FUNCTION__);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
|
||||
if ( dest_size < text_size ||
|
||||
dest_size - text_size < bss_size )
|
||||
diff --git a/tools/libxc/xc_dom_core.c b/tools/libxc/xc_dom_core.c
|
||||
index 8913e41..a54ddae 100644
|
||||
--- a/tools/libxc/xc_dom_core.c
|
||||
+++ b/tools/libxc/xc_dom_core.c
|
||||
@@ -868,6 +868,12 @@ int xc_dom_build_image(struct xc_dom_image *dom)
|
||||
ramdisklen) != 0 )
|
||||
goto err;
|
||||
ramdiskmap = xc_dom_seg_to_ptr(dom, &dom->ramdisk_seg);
|
||||
+ if ( ramdiskmap == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: xc_dom_seg_to_ptr(dom, &dom->ramdisk_seg) => NULL",
|
||||
+ __FUNCTION__);
|
||||
+ goto err;
|
||||
+ }
|
||||
if ( unziplen )
|
||||
{
|
||||
if ( xc_dom_do_gunzip(dom->xch,
|
||||
diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c
|
||||
index 9fc4b94..61b5798 100644
|
||||
--- a/tools/libxc/xc_dom_elfloader.c
|
||||
+++ b/tools/libxc/xc_dom_elfloader.c
|
||||
@@ -139,6 +139,12 @@ static elf_errorstatus xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
return 0;
|
||||
size = dom->kernel_seg.vend - dom->bsd_symtab_start;
|
||||
hdr_ptr = xc_dom_vaddr_to_ptr(dom, dom->bsd_symtab_start, &allow_size);
|
||||
+ if ( hdr_ptr == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s/load: xc_dom_vaddr_to_ptr(dom,dom->bsd_symtab_start"
|
||||
+ " => NULL", __FUNCTION__);
|
||||
+ return -1;
|
||||
+ }
|
||||
elf->caller_xdest_base = hdr_ptr;
|
||||
elf->caller_xdest_size = allow_size;
|
||||
hdr = ELF_REALPTR2PTRVAL(hdr_ptr);
|
||||
@@ -384,7 +390,14 @@ static elf_errorstatus xc_dom_load_elf_kernel(struct xc_dom_image *dom)
|
||||
xen_pfn_t pages;
|
||||
|
||||
elf->dest_base = xc_dom_seg_to_ptr_pages(dom, &dom->kernel_seg, &pages);
|
||||
+ if ( elf->dest_base == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: xc_dom_vaddr_to_ptr(dom,dom->kernel_seg)"
|
||||
+ " => NULL", __FUNCTION__);
|
||||
+ return -1;
|
||||
+ }
|
||||
elf->dest_size = pages * XC_DOM_PAGE_SIZE(dom);
|
||||
+
|
||||
rc = elf_load_binary(elf);
|
||||
if ( rc < 0 )
|
||||
{
|
||||
diff --git a/tools/libxc/xc_dom_ia64.c b/tools/libxc/xc_dom_ia64.c
|
||||
index dcd1523..7c0eff1 100644
|
||||
--- a/tools/libxc/xc_dom_ia64.c
|
||||
+++ b/tools/libxc/xc_dom_ia64.c
|
||||
@@ -60,6 +60,12 @@ int start_info_ia64(struct xc_dom_image *dom)
|
||||
|
||||
DOMPRINTF_CALLED(dom->xch);
|
||||
|
||||
+ if ( start_info == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: xc_dom_pfn_to_ptr failed on start_info", __FUNCTION__);
|
||||
+ return -1; /* our caller throws away our return value :-/ */
|
||||
+ }
|
||||
+
|
||||
memset(start_info, 0, sizeof(*start_info));
|
||||
sprintf(start_info->magic, dom->guest_type);
|
||||
start_info->flags = dom->flags;
|
||||
diff --git a/tools/libxc/xc_dom_x86.c b/tools/libxc/xc_dom_x86.c
|
||||
index 0cf1687..75d6b83 100644
|
||||
--- a/tools/libxc/xc_dom_x86.c
|
||||
+++ b/tools/libxc/xc_dom_x86.c
|
||||
@@ -144,6 +144,9 @@ static int setup_pgtables_x86_32(struct xc_dom_image *dom)
|
||||
xen_vaddr_t addr;
|
||||
xen_pfn_t pgpfn;
|
||||
|
||||
+ if ( l2tab == NULL )
|
||||
+ goto pfn_error;
|
||||
+
|
||||
for ( addr = dom->parms.virt_base; addr < dom->virt_pgtab_end;
|
||||
addr += PAGE_SIZE_X86 )
|
||||
{
|
||||
@@ -151,6 +154,8 @@ static int setup_pgtables_x86_32(struct xc_dom_image *dom)
|
||||
{
|
||||
/* get L1 tab, make L2 entry */
|
||||
l1tab = xc_dom_pfn_to_ptr(dom, l1pfn, 1);
|
||||
+ if ( l1tab == NULL )
|
||||
+ goto pfn_error;
|
||||
l2off = l2_table_offset_i386(addr);
|
||||
l2tab[l2off] =
|
||||
pfn_to_paddr(xc_dom_p2m_guest(dom, l1pfn)) | L2_PROT;
|
||||
@@ -169,6 +174,11 @@ static int setup_pgtables_x86_32(struct xc_dom_image *dom)
|
||||
l1tab = NULL;
|
||||
}
|
||||
return 0;
|
||||
+
|
||||
+pfn_error:
|
||||
+ xc_dom_panic(dom->xch, XC_INTERNAL_ERROR,
|
||||
+ "%s: xc_dom_pfn_to_ptr failed", __FUNCTION__);
|
||||
+ return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -219,6 +229,12 @@ static xen_pfn_t move_l3_below_4G(struct xc_dom_image *dom,
|
||||
goto out;
|
||||
|
||||
l3tab = xc_dom_pfn_to_ptr(dom, l3pfn, 1);
|
||||
+ if ( l3tab == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: xc_dom_pfn_to_ptr(dom, l3pfn, 1) => NULL",
|
||||
+ __FUNCTION__);
|
||||
+ return l3mfn; /* our one call site will call xc_dom_panic and fail */
|
||||
+ }
|
||||
memset(l3tab, 0, XC_DOM_PAGE_SIZE(dom));
|
||||
|
||||
DOMPRINTF("%s: successfully relocated L3 below 4G. "
|
||||
@@ -262,6 +278,8 @@ static int setup_pgtables_x86_32_pae(struct xc_dom_image *dom)
|
||||
}
|
||||
|
||||
l3tab = xc_dom_pfn_to_ptr(dom, l3pfn, 1);
|
||||
+ if ( l3tab == NULL )
|
||||
+ goto pfn_error;
|
||||
|
||||
for ( addr = dom->parms.virt_base; addr < dom->virt_pgtab_end;
|
||||
addr += PAGE_SIZE_X86 )
|
||||
@@ -270,6 +288,8 @@ static int setup_pgtables_x86_32_pae(struct xc_dom_image *dom)
|
||||
{
|
||||
/* get L2 tab, make L3 entry */
|
||||
l2tab = xc_dom_pfn_to_ptr(dom, l2pfn, 1);
|
||||
+ if ( l2tab == NULL )
|
||||
+ goto pfn_error;
|
||||
l3off = l3_table_offset_pae(addr);
|
||||
l3tab[l3off] =
|
||||
pfn_to_paddr(xc_dom_p2m_guest(dom, l2pfn)) | L3_PROT;
|
||||
@@ -280,6 +300,8 @@ static int setup_pgtables_x86_32_pae(struct xc_dom_image *dom)
|
||||
{
|
||||
/* get L1 tab, make L2 entry */
|
||||
l1tab = xc_dom_pfn_to_ptr(dom, l1pfn, 1);
|
||||
+ if ( l1tab == NULL )
|
||||
+ goto pfn_error;
|
||||
l2off = l2_table_offset_pae(addr);
|
||||
l2tab[l2off] =
|
||||
pfn_to_paddr(xc_dom_p2m_guest(dom, l1pfn)) | L2_PROT;
|
||||
@@ -306,6 +328,11 @@ static int setup_pgtables_x86_32_pae(struct xc_dom_image *dom)
|
||||
l3tab[3] = pfn_to_paddr(xc_dom_p2m_guest(dom, l2pfn)) | L3_PROT;
|
||||
}
|
||||
return 0;
|
||||
+
|
||||
+pfn_error:
|
||||
+ xc_dom_panic(dom->xch, XC_INTERNAL_ERROR,
|
||||
+ "%s: xc_dom_pfn_to_ptr failed", __FUNCTION__);
|
||||
+ return -EINVAL;
|
||||
}
|
||||
|
||||
#undef L1_PROT
|
||||
@@ -344,6 +371,9 @@ static int setup_pgtables_x86_64(struct xc_dom_image *dom)
|
||||
uint64_t addr;
|
||||
xen_pfn_t pgpfn;
|
||||
|
||||
+ if ( l4tab == NULL )
|
||||
+ goto pfn_error;
|
||||
+
|
||||
for ( addr = dom->parms.virt_base; addr < dom->virt_pgtab_end;
|
||||
addr += PAGE_SIZE_X86 )
|
||||
{
|
||||
@@ -351,6 +381,8 @@ static int setup_pgtables_x86_64(struct xc_dom_image *dom)
|
||||
{
|
||||
/* get L3 tab, make L4 entry */
|
||||
l3tab = xc_dom_pfn_to_ptr(dom, l3pfn, 1);
|
||||
+ if ( l3tab == NULL )
|
||||
+ goto pfn_error;
|
||||
l4off = l4_table_offset_x86_64(addr);
|
||||
l4tab[l4off] =
|
||||
pfn_to_paddr(xc_dom_p2m_guest(dom, l3pfn)) | L4_PROT;
|
||||
@@ -361,6 +393,8 @@ static int setup_pgtables_x86_64(struct xc_dom_image *dom)
|
||||
{
|
||||
/* get L2 tab, make L3 entry */
|
||||
l2tab = xc_dom_pfn_to_ptr(dom, l2pfn, 1);
|
||||
+ if ( l2tab == NULL )
|
||||
+ goto pfn_error;
|
||||
l3off = l3_table_offset_x86_64(addr);
|
||||
l3tab[l3off] =
|
||||
pfn_to_paddr(xc_dom_p2m_guest(dom, l2pfn)) | L3_PROT;
|
||||
@@ -373,6 +407,8 @@ static int setup_pgtables_x86_64(struct xc_dom_image *dom)
|
||||
{
|
||||
/* get L1 tab, make L2 entry */
|
||||
l1tab = xc_dom_pfn_to_ptr(dom, l1pfn, 1);
|
||||
+ if ( l1tab == NULL )
|
||||
+ goto pfn_error;
|
||||
l2off = l2_table_offset_x86_64(addr);
|
||||
l2tab[l2off] =
|
||||
pfn_to_paddr(xc_dom_p2m_guest(dom, l1pfn)) | L2_PROT;
|
||||
@@ -393,6 +429,11 @@ static int setup_pgtables_x86_64(struct xc_dom_image *dom)
|
||||
l1tab = NULL;
|
||||
}
|
||||
return 0;
|
||||
+
|
||||
+pfn_error:
|
||||
+ xc_dom_panic(dom->xch, XC_INTERNAL_ERROR,
|
||||
+ "%s: xc_dom_pfn_to_ptr failed", __FUNCTION__);
|
||||
+ return -EINVAL;
|
||||
}
|
||||
|
||||
#undef L1_PROT
|
||||
@@ -410,6 +451,8 @@ static int alloc_magic_pages(struct xc_dom_image *dom)
|
||||
if ( xc_dom_alloc_segment(dom, &dom->p2m_seg, "phys2mach", 0, p2m_size) )
|
||||
return -1;
|
||||
dom->p2m_guest = xc_dom_seg_to_ptr(dom, &dom->p2m_seg);
|
||||
+ if ( dom->p2m_guest == NULL )
|
||||
+ return -1;
|
||||
|
||||
/* allocate special pages */
|
||||
dom->start_info_pfn = xc_dom_alloc_page(dom, "start info");
|
||||
@@ -434,6 +477,12 @@ static int start_info_x86_32(struct xc_dom_image *dom)
|
||||
|
||||
DOMPRINTF_CALLED(dom->xch);
|
||||
|
||||
+ if ( start_info == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: xc_dom_pfn_to_ptr failed on start_info", __FUNCTION__);
|
||||
+ return -1; /* our caller throws away our return value :-/ */
|
||||
+ }
|
||||
+
|
||||
memset(start_info, 0, sizeof(*start_info));
|
||||
strncpy(start_info->magic, dom->guest_type, sizeof(start_info->magic));
|
||||
start_info->magic[sizeof(start_info->magic) - 1] = '\0';
|
||||
@@ -474,6 +523,12 @@ static int start_info_x86_64(struct xc_dom_image *dom)
|
||||
|
||||
DOMPRINTF_CALLED(dom->xch);
|
||||
|
||||
+ if ( start_info == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: xc_dom_pfn_to_ptr failed on start_info", __FUNCTION__);
|
||||
+ return -1; /* our caller throws away our return value :-/ */
|
||||
+ }
|
||||
+
|
||||
memset(start_info, 0, sizeof(*start_info));
|
||||
strncpy(start_info->magic, dom->guest_type, sizeof(start_info->magic));
|
||||
start_info->magic[sizeof(start_info->magic) - 1] = '\0';
|
||||
diff --git a/tools/libxc/xc_domain_restore.c b/tools/libxc/xc_domain_restore.c
|
||||
index b4c0b10..3994f8f 100644
|
||||
--- a/tools/libxc/xc_domain_restore.c
|
||||
+++ b/tools/libxc/xc_domain_restore.c
|
||||
@@ -1556,6 +1556,12 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
|
||||
mfn = ctx->p2m[pfn];
|
||||
buf = xc_map_foreign_range(xch, dom, PAGE_SIZE,
|
||||
PROT_READ | PROT_WRITE, mfn);
|
||||
+ if ( buf == NULL )
|
||||
+ {
|
||||
+ ERROR("xc_map_foreign_range for generation id"
|
||||
+ " buffer failed");
|
||||
+ goto out;
|
||||
+ }
|
||||
|
||||
generationid = *(unsigned long long *)(buf + offset);
|
||||
*(unsigned long long *)(buf + offset) = generationid + 1;
|
||||
@@ -1713,6 +1719,11 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
|
||||
l3tab = (uint64_t *)
|
||||
xc_map_foreign_range(xch, dom, PAGE_SIZE,
|
||||
PROT_READ, ctx->p2m[i]);
|
||||
+ if ( l3tab == NULL )
|
||||
+ {
|
||||
+ PERROR("xc_map_foreign_range failed (for l3tab)");
|
||||
+ goto out;
|
||||
+ }
|
||||
|
||||
for ( j = 0; j < 4; j++ )
|
||||
l3ptes[j] = l3tab[j];
|
||||
@@ -1739,6 +1750,11 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
|
||||
l3tab = (uint64_t *)
|
||||
xc_map_foreign_range(xch, dom, PAGE_SIZE,
|
||||
PROT_READ | PROT_WRITE, ctx->p2m[i]);
|
||||
+ if ( l3tab == NULL )
|
||||
+ {
|
||||
+ PERROR("xc_map_foreign_range failed (for l3tab, 2nd)");
|
||||
+ goto out;
|
||||
+ }
|
||||
|
||||
for ( j = 0; j < 4; j++ )
|
||||
l3tab[j] = l3ptes[j];
|
||||
@@ -1909,6 +1925,12 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
|
||||
SET_FIELD(ctxt, user_regs.edx, mfn);
|
||||
start_info = xc_map_foreign_range(
|
||||
xch, dom, PAGE_SIZE, PROT_READ | PROT_WRITE, mfn);
|
||||
+ if ( start_info == NULL )
|
||||
+ {
|
||||
+ PERROR("xc_map_foreign_range failed (for start_info)");
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
SET_FIELD(start_info, nr_pages, dinfo->p2m_size);
|
||||
SET_FIELD(start_info, shared_info, shared_info_frame<<PAGE_SHIFT);
|
||||
SET_FIELD(start_info, flags, 0);
|
||||
@@ -2056,6 +2078,11 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
|
||||
/* Restore contents of shared-info page. No checking needed. */
|
||||
new_shared_info = xc_map_foreign_range(
|
||||
xch, dom, PAGE_SIZE, PROT_WRITE, shared_info_frame);
|
||||
+ if ( new_shared_info == NULL )
|
||||
+ {
|
||||
+ PERROR("xc_map_foreign_range failed (for new_shared_info)");
|
||||
+ goto out;
|
||||
+ }
|
||||
|
||||
/* restore saved vcpu_info and arch specific info */
|
||||
MEMCPY_FIELD(new_shared_info, old_shared_info, vcpu_info);
|
||||
diff --git a/tools/libxc/xc_offline_page.c b/tools/libxc/xc_offline_page.c
|
||||
index 089a361..36b9812 100644
|
||||
--- a/tools/libxc/xc_offline_page.c
|
||||
+++ b/tools/libxc/xc_offline_page.c
|
||||
@@ -714,6 +714,11 @@ int xc_exchange_page(xc_interface *xch, int domid, xen_pfn_t mfn)
|
||||
|
||||
new_p = xc_map_foreign_range(xch, domid, PAGE_SIZE,
|
||||
PROT_READ|PROT_WRITE, new_mfn);
|
||||
+ if ( new_p == NULL )
|
||||
+ {
|
||||
+ ERROR("failed to map new_p for copy, guest may be broken?");
|
||||
+ goto failed;
|
||||
+ }
|
||||
memcpy(new_p, backup, PAGE_SIZE);
|
||||
munmap(new_p, PAGE_SIZE);
|
||||
mops.arg1.mfn = new_mfn;
|
||||
--
|
||||
1.7.2.5
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,261 @@
|
||||
From 59f66d58180832af6b99a9e4489031b5c2f627ab Mon Sep 17 00:00:00 2001
|
||||
From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Date: Fri, 14 Jun 2013 16:43:17 +0100
|
||||
Subject: [PATCH 09/23] tools/xcutils/readnotes: adjust print_l1_mfn_valid_note
|
||||
|
||||
Use the new PTRVAL macros and elf_access_unsigned in
|
||||
print_l1_mfn_valid_note.
|
||||
|
||||
No functional change unless the input is wrong, or we are reading a
|
||||
file for a different endianness.
|
||||
|
||||
Separated out from the previous patch because this change does produce
|
||||
a difference in the generated code.
|
||||
|
||||
This is part of the fix to a security issue, XSA-55.
|
||||
|
||||
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
---
|
||||
tools/xcutils/readnotes.c | 11 ++++++-----
|
||||
1 files changed, 6 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/tools/xcutils/readnotes.c b/tools/xcutils/readnotes.c
|
||||
index 2af047d..7ff2530 100644
|
||||
--- a/tools/xcutils/readnotes.c
|
||||
+++ b/tools/xcutils/readnotes.c
|
||||
@@ -77,22 +77,23 @@ static void print_numeric_note(const char *prefix, struct elf_binary *elf,
|
||||
}
|
||||
|
||||
static void print_l1_mfn_valid_note(const char *prefix, struct elf_binary *elf,
|
||||
- const elf_note *note)
|
||||
+ ELF_HANDLE_DECL(elf_note) note)
|
||||
{
|
||||
int descsz = elf_uval(elf, note, descsz);
|
||||
- const uint32_t *desc32 = elf_note_desc(elf, note);
|
||||
- const uint64_t *desc64 = elf_note_desc(elf, note);
|
||||
+ ELF_PTRVAL_CONST_VOID desc = elf_note_desc(elf, note);
|
||||
|
||||
/* XXX should be able to cope with a list of values. */
|
||||
switch ( descsz / 2 )
|
||||
{
|
||||
case 8:
|
||||
printf("%s: mask=%#"PRIx64" value=%#"PRIx64"\n", prefix,
|
||||
- desc64[0], desc64[1]);
|
||||
+ elf_access_unsigned(elf, desc, 0, 8),
|
||||
+ elf_access_unsigned(elf, desc, 8, 8));
|
||||
break;
|
||||
case 4:
|
||||
printf("%s: mask=%#"PRIx32" value=%#"PRIx32"\n", prefix,
|
||||
- desc32[0],desc32[1]);
|
||||
+ (uint32_t)elf_access_unsigned(elf, desc, 0, 4),
|
||||
+ (uint32_t)elf_access_unsigned(elf, desc, 4, 4));
|
||||
break;
|
||||
}
|
||||
|
||||
--
|
||||
1.7.2.5
|
||||
#From db14d5bd9b6508adfcd2b910f454fae12fa4ba00 Mon Sep 17 00:00:00 2001
|
||||
#From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
#Date: Fri, 14 Jun 2013 16:43:17 +0100
|
||||
#Subject: [PATCH 10/23] libelf: check nul-terminated strings properly
|
||||
#
|
||||
#It is not safe to simply take pointers into the ELF and use them as C
|
||||
#pointers. They might not be properly nul-terminated (and the pointers
|
||||
#might be wild).
|
||||
#
|
||||
#So we are going to introduce a new function elf_strval for safely
|
||||
#getting strings. This will check that the addresses are in range and
|
||||
#that there is a proper nul-terminated string. Of course it might
|
||||
#discover that there isn't. In that case, it will be made to fail.
|
||||
#This means that elf_note_name might fail, too.
|
||||
#
|
||||
#For the benefit of call sites which are just going to pass the value
|
||||
#to a printf-like function, we provide elf_strfmt which returns
|
||||
#"(invalid)" on failure rather than NULL.
|
||||
#
|
||||
#In this patch we introduce dummy definitions of these functions. We
|
||||
#introduce calls to elf_strval and elf_strfmt everywhere, and update
|
||||
#all the call sites with appropriate error checking.
|
||||
#
|
||||
#There is not yet any semantic change, since before this patch all the
|
||||
#places where we introduce elf_strval dereferenced the value anyway, so
|
||||
#it mustn't have been NULL.
|
||||
#
|
||||
#In future patches, when elf_strval is made able return NULL, when it
|
||||
#does so it will mark the elf "broken" so that an appropriate
|
||||
#diagnostic can be printed.
|
||||
#
|
||||
#This is part of the fix to a security issue, XSA-55.
|
||||
#
|
||||
#Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
#Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
#Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
|
||||
#---
|
||||
# tools/xcutils/readnotes.c | 11 ++++++++---
|
||||
# xen/common/libelf/libelf-dominfo.c | 13 ++++++++++---
|
||||
# xen/common/libelf/libelf-tools.c | 10 +++++++---
|
||||
# xen/include/xen/libelf.h | 7 +++++--
|
||||
# 4 files changed, 30 insertions(+), 11 deletions(-)
|
||||
#
|
||||
diff --git a/tools/xcutils/readnotes.c b/tools/xcutils/readnotes.c
|
||||
index 7ff2530..cfae994 100644
|
||||
--- a/tools/xcutils/readnotes.c
|
||||
+++ b/tools/xcutils/readnotes.c
|
||||
@@ -63,7 +63,7 @@ struct setup_header {
|
||||
static void print_string_note(const char *prefix, struct elf_binary *elf,
|
||||
ELF_HANDLE_DECL(elf_note) note)
|
||||
{
|
||||
- printf("%s: %s\n", prefix, (char*)elf_note_desc(elf, note));
|
||||
+ printf("%s: %s\n", prefix, elf_strfmt(elf, elf_note_desc(elf, note)));
|
||||
}
|
||||
|
||||
static void print_numeric_note(const char *prefix, struct elf_binary *elf,
|
||||
@@ -103,10 +103,14 @@ static int print_notes(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) start,
|
||||
{
|
||||
ELF_HANDLE_DECL(elf_note) note;
|
||||
int notes_found = 0;
|
||||
+ const char *this_note_name;
|
||||
|
||||
for ( note = start; ELF_HANDLE_PTRVAL(note) < ELF_HANDLE_PTRVAL(end); note = elf_note_next(elf, note) )
|
||||
{
|
||||
- if (0 != strcmp(elf_note_name(elf, note), "Xen"))
|
||||
+ this_note_name = elf_note_name(elf, note);
|
||||
+ if (NULL == this_note_name)
|
||||
+ continue;
|
||||
+ if (0 != strcmp(this_note_name, "Xen"))
|
||||
continue;
|
||||
|
||||
notes_found++;
|
||||
@@ -294,7 +298,8 @@ int main(int argc, char **argv)
|
||||
|
||||
shdr = elf_shdr_by_name(&elf, "__xen_guest");
|
||||
if (ELF_HANDLE_VALID(shdr))
|
||||
- printf("__xen_guest: %s\n", (char*)elf_section_start(&elf, shdr));
|
||||
+ printf("__xen_guest: %s\n",
|
||||
+ elf_strfmt(&elf, elf_section_start(&elf, shdr)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
diff --git a/xen/common/libelf/libelf-dominfo.c b/xen/common/libelf/libelf-dominfo.c
|
||||
index 7140d59..b217f8f 100644
|
||||
--- a/xen/common/libelf/libelf-dominfo.c
|
||||
+++ b/xen/common/libelf/libelf-dominfo.c
|
||||
@@ -137,7 +137,10 @@ int elf_xen_parse_note(struct elf_binary *elf,
|
||||
|
||||
if ( note_desc[type].str )
|
||||
{
|
||||
- str = elf_note_desc(elf, note);
|
||||
+ str = elf_strval(elf, elf_note_desc(elf, note));
|
||||
+ if (str == NULL)
|
||||
+ /* elf_strval will mark elf broken if it fails so no need to log */
|
||||
+ return 0;
|
||||
elf_msg(elf, "%s: %s = \"%s\"\n", __FUNCTION__,
|
||||
note_desc[type].name, str);
|
||||
parms->elf_notes[type].type = XEN_ENT_STR;
|
||||
@@ -220,6 +223,7 @@ static int elf_xen_parse_notes(struct elf_binary *elf,
|
||||
{
|
||||
int xen_elfnotes = 0;
|
||||
ELF_HANDLE_DECL(elf_note) note;
|
||||
+ const char *note_name;
|
||||
|
||||
parms->elf_note_start = start;
|
||||
parms->elf_note_end = end;
|
||||
@@ -227,7 +231,10 @@ static int elf_xen_parse_notes(struct elf_binary *elf,
|
||||
ELF_HANDLE_PTRVAL(note) < parms->elf_note_end;
|
||||
note = elf_note_next(elf, note) )
|
||||
{
|
||||
- if ( strcmp(elf_note_name(elf, note), "Xen") )
|
||||
+ note_name = elf_note_name(elf, note);
|
||||
+ if ( note_name == NULL )
|
||||
+ continue;
|
||||
+ if ( strcmp(note_name, "Xen") )
|
||||
continue;
|
||||
if ( elf_xen_parse_note(elf, parms, note) )
|
||||
return -1;
|
||||
@@ -541,7 +548,7 @@ int elf_xen_parse(struct elf_binary *elf,
|
||||
parms->elf_note_start = ELF_INVALID_PTRVAL;
|
||||
parms->elf_note_end = ELF_INVALID_PTRVAL;
|
||||
elf_msg(elf, "%s: __xen_guest: \"%s\"\n", __FUNCTION__,
|
||||
- parms->guest_info);
|
||||
+ elf_strfmt(elf, parms->guest_info));
|
||||
elf_xen_parse_guest_info(elf, parms);
|
||||
break;
|
||||
}
|
||||
diff --git a/xen/common/libelf/libelf-tools.c b/xen/common/libelf/libelf-tools.c
|
||||
index f1fd886..3a0cde1 100644
|
||||
--- a/xen/common/libelf/libelf-tools.c
|
||||
+++ b/xen/common/libelf/libelf-tools.c
|
||||
@@ -119,7 +119,7 @@ const char *elf_section_name(struct elf_binary *elf,
|
||||
if ( ELF_PTRVAL_INVALID(elf->sec_strtab) )
|
||||
return "unknown";
|
||||
|
||||
- return elf->sec_strtab + elf_uval(elf, shdr, sh_name);
|
||||
+ return elf_strval(elf, elf->sec_strtab + elf_uval(elf, shdr, sh_name));
|
||||
}
|
||||
|
||||
ELF_PTRVAL_CONST_VOID elf_section_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr)
|
||||
@@ -151,6 +151,7 @@ ELF_HANDLE_DECL(elf_sym) elf_sym_by_name(struct elf_binary *elf, const char *sym
|
||||
ELF_PTRVAL_CONST_VOID end = elf_section_end(elf, elf->sym_tab);
|
||||
ELF_HANDLE_DECL(elf_sym) sym;
|
||||
uint64_t info, name;
|
||||
+ const char *sym_name;
|
||||
|
||||
for ( ; ptr < end; ptr += elf_size(elf, sym) )
|
||||
{
|
||||
@@ -159,7 +160,10 @@ ELF_HANDLE_DECL(elf_sym) elf_sym_by_name(struct elf_binary *elf, const char *sym
|
||||
name = elf_uval(elf, sym, st_name);
|
||||
if ( ELF32_ST_BIND(info) != STB_GLOBAL )
|
||||
continue;
|
||||
- if ( strcmp(elf->sym_strtab + name, symbol) )
|
||||
+ sym_name = elf_strval(elf, elf->sym_strtab + name);
|
||||
+ if ( sym_name == NULL ) /* out of range, oops */
|
||||
+ return ELF_INVALID_HANDLE(elf_sym);
|
||||
+ if ( strcmp(sym_name, symbol) )
|
||||
continue;
|
||||
return sym;
|
||||
}
|
||||
@@ -177,7 +181,7 @@ ELF_HANDLE_DECL(elf_sym) elf_sym_by_index(struct elf_binary *elf, int index)
|
||||
|
||||
const char *elf_note_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note)
|
||||
{
|
||||
- return ELF_HANDLE_PTRVAL(note) + elf_size(elf, note);
|
||||
+ return elf_strval(elf, ELF_HANDLE_PTRVAL(note) + elf_size(elf, note));
|
||||
}
|
||||
|
||||
ELF_PTRVAL_CONST_VOID elf_note_desc(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note)
|
||||
diff --git a/xen/include/xen/libelf.h b/xen/include/xen/libelf.h
|
||||
index cefd3d3..af5b5c5 100644
|
||||
--- a/xen/include/xen/libelf.h
|
||||
+++ b/xen/include/xen/libelf.h
|
||||
@@ -252,6 +252,9 @@ uint64_t elf_access_unsigned(struct elf_binary *elf, ELF_PTRVAL_CONST_VOID ptr,
|
||||
uint64_t elf_round_up(struct elf_binary *elf, uint64_t addr);
|
||||
|
||||
|
||||
+#define elf_strval(elf,x) ((const char*)(x)) /* may return NULL in the future */
|
||||
+#define elf_strfmt(elf,x) ((const char*)(x)) /* will return (invalid) instead */
|
||||
+
|
||||
#define elf_memcpy_safe(elf, dst, src, sz) memcpy((dst),(src),(sz))
|
||||
#define elf_memset_safe(elf, dst, c, sz) memset((dst),(c),(sz))
|
||||
/*
|
||||
@@ -279,7 +282,7 @@ ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_name(struct elf_binary *elf, const char *n
|
||||
ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_index(struct elf_binary *elf, int index);
|
||||
ELF_HANDLE_DECL(elf_phdr) elf_phdr_by_index(struct elf_binary *elf, int index);
|
||||
|
||||
-const char *elf_section_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr);
|
||||
+const char *elf_section_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr); /* might return NULL if inputs are invalid */
|
||||
ELF_PTRVAL_CONST_VOID elf_section_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr);
|
||||
ELF_PTRVAL_CONST_VOID elf_section_end(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr);
|
||||
|
||||
@@ -289,7 +292,7 @@ ELF_PTRVAL_CONST_VOID elf_segment_end(struct elf_binary *elf, ELF_HANDLE_DECL(el
|
||||
ELF_HANDLE_DECL(elf_sym) elf_sym_by_name(struct elf_binary *elf, const char *symbol);
|
||||
ELF_HANDLE_DECL(elf_sym) elf_sym_by_index(struct elf_binary *elf, int index);
|
||||
|
||||
-const char *elf_note_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
|
||||
+const char *elf_note_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note); /* may return NULL */
|
||||
ELF_PTRVAL_CONST_VOID elf_note_desc(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
|
||||
uint64_t elf_note_numeric(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
|
||||
uint64_t elf_note_numeric_array(struct elf_binary *, ELF_HANDLE_DECL(elf_note),
|
||||
--
|
||||
1.7.2.5
|
||||
|
@ -0,0 +1,334 @@
|
||||
libxl: Restrict permissions on PV console device xenstore nodes
|
||||
|
||||
Matthew Daley has observed that the PV console protocol places sensitive host
|
||||
state into a guest writeable xenstore locations, this includes:
|
||||
|
||||
- The pty used to communicate between the console backend daemon and its
|
||||
client, allowing the guest administrator to read and write arbitrary host
|
||||
files.
|
||||
- The output file, allowing the guest administrator to write arbitrary host
|
||||
files or to target arbitrary qemu chardevs which include sockets, udp, ptr,
|
||||
pipes etc (see -chardev in qemu(1) for a more complete list).
|
||||
- The maximum buffer size, allowing the guest administrator to consume more
|
||||
resources than the host administrator has configured.
|
||||
- The backend to use (qemu vs xenconsoled), potentially allowing the guest
|
||||
administrator to confuse host software.
|
||||
|
||||
So we arrange to make the sensitive keys in the xenstore frontend directory
|
||||
read only for the guest. This is safe since the xenstore permissions model,
|
||||
unlike POSIX directory permissions, does not allow the guest to remove and
|
||||
recreate a node if it has write access to the containing directory.
|
||||
|
||||
There are a few associated wrinkles:
|
||||
|
||||
- The primary PV console is "special". It's xenstore node is not under the
|
||||
usual /devices/ subtree and it does not use the customary xenstore state
|
||||
machine protocol. Unfortunately its directory is used for other things,
|
||||
including the vnc-port node, which we do not want the guest to be able to
|
||||
write to. Rather than trying to track down all the possible secondary uses
|
||||
of this directory just make it r/o to the guest. All newly created
|
||||
subdirectories inherit these permissions and so are now safe by default.
|
||||
|
||||
- The other serial consoles do use the customary xenstore state machine and
|
||||
therefore need write access to at least the "protocol" and "state" nodes,
|
||||
however they may also want to use arbitrary "feature-foo" nodes (although
|
||||
I'm not aware of any) and therefore we cannot simply lock down the entire
|
||||
frontend directory. Instead we add support to libxl__device_generic_add for
|
||||
frontend keys which are explicitly read only and use that to lock down the
|
||||
sensitive keys.
|
||||
|
||||
- Minios' console frontend wants to write the "type" node, which it has no
|
||||
business doing since this is a host/toolstack level decision. This fails
|
||||
now that the node has become read only to the PV guest. Since the toolstack
|
||||
already writes this node just remove the attempt to set it.
|
||||
|
||||
This is CVE-XXXX-XXX / XSA-57
|
||||
|
||||
Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
|
||||
Conflicts:
|
||||
tools/libxl/libxl.c (no vtpm, free front_ro on error in
|
||||
libxl__device_console_add)
|
||||
|
||||
diff --git a/extras/mini-os/console/xenbus.c b/extras/mini-os/console/xenbus.c
|
||||
index 77de82a..e65baf7 100644
|
||||
--- a/extras/mini-os/console/xenbus.c
|
||||
+++ b/extras/mini-os/console/xenbus.c
|
||||
@@ -122,12 +122,6 @@ again:
|
||||
goto abort_transaction;
|
||||
}
|
||||
|
||||
- err = xenbus_printf(xbt, nodename, "type", "%s", "ioemu");
|
||||
- if (err) {
|
||||
- message = "writing type";
|
||||
- goto abort_transaction;
|
||||
- }
|
||||
-
|
||||
snprintf(path, sizeof(path), "%s/state", nodename);
|
||||
err = xenbus_switch_state(xbt, path, XenbusStateConnected);
|
||||
if (err) {
|
||||
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
|
||||
index a6e9601..32d788a 100644
|
||||
--- a/tools/libxl/libxl.c
|
||||
+++ b/tools/libxl/libxl.c
|
||||
@@ -1920,8 +1920,9 @@ static void device_disk_add(libxl__egc *egc, uint32_t domid,
|
||||
flexarray_append(front, disk->is_cdrom ? "cdrom" : "disk");
|
||||
|
||||
libxl__device_generic_add(gc, t, device,
|
||||
- libxl__xs_kvs_of_flexarray(gc, back, back->count),
|
||||
- libxl__xs_kvs_of_flexarray(gc, front, front->count));
|
||||
+ libxl__xs_kvs_of_flexarray(gc, back, back->count),
|
||||
+ libxl__xs_kvs_of_flexarray(gc, front, front->count),
|
||||
+ NULL);
|
||||
|
||||
rc = libxl__xs_transaction_commit(gc, &t);
|
||||
if (!rc) break;
|
||||
@@ -2633,8 +2634,9 @@ void libxl__device_nic_add(libxl__egc *egc, uint32_t domid,
|
||||
flexarray_append(front, libxl__sprintf(gc,
|
||||
LIBXL_MAC_FMT, LIBXL_MAC_BYTES(nic->mac)));
|
||||
libxl__device_generic_add(gc, XBT_NULL, device,
|
||||
- libxl__xs_kvs_of_flexarray(gc, back, back->count),
|
||||
- libxl__xs_kvs_of_flexarray(gc, front, front->count));
|
||||
+ libxl__xs_kvs_of_flexarray(gc, back, back->count),
|
||||
+ libxl__xs_kvs_of_flexarray(gc, front, front->count),
|
||||
+ NULL);
|
||||
|
||||
aodev->dev = device;
|
||||
aodev->action = DEVICE_CONNECT;
|
||||
@@ -2830,7 +2832,7 @@ int libxl__device_console_add(libxl__gc *gc, uint32_t domid,
|
||||
libxl__device_console *console,
|
||||
libxl__domain_build_state *state)
|
||||
{
|
||||
- flexarray_t *front;
|
||||
+ flexarray_t *front, *ro_front;
|
||||
flexarray_t *back;
|
||||
libxl__device device;
|
||||
int rc;
|
||||
@@ -2845,6 +2847,11 @@ int libxl__device_console_add(libxl__gc *gc, uint32_t domid,
|
||||
rc = ERROR_NOMEM;
|
||||
goto out;
|
||||
}
|
||||
+ ro_front = flexarray_make(16, 1);
|
||||
+ if (!ro_front) {
|
||||
+ rc = ERROR_NOMEM;
|
||||
+ goto out;
|
||||
+ }
|
||||
back = flexarray_make(16, 1);
|
||||
if (!back) {
|
||||
rc = ERROR_NOMEM;
|
||||
@@ -2871,21 +2878,24 @@ int libxl__device_console_add(libxl__gc *gc, uint32_t domid,
|
||||
|
||||
flexarray_append(front, "backend-id");
|
||||
flexarray_append(front, libxl__sprintf(gc, "%d", console->backend_domid));
|
||||
- flexarray_append(front, "limit");
|
||||
- flexarray_append(front, libxl__sprintf(gc, "%d", LIBXL_XENCONSOLE_LIMIT));
|
||||
- flexarray_append(front, "type");
|
||||
+
|
||||
+ flexarray_append(ro_front, "limit");
|
||||
+ flexarray_append(ro_front, libxl__sprintf(gc, "%d", LIBXL_XENCONSOLE_LIMIT));
|
||||
+ flexarray_append(ro_front, "type");
|
||||
if (console->consback == LIBXL__CONSOLE_BACKEND_XENCONSOLED)
|
||||
- flexarray_append(front, "xenconsoled");
|
||||
+ flexarray_append(ro_front, "xenconsoled");
|
||||
else
|
||||
- flexarray_append(front, "ioemu");
|
||||
- flexarray_append(front, "output");
|
||||
- flexarray_append(front, console->output);
|
||||
+ flexarray_append(ro_front, "ioemu");
|
||||
+ flexarray_append(ro_front, "output");
|
||||
+ flexarray_append(ro_front, console->output);
|
||||
+ flexarray_append(ro_front, "tty");
|
||||
+ flexarray_append(ro_front, "");
|
||||
|
||||
if (state) {
|
||||
- flexarray_append(front, "port");
|
||||
- flexarray_append(front, libxl__sprintf(gc, "%"PRIu32, state->console_port));
|
||||
- flexarray_append(front, "ring-ref");
|
||||
- flexarray_append(front, libxl__sprintf(gc, "%lu", state->console_mfn));
|
||||
+ flexarray_append(ro_front, "port");
|
||||
+ flexarray_append(ro_front, libxl__sprintf(gc, "%"PRIu32, state->console_port));
|
||||
+ flexarray_append(ro_front, "ring-ref");
|
||||
+ flexarray_append(ro_front, libxl__sprintf(gc, "%lu", state->console_mfn));
|
||||
} else {
|
||||
flexarray_append(front, "state");
|
||||
flexarray_append(front, libxl__sprintf(gc, "%d", 1));
|
||||
@@ -2894,11 +2904,13 @@ int libxl__device_console_add(libxl__gc *gc, uint32_t domid,
|
||||
}
|
||||
|
||||
libxl__device_generic_add(gc, XBT_NULL, &device,
|
||||
- libxl__xs_kvs_of_flexarray(gc, back, back->count),
|
||||
- libxl__xs_kvs_of_flexarray(gc, front, front->count));
|
||||
+ libxl__xs_kvs_of_flexarray(gc, back, back->count),
|
||||
+ libxl__xs_kvs_of_flexarray(gc, front, front->count),
|
||||
+ libxl__xs_kvs_of_flexarray(gc, ro_front, ro_front->count));
|
||||
rc = 0;
|
||||
out_free:
|
||||
flexarray_free(back);
|
||||
+ flexarray_free(ro_front);
|
||||
flexarray_free(front);
|
||||
out:
|
||||
return rc;
|
||||
@@ -2982,8 +2994,9 @@ int libxl__device_vkb_add(libxl__gc *gc, uint32_t domid,
|
||||
flexarray_append(front, libxl__sprintf(gc, "%d", 1));
|
||||
|
||||
libxl__device_generic_add(gc, XBT_NULL, &device,
|
||||
- libxl__xs_kvs_of_flexarray(gc, back, back->count),
|
||||
- libxl__xs_kvs_of_flexarray(gc, front, front->count));
|
||||
+ libxl__xs_kvs_of_flexarray(gc, back, back->count),
|
||||
+ libxl__xs_kvs_of_flexarray(gc, front, front->count),
|
||||
+ NULL);
|
||||
rc = 0;
|
||||
out_free:
|
||||
flexarray_free(back);
|
||||
@@ -3096,8 +3109,9 @@ int libxl__device_vfb_add(libxl__gc *gc, uint32_t domid, libxl_device_vfb *vfb)
|
||||
flexarray_append_pair(front, "state", libxl__sprintf(gc, "%d", 1));
|
||||
|
||||
libxl__device_generic_add(gc, XBT_NULL, &device,
|
||||
- libxl__xs_kvs_of_flexarray(gc, back, back->count),
|
||||
- libxl__xs_kvs_of_flexarray(gc, front, front->count));
|
||||
+ libxl__xs_kvs_of_flexarray(gc, back, back->count),
|
||||
+ libxl__xs_kvs_of_flexarray(gc, front, front->count),
|
||||
+ NULL);
|
||||
rc = 0;
|
||||
out_free:
|
||||
flexarray_free(front);
|
||||
diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
|
||||
index c3283f1..1c04a21 100644
|
||||
--- a/tools/libxl/libxl_device.c
|
||||
+++ b/tools/libxl/libxl_device.c
|
||||
@@ -84,11 +84,12 @@ out:
|
||||
}
|
||||
|
||||
int libxl__device_generic_add(libxl__gc *gc, xs_transaction_t t,
|
||||
- libxl__device *device, char **bents, char **fents)
|
||||
+ libxl__device *device, char **bents, char **fents, char **ro_fents)
|
||||
{
|
||||
libxl_ctx *ctx = libxl__gc_owner(gc);
|
||||
char *frontend_path, *backend_path;
|
||||
struct xs_permissions frontend_perms[2];
|
||||
+ struct xs_permissions ro_frontend_perms[2];
|
||||
struct xs_permissions backend_perms[2];
|
||||
int create_transaction = t == XBT_NULL;
|
||||
|
||||
@@ -100,22 +101,37 @@ int libxl__device_generic_add(libxl__gc *gc, xs_transaction_t t,
|
||||
frontend_perms[1].id = device->backend_domid;
|
||||
frontend_perms[1].perms = XS_PERM_READ;
|
||||
|
||||
- backend_perms[0].id = device->backend_domid;
|
||||
- backend_perms[0].perms = XS_PERM_NONE;
|
||||
- backend_perms[1].id = device->domid;
|
||||
- backend_perms[1].perms = XS_PERM_READ;
|
||||
+ ro_frontend_perms[0].id = backend_perms[0].id = device->backend_domid;
|
||||
+ ro_frontend_perms[0].perms = backend_perms[0].perms = XS_PERM_NONE;
|
||||
+ ro_frontend_perms[1].id = backend_perms[1].id = device->domid;
|
||||
+ ro_frontend_perms[1].perms = backend_perms[1].perms = XS_PERM_READ;
|
||||
|
||||
retry_transaction:
|
||||
if (create_transaction)
|
||||
t = xs_transaction_start(ctx->xsh);
|
||||
/* FIXME: read frontend_path and check state before removing stuff */
|
||||
|
||||
- if (fents) {
|
||||
+ if (fents || ro_fents) {
|
||||
xs_rm(ctx->xsh, t, frontend_path);
|
||||
xs_mkdir(ctx->xsh, t, frontend_path);
|
||||
- xs_set_permissions(ctx->xsh, t, frontend_path, frontend_perms, ARRAY_SIZE(frontend_perms));
|
||||
+ /* Console 0 is a special case. It doesn't use the regular PV
|
||||
+ * state machine but also the frontend directory has
|
||||
+ * historically contained other information, such as the
|
||||
+ * vnc-port, which we don't want the guest fiddling with.
|
||||
+ */
|
||||
+ if (device->kind == LIBXL__DEVICE_KIND_CONSOLE && device->devid == 0)
|
||||
+ xs_set_permissions(ctx->xsh, t, frontend_path,
|
||||
+ ro_frontend_perms, ARRAY_SIZE(ro_frontend_perms));
|
||||
+ else
|
||||
+ xs_set_permissions(ctx->xsh, t, frontend_path,
|
||||
+ frontend_perms, ARRAY_SIZE(frontend_perms));
|
||||
xs_write(ctx->xsh, t, libxl__sprintf(gc, "%s/backend", frontend_path), backend_path, strlen(backend_path));
|
||||
- libxl__xs_writev(gc, t, frontend_path, fents);
|
||||
+ if (fents)
|
||||
+ libxl__xs_writev_perms(gc, t, frontend_path, fents,
|
||||
+ frontend_perms, ARRAY_SIZE(frontend_perms));
|
||||
+ if (ro_fents)
|
||||
+ libxl__xs_writev_perms(gc, t, frontend_path, ro_fents,
|
||||
+ ro_frontend_perms, ARRAY_SIZE(ro_frontend_perms));
|
||||
}
|
||||
|
||||
if (bents) {
|
||||
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
|
||||
index 13fa509..ae96a74 100644
|
||||
--- a/tools/libxl/libxl_internal.h
|
||||
+++ b/tools/libxl/libxl_internal.h
|
||||
@@ -516,6 +516,11 @@ _hidden char **libxl__xs_kvs_of_flexarray(libxl__gc *gc, flexarray_t *array, int
|
||||
/* treats kvs as pairs of keys and values and writes each to dir. */
|
||||
_hidden int libxl__xs_writev(libxl__gc *gc, xs_transaction_t t,
|
||||
const char *dir, char **kvs);
|
||||
+/* as writev but also sets the permissions on each path */
|
||||
+_hidden int libxl__xs_writev_perms(libxl__gc *gc, xs_transaction_t t,
|
||||
+ const char *dir, char *kvs[],
|
||||
+ struct xs_permissions *perms,
|
||||
+ unsigned int num_perms);
|
||||
/* _atonce creates a transaction and writes all keys at once */
|
||||
_hidden int libxl__xs_writev_atonce(libxl__gc *gc,
|
||||
const char *dir, char **kvs);
|
||||
@@ -930,7 +935,7 @@ _hidden int libxl__device_console_add(libxl__gc *gc, uint32_t domid,
|
||||
libxl__domain_build_state *state);
|
||||
|
||||
_hidden int libxl__device_generic_add(libxl__gc *gc, xs_transaction_t t,
|
||||
- libxl__device *device, char **bents, char **fents);
|
||||
+ libxl__device *device, char **bents, char **fents, char **ro_fents);
|
||||
_hidden char *libxl__device_backend_path(libxl__gc *gc, libxl__device *device);
|
||||
_hidden char *libxl__device_frontend_path(libxl__gc *gc, libxl__device *device);
|
||||
_hidden int libxl__parse_backend_path(libxl__gc *gc, const char *path,
|
||||
diff --git a/tools/libxl/libxl_pci.c b/tools/libxl/libxl_pci.c
|
||||
index 48986f3..d373b4d 100644
|
||||
--- a/tools/libxl/libxl_pci.c
|
||||
+++ b/tools/libxl/libxl_pci.c
|
||||
@@ -106,7 +106,8 @@ int libxl__create_pci_backend(libxl__gc *gc, uint32_t domid,
|
||||
|
||||
libxl__device_generic_add(gc, XBT_NULL, &device,
|
||||
libxl__xs_kvs_of_flexarray(gc, back, back->count),
|
||||
- libxl__xs_kvs_of_flexarray(gc, front, front->count));
|
||||
+ libxl__xs_kvs_of_flexarray(gc, front, front->count),
|
||||
+ NULL);
|
||||
|
||||
out:
|
||||
if (back)
|
||||
diff --git a/tools/libxl/libxl_xshelp.c b/tools/libxl/libxl_xshelp.c
|
||||
index 52af484..d7eaa66 100644
|
||||
--- a/tools/libxl/libxl_xshelp.c
|
||||
+++ b/tools/libxl/libxl_xshelp.c
|
||||
@@ -41,8 +41,10 @@ char **libxl__xs_kvs_of_flexarray(libxl__gc *gc, flexarray_t *array, int length)
|
||||
return kvs;
|
||||
}
|
||||
|
||||
-int libxl__xs_writev(libxl__gc *gc, xs_transaction_t t,
|
||||
- const char *dir, char *kvs[])
|
||||
+int libxl__xs_writev_perms(libxl__gc *gc, xs_transaction_t t,
|
||||
+ const char *dir, char *kvs[],
|
||||
+ struct xs_permissions *perms,
|
||||
+ unsigned int num_perms)
|
||||
{
|
||||
libxl_ctx *ctx = libxl__gc_owner(gc);
|
||||
char *path;
|
||||
@@ -56,11 +58,19 @@ int libxl__xs_writev(libxl__gc *gc, xs_transaction_t t,
|
||||
if (path && kvs[i + 1]) {
|
||||
int length = strlen(kvs[i + 1]);
|
||||
xs_write(ctx->xsh, t, path, kvs[i + 1], length);
|
||||
+ if (perms)
|
||||
+ xs_set_permissions(ctx->xsh, t, path, perms, num_perms);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
+int libxl__xs_writev(libxl__gc *gc, xs_transaction_t t,
|
||||
+ const char *dir, char *kvs[])
|
||||
+{
|
||||
+ return libxl__xs_writev_perms(gc, t, dir, kvs, NULL, 0);
|
||||
+}
|
||||
+
|
||||
int libxl__xs_writev_atonce(libxl__gc *gc,
|
||||
const char *dir, char *kvs[])
|
||||
{
|
||||
|
@ -1,26 +0,0 @@
|
||||
Index: xen-3.3.0/tools/ioemu-qemu-xen/Makefile
|
||||
===================================================================
|
||||
--- xen-3.3.0.orig/tools/ioemu-qemu-xen/Makefile
|
||||
+++ xen-3.3.0/tools/ioemu-qemu-xen/Makefile
|
||||
@@ -205,7 +205,7 @@ endif
|
||||
install: all $(if $(BUILD_DOCS),install-doc)
|
||||
mkdir -p "$(DESTDIR)$(bindir)"
|
||||
ifneq ($(TOOLS),)
|
||||
- $(INSTALL) -m 755 -s $(TOOLS) "$(DESTDIR)$(bindir)"
|
||||
+ $(INSTALL) -m 755 $(TOOLS) "$(DESTDIR)$(bindir)"
|
||||
endif
|
||||
mkdir -p "$(DESTDIR)$(datadir)"
|
||||
set -e; for x in bios.bin vgabios.bin vgabios-cirrus.bin ppc_rom.bin \
|
||||
Index: xen-3.3.0/tools/ioemu-qemu-xen/Makefile.target
|
||||
===================================================================
|
||||
--- xen-3.3.0.orig/tools/ioemu-qemu-xen/Makefile.target
|
||||
+++ xen-3.3.0/tools/ioemu-qemu-xen/Makefile.target
|
||||
@@ -707,7 +707,7 @@ clean:
|
||||
|
||||
install: all install-hook
|
||||
ifneq ($(PROGS),)
|
||||
- $(INSTALL) -m 755 -s $(PROGS) "$(DESTDIR)$(bindir)"
|
||||
+ $(INSTALL) -m 755 $(PROGS) "$(DESTDIR)$(bindir)"
|
||||
endif
|
||||
|
||||
# Include automatically generated dependency files
|
@ -1,15 +0,0 @@
|
||||
2011-10-22 Ralf Glauberman <ralfglauberman@gmx.de>
|
||||
|
||||
#360805 Don't compile ipxe with pie on hardened.
|
||||
* /tools/firmware/etherboot/patches/ipxe-nopie.patche New patch
|
||||
Reconstituted patch; Tue Jan 29 14:35:13 WST 2013
|
||||
|
||||
diff -ur xen-4.2.0.orig/tools/firmware/etherboot/patches/series xen-4.2.0/tools/firmware/etherboot/patches/series
|
||||
--- tools/firmware/etherboot/patches/series 2013-01-29 14:34:10.773520921 +0800
|
||||
+++ tools/firmware/etherboot/patches/series 2013-01-29 14:33:31.781519209 +0800
|
||||
@@ -2,3 +2,4 @@
|
||||
build_fix_1.patch
|
||||
build_fix_2.patch
|
||||
build_fix_3.patch
|
||||
+ipxe-nopie.patch
|
||||
|
@ -1,10 +0,0 @@
|
||||
diff -ur xen-4.1.1.orig//tools/check/check_curl xen-4.1.1/tools/check/check_curl
|
||||
--- xen-4.1.1.orig//tools/check/check_curl 2011-06-15 00:03:44.000000000 +0800
|
||||
+++ xen-4.1.1/tools/check/check_curl 2011-10-14 00:42:08.189717078 +0800
|
||||
@@ -9,5 +9,6 @@
|
||||
fi
|
||||
|
||||
has_or_fail curl-config
|
||||
curl_libs=`curl-config --libs` || fail "curl-config --libs failed"
|
||||
+curl_libs=`echo $curl_libs | sed -re 's/-(W|march|mtune|pipe)[^[:space:]]*[[:space:]]//g'` || fail "curl-config --libs failed"
|
||||
test_link $curl_libs || fail "dependency libraries for curl are missing"
|
@ -1,37 +0,0 @@
|
||||
Index: xen-tools-4.1.1/tools/libxl/libxl_dm.c
|
||||
===================================================================
|
||||
--- xen-4.1.1.orig/tools/libxl/libxl_dm.c Tue Mar 15 10:14:27 2011 +0000
|
||||
+++ xen-4.1.1/tools/libxl/libxl_dm.c Tue Mar 15 18:19:47 2011 +0000
|
||||
@@ -828,8 +828,29 @@
|
||||
goto out;
|
||||
}
|
||||
|
||||
- if (nr_disks > 0 && !libxl__blktap_enabled(&gc))
|
||||
- ret = 1;
|
||||
+ if (nr_disks > 0) {
|
||||
+ int blktap_enabled = -1;
|
||||
+ for (i = 0; i < nr_disks; i++) {
|
||||
+ switch (disks[i].backend) {
|
||||
+ case DISK_BACKEND_TAP:
|
||||
+ if (blktap_enabled == -1)
|
||||
+ blktap_enabled = libxl__blktap_enabled(&gc);
|
||||
+ if (!blktap_enabled) {
|
||||
+ ret = 1;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ break;
|
||||
+
|
||||
+ case DISK_BACKEND_QDISK:
|
||||
+ ret = 1;
|
||||
+ goto out;
|
||||
+
|
||||
+ case DISK_BACKEND_PHY:
|
||||
+ case DISK_BACKEND_UNKNOWN:
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
|
||||
out:
|
||||
libxl__free_all(&gc);
|
||||
|
@ -1,12 +0,0 @@
|
||||
--- tools/python/xen/xm/create.py
|
||||
+++ tools/python/xen/xm/create.py
|
||||
@@ -1538,6 +1538,9 @@
|
||||
SXPPrettyPrint.prettyprint(config)
|
||||
|
||||
if opts.vals.xmldryrun and serverType == SERVER_XEN_API:
|
||||
+ import xml
|
||||
+ if hasattr(xml, "use_pyxml"):
|
||||
+ xml.use_pyxml()
|
||||
from xml.dom.ext import PrettyPrint as XMLPrettyPrint
|
||||
XMLPrettyPrint(doc)
|
||||
|
@ -1,345 +0,0 @@
|
||||
# Copyright 1999-2013 Gentoo Foundation
|
||||
# Distributed under the terms of the GNU General Public License v2
|
||||
# $Header: /var/cvsroot/gentoo-x86/app-emulation/xen-tools/xen-tools-4.2.0-r3.ebuild,v 1.10 2013/03/05 18:05:35 idella4 Exp $
|
||||
|
||||
EAPI=5
|
||||
|
||||
PYTHON_COMPAT=( python{2_6,2_7} )
|
||||
PYTHON_REQ_USE='xml,threads'
|
||||
|
||||
IPXE_TARBALL_URL="http://dev.gentoo.org/~idella4/tarballs/ipxe.tar.gz"
|
||||
XEN_SEABIOS_URL="http://dev.gentoo.org/~idella4/tarballs/seabios-0-20121121.tar.bz2"
|
||||
|
||||
if [[ $PV == *9999 ]]; then
|
||||
KEYWORDS=""
|
||||
REPO="xen-unstable.hg"
|
||||
EHG_REPO_URI="http://xenbits.xensource.com/${REPO}"
|
||||
S="${WORKDIR}/${REPO}"
|
||||
live_eclass="mercurial"
|
||||
else
|
||||
KEYWORDS="amd64 x86"
|
||||
SRC_URI="http://bits.xensource.com/oss-xen/release/${PV}/xen-${PV}.tar.gz
|
||||
$IPXE_TARBALL_URL
|
||||
$XEN_SEABIOS_URL"
|
||||
S="${WORKDIR}/xen-${PV}"
|
||||
fi
|
||||
|
||||
inherit flag-o-matic eutils multilib python-single-r1 toolchain-funcs udev ${live_eclass}
|
||||
|
||||
DESCRIPTION="Xend daemon and tools"
|
||||
HOMEPAGE="http://xen.org/"
|
||||
DOCS=( README docs/README.xen-bugtool )
|
||||
|
||||
LICENSE="GPL-2"
|
||||
SLOT="0"
|
||||
# TODO soon; ocaml up for a potential name change
|
||||
IUSE="api custom-cflags debug doc flask hvm ocaml qemu pygrub screen static-libs xend"
|
||||
|
||||
REQUIRED_USE="hvm? ( qemu )"
|
||||
|
||||
CDEPEND="dev-libs/yajl
|
||||
dev-python/lxml[${PYTHON_USEDEP}]
|
||||
dev-python/pypam[${PYTHON_USEDEP}]
|
||||
sys-libs/zlib
|
||||
sys-power/iasl
|
||||
ocaml? ( dev-ml/findlib )
|
||||
hvm? ( media-libs/libsdl )
|
||||
${PYTHON_DEPS}
|
||||
api? ( dev-libs/libxml2
|
||||
net-misc/curl )
|
||||
${PYTHON_DEPS}
|
||||
pygrub? ( ${PYTHON_DEPS//${PYTHON_REQ_USE}/ncurses} )"
|
||||
DEPEND="${CDEPEND}
|
||||
sys-devel/bin86
|
||||
sys-devel/dev86
|
||||
dev-lang/perl
|
||||
app-misc/pax-utils
|
||||
doc? (
|
||||
app-doc/doxygen
|
||||
dev-tex/latex2html[png,gif]
|
||||
media-gfx/transfig
|
||||
media-gfx/graphviz
|
||||
dev-tex/xcolor
|
||||
dev-texlive/texlive-latexextra
|
||||
virtual/latex-base
|
||||
dev-tex/latexmk
|
||||
dev-texlive/texlive-latex
|
||||
dev-texlive/texlive-pictures
|
||||
dev-texlive/texlive-latexrecommended
|
||||
)
|
||||
hvm? ( x11-proto/xproto
|
||||
)"
|
||||
RDEPEND="${CDEPEND}
|
||||
sys-apps/iproute2
|
||||
net-misc/bridge-utils
|
||||
ocaml? ( >=dev-lang/ocaml-3.12.0 )
|
||||
screen? (
|
||||
app-misc/screen
|
||||
app-admin/logrotate
|
||||
)
|
||||
virtual/udev"
|
||||
|
||||
# hvmloader is used to bootstrap a fully virtualized kernel
|
||||
# Approved by QA team in bug #144032
|
||||
QA_WX_LOAD="usr/lib/xen/boot/hvmloader"
|
||||
|
||||
RESTRICT="test"
|
||||
|
||||
pkg_setup() {
|
||||
python-single-r1_pkg_setup
|
||||
export "CONFIG_LOMOUNT=y"
|
||||
|
||||
if has_version dev-libs/libgcrypt; then
|
||||
export "CONFIG_GCRYPT=y"
|
||||
fi
|
||||
|
||||
if use qemu; then
|
||||
export "CONFIG_IOEMU=y"
|
||||
else
|
||||
export "CONFIG_IOEMU=n"
|
||||
fi
|
||||
|
||||
if ! use x86 && ! has x86 $(get_all_abis) && use hvm; then
|
||||
eerror "HVM (VT-x and AMD-v) cannot be built on this system. An x86 or"
|
||||
eerror "an amd64 multilib profile is required. Remove the hvm use flag"
|
||||
eerror "to build xen-tools on your current profile."
|
||||
die "USE=hvm is unsupported on this system."
|
||||
fi
|
||||
|
||||
if [[ -z ${XEN_TARGET_ARCH} ]] ; then
|
||||
if use x86 && use amd64; then
|
||||
die "Confusion! Both x86 and amd64 are set in your use flags!"
|
||||
elif use x86; then
|
||||
export XEN_TARGET_ARCH="x86_32"
|
||||
elif use amd64 ; then
|
||||
export XEN_TARGET_ARCH="x86_64"
|
||||
else
|
||||
die "Unsupported architecture!"
|
||||
fi
|
||||
fi
|
||||
|
||||
use api && export "LIBXENAPI_BINDINGS=y"
|
||||
use flask && export "FLASK_ENABLE=y"
|
||||
}
|
||||
|
||||
src_prepare() {
|
||||
# Drop .config, fixes to gcc-4.6
|
||||
epatch "${FILESDIR}"/${PN/-tools/}-4-fix_dotconfig-gcc.patch
|
||||
|
||||
# Xend
|
||||
if ! use xend; then
|
||||
sed -e 's:xm xen-bugtool xen-python-path xend:xen-bugtool xen-python-path:' \
|
||||
-i tools/misc/Makefile || die "Disabling xend failed"
|
||||
sed -e 's:^XEND_INITD:#XEND_INITD:' \
|
||||
-i tools/examples/Makefile || die "Disabling xend failed"
|
||||
fi
|
||||
|
||||
# if the user *really* wants to use their own custom-cflags, let them
|
||||
if use custom-cflags; then
|
||||
einfo "User wants their own CFLAGS - removing defaults"
|
||||
|
||||
# try and remove all the default cflags
|
||||
find "${S}" \( -name Makefile -o -name Rules.mk -o -name Config.mk \) \
|
||||
-exec sed \
|
||||
-e 's/CFLAGS\(.*\)=\(.*\)-O3\(.*\)/CFLAGS\1=\2\3/' \
|
||||
-e 's/CFLAGS\(.*\)=\(.*\)-march=i686\(.*\)/CFLAGS\1=\2\3/' \
|
||||
-e 's/CFLAGS\(.*\)=\(.*\)-fomit-frame-pointer\(.*\)/CFLAGS\1=\2\3/' \
|
||||
-e 's/CFLAGS\(.*\)=\(.*\)-g3*\s\(.*\)/CFLAGS\1=\2 \3/' \
|
||||
-e 's/CFLAGS\(.*\)=\(.*\)-O2\(.*\)/CFLAGS\1=\2\3/' \
|
||||
-i {} + || die "failed to re-set custom-cflags"
|
||||
fi
|
||||
|
||||
if ! use pygrub; then
|
||||
sed -e '/^SUBDIRS-$(PYTHON_TOOLS) += pygrub$/d' -i tools/Makefile || die
|
||||
fi
|
||||
|
||||
# Disable hvm support on systems that don't support x86_32 binaries.
|
||||
if ! use hvm; then
|
||||
sed -e '/^CONFIG_IOEMU := y$/d' -i config/*.mk || die
|
||||
sed -e '/SUBDIRS-$(CONFIG_X86) += firmware/d' -i tools/Makefile || die
|
||||
fi
|
||||
|
||||
# Don't bother with qemu, only needed for fully virtualised guests
|
||||
if ! use qemu; then
|
||||
sed -e "/^CONFIG_IOEMU := y$/d" -i config/*.mk || die
|
||||
sed -e "s:install-tools\: tools/ioemu-dir:install-tools\: :g" -i Makefile || die
|
||||
fi
|
||||
|
||||
# Fix texi2html build error with new texi2html
|
||||
epatch "${FILESDIR}"/${PN}-4-docfix.patch
|
||||
|
||||
# Fix network broadcast on bridged networks
|
||||
epatch "${FILESDIR}/${PN}-3.4.0-network-bridge-broadcast.patch"
|
||||
|
||||
# Prevent the downloading of ipxe, seabios
|
||||
epatch "${FILESDIR}"/${P/-tools/}-anti-download.patch
|
||||
cp "${DISTDIR}"/ipxe.tar.gz tools/firmware/etherboot/ || die
|
||||
mv ../seabios-dir-remote tools/firmware/ || die
|
||||
pushd tools/firmware/ > /dev/null
|
||||
ln -s seabios-dir-remote seabios-dir || die
|
||||
popd > /dev/null
|
||||
|
||||
# Fix bridge by idella4, bug #362575
|
||||
epatch "${FILESDIR}/${PN}-4.1.1-bridge.patch"
|
||||
|
||||
# Don't build ipxe with pie on hardened, Bug #360805
|
||||
if gcc-specs-pie; then
|
||||
epatch "${FILESDIR}"/ipxe-nopie.patch
|
||||
fi
|
||||
|
||||
# Prevent double stripping of files at install
|
||||
epatch "${FILESDIR}"/${P/-tools/}-nostrip.patch
|
||||
|
||||
# fix jobserver in Makefile
|
||||
epatch "${FILESDIR}"/${P/-tools/}-jserver.patch
|
||||
|
||||
#Sec patches
|
||||
epatch "${FILESDIR}"/xen-4-CVE-2012-4544-XSA-25.patch \
|
||||
"${FILESDIR}"/xen-4-CVE-2012-6075-XSA-41.patch
|
||||
}
|
||||
|
||||
src_compile() {
|
||||
export VARTEXFONTS="${T}/fonts"
|
||||
local myopt
|
||||
use debug && myopt="${myopt} debug=y"
|
||||
|
||||
use custom-cflags || unset CFLAGS
|
||||
if test-flag-CC -fno-strict-overflow; then
|
||||
append-flags -fno-strict-overflow
|
||||
fi
|
||||
|
||||
unset LDFLAGS
|
||||
unset CFLAGS
|
||||
emake CC="$(tc-getCC)" LD="$(tc-getLD)" -C tools ${myopt}
|
||||
|
||||
use doc && emake -C docs txt html
|
||||
emake -C docs man-pages
|
||||
}
|
||||
|
||||
src_install() {
|
||||
# Override auto-detection in the build system, bug #382573
|
||||
export INITD_DIR=/tmp/init.d
|
||||
export CONFIG_LEAF_DIR=../tmp/default
|
||||
|
||||
# Let the build system compile installed Python modules.
|
||||
local PYTHONDONTWRITEBYTECODE
|
||||
export PYTHONDONTWRITEBYTECODE
|
||||
|
||||
emake DESTDIR="${D}" DOCDIR="/usr/share/doc/${PF}" \
|
||||
install-tools
|
||||
|
||||
# Fix the remaining Python shebangs.
|
||||
python_fix_shebang "${D}"
|
||||
|
||||
# Remove RedHat-specific stuff
|
||||
rm -rf "${D}"tmp || die
|
||||
|
||||
# uncomment lines in xl.conf
|
||||
sed -e 's:^#autoballoon=1:autoballoon=1:' \
|
||||
-e 's:^#lockfile="/var/lock/xl":lockfile="/var/lock/xl":' \
|
||||
-e 's:^#vifscript="vif-bridge":vifscript="vif-bridge":' \
|
||||
-i tools/examples/xl.conf || die
|
||||
|
||||
if use doc; then
|
||||
emake DESTDIR="${D}" DOCDIR="/usr/share/doc/${PF}" install-docs
|
||||
|
||||
dohtml -r docs/html/
|
||||
docinto pdf
|
||||
dodoc ${DOCS[@]}
|
||||
[ -d "${D}"/usr/share/doc/xen ] && mv "${ED}"/usr/share/doc/xen/* "${ED}"/usr/share/doc/${PF}/html
|
||||
fi
|
||||
|
||||
rm -rf "${D}"/usr/share/doc/xen/
|
||||
doman docs/man?/*
|
||||
|
||||
if use xend; then
|
||||
newinitd "${FILESDIR}"/xend.initd-r2 xend || die "Couldn't install xen.initd"
|
||||
fi
|
||||
newconfd "${FILESDIR}"/xendomains.confd xendomains
|
||||
newconfd "${FILESDIR}"/xenstored.confd xenstored
|
||||
newconfd "${FILESDIR}"/xenconsoled.confd xenconsoled
|
||||
newinitd "${FILESDIR}"/xendomains.initd-r2 xendomains
|
||||
newinitd "${FILESDIR}"/xenstored.initd xenstored
|
||||
newinitd "${FILESDIR}"/xenconsoled.initd xenconsoled
|
||||
|
||||
if use screen; then
|
||||
cat "${FILESDIR}"/xendomains-screen.confd >> "${D}"/etc/conf.d/xendomains || die
|
||||
cp "${FILESDIR}"/xen-consoles.logrotate "${D}"/etc/xen/ || die
|
||||
keepdir /var/log/xen-consoles
|
||||
fi
|
||||
|
||||
# Set dirs for qemu files,; Bug #458818
|
||||
if use qemu; then
|
||||
if use x86; then
|
||||
dodir /usr/lib/xen/bin
|
||||
elif use amd64; then
|
||||
mv "${D}"usr/lib/xen/bin/qemu* "${D}"usr/$(get_libdir)/xen/bin/ || die
|
||||
fi
|
||||
fi
|
||||
|
||||
# For -static-libs wrt Bug 384355
|
||||
if ! use static-libs; then
|
||||
rm -f "${D}"usr/$(get_libdir)/*.a "${ED}"usr/$(get_libdir)/ocaml/*/*.a
|
||||
fi
|
||||
|
||||
# xend expects these to exist
|
||||
keepdir /var/run/xenstored /var/lib/xenstored /var/xen/dump /var/lib/xen /var/log/xen
|
||||
|
||||
# for xendomains
|
||||
keepdir /etc/xen/auto
|
||||
|
||||
# Temp QA workaround
|
||||
dodir "$(udev_get_udevdir)"
|
||||
mv "${D}"/etc/udev/* "${ED}/$(udev_get_udevdir)"
|
||||
rm -rf "${D}"/etc/udev
|
||||
|
||||
# Remove files failing QA AFTER emake installs them, avoiding seeking absent files
|
||||
find "${D}" \( -name openbios-sparc32 -o -name openbios-sparc64 \
|
||||
-o -name openbios-ppc -o -name palcode-clipper \) -delete || die
|
||||
}
|
||||
|
||||
pkg_postinst() {
|
||||
elog "Official Xen Guide and the unoffical wiki page:"
|
||||
elog " http://www.gentoo.org/doc/en/xen-guide.xml"
|
||||
elog " http://gentoo-wiki.com/HOWTO_Xen_and_Gentoo"
|
||||
|
||||
if [[ "$(scanelf -s __guard -q "${PYTHON}")" ]] ; then
|
||||
echo
|
||||
ewarn "xend may not work when python is built with stack smashing protection (ssp)."
|
||||
ewarn "If 'xm create' fails with '<ProtocolError for /RPC2: -1 >', see bug #141866"
|
||||
ewarn "This problem may be resolved as of Xen 3.0.4, if not post in the bug."
|
||||
fi
|
||||
|
||||
# TODO: we need to have the current Python slot here.
|
||||
if ! has_version "dev-lang/python[ncurses]"; then
|
||||
echo
|
||||
ewarn "NB: Your dev-lang/python is built without USE=ncurses."
|
||||
ewarn "Please rebuild python with USE=ncurses to make use of xenmon.py."
|
||||
fi
|
||||
|
||||
if has_version "sys-apps/iproute2[minimal]"; then
|
||||
echo
|
||||
ewarn "Your sys-apps/iproute2 is built with USE=minimal. Networking"
|
||||
ewarn "will not work until you rebuild iproute2 without USE=minimal."
|
||||
fi
|
||||
|
||||
if ! use hvm; then
|
||||
echo
|
||||
elog "HVM (VT-x and AMD-V) support has been disabled. If you need hvm"
|
||||
elog "support enable the hvm use flag."
|
||||
elog "An x86 or amd64 multilib system is required to build HVM support."
|
||||
echo
|
||||
elog "The qemu use flag has been removed and replaced with hvm."
|
||||
fi
|
||||
|
||||
if use xend; then
|
||||
echo
|
||||
elog "xend capability has been enabled and installed"
|
||||
fi
|
||||
|
||||
if grep -qsF XENSV= "${ROOT}/etc/conf.d/xend"; then
|
||||
echo
|
||||
elog "xensv is broken upstream (Gentoo bug #142011)."
|
||||
elog "Please remove '${ROOT%/}/etc/conf.d/xend', as it is no longer needed."
|
||||
fi
|
||||
}
|
@ -1,347 +0,0 @@
|
||||
# Copyright 1999-2013 Gentoo Foundation
|
||||
# Distributed under the terms of the GNU General Public License v2
|
||||
# $Header: /var/cvsroot/gentoo-x86/app-emulation/xen-tools/xen-tools-4.2.1-r2.ebuild,v 1.6 2013/03/05 18:05:35 idella4 Exp $
|
||||
|
||||
EAPI=5
|
||||
|
||||
PYTHON_COMPAT=( python{2_6,2_7} )
|
||||
PYTHON_REQ_USE='xml,threads'
|
||||
|
||||
IPXE_TARBALL_URL="http://dev.gentoo.org/~idella4/tarballs/ipxe.tar.gz"
|
||||
XEN_SEABIOS_URL="http://dev.gentoo.org/~idella4/tarballs/seabios-0-20121121.tar.bz2"
|
||||
|
||||
if [[ $PV == *9999 ]]; then
|
||||
KEYWORDS=""
|
||||
REPO="xen-unstable.hg"
|
||||
EHG_REPO_URI="http://xenbits.xensource.com/${REPO}"
|
||||
S="${WORKDIR}/${REPO}"
|
||||
live_eclass="mercurial"
|
||||
else
|
||||
KEYWORDS="~amd64 ~x86"
|
||||
SRC_URI="http://bits.xensource.com/oss-xen/release/${PV}/xen-${PV}.tar.gz
|
||||
$IPXE_TARBALL_URL
|
||||
$XEN_SEABIOS_URL"
|
||||
S="${WORKDIR}/xen-${PV}"
|
||||
fi
|
||||
|
||||
inherit flag-o-matic eutils multilib python-single-r1 toolchain-funcs udev ${live_eclass}
|
||||
|
||||
DESCRIPTION="Xend daemon and tools"
|
||||
HOMEPAGE="http://xen.org/"
|
||||
DOCS=( README docs/README.xen-bugtool )
|
||||
|
||||
LICENSE="GPL-2"
|
||||
SLOT="0"
|
||||
IUSE="api custom-cflags debug doc flask hvm qemu ocaml pygrub screen static-libs xend"
|
||||
|
||||
REQUIRED_USE="hvm? ( qemu )"
|
||||
|
||||
CDEPEND="<dev-libs/yajl-2
|
||||
dev-python/lxml[${PYTHON_USEDEP}]
|
||||
dev-python/pypam[${PYTHON_USEDEP}]
|
||||
sys-libs/zlib
|
||||
sys-power/iasl
|
||||
ocaml? ( dev-ml/findlib )
|
||||
hvm? ( media-libs/libsdl )
|
||||
${PYTHON_DEPS}
|
||||
api? ( dev-libs/libxml2
|
||||
net-misc/curl )
|
||||
${PYTHON_DEPS}
|
||||
pygrub? ( ${PYTHON_DEPS//${PYTHON_REQ_USE}/ncurses} )"
|
||||
DEPEND="${CDEPEND}
|
||||
sys-devel/bin86
|
||||
sys-devel/dev86
|
||||
dev-lang/perl
|
||||
app-misc/pax-utils
|
||||
doc? (
|
||||
app-doc/doxygen
|
||||
dev-tex/latex2html[png,gif]
|
||||
media-gfx/transfig
|
||||
media-gfx/graphviz
|
||||
dev-tex/xcolor
|
||||
dev-texlive/texlive-latexextra
|
||||
virtual/latex-base
|
||||
dev-tex/latexmk
|
||||
dev-texlive/texlive-latex
|
||||
dev-texlive/texlive-pictures
|
||||
dev-texlive/texlive-latexrecommended
|
||||
)
|
||||
hvm? ( x11-proto/xproto
|
||||
)"
|
||||
RDEPEND="${CDEPEND}
|
||||
sys-apps/iproute2
|
||||
net-misc/bridge-utils
|
||||
ocaml? ( >=dev-lang/ocaml-3.12.0 )
|
||||
screen? (
|
||||
app-misc/screen
|
||||
app-admin/logrotate
|
||||
)
|
||||
virtual/udev"
|
||||
|
||||
# hvmloader is used to bootstrap a fully virtualized kernel
|
||||
# Approved by QA team in bug #144032
|
||||
QA_WX_LOAD="usr/lib/xen/boot/hvmloader"
|
||||
|
||||
RESTRICT="test"
|
||||
|
||||
pkg_setup() {
|
||||
python-single-r1_pkg_setup
|
||||
export "CONFIG_LOMOUNT=y"
|
||||
|
||||
if has_version dev-libs/libgcrypt; then
|
||||
export "CONFIG_GCRYPT=y"
|
||||
fi
|
||||
|
||||
if use qemu; then
|
||||
export "CONFIG_IOEMU=y"
|
||||
else
|
||||
export "CONFIG_IOEMU=n"
|
||||
fi
|
||||
|
||||
if ! use x86 && ! has x86 $(get_all_abis) && use hvm; then
|
||||
eerror "HVM (VT-x and AMD-v) cannot be built on this system. An x86 or"
|
||||
eerror "an amd64 multilib profile is required. Remove the hvm use flag"
|
||||
eerror "to build xen-tools on your current profile."
|
||||
die "USE=hvm is unsupported on this system."
|
||||
fi
|
||||
|
||||
if [[ -z ${XEN_TARGET_ARCH} ]] ; then
|
||||
if use x86 && use amd64; then
|
||||
die "Confusion! Both x86 and amd64 are set in your use flags!"
|
||||
elif use x86; then
|
||||
export XEN_TARGET_ARCH="x86_32"
|
||||
elif use amd64 ; then
|
||||
export XEN_TARGET_ARCH="x86_64"
|
||||
else
|
||||
die "Unsupported architecture!"
|
||||
fi
|
||||
fi
|
||||
|
||||
use api && export "LIBXENAPI_BINDINGS=y"
|
||||
use flask && export "FLASK_ENABLE=y"
|
||||
}
|
||||
|
||||
src_prepare() {
|
||||
# Drop .config, fixes to gcc-4.6
|
||||
epatch "${FILESDIR}"/${PN/-tools/}-4-fix_dotconfig-gcc.patch
|
||||
|
||||
# Xend
|
||||
if ! use xend; then
|
||||
sed -e 's:xm xen-bugtool xen-python-path xend:xen-bugtool xen-python-path:' \
|
||||
-i tools/misc/Makefile || die "Disabling xend failed"
|
||||
sed -e 's:^XEND_INITD:#XEND_INITD:' \
|
||||
-i tools/examples/Makefile || die "Disabling xend failed"
|
||||
fi
|
||||
|
||||
# if the user *really* wants to use their own custom-cflags, let them
|
||||
if use custom-cflags; then
|
||||
einfo "User wants their own CFLAGS - removing defaults"
|
||||
|
||||
# try and remove all the default cflags
|
||||
find "${S}" \( -name Makefile -o -name Rules.mk -o -name Config.mk \) \
|
||||
-exec sed \
|
||||
-e 's/CFLAGS\(.*\)=\(.*\)-O3\(.*\)/CFLAGS\1=\2\3/' \
|
||||
-e 's/CFLAGS\(.*\)=\(.*\)-march=i686\(.*\)/CFLAGS\1=\2\3/' \
|
||||
-e 's/CFLAGS\(.*\)=\(.*\)-fomit-frame-pointer\(.*\)/CFLAGS\1=\2\3/' \
|
||||
-e 's/CFLAGS\(.*\)=\(.*\)-g3*\s\(.*\)/CFLAGS\1=\2 \3/' \
|
||||
-e 's/CFLAGS\(.*\)=\(.*\)-O2\(.*\)/CFLAGS\1=\2\3/' \
|
||||
-i {} + || die "failed to re-set custom-cflags"
|
||||
fi
|
||||
|
||||
if ! use pygrub; then
|
||||
sed -e '/^SUBDIRS-$(PYTHON_TOOLS) += pygrub$/d' -i tools/Makefile || die
|
||||
fi
|
||||
|
||||
# Disable hvm support on systems that don't support x86_32 binaries.
|
||||
if ! use hvm; then
|
||||
sed -e '/^CONFIG_IOEMU := y$/d' -i config/*.mk || die
|
||||
sed -e '/SUBDIRS-$(CONFIG_X86) += firmware/d' -i tools/Makefile || die
|
||||
fi
|
||||
|
||||
# Don't bother with qemu, only needed for fully virtualised guests
|
||||
if ! use qemu; then
|
||||
sed -e "/^CONFIG_IOEMU := y$/d" -i config/*.mk || die
|
||||
sed -e "s:install-tools\: tools/ioemu-dir:install-tools\: :g" -i Makefile || die
|
||||
fi
|
||||
|
||||
# Fix texi2html build error with new texi2html
|
||||
epatch "${FILESDIR}"/${PN}-4-docfix.patch
|
||||
|
||||
# Fix network broadcast on bridged networks
|
||||
epatch "${FILESDIR}/${PN}-3.4.0-network-bridge-broadcast.patch"
|
||||
|
||||
# Prevent the downloading of ipxe, seabios
|
||||
epatch "${FILESDIR}"/${PN/-tools/}-4.2.0-anti-download.patch
|
||||
cp "${DISTDIR}"/ipxe.tar.gz tools/firmware/etherboot/ || die
|
||||
mv ../seabios-dir-remote tools/firmware/ || die
|
||||
pushd tools/firmware/ > /dev/null
|
||||
ln -s seabios-dir-remote seabios-dir || die
|
||||
popd > /dev/null
|
||||
|
||||
# Fix bridge by idella4, bug #362575
|
||||
epatch "${FILESDIR}/${PN}-4.1.1-bridge.patch"
|
||||
|
||||
# Don't build ipxe with pie on hardened, Bug #360805
|
||||
if gcc-specs-pie; then
|
||||
epatch "${FILESDIR}"/ipxe-nopie.patch
|
||||
fi
|
||||
|
||||
# Prevent double stripping of files at install
|
||||
epatch "${FILESDIR}"/${PN/-tools/}-4.2.0-nostrip.patch
|
||||
|
||||
# fix jobserver in Makefile
|
||||
epatch "${FILESDIR}"/${PN/-tools/}-4.2.0-jserver.patch
|
||||
|
||||
#Sec patch, currently valid
|
||||
epatch "${FILESDIR}"/xen-4-CVE-2012-6075-XSA-41.patch
|
||||
|
||||
if use hvm; then
|
||||
cp -r "${FILESDIR}"/stubs-32.h xen/tools/include || die "copy of header file failed"
|
||||
einfo "stubs-32.h added"
|
||||
fi
|
||||
}
|
||||
|
||||
src_compile() {
|
||||
export VARTEXFONTS="${T}/fonts"
|
||||
local myopt
|
||||
use debug && myopt="${myopt} debug=y"
|
||||
|
||||
use custom-cflags || unset CFLAGS
|
||||
if test-flag-CC -fno-strict-overflow; then
|
||||
append-flags -fno-strict-overflow
|
||||
fi
|
||||
|
||||
unset LDFLAGS
|
||||
unset CFLAGS
|
||||
emake CC="$(tc-getCC)" LD="$(tc-getLD)" -C tools ${myopt}
|
||||
|
||||
use doc && emake -C docs txt html
|
||||
emake -C docs man-pages
|
||||
}
|
||||
|
||||
src_install() {
|
||||
# Override auto-detection in the build system, bug #382573
|
||||
export INITD_DIR=/tmp/init.d
|
||||
export CONFIG_LEAF_DIR=../tmp/default
|
||||
|
||||
# Let the build system compile installed Python modules.
|
||||
local PYTHONDONTWRITEBYTECODE
|
||||
export PYTHONDONTWRITEBYTECODE
|
||||
|
||||
emake DESTDIR="${D}" DOCDIR="/usr/share/doc/${PF}" install-tools
|
||||
|
||||
# Fix the remaining Python shebangs.
|
||||
python_fix_shebang "${D}"
|
||||
|
||||
# Remove RedHat-specific stuff
|
||||
rm -rf "${D}"tmp || die
|
||||
|
||||
# uncomment lines in xl.conf
|
||||
sed -e 's:^#autoballoon=1:autoballoon=1:' \
|
||||
-e 's:^#lockfile="/var/lock/xl":lockfile="/var/lock/xl":' \
|
||||
-e 's:^#vifscript="vif-bridge":vifscript="vif-bridge":' \
|
||||
-i tools/examples/xl.conf || die
|
||||
|
||||
if use doc; then
|
||||
emake DESTDIR="${D}" DOCDIR="/usr/share/doc/${PF}" install-docs
|
||||
|
||||
dohtml -r docs/
|
||||
docinto pdf
|
||||
dodoc ${DOCS[@]}
|
||||
[ -d "${D}"/usr/share/doc/xen ] && mv "${D}"/usr/share/doc/xen/* "${D}"/usr/share/doc/${PF}/html
|
||||
fi
|
||||
|
||||
rm -rf "${D}"/usr/share/doc/xen/
|
||||
doman docs/man?/*
|
||||
|
||||
if use xend; then
|
||||
newinitd "${FILESDIR}"/xend.initd-r2 xend || die "Couldn't install xen.initd"
|
||||
fi
|
||||
newconfd "${FILESDIR}"/xendomains.confd xendomains
|
||||
newconfd "${FILESDIR}"/xenstored.confd xenstored
|
||||
newconfd "${FILESDIR}"/xenconsoled.confd xenconsoled
|
||||
newinitd "${FILESDIR}"/xendomains.initd-r2 xendomains
|
||||
newinitd "${FILESDIR}"/xenstored.initd xenstored
|
||||
newinitd "${FILESDIR}"/xenconsoled.initd xenconsoled
|
||||
|
||||
if use screen; then
|
||||
cat "${FILESDIR}"/xendomains-screen.confd >> "${D}"/etc/conf.d/xendomains || die
|
||||
cp "${FILESDIR}"/xen-consoles.logrotate "${D}"/etc/xen/ || die
|
||||
keepdir /var/log/xen-consoles
|
||||
fi
|
||||
|
||||
# Set dirs for qemu files,; Bug #458818
|
||||
if use qemu; then
|
||||
if use x86; then
|
||||
dodir /usr/lib/xen/bin
|
||||
elif use amd64; then
|
||||
mv "${D}"usr/lib/xen/bin/qemu* "${D}"usr/$(get_libdir)/xen/bin/ || die
|
||||
fi
|
||||
fi
|
||||
|
||||
# For -static-libs wrt Bug 384355
|
||||
if ! use static-libs; then
|
||||
rm -f "${D}"usr/$(get_libdir)/*.a "${D}"usr/$(get_libdir)/ocaml/*/*.a
|
||||
fi
|
||||
|
||||
# xend expects these to exist
|
||||
keepdir /var/run/xenstored /var/lib/xenstored /var/xen/dump /var/lib/xen /var/log/xen
|
||||
|
||||
# for xendomains
|
||||
keepdir /etc/xen/auto
|
||||
|
||||
# Temp QA workaround
|
||||
dodir "$(udev_get_udevdir)"
|
||||
mv "${D}"/etc/udev/* "${D}/$(udev_get_udevdir)"
|
||||
rm -rf "${D}"/etc/udev
|
||||
|
||||
# Remove files failing QA AFTER emake installs them, avoiding seeking absent files
|
||||
find "${D}" \( -name openbios-sparc32 -o -name openbios-sparc64 \
|
||||
-o -name openbios-ppc -o -name palcode-clipper \) -delete || die
|
||||
}
|
||||
|
||||
pkg_postinst() {
|
||||
elog "Official Xen Guide and the unoffical wiki page:"
|
||||
elog " http://www.gentoo.org/doc/en/xen-guide.xml"
|
||||
elog " http://gentoo-wiki.com/HOWTO_Xen_and_Gentoo"
|
||||
|
||||
if [[ "$(scanelf -s __guard -q "${PYTHON}")" ]] ; then
|
||||
echo
|
||||
ewarn "xend may not work when python is built with stack smashing protection (ssp)."
|
||||
ewarn "If 'xm create' fails with '<ProtocolError for /RPC2: -1 >', see bug #141866"
|
||||
ewarn "This problem may be resolved as of Xen 3.0.4, if not post in the bug."
|
||||
fi
|
||||
|
||||
# TODO: we need to have the current Python slot here.
|
||||
if ! has_version "dev-lang/python[ncurses]"; then
|
||||
echo
|
||||
ewarn "NB: Your dev-lang/python is built without USE=ncurses."
|
||||
ewarn "Please rebuild python with USE=ncurses to make use of xenmon.py."
|
||||
fi
|
||||
|
||||
if has_version "sys-apps/iproute2[minimal]"; then
|
||||
echo
|
||||
ewarn "Your sys-apps/iproute2 is built with USE=minimal. Networking"
|
||||
ewarn "will not work until you rebuild iproute2 without USE=minimal."
|
||||
fi
|
||||
|
||||
if ! use hvm; then
|
||||
echo
|
||||
elog "HVM (VT-x and AMD-V) support has been disabled. If you need hvm"
|
||||
elog "support enable the hvm use flag."
|
||||
elog "An x86 or amd64 multilib system is required to build HVM support."
|
||||
echo
|
||||
elog "The qemu use flag has been removed and replaced with hvm."
|
||||
fi
|
||||
|
||||
if use xend; then
|
||||
echo
|
||||
elog "xend capability has been enabled and installed"
|
||||
fi
|
||||
|
||||
if grep -qsF XENSV= "${ROOT}/etc/conf.d/xend"; then
|
||||
echo
|
||||
elog "xensv is broken upstream (Gentoo bug #142011)."
|
||||
elog "Please remove '${ROOT%/}/etc/conf.d/xend', as it is no longer needed."
|
||||
fi
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
|
||||
# HG changeset patch
|
||||
# User Ian Jackson <Ian.Jackson@eu.citrix.com>
|
||||
# Date 1352892795 0
|
||||
# Node ID 788af5959f692ca16942937055afb09b760f2166
|
||||
# Parent bdb5cde7f79d77f8578bcd8e24d74d09a2c7caa6
|
||||
VCPU/timers: Prevent overflow in calculations, leading to DoS vulnerability
|
||||
|
||||
The timer action for a vcpu periodic timer is to calculate the next
|
||||
expiry time, and to reinsert itself into the timer queue. If the
|
||||
deadline ends up in the past, Xen never leaves __do_softirq(). The
|
||||
affected PCPU will stay in an infinite loop until Xen is killed by the
|
||||
watchdog (if enabled).
|
||||
|
||||
This is a security problem, XSA-20 / CVE-2012-4535.
|
||||
|
||||
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
|
||||
Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
Committed-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
|
||||
xen-unstable changeset: 26148:bf58b94b3cef
|
||||
Backport-requested-by: security@xen.org
|
||||
Committed-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
|
||||
diff -r bdb5cde7f79d -r 788af5959f69 xen/common/domain.c
|
||||
--- xen/common/domain.c Wed Nov 14 10:40:41 2012 +0100
|
||||
+++ xen/common/domain.c Wed Nov 14 11:33:15 2012 +0000
|
||||
@@ -882,6 +882,9 @@ long do_vcpu_op(int cmd, int vcpuid, XEN
|
||||
if ( set.period_ns < MILLISECS(1) )
|
||||
return -EINVAL;
|
||||
|
||||
+ if ( set.period_ns > STIME_DELTA_MAX )
|
||||
+ return -EINVAL;
|
||||
+
|
||||
v->periodic_period = set.period_ns;
|
||||
vcpu_force_reschedule(v);
|
||||
|
||||
diff -r bdb5cde7f79d -r 788af5959f69 xen/include/xen/time.h
|
||||
--- xen/include/xen/time.h Wed Nov 14 10:40:41 2012 +0100
|
||||
+++ xen/include/xen/time.h Wed Nov 14 11:33:15 2012 +0000
|
||||
@@ -55,6 +55,8 @@ struct tm gmtime(unsigned long t);
|
||||
#define MILLISECS(_ms) ((s_time_t)((_ms) * 1000000ULL))
|
||||
#define MICROSECS(_us) ((s_time_t)((_us) * 1000ULL))
|
||||
#define STIME_MAX ((s_time_t)((uint64_t)~0ull>>1))
|
||||
+/* Chosen so (NOW() + delta) wont overflow without an uptime of 200 years */
|
||||
+#define STIME_DELTA_MAX ((s_time_t)((uint64_t)~0ull>>2))
|
||||
|
||||
extern void update_vcpu_system_time(struct vcpu *v);
|
||||
extern void update_domain_wallclock_time(struct domain *d);
|
||||
|
@ -1,50 +0,0 @@
|
||||
# HG changeset patch
|
||||
# User Ian Jackson <Ian.Jackson@eu.citrix.com>
|
||||
# Date 1352893017 0
|
||||
# Node ID 4cffe28427e0c7dbeaa7c109ed393dde0fe026ba
|
||||
# Parent 788af5959f692ca16942937055afb09b760f2166
|
||||
x86/physmap: Prevent incorrect updates of m2p mappings
|
||||
|
||||
In certain conditions, such as low memory, set_p2m_entry() can fail.
|
||||
Currently, the p2m and m2p tables will get out of sync because we still
|
||||
update the m2p table after the p2m update has failed.
|
||||
|
||||
If that happens, subsequent guest-invoked memory operations can cause
|
||||
BUG()s and ASSERT()s to kill Xen.
|
||||
|
||||
This is fixed by only updating the m2p table iff the p2m was
|
||||
successfully updated.
|
||||
|
||||
This is a security problem, XSA-22 / CVE-2012-4537.
|
||||
|
||||
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
|
||||
Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Committed-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
|
||||
xen-unstable changeset: 26149:6b6a4007a609
|
||||
Backport-requested-by: security@xen.org
|
||||
Committed-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
|
||||
diff -r 788af5959f69 -r 4cffe28427e0 xen/arch/x86/mm/p2m.c
|
||||
--- xen/arch/x86/mm/p2m.c Wed Nov 14 11:33:15 2012 +0000
|
||||
+++ xen/arch/x86/mm/p2m.c Wed Nov 14 11:36:57 2012 +0000
|
||||
@@ -654,7 +654,10 @@ guest_physmap_add_entry(struct domain *d
|
||||
if ( mfn_valid(_mfn(mfn)) )
|
||||
{
|
||||
if ( !set_p2m_entry(p2m, gfn, _mfn(mfn), page_order, t, p2m->default_access) )
|
||||
+ {
|
||||
rc = -EINVAL;
|
||||
+ goto out; /* Failed to update p2m, bail without updating m2p. */
|
||||
+ }
|
||||
if ( !p2m_is_grant(t) )
|
||||
{
|
||||
for ( i = 0; i < (1UL << page_order); i++ )
|
||||
@@ -677,6 +680,7 @@ guest_physmap_add_entry(struct domain *d
|
||||
}
|
||||
}
|
||||
|
||||
+out:
|
||||
p2m_unlock(p2m);
|
||||
|
||||
return rc;
|
@ -1,43 +0,0 @@
|
||||
|
||||
# HG changeset patch
|
||||
# User Ian Jackson <Ian.Jackson@eu.citrix.com>
|
||||
# Date 1352893365 0
|
||||
# Node ID 159080b58dda9d19a5d3be42359e667bdb3e61ca
|
||||
# Parent 4cffe28427e0c7dbeaa7c109ed393dde0fe026ba
|
||||
xen/mm/shadow: check toplevel pagetables are present before unhooking them.
|
||||
|
||||
If the guest has not fully populated its top-level PAE entries when it calls
|
||||
HVMOP_pagetable_dying, the shadow code could try to unhook entries from
|
||||
MFN 0. Add a check to avoid that case.
|
||||
|
||||
This issue was introduced by c/s 21239:b9d2db109cf5.
|
||||
|
||||
This is a security problem, XSA-23 / CVE-2012-4538.
|
||||
|
||||
Signed-off-by: Tim Deegan <tim@xen.org>
|
||||
Tested-by: Andrew Cooper <andrew.cooper3@citrix.com>
|
||||
Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
Committed-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
|
||||
xen-unstable changeset: 26150:c7a01b6450e4
|
||||
Backport-requested-by: security@xen.org
|
||||
Committed-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
|
||||
diff -r 4cffe28427e0 -r 159080b58dda xen/arch/x86/mm/shadow/multi.c
|
||||
--- xen/arch/x86/mm/shadow/multi.c Wed Nov 14 11:36:57 2012 +0000
|
||||
+++ xen/arch/x86/mm/shadow/multi.c Wed Nov 14 11:42:45 2012 +0000
|
||||
@@ -4734,8 +4734,12 @@ static void sh_pagetable_dying(struct vc
|
||||
unsigned long gfn;
|
||||
mfn_t smfn, gmfn;
|
||||
|
||||
- if ( fast_path )
|
||||
- smfn = _mfn(pagetable_get_pfn(v->arch.shadow_table[i]));
|
||||
+ if ( fast_path ) {
|
||||
+ if ( pagetable_is_null(v->arch.shadow_table[i]) )
|
||||
+ smfn = _mfn(INVALID_MFN);
|
||||
+ else
|
||||
+ smfn = _mfn(pagetable_get_pfn(v->arch.shadow_table[i]));
|
||||
+ }
|
||||
else
|
||||
{
|
||||
/* retrieving the l2s */
|
@ -1,36 +0,0 @@
|
||||
# HG changeset patch
|
||||
# User Ian Jackson <Ian.Jackson@eu.citrix.com>
|
||||
# Date 1352893567 0
|
||||
# Node ID 8ca6372315f826881f9de141ac1227ef962100cf
|
||||
# Parent 159080b58dda9d19a5d3be42359e667bdb3e61ca
|
||||
compat/gnttab: Prevent infinite loop in compat code
|
||||
|
||||
c/s 20281:95ea2052b41b, which introduces Grant Table version 2
|
||||
hypercalls introduces a vulnerability whereby the compat hypercall
|
||||
handler can fall into an infinite loop.
|
||||
|
||||
If the watchdog is enabled, Xen will die after the timeout.
|
||||
|
||||
This is a security problem, XSA-24 / CVE-2012-4539.
|
||||
|
||||
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
|
||||
Acked-by: Jan Beulich <jbeulich@suse.com>
|
||||
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Committed-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
|
||||
xen-unstable changeset: 26151:b64a7d868f06
|
||||
Backport-requested-by: security@xen.org
|
||||
Committed-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
|
||||
diff -r 159080b58dda -r 8ca6372315f8 xen/common/compat/grant_table.c
|
||||
--- xen/common/compat/grant_table.c Wed Nov 14 11:42:45 2012 +0000
|
||||
+++ xen/common/compat/grant_table.c Wed Nov 14 11:46:07 2012 +0000
|
||||
@@ -318,6 +318,8 @@ int compat_grant_table_op(unsigned int c
|
||||
#undef XLAT_gnttab_get_status_frames_HNDL_frame_list
|
||||
if ( unlikely(__copy_to_guest(cmp_uop, &cmp.get_status, 1)) )
|
||||
rc = -EFAULT;
|
||||
+ else
|
||||
+ i = 1;
|
||||
}
|
||||
break;
|
||||
}
|
@ -1,113 +0,0 @@
|
||||
# HG changeset patch
|
||||
# User Jan Beulich <jbeulich@suse.com>
|
||||
# Date 1354644138 0
|
||||
# Node ID dea7d4e5bfc1627133c0c19706fea1fbc9e5a378
|
||||
# Parent 9e13427c023020756768c73217dab05295709fb3
|
||||
gnttab: fix releasing of memory upon switches between versions
|
||||
|
||||
gnttab_unpopulate_status_frames() incompletely freed the pages
|
||||
previously used as status frame in that they did not get removed from
|
||||
the domain's xenpage_list, thus causing subsequent list corruption
|
||||
when those pages did get allocated again for the same or another purpose.
|
||||
|
||||
Similarly, grant_table_create() and gnttab_grow_table() both improperly
|
||||
clean up in the event of an error - pages already shared with the guest
|
||||
can't be freed by just passing them to free_xenheap_page(). Fix this by
|
||||
sharing the pages only after all allocations succeeded.
|
||||
|
||||
This is CVE-2012-5510 / XSA-26.
|
||||
|
||||
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
||||
Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
Committed-by: Ian Jackson <ian.jackson.citrix.com>
|
||||
|
||||
diff -r 9e13427c0230 -r dea7d4e5bfc1 xen/common/grant_table.c
|
||||
--- xen/common/grant_table.c Thu Nov 29 16:59:43 2012 +0000
|
||||
+++ xen/common/grant_table.c Tue Dec 04 18:02:18 2012 +0000
|
||||
@@ -1173,12 +1173,13 @@ fault:
|
||||
}
|
||||
|
||||
static int
|
||||
-gnttab_populate_status_frames(struct domain *d, struct grant_table *gt)
|
||||
+gnttab_populate_status_frames(struct domain *d, struct grant_table *gt,
|
||||
+ unsigned int req_nr_frames)
|
||||
{
|
||||
unsigned i;
|
||||
unsigned req_status_frames;
|
||||
|
||||
- req_status_frames = grant_to_status_frames(gt->nr_grant_frames);
|
||||
+ req_status_frames = grant_to_status_frames(req_nr_frames);
|
||||
for ( i = nr_status_frames(gt); i < req_status_frames; i++ )
|
||||
{
|
||||
if ( (gt->status[i] = alloc_xenheap_page()) == NULL )
|
||||
@@ -1209,7 +1210,12 @@ gnttab_unpopulate_status_frames(struct d
|
||||
|
||||
for ( i = 0; i < nr_status_frames(gt); i++ )
|
||||
{
|
||||
- page_set_owner(virt_to_page(gt->status[i]), dom_xen);
|
||||
+ struct page_info *pg = virt_to_page(gt->status[i]);
|
||||
+
|
||||
+ BUG_ON(page_get_owner(pg) != d);
|
||||
+ if ( test_and_clear_bit(_PGC_allocated, &pg->count_info) )
|
||||
+ put_page(pg);
|
||||
+ BUG_ON(pg->count_info & ~PGC_xen_heap);
|
||||
free_xenheap_page(gt->status[i]);
|
||||
gt->status[i] = NULL;
|
||||
}
|
||||
@@ -1247,19 +1253,18 @@ gnttab_grow_table(struct domain *d, unsi
|
||||
clear_page(gt->shared_raw[i]);
|
||||
}
|
||||
|
||||
+ /* Status pages - version 2 */
|
||||
+ if (gt->gt_version > 1)
|
||||
+ {
|
||||
+ if ( gnttab_populate_status_frames(d, gt, req_nr_frames) )
|
||||
+ goto shared_alloc_failed;
|
||||
+ }
|
||||
+
|
||||
/* Share the new shared frames with the recipient domain */
|
||||
for ( i = nr_grant_frames(gt); i < req_nr_frames; i++ )
|
||||
gnttab_create_shared_page(d, gt, i);
|
||||
-
|
||||
gt->nr_grant_frames = req_nr_frames;
|
||||
|
||||
- /* Status pages - version 2 */
|
||||
- if (gt->gt_version > 1)
|
||||
- {
|
||||
- if ( gnttab_populate_status_frames(d, gt) )
|
||||
- goto shared_alloc_failed;
|
||||
- }
|
||||
-
|
||||
return 1;
|
||||
|
||||
shared_alloc_failed:
|
||||
@@ -2157,7 +2162,7 @@ gnttab_set_version(XEN_GUEST_HANDLE(gntt
|
||||
|
||||
if ( op.version == 2 && gt->gt_version < 2 )
|
||||
{
|
||||
- res = gnttab_populate_status_frames(d, gt);
|
||||
+ res = gnttab_populate_status_frames(d, gt, nr_grant_frames(gt));
|
||||
if ( res < 0)
|
||||
goto out_unlock;
|
||||
}
|
||||
@@ -2600,14 +2605,15 @@ grant_table_create(
|
||||
clear_page(t->shared_raw[i]);
|
||||
}
|
||||
|
||||
- for ( i = 0; i < INITIAL_NR_GRANT_FRAMES; i++ )
|
||||
- gnttab_create_shared_page(d, t, i);
|
||||
-
|
||||
/* Status pages for grant table - for version 2 */
|
||||
t->status = xzalloc_array(grant_status_t *,
|
||||
grant_to_status_frames(max_nr_grant_frames));
|
||||
if ( t->status == NULL )
|
||||
goto no_mem_4;
|
||||
+
|
||||
+ for ( i = 0; i < INITIAL_NR_GRANT_FRAMES; i++ )
|
||||
+ gnttab_create_shared_page(d, t, i);
|
||||
+
|
||||
t->nr_status_frames = 0;
|
||||
|
||||
/* Okay, install the structure. */
|
||||
|
||||
|
@ -1,56 +0,0 @@
|
||||
|
||||
# HG changeset patch
|
||||
# User Jan Beulich <jbeulich@suse.com>
|
||||
# Date 1354644164 0
|
||||
# Node ID 83ab3cd0f8e44ad588932aba93d3b5f92a888a08
|
||||
# Parent 5771c761ff1bb249dc683d7ec019d76a2a03a048
|
||||
xen: add missing guest address range checks to XENMEM_exchange handlers
|
||||
|
||||
Ever since its existence (3.0.3 iirc) the handler for this has been
|
||||
using non address range checking guest memory accessors (i.e.
|
||||
the ones prefixed with two underscores) without first range
|
||||
checking the accessed space (via guest_handle_okay()), allowing
|
||||
a guest to access and overwrite hypervisor memory.
|
||||
|
||||
This is XSA-29 / CVE-2012-5513.
|
||||
|
||||
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
||||
Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Committed-by: Ian Jackson <ian.jackson.citrix.com>
|
||||
|
||||
diff -r 5771c761ff1b -r 83ab3cd0f8e4 xen/common/compat/memory.c
|
||||
--- a/xen/common/compat/memory.c Tue Dec 04 18:02:38 2012 +0000
|
||||
+++ b/xen/common/compat/memory.c Tue Dec 04 18:02:44 2012 +0000
|
||||
@@ -115,6 +115,12 @@ int compat_memory_op(unsigned int cmd, X
|
||||
(cmp.xchg.out.nr_extents << cmp.xchg.out.extent_order)) )
|
||||
return -EINVAL;
|
||||
|
||||
+ if ( !compat_handle_okay(cmp.xchg.in.extent_start,
|
||||
+ cmp.xchg.in.nr_extents) ||
|
||||
+ !compat_handle_okay(cmp.xchg.out.extent_start,
|
||||
+ cmp.xchg.out.nr_extents) )
|
||||
+ return -EFAULT;
|
||||
+
|
||||
start_extent = cmp.xchg.nr_exchanged;
|
||||
end_extent = (COMPAT_ARG_XLAT_SIZE - sizeof(*nat.xchg)) /
|
||||
(((1U << ABS(order_delta)) + 1) *
|
||||
diff -r 5771c761ff1b -r 83ab3cd0f8e4 xen/common/memory.c
|
||||
--- a/xen/common/memory.c Tue Dec 04 18:02:38 2012 +0000
|
||||
+++ b/xen/common/memory.c Tue Dec 04 18:02:44 2012 +0000
|
||||
@@ -308,6 +308,13 @@ static long memory_exchange(XEN_GUEST_HA
|
||||
goto fail_early;
|
||||
}
|
||||
|
||||
+ if ( !guest_handle_okay(exch.in.extent_start, exch.in.nr_extents) ||
|
||||
+ !guest_handle_okay(exch.out.extent_start, exch.out.nr_extents) )
|
||||
+ {
|
||||
+ rc = -EFAULT;
|
||||
+ goto fail_early;
|
||||
+ }
|
||||
+
|
||||
/* Only privileged guests can allocate multi-page contiguous extents. */
|
||||
if ( !multipage_allocation_permitted(current->domain,
|
||||
exch.in.extent_order) ||
|
||||
|
||||
|
@ -1,56 +0,0 @@
|
||||
xen: fix error handling of guest_physmap_mark_populate_on_demand()
|
||||
|
||||
The only user of the "out" label bypasses a necessary unlock, thus
|
||||
enabling the caller to lock up Xen.
|
||||
|
||||
Also, the function was never meant to be called by a guest for itself,
|
||||
so rather than inspecting the code paths in depth for potential other
|
||||
problems this might cause, and adjusting e.g. the non-guest printk()
|
||||
in the above error path, just disallow the guest access to it.
|
||||
|
||||
Finally, the printk() (considering its potential of spamming the log,
|
||||
the more that it's not using XENLOG_GUEST), is being converted to
|
||||
P2M_DEBUG(), as debugging is what it apparently was added for in the
|
||||
first place.
|
||||
|
||||
This is XSA-30 / CVE-2012-5514.
|
||||
|
||||
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
||||
Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
Acked-by: George Dunlap <george.dunlap@eu.citrix.com>
|
||||
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Committed-by: Ian Jackson <ian.jackson.citrix.com>
|
||||
|
||||
diff -r 83ab3cd0f8e4 -r 09a48c5da636 xen/arch/x86/mm/p2m-pod.c
|
||||
--- xen/arch/x86/mm/p2m-pod.c Tue Dec 04 18:02:44 2012 +0000
|
||||
+++ xen/arch/x86/mm/p2m-pod.c Tue Dec 04 18:02:48 2012 +0000
|
||||
@@ -1117,6 +1117,9 @@ guest_physmap_mark_populate_on_demand(st
|
||||
mfn_t omfn;
|
||||
int rc = 0;
|
||||
|
||||
+ if ( !IS_PRIV_FOR(current->domain, d) )
|
||||
+ return -EPERM;
|
||||
+
|
||||
if ( !paging_mode_translate(d) )
|
||||
return -EINVAL;
|
||||
|
||||
@@ -1135,8 +1138,7 @@ guest_physmap_mark_populate_on_demand(st
|
||||
omfn = p2m->get_entry(p2m, gfn + i, &ot, &a, 0, NULL);
|
||||
if ( p2m_is_ram(ot) )
|
||||
{
|
||||
- printk("%s: gfn_to_mfn returned type %d!\n",
|
||||
- __func__, ot);
|
||||
+ P2M_DEBUG("gfn_to_mfn returned type %d!\n", ot);
|
||||
rc = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
@@ -1160,9 +1162,9 @@ guest_physmap_mark_populate_on_demand(st
|
||||
pod_unlock(p2m);
|
||||
}
|
||||
|
||||
+out:
|
||||
gfn_unlock(p2m, gfn, order);
|
||||
|
||||
-out:
|
||||
return rc;
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
|
||||
# HG changeset patch
|
||||
# User Jan Beulich <jbeulich@suse.com>
|
||||
# Date 1354644172 0
|
||||
# Node ID 2c3f00c5189b9269f9840be93d03f058c8994f6e
|
||||
# Parent 09a48c5da6368ac61bdba5ee09253c2b20d7b577
|
||||
memop: limit guest specified extent order
|
||||
|
||||
Allowing unbounded order values here causes almost unbounded loops
|
||||
and/or partially incomplete requests, particularly in PoD code.
|
||||
|
||||
The added range checks in populate_physmap(), decrease_reservation(),
|
||||
and the "in" one in memory_exchange() architecturally all could use
|
||||
PADDR_BITS - PAGE_SHIFT, and are being artificially constrained to
|
||||
MAX_ORDER.
|
||||
|
||||
This is XSA-31 / CVE-2012-5515.
|
||||
|
||||
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
||||
Acked-by: Tim Deegan <tim@xen.org>
|
||||
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Committed-by: Ian Jackson <ian.jackson.citrix.com>
|
||||
|
||||
diff -r 09a48c5da636 -r 2c3f00c5189b xen/common/memory.c
|
||||
--- xen/common/memory.c Tue Dec 04 18:02:48 2012 +0000
|
||||
+++ xen/common/memory.c Tue Dec 04 18:02:52 2012 +0000
|
||||
@@ -115,7 +115,8 @@ static void populate_physmap(struct memo
|
||||
|
||||
if ( a->memflags & MEMF_populate_on_demand )
|
||||
{
|
||||
- if ( guest_physmap_mark_populate_on_demand(d, gpfn,
|
||||
+ if ( a->extent_order > MAX_ORDER ||
|
||||
+ guest_physmap_mark_populate_on_demand(d, gpfn,
|
||||
a->extent_order) < 0 )
|
||||
goto out;
|
||||
}
|
||||
@@ -235,7 +236,8 @@ static void decrease_reservation(struct
|
||||
xen_pfn_t gmfn;
|
||||
|
||||
if ( !guest_handle_subrange_okay(a->extent_list, a->nr_done,
|
||||
- a->nr_extents-1) )
|
||||
+ a->nr_extents-1) ||
|
||||
+ a->extent_order > MAX_ORDER )
|
||||
return;
|
||||
|
||||
for ( i = a->nr_done; i < a->nr_extents; i++ )
|
||||
@@ -297,6 +299,9 @@ static long memory_exchange(XEN_GUEST_HA
|
||||
if ( (exch.nr_exchanged > exch.in.nr_extents) ||
|
||||
/* Input and output domain identifiers match? */
|
||||
(exch.in.domid != exch.out.domid) ||
|
||||
+ /* Extent orders are sensible? */
|
||||
+ (exch.in.extent_order > MAX_ORDER) ||
|
||||
+ (exch.out.extent_order > MAX_ORDER) ||
|
||||
/* Sizes of input and output lists do not overflow a long? */
|
||||
((~0UL >> exch.in.extent_order) < exch.in.nr_extents) ||
|
||||
((~0UL >> exch.out.extent_order) < exch.out.nr_extents) ||
|
||||
|
||||
|
@ -1,23 +0,0 @@
|
||||
x86: get_page_from_gfn() must return NULL for invalid GFNs
|
||||
|
||||
... also in the non-translated case.
|
||||
|
||||
This is XSA-32 / CVE-2012-xxxx.
|
||||
|
||||
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
||||
Acked-by: Tim Deegan <tim@xen.org>
|
||||
|
||||
diff --git a/xen/include/asm-x86/p2m.h b/xen/include/asm-x86/p2m.h
|
||||
index 28be4e8..907a817 100644
|
||||
--- xen/include/asm-x86/p2m.h
|
||||
+++ xen/include/asm-x86/p2m.h
|
||||
@@ -384,7 +384,7 @@ static inline struct page_info *get_page_from_gfn(
|
||||
if (t)
|
||||
*t = p2m_ram_rw;
|
||||
page = __mfn_to_page(gfn);
|
||||
- return get_page(page, d) ? page : NULL;
|
||||
+ return mfn_valid(gfn) && get_page(page, d) ? page : NULL;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,211 +0,0 @@
|
||||
commit 66141b2e068fa39f28bdda6be05882e323663687
|
||||
Author: Michael Young
|
||||
Date: Tue Jan 22 22:22:10 2013 +0000
|
||||
|
||||
Security fix from nested virtualization CVE-2013-0151,
|
||||
restore status option to xend which is used by libvirt
|
||||
#diff --git a/xsa34-4.2.patch b/xsa34-4.2.patch
|
||||
#new file mode 100644
|
||||
#index 0000000..f5328ef
|
||||
#--- /dev/null
|
||||
#+++ xsa34-4.2.patch
|
||||
#@@ -0,0 +1,30 @@
|
||||
#+x86_32: don't allow use of nested HVM
|
||||
#+
|
||||
#+There are (indirect) uses of map_domain_page() in the nested HVM code
|
||||
#+that are unsafe when not just using the 1:1 mapping.
|
||||
#+
|
||||
#+This is XSA-34 / CVE-2013-0151.
|
||||
#+
|
||||
#+Signed-off-by: Jan Beulich
|
||||
#+
|
||||
#diff --git a/xsa35-4.2-with-xsa34.patch b/xsa35-4.2-with-xsa34.patch
|
||||
#new file mode 100644
|
||||
#index 0000000..28c6171
|
||||
#--- /dev/null
|
||||
#+++ xsa35-4.2-with-xsa34.patch
|
||||
#@@ -0,0 +1,24 @@
|
||||
#+xen: Do not allow guests to enable nested HVM on themselves
|
||||
#+
|
||||
#+There is no reason for this and doing so exposes a memory leak to
|
||||
#+guests. Only toolstacks need write access to this HVM param.
|
||||
#+
|
||||
#+This is XSA-35 / CVE-2013-0152.
|
||||
#+
|
||||
#+Signed-off-by: Ian Campbell
|
||||
#+Acked-by: Jan Beulich
|
||||
#+
|
||||
--- xen/arch/x86/hvm/hvm.c
|
||||
+++ xen/arch/x86/hvm/hvm.c
|
||||
@@ -3858,6 +3858,11 @@
|
||||
rc = -EINVAL;
|
||||
break;
|
||||
case HVM_PARAM_NESTEDHVM:
|
||||
+ if ( !IS_PRIV(current->domain) )
|
||||
+ {
|
||||
+ rc = -EPERM;
|
||||
+ break;
|
||||
+ }
|
||||
if ( a.value > 1 )
|
||||
rc = -EINVAL;
|
||||
if ( !is_hvm_domain(d) )
|
||||
@@ -3926,6 +3926,10 @@ long do_hvm_op(unsigned long op, XEN_GUE
|
||||
rc = -EINVAL;
|
||||
break;
|
||||
case HVM_PARAM_NESTEDHVM:
|
||||
+#ifdef __i386__
|
||||
+ if ( a.value )
|
||||
+ rc = -EINVAL;
|
||||
+#else
|
||||
if ( a.value > 1 )
|
||||
rc = -EINVAL;
|
||||
if ( !is_hvm_domain(d) )
|
||||
@@ -3940,6 +3944,7 @@ long do_hvm_op(unsigned long op, XEN_GUE
|
||||
for_each_vcpu(d, v)
|
||||
if ( rc == 0 )
|
||||
rc = nestedhvm_vcpu_initialise(v);
|
||||
+#endif
|
||||
break;
|
||||
case HVM_PARAM_BUFIOREQ_EVTCHN:
|
||||
rc = -EINVAL;
|
||||
# HG changeset patch
|
||||
# User Tim Deegan <tim@xen.org>
|
||||
# Date 1354644158 0
|
||||
# Node ID 5771c761ff1bb249dc683d7ec019d76a2a03a048
|
||||
# Parent dea7d4e5bfc1627133c0c19706fea1fbc9e5a378
|
||||
#hvm: Limit the size of large HVM op batches
|
||||
#
|
||||
#Doing large p2m updates for HVMOP_track_dirty_vram without preemption
|
||||
#ties up the physical processor. Integrating preemption into the p2m
|
||||
#updates is hard so simply limit to 1GB which is sufficient for a 15000
|
||||
#* 15000 * 32bpp framebuffer.
|
||||
#
|
||||
#For HVMOP_modified_memory and HVMOP_set_mem_type preemptible add the
|
||||
#necessary machinery to handle preemption.
|
||||
#
|
||||
#This is CVE-2012-5511 / XSA-27.
|
||||
#
|
||||
#Signed-off-by: Tim Deegan <tim@xen.org>
|
||||
#Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
#Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
#Committed-by: Ian Jackson <ian.jackson.citrix.com>
|
||||
#
|
||||
#v2: Provide definition of GB to fix x86-32 compile.
|
||||
#
|
||||
#Signed-off-by: Jan Beulich <JBeulich@suse.com>
|
||||
#Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
diff -r dea7d4e5bfc1 -r 5771c761ff1b xen/arch/x86/hvm/hvm.c
|
||||
--- xen/arch/x86/hvm/hvm.c Tue Dec 04 18:02:18 2012 +0000
|
||||
+++ xen/arch/x86/hvm/hvm.c Tue Dec 04 18:02:38 2012 +0000
|
||||
@@ -3969,6 +3969,9 @@ long do_hvm_op(unsigned long op, XEN_GUE
|
||||
if ( !is_hvm_domain(d) )
|
||||
goto param_fail2;
|
||||
|
||||
+ if ( a.nr > GB(1) >> PAGE_SHIFT )
|
||||
+ goto param_fail2;
|
||||
+
|
||||
rc = xsm_hvm_param(d, op);
|
||||
if ( rc )
|
||||
goto param_fail2;
|
||||
@@ -3995,7 +3998,6 @@ long do_hvm_op(unsigned long op, XEN_GUE
|
||||
{
|
||||
struct xen_hvm_modified_memory a;
|
||||
struct domain *d;
|
||||
- unsigned long pfn;
|
||||
|
||||
if ( copy_from_guest(&a, arg, 1) )
|
||||
return -EFAULT;
|
||||
@@ -4022,9 +4024,11 @@ long do_hvm_op(unsigned long op, XEN_GUE
|
||||
if ( !paging_mode_log_dirty(d) )
|
||||
goto param_fail3;
|
||||
|
||||
- for ( pfn = a.first_pfn; pfn < a.first_pfn + a.nr; pfn++ )
|
||||
+ while ( a.nr > 0 )
|
||||
{
|
||||
+ unsigned long pfn = a.first_pfn;
|
||||
struct page_info *page;
|
||||
+
|
||||
page = get_page_from_gfn(d, pfn, NULL, P2M_UNSHARE);
|
||||
if ( page )
|
||||
{
|
||||
@@ -4034,6 +4038,19 @@ long do_hvm_op(unsigned long op, XEN_GUE
|
||||
sh_remove_shadows(d->vcpu[0], _mfn(page_to_mfn(page)), 1, 0);
|
||||
put_page(page);
|
||||
}
|
||||
+
|
||||
+ a.first_pfn++;
|
||||
+ a.nr--;
|
||||
+
|
||||
+ /* Check for continuation if it's not the last interation */
|
||||
+ if ( a.nr > 0 && hypercall_preempt_check() )
|
||||
+ {
|
||||
+ if ( copy_to_guest(arg, &a, 1) )
|
||||
+ rc = -EFAULT;
|
||||
+ else
|
||||
+ rc = -EAGAIN;
|
||||
+ break;
|
||||
+ }
|
||||
}
|
||||
|
||||
param_fail3:
|
||||
@@ -4089,7 +4106,6 @@ long do_hvm_op(unsigned long op, XEN_GUE
|
||||
{
|
||||
struct xen_hvm_set_mem_type a;
|
||||
struct domain *d;
|
||||
- unsigned long pfn;
|
||||
|
||||
/* Interface types to internal p2m types */
|
||||
p2m_type_t memtype[] = {
|
||||
@@ -4122,8 +4138,9 @@ long do_hvm_op(unsigned long op, XEN_GUE
|
||||
if ( a.hvmmem_type >= ARRAY_SIZE(memtype) )
|
||||
goto param_fail4;
|
||||
|
||||
- for ( pfn = a.first_pfn; pfn < a.first_pfn + a.nr; pfn++ )
|
||||
+ while ( a.nr )
|
||||
{
|
||||
+ unsigned long pfn = a.first_pfn;
|
||||
p2m_type_t t;
|
||||
p2m_type_t nt;
|
||||
mfn_t mfn;
|
||||
@@ -4163,6 +4180,19 @@ long do_hvm_op(unsigned long op, XEN_GUE
|
||||
}
|
||||
}
|
||||
put_gfn(d, pfn);
|
||||
+
|
||||
+ a.first_pfn++;
|
||||
+ a.nr--;
|
||||
+
|
||||
+ /* Check for continuation if it's not the last interation */
|
||||
+ if ( a.nr > 0 && hypercall_preempt_check() )
|
||||
+ {
|
||||
+ if ( copy_to_guest(arg, &a, 1) )
|
||||
+ rc = -EFAULT;
|
||||
+ else
|
||||
+ rc = -EAGAIN;
|
||||
+ goto param_fail4;
|
||||
+ }
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
diff -r dea7d4e5bfc1 -r 5771c761ff1b xen/include/asm-x86/config.h
|
||||
--- xen/include/asm-x86/config.h Tue Dec 04 18:02:18 2012 +0000
|
||||
+++ xen/include/asm-x86/config.h Tue Dec 04 18:02:38 2012 +0000
|
||||
@@ -119,6 +119,9 @@ extern char wakeup_start[];
|
||||
extern unsigned int video_mode, video_flags;
|
||||
extern unsigned short boot_edid_caps;
|
||||
extern unsigned char boot_edid_info[128];
|
||||
+
|
||||
+#define GB(_gb) (_gb ## UL << 30)
|
||||
+
|
||||
#endif
|
||||
|
||||
#define asmlinkage
|
||||
@@ -134,7 +137,6 @@ extern unsigned char boot_edid_info[128]
|
||||
#define PML4_ADDR(_slot) \
|
||||
((((_slot ## UL) >> 8) * 0xffff000000000000UL) | \
|
||||
(_slot ## UL << PML4_ENTRY_BITS))
|
||||
-#define GB(_gb) (_gb ## UL << 30)
|
||||
#else
|
||||
#define PML4_ENTRY_BYTES (1 << PML4_ENTRY_BITS)
|
||||
#define PML4_ADDR(_slot) \
|
||||
|
@ -1,31 +0,0 @@
|
||||
defer event channel bucket pointer store until after XSM checks
|
||||
|
||||
Otherwise a dangling pointer can be left, which would cause subsequent
|
||||
memory corruption as soon as the space got re-allocated for some other
|
||||
purpose.
|
||||
|
||||
This is CVE-2013-1920 / XSA-47.
|
||||
|
||||
Reported-by: Wei Liu <wei.liu2@citrix.com>
|
||||
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
||||
Reviewed-by: Tim Deegan <tim@xen.org>
|
||||
|
||||
--- a/xen/common/event_channel.c
|
||||
+++ b/xen/common/event_channel.c
|
||||
@@ -140,7 +140,6 @@ static int get_free_port(struct domain *
|
||||
chn = xzalloc_array(struct evtchn, EVTCHNS_PER_BUCKET);
|
||||
if ( unlikely(chn == NULL) )
|
||||
return -ENOMEM;
|
||||
- bucket_from_port(d, port) = chn;
|
||||
|
||||
for ( i = 0; i < EVTCHNS_PER_BUCKET; i++ )
|
||||
{
|
||||
@@ -153,6 +152,8 @@ static int get_free_port(struct domain *
|
||||
}
|
||||
}
|
||||
|
||||
+ bucket_from_port(d, port) = chn;
|
||||
+
|
||||
return port;
|
||||
}
|
||||
|
@ -1,74 +0,0 @@
|
||||
|
||||
# HG changeset patch
|
||||
# User Tim Deegan <Tim.Deegan@citrix.com>
|
||||
# Date 1313145221 -3600
|
||||
# Node ID 84e3706df07a1963e23cd3875d8603917657d462
|
||||
# Parent cb22fa57ff252893b6adb1481e09b1287eacd990
|
||||
Passthrough: disable bus-mastering on any card that causes an IOMMU fault.
|
||||
|
||||
This stops the card from raising back-to-back faults and live-locking
|
||||
the CPU that handles them.
|
||||
|
||||
Signed-off-by: Tim Deegan <tim@xen.org>
|
||||
Acked-by: Wei Wang2 <wei.wang2@amd.com>
|
||||
Acked-by: Allen M Kay <allen.m.kay@intel.com>
|
||||
|
||||
diff -r cb22fa57ff25 -r 84e3706df07a xen/drivers/passthrough/amd/iommu_init.c
|
||||
--- a/xen/drivers/passthrough/amd/iommu_init.c Mon Jul 25 16:48:39 2011 +0100
|
||||
+++ b/xen/drivers/passthrough/amd/iommu_init.c Fri Aug 12 11:33:41 2011 +0100
|
||||
@@ -462,7 +462,7 @@
|
||||
|
||||
static void parse_event_log_entry(u32 entry[])
|
||||
{
|
||||
- u16 domain_id, device_id;
|
||||
+ u16 domain_id, device_id, bdf, cword;
|
||||
u32 code;
|
||||
u64 *addr;
|
||||
char * event_str[] = {"ILLEGAL_DEV_TABLE_ENTRY",
|
||||
@@ -497,6 +497,18 @@
|
||||
"%s: domain = %d, device id = 0x%04x, "
|
||||
"fault address = 0x%"PRIx64"\n",
|
||||
event_str[code-1], domain_id, device_id, *addr);
|
||||
+
|
||||
+ /* Tell the device to stop DMAing; we can't rely on the guest to
|
||||
+ * control it for us. */
|
||||
+ for ( bdf = 0; bdf < ivrs_bdf_entries; bdf++ )
|
||||
+ if ( get_dma_requestor_id(bdf) == device_id )
|
||||
+ {
|
||||
+ cword = pci_conf_read16(PCI_BUS(bdf), PCI_SLOT(bdf),
|
||||
+ PCI_FUNC(bdf), PCI_COMMAND);
|
||||
+ pci_conf_write16(PCI_BUS(bdf), PCI_SLOT(bdf),
|
||||
+ PCI_FUNC(bdf), PCI_COMMAND,
|
||||
+ cword & ~PCI_COMMAND_MASTER);
|
||||
+ }
|
||||
}
|
||||
else
|
||||
{
|
||||
diff -r cb22fa57ff25 -r 84e3706df07a xen/drivers/passthrough/vtd/iommu.c
|
||||
--- a/xen/drivers/passthrough/vtd/iommu.c Mon Jul 25 16:48:39 2011 +0100
|
||||
+++ b/xen/drivers/passthrough/vtd/iommu.c Fri Aug 12 11:33:41 2011 +0100
|
||||
@@ -893,7 +893,7 @@
|
||||
while (1)
|
||||
{
|
||||
u8 fault_reason;
|
||||
- u16 source_id;
|
||||
+ u16 source_id, cword;
|
||||
u32 data;
|
||||
u64 guest_addr;
|
||||
int type;
|
||||
@@ -926,6 +926,14 @@
|
||||
iommu_page_fault_do_one(iommu, type, fault_reason,
|
||||
source_id, guest_addr);
|
||||
|
||||
+ /* Tell the device to stop DMAing; we can't rely on the guest to
|
||||
+ * control it for us. */
|
||||
+ cword = pci_conf_read16(PCI_BUS(source_id), PCI_SLOT(source_id),
|
||||
+ PCI_FUNC(source_id), PCI_COMMAND);
|
||||
+ pci_conf_write16(PCI_BUS(source_id), PCI_SLOT(source_id),
|
||||
+ PCI_FUNC(source_id), PCI_COMMAND,
|
||||
+ cword & ~PCI_COMMAND_MASTER);
|
||||
+
|
||||
fault_index++;
|
||||
if ( fault_index > cap_num_fault_regs(iommu->cap) )
|
||||
fault_index = 0;
|
||||
|
@ -0,0 +1,28 @@
|
||||
# Copyright 1999-2013 Gentoo Foundation
|
||||
# Distributed under the terms of the GNU General Public License v2
|
||||
# $Header: /var/cvsroot/gentoo-x86/app-i18n/man-pages-ru/man-pages-ru-3.51.2170.1766.20130613.ebuild,v 1.1 2013/06/26 18:49:42 pinkbyte Exp $
|
||||
|
||||
EAPI="5"
|
||||
|
||||
inherit versionator
|
||||
|
||||
MY_PV="$(replace_version_separator 1 . $(replace_all_version_separators -))"
|
||||
|
||||
DESCRIPTION="A collection of Russian translations of Linux manual pages"
|
||||
HOMEPAGE="http://man-pages-ru.sourceforge.net/"
|
||||
SRC_URI="mirror://sourceforge/${PN}/${PN}_${MY_PV}.tar.bz2"
|
||||
|
||||
LICENSE="FDL-1.3"
|
||||
SLOT="0"
|
||||
KEYWORDS="~alpha ~amd64 ~arm ~hppa ~ia64 ~m68k ~mips ~ppc ~ppc64 ~s390 ~sh ~sparc ~x86 ~amd64-linux ~x86-linux"
|
||||
|
||||
DEPEND=""
|
||||
RDEPEND="virtual/man"
|
||||
|
||||
S="${WORKDIR}/${PN}_${MY_PV}"
|
||||
|
||||
src_install() {
|
||||
insinto /usr/share/man/ru
|
||||
doins -r man*
|
||||
dodoc README
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue