Sync with portage [Thu Jun 27 00:47:54 MSK 2013].

mhiretskiy
root 11 years ago
parent 0f27d023e0
commit a2f65af846

@ -1,6 +1,6 @@
# Copyright 1999-2013 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: /var/cvsroot/gentoo-x86/app-admin/logrotate/logrotate-3.8.4.ebuild,v 1.8 2013/06/26 08:52:51 ago Exp $
# $Header: /var/cvsroot/gentoo-x86/app-admin/logrotate/logrotate-3.8.4.ebuild,v 1.9 2013/06/26 11:56:30 ago Exp $
EAPI=5
@ -12,7 +12,7 @@ SRC_URI="https://fedorahosted.org/releases/l/o/logrotate/${P}.tar.gz"
LICENSE="GPL-2"
SLOT="0"
KEYWORDS="alpha amd64 ~arm hppa ia64 ppc ppc64 ~s390 ~sh ~sparc x86 ~amd64-fbsd ~x86-fbsd"
KEYWORDS="alpha amd64 arm hppa ia64 ppc ppc64 ~s390 ~sh ~sparc x86 ~amd64-fbsd ~x86-fbsd"
IUSE="acl selinux"
RDEPEND="

@ -1,6 +1,6 @@
# Copyright 1999-2013 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: /var/cvsroot/gentoo-x86/app-arch/dpkg/dpkg-1.16.10.ebuild,v 1.10 2013/06/26 08:52:30 ago Exp $
# $Header: /var/cvsroot/gentoo-x86/app-arch/dpkg/dpkg-1.16.10.ebuild,v 1.11 2013/06/26 12:00:57 ago Exp $
EAPI=4
inherit eutils multilib autotools toolchain-funcs
@ -11,7 +11,7 @@ SRC_URI="mirror://debian/pool/main/d/${PN}/${P/-/_}.tar.xz"
LICENSE="GPL-2"
SLOT="0"
KEYWORDS="alpha amd64 ~arm hppa ia64 ~m68k ppc ppc64 ~s390 ~sh ~sparc x86 ~amd64-linux ~ia64-linux ~x86-linux ~ppc-macos ~x64-solaris ~x86-solaris"
KEYWORDS="alpha amd64 arm hppa ia64 ~m68k ppc ppc64 ~s390 ~sh ~sparc x86 ~amd64-linux ~ia64-linux ~x86-linux ~ppc-macos ~x64-solaris ~x86-solaris"
IUSE="bzip2 dselect nls test unicode zlib"
LANGS="

@ -1,6 +1,6 @@
# Copyright 1999-2013 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: /var/cvsroot/gentoo-x86/app-crypt/loop-aes-losetup/loop-aes-losetup-2.21.ebuild,v 1.2 2013/06/13 19:58:01 nimiux Exp $
# $Header: /var/cvsroot/gentoo-x86/app-crypt/loop-aes-losetup/loop-aes-losetup-2.21.ebuild,v 1.3 2013/06/26 11:53:51 ago Exp $
EAPI="4"
@ -16,7 +16,7 @@ DESCRIPTION="Various useful Linux utilities"
HOMEPAGE="http://www.kernel.org/pub/linux/utils/util-linux/"
SRC_URI="mirror://kernel/linux/utils/util-linux/v${PV:0:4}/${MY_P}.tar.xz
http://loop-aes.sourceforge.net/updates/util-linux-${LOOPAES_PV}.diff.bz2"
KEYWORDS="~alpha amd64 ~arm ~hppa ~ia64 ~m68k ~mips ~ppc ~ppc64 ~s390 ~sh ~sparc ~x86 ~x86-linux"
KEYWORDS="~alpha amd64 arm ~hppa ~ia64 ~m68k ~mips ~ppc ~ppc64 ~s390 ~sh ~sparc ~x86 ~x86-linux"
LICENSE="GPL-2 GPL-3 LGPL-2.1 BSD-4 MIT public-domain"
SLOT="0"

@ -1,6 +1,6 @@
# 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-r1.ebuild,v 1.1 2013/06/04 12:21:06 scarabeus Exp $
# $Header: /var/cvsroot/gentoo-x86/app-doc/doxygen/doxygen-1.8.4-r2.ebuild,v 1.1 2013/06/26 10:58:45 xarthisius Exp $
EAPI=4
@ -108,8 +108,9 @@ src_prepare() {
epatch "${FILESDIR}"/${PN}-1.8.1-prefix-misc-alt.patch
epatch "${FILESDIR}"/${PN}-1.8.3.1-empty-line-sigsegv.patch #454348
# patch applied upstream
epatch ""${FILESDIR}"/${P}-libreoffice.patch"
# patches applied upstream
epatch "${FILESDIR}"/${P}-libreoffice.patch \
"${FILESDIR}"/${P}-infinite_loop.patch #474716
# fix final DESTDIR issue
sed -i.orig -e "s:\$(INSTALL):\$(DESTDIR)/\$(INSTALL):g" \

@ -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,6 +1,6 @@
# Copyright 1999-2013 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: /var/cvsroot/gentoo-x86/app-editors/hexedit/hexedit-1.2.13.ebuild,v 1.5 2013/06/26 03:01:04 ago Exp $
# $Header: /var/cvsroot/gentoo-x86/app-editors/hexedit/hexedit-1.2.13.ebuild,v 1.7 2013/06/26 12:01:16 ago Exp $
DESCRIPTION="View and edit files in hex or ASCII"
HOMEPAGE="http://rigaux.org/hexedit.html"
@ -8,7 +8,7 @@ SRC_URI="http://rigaux.org/${P}.src.tgz"
LICENSE="GPL-2"
SLOT="0"
KEYWORDS="alpha amd64 ~arm ~hppa ~mips ~ppc ppc64 ~s390 ~sh ~sparc x86 ~x86-interix ~amd64-linux ~x86-linux ~ppc-macos ~x86-macos ~sparc-solaris ~x86-solaris"
KEYWORDS="alpha amd64 arm hppa ~mips ~ppc ppc64 ~s390 ~sh ~sparc x86 ~x86-interix ~amd64-linux ~x86-linux ~ppc-macos ~x86-macos ~sparc-solaris ~x86-solaris"
IUSE=""
DEPEND="sys-libs/ncurses"

@ -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

@ -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

@ -2,7 +2,6 @@ DIST grub-0.97.tar.gz 971783 SHA256 4e1d15d12dbd3e9208111d6b806ad5a9857ca8850c47
DIST lwip-1.3.0.tar.gz 398933 SHA256 772e4d550e07826665ed0528c071dd5404ef7dbe1825a38c8adbc2a00bca948f SHA512 1465b58279af1647f909450e394fe002ca165f0ff4a0254bfa9fe0e64316f50facdde2729d79a4e632565b4500cf4d6c74192ac0dd3bc9fe09129bbd67ba089d WHIRLPOOL 63bdd9eb70f168ba2006a8f4bbe166b68528abe8364b23cdc1d468ccc4b137bb3447bf90695920f016e09d53d3b93ccf6e3697b3c46840f00b794789cb424acc
DIST newlib-1.16.0.tar.gz 12024353 SHA256 db426394965c48c1d29023e1cc6d965ea6b9a9035d8a849be2750ca4659a3d07 SHA512 40eb96bbc6736a16b6399e0cdb73e853d0d90b685c967e77899183446664d64570277a633fdafdefc351b46ce210a99115769a1d9f47ac749d7e82837d4d1ac3 WHIRLPOOL 47f7afd525f482d79d9e964f0e75ee8a77e59551bd19cd94f9b95ac3af9406afa381c9d8d224f76eb568441ab613b2b194f8e5be50aa222f9ed2d9b9761829db
DIST pciutils-2.2.9.tar.bz2 212265 SHA256 f60ae61cfbd5da1d849d0beaa21f593c38dac9359f0b3ddc612f447408265b24 SHA512 2b3d98d027e46d8c08037366dde6f0781ca03c610ef2b380984639e4ef39899ed8d8b8e4cd9c9dc54df101279b95879bd66bfd4d04ad07fef41e847ea7ae32b5 WHIRLPOOL ce801947fcf7ba0b56710029f25e746d3e03a80699af9d3570efcd417b12b546264f286b2e78b1402cca766c08e35bdd0ff0a692ab4ad419295f00bcfe91130e
DIST xen-4.2.0.tar.gz 15587687 SHA256 43f4a086e4e0330145a27b7ace8365c42b5afbc95cefadafe067be91bd3e5cfb SHA512 4fb56c79d722fb307bc657f16d02079c6636427e7650c4354193632d38d2d1db8e588f844ff0ca6e757c108ed639a528565ec9fc7c00bb4d5b6fbc9d122d8a70 WHIRLPOOL 369a109375864cb61920b56cf501522051d28513e738f0fd0e7b76244c3e08a8a0a6ff6cf245872d9bbd9c0f22c7da76c9cbc0f852bad6108ca25fd42dc677c0
DIST xen-4.2.1.tar.gz 15593695 SHA256 fb8df5827ce3e2d2d3b078d9e5afde502beb5e7ab9442e51a94087061bd450c6 SHA512 fe27a965e2b34035bd025482eda9fc4d4e82523c929323fd30813367d5ffbe2fa1ed3d7d4479f2632e8b5625972448b7bd6a7768e8dc1dcd1b6747d281cc1a9e WHIRLPOOL 226bbed059541e804f1a44e721023ffbc04bae43000653b1d7d6a9bfec0d9efbf7a48b1b0a7ad3fcb8e34f8b91e1c620c2a8eddf97baad487e9db37d49a58f37
DIST xen-4.2.2.tar.gz 15602746 SHA256 c9bfe91a5e72f8545acebad9889d64368020359bfe18044c0e683133e55ae005 SHA512 4943b18016ed8c2b194a3b55e6655b3b734b39ffb8cb7ee0a0580f2f4460a1d0e92e1de8ac23f5186272914fad1650586af51fd7c3644d0310eb16f2e11c5e80 WHIRLPOOL 519eb87cb2da694696cbc3e72070a0a3bdb07c46fa266d855d8379eec3a92adfa4d434af3ac01c37834ce4a9174081a6c40030b185a70902329b185cb8d0bbea
DIST zlib-1.2.3.tar.gz 496597 SHA256 1795c7d067a43174113fdf03447532f373e1c6c57c08d61d9e4e9be5e244b05e SHA512 021b958fcd0d346c4ba761bcf0cc40f3522de6186cf5a0a6ea34a70504ce9622b1c2626fce40675bc8282cf5f5ade18473656abc38050f72f5d6480507a2106e WHIRLPOOL 8fd7010faf6a48a9c7ff4bcfe3ce4fe9061eb541259e0a2d0def214e8c4becf2b22e8d6f96f65ca827abffeaa9d96e95ed2402844f99835f7b079fc9f3e84276

@ -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

@ -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,6 +1,6 @@
# 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.0-r1.ebuild,v 1.5 2013/02/19 19:18:02 idella4 Exp $
# $Header: /var/cvsroot/gentoo-x86/app-emulation/xen-pvgrub/xen-pvgrub-4.2.1-r3.ebuild,v 1.1 2013/06/26 16:16:38 idella4 Exp $
EAPI=4
PYTHON_DEPEND="2:2.6"
@ -24,12 +24,12 @@ DESCRIPTION="allows to boot Xen domU kernels from a menu.lst laying inside guest
HOMEPAGE="http://xen.org/"
LICENSE="GPL-2"
SLOT="0"
KEYWORDS="amd64 x86"
KEYWORDS="~amd64 ~x86"
IUSE="custom-cflags"
DEPEND="sys-devel/gettext"
RDEPEND=">=app-emulation/xen-4.2.0"
DEPEND="sys-devel/gettext
dev-libs/yajl"
RDEPEND=">=app-emulation/xen-4.2.1"
pkg_setup() {
python_set_active_version 2
@ -71,10 +71,6 @@ src_prepare() {
-i {} \;
fi
#Substitute for internal downloading
cp $DISTDIR/pciutils-2.2.9.tar.bz2 ./stubdom/ || die "pciutils not coped to stubdom"
einfo "files copied to stubdom"
# Patch the unmergeable newlib, fix most of the leftover gcc QA issues
cp "${FILESDIR}"/newlib-implicits.patch stubdom || die
@ -88,7 +84,26 @@ src_prepare() {
epatch "${FILESDIR}"/${PN/-pvgrub/}-4.2.0-jserver.patch
#Sec patch
epatch "${FILESDIR}"/${PN/-pvgrub/}-4-CVE-2012-4544-XSA-25.patch
epatch "${FILESDIR}"/${PN/-pvgrub/}-4-CVE-2012-6075-XSA-41.patch \
"${FILESDIR}"/xen-4-CVE-2013-0215-XSA-38.patch \
"${FILESDIR}"/xen-4-CVE-2013-1919-XSA-46.patch \
"${FILESDIR}"/xen-4-CVE-2013-1922-XSA-48.patch \
"${FILESDIR}"/xen-4-CVE-2013-1952-XSA_49.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-1-XSA-55.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-2-XSA-55.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-3-XSA-55.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-4-XSA-55.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-5to7-XSA-55.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-8-XSA-55.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-9to10-XSA-55.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-11-XSA-55.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-12to13-XSA-55.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-14-XSA-55.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-15-XSA-55.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-16-XSA-55.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-17-XSA-55.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-18to19-XSA-55.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-20to23-XSA-55.patch
#Substitute for internal downloading. pciutils copied only due to the only .bz2
cp $DISTDIR/pciutils-2.2.9.tar.bz2 ./stubdom/ || die "pciutils not copied to stubdom"
@ -103,16 +118,15 @@ src_compile() {
emake CC="$(tc-getCC)" LD="$(tc-getLD)" AR="$(tc-getAR)" -C tools/include
# TODO; fix those -j1
if use x86; then
emake -j1 CC="$(tc-getCC)" LD="$(tc-getLD)" AR="$(tc-getAR)" \
emake CC="$(tc-getCC)" LD="$(tc-getLD)" AR="$(tc-getAR)" \
XEN_TARGET_ARCH="x86_32" -C stubdom pv-grub
elif use amd64; then
emake -j1 CC="$(tc-getCC)" LD="$(tc-getLD)" AR="$(tc-getAR)" \
emake CC="$(tc-getCC)" LD="$(tc-getLD)" AR="$(tc-getAR)" \
XEN_TARGET_ARCH="x86_64" -C stubdom pv-grub
if use multilib; then
multilib_toolchain_setup x86
emake -j1 CC="$(tc-getCC)" AR="$(tc-getAR)" \
emake CC="$(tc-getCC)" AR="$(tc-getAR)" \
XEN_TARGET_ARCH="x86_32" -C stubdom pv-grub
fi
fi

@ -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,6 +1,6 @@
# 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-r1.ebuild,v 1.4 2013/02/19 20:20:56 idella4 Exp $
# $Header: /var/cvsroot/gentoo-x86/app-emulation/xen-pvgrub/xen-pvgrub-4.2.2-r1.ebuild,v 1.1 2013/06/26 16:16:38 idella4 Exp $
EAPI=4
PYTHON_DEPEND="2:2.6"
@ -75,7 +75,7 @@ src_prepare() {
cp "${FILESDIR}"/newlib-implicits.patch stubdom || die
# Patch stubdom/Makefile to patch insource newlib & prevent internal downloading
epatch "${FILESDIR}"/${P/-pvgrub/}-externals.patch
epatch "${FILESDIR}"/${PN/-pvgrub/}-4.2.1-externals.patch
# Drop .config and Fix gcc-4.6
epatch "${FILESDIR}"/${PN/-pvgrub/}-4-fix_dotconfig-gcc.patch
@ -83,8 +83,25 @@ src_prepare() {
# fix jobserver in Makefile
epatch "${FILESDIR}"/${PN/-pvgrub/}-4.2.0-jserver.patch
#Sec patch
epatch "${FILESDIR}"/${PN/-pvgrub/}-4-CVE-2012-6075-XSA-41.patch
# Sec patch
epatch "${FILESDIR}"/${PN/-pvgrub/}-4-CVE-2012-6075-XSA-41.patch \
"${FILESDIR}"/xen-4-CVE-2013-1922-XSA-48.patch \
"${FILESDIR}"/xen-4-CVE-2013-1952-XSA-49.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-1-XSA-55.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-2-XSA-55.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-3-XSA-55.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-4-XSA-55.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-5to7-XSA-55.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-8-XSA-55.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-9to10-XSA-55.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-11-XSA-55.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-12to13-XSA-55.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-14-XSA-55.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-15-XSA-55.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-16-XSA-55.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-17-XSA-55.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-18to19-XSA-55.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-20to23-XSA-55.patch \
#Substitute for internal downloading. pciutils copied only due to the only .bz2
cp $DISTDIR/pciutils-2.2.9.tar.bz2 ./stubdom/ || die "pciutils not copied to stubdom"

@ -1,5 +1,4 @@
DIST ipxe.tar.gz 2867999 SHA256 632ce8c193ccacc3012bd354bdb733a4be126f7c098e111930aa41dad537405c SHA512 c5cb1cdff40d2d71fd3e692a9d0efadf2aa17290daf5195391a1c81ddd9dfc913a8e44d5be2b12be85b2a5565ea31631c99c7053564f2fb2225c80ea0bb0e4a4 WHIRLPOOL 58b7459aaf7323968e2f4d1cdcb563a04a0ee40d7d0e8fc600495baf6914127fbbbcddfb66199cd9f462eb59565b3d1ae90a05b3c771b8f13c2d2dcb6070eebc
DIST seabios-0-20121121.tar.bz2 2199282 SHA256 f7f67181c6c0b4cea3a9db48e2569fdcbbc81b732a2f672079c42fb44153ee62 SHA512 4f886088ebaa911590b8cb19db5c5dbc8f1384d2d5a7c4bf04df083e177513b3123b1839dad744171670eded8b69ce092a774288aec1804d00aa32b1b6778599 WHIRLPOOL f2e62682d7213ee5eaecbc2590637ef36d9c86f746840c0ee758c0c153139f485032ea2cd098c87bb8a2b5f17f91375b8fb65599e3b71b45b1645df85a88887f
DIST xen-4.2.0.tar.gz 15587687 SHA256 43f4a086e4e0330145a27b7ace8365c42b5afbc95cefadafe067be91bd3e5cfb SHA512 4fb56c79d722fb307bc657f16d02079c6636427e7650c4354193632d38d2d1db8e588f844ff0ca6e757c108ed639a528565ec9fc7c00bb4d5b6fbc9d122d8a70 WHIRLPOOL 369a109375864cb61920b56cf501522051d28513e738f0fd0e7b76244c3e08a8a0a6ff6cf245872d9bbd9c0f22c7da76c9cbc0f852bad6108ca25fd42dc677c0
DIST xen-4.2.1.tar.gz 15593695 SHA256 fb8df5827ce3e2d2d3b078d9e5afde502beb5e7ab9442e51a94087061bd450c6 SHA512 fe27a965e2b34035bd025482eda9fc4d4e82523c929323fd30813367d5ffbe2fa1ed3d7d4479f2632e8b5625972448b7bd6a7768e8dc1dcd1b6747d281cc1a9e WHIRLPOOL 226bbed059541e804f1a44e721023ffbc04bae43000653b1d7d6a9bfec0d9efbf7a48b1b0a7ad3fcb8e34f8b91e1c620c2a8eddf97baad487e9db37d49a58f37
DIST xen-4.2.2.tar.gz 15602746 SHA256 c9bfe91a5e72f8545acebad9889d64368020359bfe18044c0e683133e55ae005 SHA512 4943b18016ed8c2b194a3b55e6655b3b734b39ffb8cb7ee0a0580f2f4460a1d0e92e1de8ac23f5186272914fad1650586af51fd7c3644d0310eb16f2e11c5e80 WHIRLPOOL 519eb87cb2da694696cbc3e72070a0a3bdb07c46fa266d855d8379eec3a92adfa4d434af3ac01c37834ce4a9174081a6c40030b185a70902329b185cb8d0bbea

@ -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

@ -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,6 +1,6 @@
# 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.ebuild,v 1.2 2013/01/24 08:53:49 idella4 Exp $
# $Header: /var/cvsroot/gentoo-x86/app-emulation/xen-tools/xen-tools-4.2.1-r4.ebuild,v 1.1 2013/06/26 14:41:37 idella4 Exp $
EAPI=5
@ -23,6 +23,7 @@ else
$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"
@ -31,29 +32,28 @@ DOCS=( README docs/README.xen-bugtool )
LICENSE="GPL-2"
SLOT="0"
# TODO soon;ocaml
IUSE="api custom-cflags debug doc flask hvm qemu ocaml pygrub screen static-libs xend"
REQUIRED_USE="hvm? ( qemu )"
CDEPEND="<dev-libs/yajl-2
CDEPEND="dev-libs/yajl
dev-python/lxml[${PYTHON_USEDEP}]
dev-python/pypam[${PYTHON_USEDEP}]
dev-python/pyxml[${PYTHON_USEDEP}]
sys-libs/zlib
sys-power/iasl
dev-ml/findlib
ocaml? ( dev-ml/findlib )
hvm? ( media-libs/libsdl )
api? ( dev-libs/libxml2 net-misc/curl )
${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
dev-ml/findlib
doc? (
app-doc/doxygen
dev-tex/latex2html[png,gif]
@ -67,16 +67,12 @@ DEPEND="${CDEPEND}
dev-texlive/texlive-pictures
dev-texlive/texlive-latexrecommended
)
hvm? (
x11-proto/xproto
sys-devel/dev86
)
"
hvm? ( x11-proto/xproto )
qemu? ( >=sys-apps/texinfo-5 )"
RDEPEND="${CDEPEND}
sys-apps/iproute2
net-misc/bridge-utils
>=dev-lang/ocaml-3.12.0
ocaml? ( >=dev-lang/ocaml-3.12.0 )
screen? (
app-misc/screen
app-admin/logrotate
@ -127,10 +123,8 @@ pkg_setup() {
}
src_prepare() {
sed -e 's/-Wall//' -i Config.mk || die "Couldn't sanitize CFLAGS"
# Drop .config
sed -e '/-include $(XEN_ROOT)\/.config/d' -i Config.mk || die "Couldn't drop"
# Drop .config, fixes to gcc-4.6
epatch "${FILESDIR}"/${PN/-tools/}-4-fix_dotconfig-gcc.patch
# Xend
if ! use xend; then
@ -139,6 +133,7 @@ src_prepare() {
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"
@ -170,13 +165,9 @@ src_prepare() {
sed -e "s:install-tools\: tools/ioemu-dir:install-tools\: :g" -i Makefile || die
fi
# Fix build for gcc-4.6
find "${S}" \( -name Makefile -o -name Rules.mk -o -name Config.mk \) \
-exec sed -e "s:-Werror::g" -i {} + || die "Failed to remove -Werror"
# Fix texi2html build error with new texi2html
sed -r -e "s:(texi2html.*) -number:\1:" \
-i tools/qemu-xen-traditional/Makefile || die
# Fix texi2html build error with new texi2html, qemu.doc.html
epatch "${FILESDIR}"/${PN}-4-docfix.patch \
"${FILESDIR}"/${PN}-4-qemu-xen-doc.patch
# Fix network broadcast on bridged networks
epatch "${FILESDIR}/${PN}-3.4.0-network-bridge-broadcast.patch"
@ -194,7 +185,7 @@ src_prepare() {
# Don't build ipxe with pie on hardened, Bug #360805
if gcc-specs-pie; then
epatch "${FILESDIR}/ipxe-nopie.patch"
epatch "${FILESDIR}"/ipxe-nopie.patch
fi
# Prevent double stripping of files at install
@ -202,6 +193,34 @@ src_prepare() {
# fix jobserver in Makefile
epatch "${FILESDIR}"/${PN/-tools/}-4.2.0-jserver.patch
# add missing typedef
epatch "${FILESDIR}"/xen-4-ulong.patch \
"${FILESDIR}"/${PN}-4.2-xen_disk_leak.patch
#Sec patches currently valid
epatch "${FILESDIR}"/xen-4-CVE-2012-6075-XSA-41.patch \
"${FILESDIR}"/xen-4-CVE-2013-0215-XSA-38.patch \
"${FILESDIR}"/xen-4-CVE-2013-1919-XSA-46.patch \
"${FILESDIR}"/xen-4-CVE-2013-1922-XSA-48.patch \
"${FILESDIR}"/xen-4-CVE-2013-1952-XSA_49.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-1-XSA-55.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-2-XSA-55.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-3-XSA-55.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-4-XSA-55.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-5to7-XSA-55.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-8-XSA-55.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-9to10-XSA-55.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-11-XSA-55.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-12to13-XSA-55.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-14-XSA-55.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-15-XSA-55.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-16-XSA-55.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-17-XSA-55.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-18to19-XSA-55.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-20to23-XSA-55.patch \
"${FILESDIR}"/xen-4-CVE-2013-2072-XSA-56.patch \
"${FILESDIR}"/xen-4.2-CVE-XSA-57.patch
}
src_compile() {
@ -218,12 +237,7 @@ src_compile() {
unset CFLAGS
emake CC="$(tc-getCC)" LD="$(tc-getLD)" -C tools ${myopt}
if use doc; then
sh ./docs/check_pkgs || die "package check failed"
emake docs
emake dev-docs
fi
use doc && emake -C docs txt html
emake -C docs man-pages
}
@ -254,7 +268,7 @@ src_install() {
if use doc; then
emake DESTDIR="${ED}" DOCDIR="/usr/share/doc/${PF}" install-docs
dohtml -r docs/api/
dohtml -r docs/
docinto pdf
dodoc ${DOCS[@]}
[ -d "${ED}"/usr/share/doc/xen ] && mv "${ED}"/usr/share/doc/xen/* "${ED}"/usr/share/doc/${PF}/html
@ -279,6 +293,11 @@ src_install() {
keepdir /var/log/xen-consoles
fi
if use qemu; then
mkdir -p "${D}"usr/lib64/xen/bin || die
mv "${D}"usr/lib/xen/bin/qemu* "${D}"usr/lib64/xen/bin/ || die
fi
# For -static-libs wrt Bug 384355
if ! use static-libs; then
rm -f "${ED}"usr/$(get_libdir)/*.a "${ED}"usr/$(get_libdir)/ocaml/*/*.a

@ -1,6 +1,6 @@
# 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-r1.ebuild,v 1.9 2013/05/15 17:47:47 idella4 Exp $
# $Header: /var/cvsroot/gentoo-x86/app-emulation/xen-tools/xen-tools-4.2.2-r2.ebuild,v 1.1 2013/06/26 14:41:37 idella4 Exp $
EAPI=5
@ -36,13 +36,14 @@ IUSE="api custom-cflags debug doc flask hvm qemu ocaml pygrub screen static-libs
REQUIRED_USE="hvm? ( qemu )"
CDEPEND="dev-libs/yajl
CDEPEND="dev-libs/lzo:2
dev-libs/yajl
dev-python/lxml[${PYTHON_USEDEP}]
dev-python/pypam[${PYTHON_USEDEP}]
dev-python/pyxml[${PYTHON_USEDEP}]
sys-libs/zlib
sys-power/iasl
ocaml? ( dev-ml/findlib )
dev-ml/findlib
hvm? ( media-libs/libsdl )
${PYTHON_DEPS}
api? ( dev-libs/libxml2
@ -67,12 +68,12 @@ DEPEND="${CDEPEND}
dev-texlive/texlive-pictures
dev-texlive/texlive-latexrecommended
)
hvm? ( x11-proto/xproto
)"
hvm? ( x11-proto/xproto )
qemu? ( >=sys-apps/texinfo-5 )"
RDEPEND="${CDEPEND}
sys-apps/iproute2
net-misc/bridge-utils
ocaml? ( >=dev-lang/ocaml-3.12.0 )
ocaml? ( >=dev-lang/ocaml-4 )
screen? (
app-misc/screen
app-admin/logrotate
@ -165,8 +166,9 @@ src_prepare() {
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 texi2html build error with new texi2html, qemu.doc.html
epatch "${FILESDIR}"/${PN}-4-docfix.patch \
"${FILESDIR}"/${PN}-4-qemu-xen-doc.patch
# Fix network broadcast on bridged networks
epatch "${FILESDIR}/${PN}-3.4.0-network-bridge-broadcast.patch"
@ -193,8 +195,33 @@ src_prepare() {
# 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
# add missing header
epatch "${FILESDIR}"/xen-4-ulong.patch \
"${FILESDIR}"/${PN}-4.2-xen_disk_leak.patch
#Security patches, currently valid
epatch "${FILESDIR}"/xen-4-CVE-2012-6075-XSA-41.patch \
"${FILESDIR}"/xen-4-CVE-2013-1922-XSA-48.patch \
"${FILESDIR}"/xen-4-CVE-2013-1952-XSA-49.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-1-XSA-55.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-2-XSA-55.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-3-XSA-55.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-4-XSA-55.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-5to7-XSA-55.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-8-XSA-55.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-9to10-XSA-55.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-11-XSA-55.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-12to13-XSA-55.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-14-XSA-55.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-15-XSA-55.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-16-XSA-55.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-17-XSA-55.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-18to19-XSA-55.patch \
"${FILESDIR}"/xen-4.2-CVE-2013-20to23-XSA-55.patch \
"${FILESDIR}"/xen-4-CVE-2013-2072-XSA-56.patch \
"${FILESDIR}"/xen-4.2-CVE-XSA-57.patch
epatch_user
}
src_compile() {

@ -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;

@ -1,6 +1,6 @@
# 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-ja/man-pages-ja-20130215.ebuild,v 1.7 2013/06/26 08:54:15 ago Exp $
# $Header: /var/cvsroot/gentoo-x86/app-i18n/man-pages-ja/man-pages-ja-20130215.ebuild,v 1.8 2013/06/26 11:58:20 ago Exp $
EAPI="3"
GENTOO_MAN_P="portage-${PN}-20060415"
@ -12,7 +12,7 @@ SRC_URI="http://linuxjm.sourceforge.jp/${P}.tar.gz
LICENSE="GPL-2+ GPL-2 LGPL-2+ LGPL-2 BSD MIT ISC HPND FDL-1.1+ LDP-1 LDP-1a man-pages Texinfo-manual"
SLOT="0"
KEYWORDS="alpha amd64 ~arm hppa ia64 ~m68k ~mips ppc ppc64 ~s390 ~sh ~sparc x86"
KEYWORDS="alpha amd64 arm hppa ia64 ~m68k ~mips ppc ppc64 ~s390 ~sh ~sparc x86"
IUSE=""
RDEPEND="virtual/man"

@ -1,2 +1,3 @@
DIST man-pages-ru_3.41-2145-1724-20130102.tar.bz2 669902 SHA256 23e76ba0025616b3670716363227440e6fdda17bd8498be5beb565561b25f8ba SHA512 1bc37cbea0ee559985f2ded4dec136e5b178db26d25d571fe9fbf10f611d91be65d08973b5d9a2db1e80aa1da3f0b54ae6a28a8b6d63ac0c559f606e4779e403 WHIRLPOOL ea224a6182c1de420a75e5a851bae9ddf3522ed14a053d9ad835fb156301410bb392c704273a205421ab50bd27f264dcc2da9c95fb4ad1889e6fb708a1cd8845
DIST man-pages-ru_3.49-2170-1764-20130606.tar.bz2 727102 SHA256 a0e8d5960511786aa2ed377471f265c8c6153cb82f01a0a1ab8d58fadd6336a4 SHA512 de428e1382b99211ad20a5ff47a41dfd78b0c8356725f0264412dbd15f89f3dcb67f7493de1eefe4b0ce897860884733f1bbf4628c9b9ef972a3ac5ccdf4421d WHIRLPOOL e049d78bd7c1479c7baf205f39e9ba7e8e05f443b9e1a70bbd8e0b2c1baf549c9e6cc10d82698897690a4905fd4fac6e8f1a173ca5d446d01eaf7ee4efe311ea
DIST man-pages-ru_3.51-2170-1766-20130613.tar.bz2 732257 SHA256 ae64c5676ce3c39ac1093c25feca27113b7282139479fd10e458c7b35b3df8f6 SHA512 8b521b6d7fa9cc51ca1d1b65ac2002d80d59ede8a4f7eb1dcfcb8eef89eccbb45b21b1331f32591b13493b525ea314d0d5857ea87420e9d4bc51348b3829cdf0 WHIRLPOOL d81a8c4994227c4099e6dd911779df6815c89e44d3d4282b1d679aaa0b5dc918e603c41a7d690c9af8d5d052a5370ff645ac35adc16c9e2a39b0b34b57921e24

@ -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
}

@ -1,11 +0,0 @@
# The name of the disk device that hdapsd should monitor.
# Usually this is 'hda' or 'sda' the primary master.
DISK="sda"
# hdapsd sensitivity
# The lower the threshold is the earlier
# the heads are parked when the laptop is shaked
THRESHOLD="10"
# Set any extra options here, like -a for Adaptive mode
OPTIONS="-a"

@ -1,55 +0,0 @@
#!/sbin/runscript
# Copyright 1999-2006 Gentoo Foundation
# Distributed under the terms of the GNU General Public License, v2
depend() {
need localmount
}
checkconfig() {
if [[ -z ${DISK} || -z ${THRESHOLD} ]] ; then
eerror "You should setup DISK and THRESHOLD in /etc/conf.d/hdapsd."
return 1
fi
if [ ! -b /dev/${DISK} ]; then
eerror "Could not find disk /dev/${DISK}!"
eerror "Adjust the DISK setting in /etc/conf.d/hdapsd"
return 1
fi
if [[ ! -e /sys/block/${DISK}/queue/protect ]] && [[ ! -e /sys/block/${DISK}/device/unload_heads ]] ; then
eerror "No protect entry for ${DISK}!"
eerror "Make sure your kernel is patched with the blk_freeze patch"
return 1
fi
# Load the tp_smapi module first
# This is not a requirement, but it helps hdapsd adaptive mode
if [[ ! -e /sys/devices/platform/smapi ]] ; then
modprobe tp_smapi 2>/dev/null
fi
if [[ ! -d /sys/devices/platform/hdaps ]]; then
ebegin "Loading hdaps module"
modprobe hdaps
eend $? || return 1
fi
}
start() {
checkconfig || return 1
ebegin "Starting Hard Drive Active Protection System daemon"
start-stop-daemon --start --exec /usr/sbin/hdapsd \
--pidfile /var/run/hdapsd.pid \
-- -b -p -d "${DISK}" -s "${THRESHOLD}" ${OPTIONS}
eend $?
}
stop() {
ebegin "Stopping Hard Drive Active Protection System daemon"
start-stop-daemon --stop --exec /usr/sbin/hdapsd \
--pidfile /var/run/hdapsd.pid
eend $?
}

@ -1,5 +1,5 @@
#!/sbin/runscript
# Copyright 1999-2012 Gentoo Foundation
# Copyright 1999-2013 Gentoo Foundation
# Distributed under the terms of the GNU General Public License, v2
depend() {
@ -7,12 +7,12 @@ depend() {
}
checkconfig() {
if [[ -n ${DISK} ]]; then
if [ -n "${DISK}" ]; then
ewarn "Please migrate DISK to DISKLIST in /etc/conf.d/hdapsd."
DISKLIST=${DISK}
fi
if [[ -z ${THRESHOLD} ]] ; then
if [ -z "${THRESHOLD}" ] ; then
eerror "You should setup THRESHOLD in /etc/conf.d/hdapsd."
return 1
fi
@ -25,7 +25,7 @@ checkconfig() {
return 1
fi
if [[ ! -e /sys/block/${DISK}/queue/protect ]] && [[ ! -e /sys/block/${DISK}/device/unload_heads ]] ; then
if [ ! -e /sys/block/${DISK}/queue/protect ] && [ ! -e /sys/block/${DISK}/device/unload_heads ] ; then
eerror "No protect entry for ${DISK}!"
eerror "Make sure your kernel is patched with the blk_freeze patch"
return 1
@ -34,11 +34,11 @@ checkconfig() {
# Load the tp_smapi module first
# This is not a requirement, but it helps hdapsd adaptive mode
if [[ ! -e /sys/devices/platform/smapi ]] ; then
if [ ! -e /sys/devices/platform/smapi ] ; then
modprobe tp_smapi 2>/dev/null
fi
if [[ ! -d /sys/devices/platform/hdaps ]]; then
if [ ! -d /sys/devices/platform/hdaps ] ; then
ebegin "Loading hdaps module"
modprobe hdaps
eend $? || return 1

@ -1,6 +1,6 @@
# Copyright 1999-2013 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: /var/cvsroot/gentoo-x86/app-laptop/hdapsd/hdapsd-20090401-r2.ebuild,v 1.4 2013/06/25 12:49:05 ago Exp $
# $Header: /var/cvsroot/gentoo-x86/app-laptop/hdapsd/hdapsd-20090401-r2.ebuild,v 1.5 2013/06/26 14:05:53 ottxor Exp $
EAPI=4
inherit linux-info readme.gentoo
@ -15,8 +15,8 @@ KEYWORDS="amd64 x86"
IUSE=""
pkg_setup() {
# We require the hdaps module which can either come from kernel sources or
# from the tp_smapi package.
# We require the hdaps module which can either come from kernel sources
# or from the tp_smapi package.
if ! has_version app-laptop/tp_smapi[hdaps]; then
CONFIG_CHECK="~SENSORS_HDAPS"
ERROR_SENSORS_HDAPS="${P} requires app-laptop/tp_smapi (with hdaps USE enabled) or support for CONFIG_SENSORS_HDAPS enabled"

@ -1,48 +0,0 @@
# Copyright 1999-2011 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: /var/cvsroot/gentoo-x86/app-laptop/hdapsd/hdapsd-20090401.ebuild,v 1.5 2011/05/04 15:44:37 tomka Exp $
EAPI=2
inherit eutils linux-info toolchain-funcs
DESCRIPTION="IBM ThinkPad Harddrive Active Protection disk head parking daemon"
HOMEPAGE="http://hdaps.sourceforge.net/"
SRC_URI="mirror://sourceforge/hdaps/${P}.tar.gz"
LICENSE="GPL-2"
SLOT="0"
KEYWORDS="amd64 x86"
IUSE=""
pkg_setup() {
# We require the hdaps module which can either come from kernel sources or
# from the tp_smapi package.
if ! has_version app-laptop/tp_smapi[hdaps]; then
CONFIG_CHECK="~SENSORS_HDAPS"
ERROR_SENSORS_HDAPS="${P} requires app-laptop/tp_smapi (with hdaps USE enabled) or support for CONFIG_SENSORS_HDAPS enabled"
linux-info_pkg_setup
fi
}
src_install() {
emake DESTDIR="${D}" install || die
rm -rf "${D}"/usr/share/doc/hdapsd
dodoc ChangeLog README AUTHORS
newconfd "${FILESDIR}"/hdapsd.conf hdapsd
newinitd "${FILESDIR}"/hdapsd.init hdapsd
}
pkg_postinst(){
[[ -z $(ls ${ROOT}/sys/block/*/queue/protect 2>/dev/null) ]] && \
[[ -z $(ls ${ROOT}/sys/block/*/device/unload_heads 2>/dev/null) ]] && \
ewarn "Your kernel does NOT support shock protection. Kernel 2.6.28 and above is recommended!"
if ! has_version app-laptop/tp_smapi[hdaps]; then
ewarn "Using the hdaps module provided by app-laptop/tp_smapi instead"
ewarn "of the in-kernel driver is strongly recommended!"
fi
elog "You can change the default frequency by modifing /sys/devices/platform/hdaps/sampling_rate"
elog "You might need to enable shock protection manually by running "
elog " echo -1 > /sys/block/DEVICE/device/unload_heads"
}

@ -1,6 +1,6 @@
# Copyright 1999-2013 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: /var/cvsroot/gentoo-x86/app-misc/ca-certificates/ca-certificates-20130119.ebuild,v 1.8 2013/06/26 08:55:30 ago Exp $
# $Header: /var/cvsroot/gentoo-x86/app-misc/ca-certificates/ca-certificates-20130119.ebuild,v 1.9 2013/06/26 11:59:29 ago Exp $
EAPI="3"
@ -13,7 +13,7 @@ SRC_URI="mirror://debian/pool/main/c/${PN}/${PN}_${PV}${NMU_PR:++nmu}${NMU_PR}_a
LICENSE="MPL-1.1"
SLOT="0"
KEYWORDS="alpha amd64 ~arm hppa ia64 ~m68k ~mips ppc ppc64 ~s390 ~sh ~sparc ~x86 ~ppc-aix ~amd64-fbsd ~sparc-fbsd ~x86-fbsd ~x64-freebsd ~x86-freebsd ~hppa-hpux ~ia64-hpux ~x86-interix ~amd64-linux ~arm-linux ~ia64-linux ~x86-linux ~ppc-macos ~x64-macos ~x86-macos ~m68k-mint ~sparc-solaris ~sparc64-solaris ~x64-solaris ~x86-solaris ~x86-winnt"
KEYWORDS="alpha amd64 arm hppa ia64 ~m68k ~mips ppc ppc64 ~s390 ~sh ~sparc ~x86 ~ppc-aix ~amd64-fbsd ~sparc-fbsd ~x86-fbsd ~x64-freebsd ~x86-freebsd ~hppa-hpux ~ia64-hpux ~x86-interix ~amd64-linux ~arm-linux ~ia64-linux ~x86-linux ~ppc-macos ~x64-macos ~x86-macos ~m68k-mint ~sparc-solaris ~sparc64-solaris ~x64-solaris ~x86-solaris ~x86-winnt"
IUSE=""
# platforms like AIX don't have a good ar

@ -1,4 +1,4 @@
DIST gnumeric-1.12.0-annotation-syntax.patch.xz 13408 SHA256 8cc904ced03d1cdb894afa896c7fc8be22bd3cf16f0c8427c965eb813a406a48 SHA512 b1062a75750630e4e0cb479a994db2c98aae4668355a7756bd6ca9f64407571d73af0fd428453e373d4d0d9f77d842869cbe4f7d5ba0054103cd8add0e09d5b6 WHIRLPOOL aec5b51c9af1e6b3806c7f5f22930c41d42ed0dfbcb66407a18ded9cf565b78daae76d2b8a5952ce4f7379b11c9bad68a02982f7248a62d0c5a87e8ae60a71f4
DIST gnumeric-1.12.0.tar.xz 15631708 SHA256 037b53d909e5d1454b2afda8c4fb1e7838e260343e36d4e36245f4a5d0e04111 SHA512 5bcf5e04d3c871d755a560207db2bce9d81bbe24f9c330a8a0555a386c38f505997c0a24a44afe0ab28539f03a921ce13f82ea8c6e828e17d998ce4951639223 WHIRLPOOL 2de92f2fecc9389e92a1e50f3c37361e0c06e792d0e75ca17beb1a5c6a9b344bc14d3eeef561ecdda5a3e6c60f4fe73f6fb2fd22e343b6edf842f7a81d64a825
DIST gnumeric-1.12.1.tar.xz 15692328 SHA256 0f5a7af3acae7db643eb00e8b4fca6a9e90162259c6a73e4214cfa8c96cc3901 SHA512 641d8ac9e57f397a84c0112c325482093ef0c5172fec2027788cb53193e065ebf093ffa91949da10907c1cd9150d73d84fb96096df8e7f4f7ad3cd9d2bb7ca29 WHIRLPOOL 53581cc8cd37ffc4a8a5c246da4e6c9f9e48e0ec01eb967ed1d421709f85636eabd871d306a34bc8ddfb82303b02d7bebbfff92e8495f0fc8b9eb444e55d79a9
DIST gnumeric-1.12.2.tar.xz 15517296 SHA256 d6fda191c1c76be2ede21fe78b8c9f96d39aea82ccfb537775a83bf88d781874 SHA512 6f41941e40f5fb3cafebb194082e6d4597caee6b9b1d2c271b8d67e8c78e2d87e366932914d62bd6f5ce6c1bbc2b7e26d5800fbfbc16905576057c3de1244fed WHIRLPOOL 6d8aab376cde73feb2d51d2110ec12c3eecf6e31f8d815e332c88dbfd21040f31828563d4ab5464b79fa238f40e3cefc066b65c0cd5e890eed061dd544ead7a9
DIST gnumeric-1.12.3.tar.xz 15503384 SHA256 b332e6785077a2e7febf26a6ccac73e9ae1813c365bc3bf851fb27a5477713a6 SHA512 f3591db341d378979eef4de5eeae0f9b7035940d46ff0876ad7cc038879a722541b098520f60078f83c47280870a0c6b90369a03394d05adcdcc10b0e072a15c WHIRLPOOL 39dd401d6f4e83d736aaa6816e3f917c7f43ca20fb809ce2f93b15b8fe7a3f000e2ea9f9921be1b09dfba798096c1cb9843b2db3c7ad4d2eb5cee709a9688d7d

@ -1,6 +1,6 @@
# Copyright 1999-2013 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: /var/cvsroot/gentoo-x86/app-office/gnumeric/gnumeric-1.12.1.ebuild,v 1.1 2013/03/31 14:53:31 eva Exp $
# $Header: /var/cvsroot/gentoo-x86/app-office/gnumeric/gnumeric-1.12.3.ebuild,v 1.1 2013/06/26 17:18:42 pacho Exp $
EAPI="5"
GCONF_DEBUG="no"
@ -17,6 +17,8 @@ SLOT="0"
KEYWORDS="~alpha ~amd64 ~ia64 ~ppc ~ppc64 ~sparc ~x86 ~x86-fbsd"
IUSE="+introspection perl python"
REQUIRED_USE="python? ( ${PYTHON_REQUIRED_USE} )"
# Missing gnome-extra/libgnomedb required version in tree
# but its upstream is dead and will be dropped soon.
@ -29,7 +31,7 @@ RDEPEND="
sys-libs/zlib
>=dev-libs/glib-2.28:2
>=gnome-extra/libgsf-1.14.24:=
>=x11-libs/goffice-0.10.1:0.10
>=x11-libs/goffice-0.10.3:0.10
>=dev-libs/libxml2-2.4.12:2
>=x11-libs/pango-1.24.0:=
@ -52,7 +54,6 @@ DEPEND="${RDEPEND}
src_configure() {
gnome2_src_configure \
--enable-ssindex \
--disable-static \
--without-gda \
--with-zlib \

@ -1 +1,2 @@
DIST texstudio-2.5.2.tar.gz 20731701 SHA256 50cc2163b872590c0af8edd22f1795aaa424a821956c38db24e5d72ecdad4f08 SHA512 d85cb4375a6828bac17e9d0cf97158e54fcd492ddfbc5e632dec9ca52616b3a2fd83f9ec696285d2ebe8627b78b26fd2a37fc9f0d10c96f2ec87b0c6de1bd061 WHIRLPOOL 183ebf3f4b97917449ceea991288ddc1f4a8b6c383d5ed2592ba8de2a05048df2eae5b69a4e0f57db87ef661b7b8086ac9c4ec55bff13ab8236ee81a95d7c64c
DIST texstudio-2.6.0.tar.gz 22913723 SHA256 23899dc7d57352f84deb375fefea33e3394f3fc497998abcdba003ef1856fc30 SHA512 e958c8e6bb73d3432cd54610c2ece3120c824c53c0fe2d367f2026fc3149bd837638f803706eacac44f48905032f39ad6792e3afbe721f6664a2b551dfdb47a2 WHIRLPOOL c16c4555ed63addb024b279589db09cd5d70f3af9940c4ae57394a04bc66b0be2bf22702bdba21342ed56be859db4b8943b832f6ec6d44ec96e6215bea2a0d93

@ -0,0 +1,22 @@
utilities/texstudio.desktop | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/utilities/texstudio.desktop b/utilities/texstudio.desktop
index 199255f..9c95afd 100644
--- a/utilities/texstudio.desktop
+++ b/utilities/texstudio.desktop
@@ -1,13 +1,12 @@
[Desktop Entry]
Categories=Office;Publishing;Qt;X-SuSE-Core-Office;X-Mandriva-Office-Publishing;X-Misc;
-Encoding=UTF-8
Exec=texstudio %F
GenericName=LaTeX Editor
GenericName[fr]=Editeur LaTeX
Comment=LaTeX development environment
Comment[fr]=Environnement de développement LaTeX
Icon=/usr/share/texstudio/texstudio.svg
-MimeType=text/x-tex;
+MimeType=text/X-tex;
Name=TeXstudio
StartupNotify=false
Terminal=false

@ -0,0 +1,93 @@
spellerutility.h | 2 +-
texstudio.pro | 45 ++++++++++++---------------------------------
2 files changed, 13 insertions(+), 34 deletions(-)
diff --git a/spellerutility.h b/spellerutility.h
index 7e1b980..b0bc8b8 100644
--- a/spellerutility.h
+++ b/spellerutility.h
@@ -13,7 +13,7 @@
#include "mostQtHeaders.h"
-#include "hunspell/hunspell.hxx"
+#include <hunspell.hxx>
class SpellerUtility: public QObject {
Q_OBJECT
public:
diff --git a/texstudio.pro b/texstudio.pro
index b073255..3d4ee64 100644
--- a/texstudio.pro
+++ b/texstudio.pro
@@ -53,25 +53,6 @@ HEADERS += texmaker.h \
debughelper.h \
thesaurusdialog.h \
xmltagslistwidget.h \
- hunspell/affentry.hxx \
- hunspell/affixmgr.hxx \
- hunspell/atypes.hxx \
- hunspell/baseaffix.hxx \
- hunspell/csutil.hxx \
- hunspell/dictmgr.hxx \
- hunspell/hashmgr.hxx \
- hunspell/htypes.hxx \
- hunspell/hunspell.hxx \
- hunspell/hunspell.h \
- hunspell/langnum.hxx \
- hunspell/license.hunspell \
- hunspell/phonet.hxx \
- hunspell/suggestmgr.hxx \
- hunspell/license.myspell \
- hunspell/filemgr.hxx \
- hunspell/hunzip.hxx \
- hunspell/w_char.hxx \
- hunspell/replist.hxx \
qcodeedit/lib/qeditorinputbinding.h \
qcodeedit/lib/qeditorinputbindinginterface.h \
qcodeedit/lib/qformat.h \
@@ -171,18 +152,6 @@ SOURCES += main.cpp \
codesnippet.cpp \
thesaurusdialog.cpp \
xmltagslistwidget.cpp \
- hunspell/affentry.cxx \
- hunspell/affixmgr.cxx \
- hunspell/csutil.cxx \
- hunspell/dictmgr.cxx \
- hunspell/hashmgr.cxx \
- hunspell/hunspell.cxx \
- hunspell/phonet.cxx \
- hunspell/replist.cxx \
- hunspell/suggestmgr.cxx \
- hunspell/utf_info.cxx \
- hunspell/filemgr.cxx \
- hunspell/hunzip.cxx \
encodingdialog.cpp \
qcodeedit/lib/qeditorinputbinding.cpp \
qcodeedit/lib/qformat.cpp \
@@ -537,10 +506,14 @@ SOURCES += qcodeedit/lib/qnfa/qnfa.cpp \
# ###############################
# ##########QUAZIP###############
-DEFINES += QUAZIP_STATIC
+#DEFINES += QUAZIP_STATIC
# Input
-include(quazip/quazip/quazip.pri)
+#include(quazip/quazip/quazip.pri)
+unix {
+ INCLUDEPATH += $${PREFIX}/include/quazip
+ LIBS += -lquazip
+}
# ###############################
@@ -677,3 +650,9 @@ else {
QMAKE_LFLAGS_RELEASE -= -Wl,-s
}
+unix {
+ CONFIG += link_pkgconfig
+ # use system quazip
+ # use system hunspell
+ PKGCONFIG += hunspell
+}

@ -0,0 +1,68 @@
# Copyright 1999-2013 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: /var/cvsroot/gentoo-x86/app-office/texstudio/texstudio-2.6.0.ebuild,v 1.1 2013/06/26 13:51:59 jlec Exp $
EAPI=5
inherit base fdo-mime qt4-r2
DESCRIPTION="Free cross-platform LaTeX editor (former texmakerX)"
HOMEPAGE="http://texstudio.sourceforge.net/"
SRC_URI="mirror://sourceforge/${PN}/${PN}/TeXstudio%20${PV}/${P}.tar.gz"
LICENSE="GPL-2"
SLOT="0"
KEYWORDS="~amd64 ~ppc ~ppc64 ~x86 ~x86-fbsd"
IUSE="video"
COMMON_DEPEND="
app-text/hunspell
app-text/poppler:=[qt4]
dev-libs/quazip
x11-libs/libX11
x11-libs/libXext
>=dev-qt/qtgui-4.6.1:4
>=dev-qt/qtcore-4.6.1:4
>=dev-qt/qtscript-4.6.1:4
>=dev-qt/qtsvg-4.6.1:4
>=dev-qt/qttest-4.6.1:4
video? ( media-libs/phonon )"
RDEPEND="${COMMON_DEPEND}
virtual/latex-base
app-text/psutils
app-text/ghostscript-gpl
media-libs/netpbm"
DEPEND="${COMMON_DEPEND}
virtual/pkgconfig"
S="${WORKDIR}"/${P/-/}
PATCHES=(
"${FILESDIR}"/${P}-hunspell-quazip.patch
# 441914
# "${FILESDIR}"/${P}-qtsingle.patch
"${FILESDIR}"/${P}-desktop.patch
# Get it from fedora
"${FILESDIR}"/${PN}-2.5-viewers-use-xdg-open.patch
)
src_prepare() {
find hunspell quazip utilities/poppler-data -delete || die
if use video; then
sed "/^PHONON/s:$:true:g" -i ${PN}.pro || die
fi
qt4-r2_src_prepare
}
src_install() {
local i
for i in 16x16 22x22 32x32 48x48 64x64; do
insinto /usr/share/icons/hicolor/${i}
newins utilities/${PN}${i}.png ${PN}.png
done
qt4-r2_src_install
}
pkg_postinst() {
fdo-mime_desktop_database_update
}

@ -1,27 +0,0 @@
# Copyright 1999-2013 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: /var/cvsroot/gentoo-x86/app-office/tpp/tpp-1.3.1-r1.ebuild,v 1.4 2013/06/21 14:25:06 prometheanfire Exp $
EAPI=2
USE_RUBY="ruby18"
inherit eutils ruby-ng
DESCRIPTION="An ncurses-based presentation tool."
HOMEPAGE="http://synflood.at/tpp.html"
SRC_URI="http://synflood.at/tpp/${P}.tar.gz"
LICENSE="GPL-2"
SLOT="0"
KEYWORDS="~amd64 ppc x86"
IUSE="figlet"
RDEPEND="${RDEPEND} figlet? ( app-misc/figlet )"
ruby_add_rdepend "dev-ruby/ncurses-ruby"
RUBY_PATCHES=( "${FILESDIR}/${P}-Makefile.patch" )
each_ruby_install() {
make DESTDIR="${D}" install || die "make install failed"
}

@ -1,2 +1 @@
DIST pdfgrep-1.2.tar.gz 94153 SHA256 0f7d20c0be171f4c1ac8f5c4bf141c355ad4e1440c99cb40b63f4e06eacb5cdf SHA512 de947ab4b61db7b04d5f3cb879b3a91e2e69392abf8ab8a3edf134ec2f37f51454a39b19f4afa4d2db2947bda08463d92e31277aea274999b7f72c6597d4fae7 WHIRLPOOL ed288a45b571c4471f9938cbae938d6734d0459d4d429a203f1caef0d608b5603a3e6d533f3eb97e48f9a03679b5702c1d61a16dd9e687a0e3d47f7747ec68f9
DIST pdfgrep-1.3.0.tar.gz 99739 SHA256 392aeb710b74970fee7d96bec7e2a5c7f175ab8c7daf36c42eae47821635ee17 SHA512 3555ac28685ddfaf9ea6c172aafbc251c0d622caa1c6f98e89c2fae1800e7299d97d3fa5497414f880235fba93963ec00fcea4ff199831abed5817f39ea318ca WHIRLPOOL ce1bbdece0bb69e9065a22625037f11f13e142fa56bca1d2736e4a4b9c853267eb45420b0d14cfecd1dc7639cb340733c0e4c0416fa69c1180cc4ae77d4b788d

@ -1,16 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd">
<pkgmetadata>
<herd>proxy-maintainers</herd>
<maintainer>
<email>jlec@gentoo.org</email>
<description>Tree Proxy</description>
</maintainer>
<maintainer>
<email>flo@freakempire.de</email>
<description>Maintainer, CC him on bugs</description>
</maintainer>
<use>
<flag name="unac">Removing accents and ligatures before search</flag>
</use>
<herd>proxy-maintainers</herd>
<maintainer>
<email>jlec@gentoo.org</email>
<description>Tree Proxy</description>
</maintainer>
<maintainer>
<email>flo@freakempire.de</email>
<description>Maintainer, CC him on bugs</description>
</maintainer>
<use>
<flag name="unac">Removing accents and ligatures before search</flag>
</use>
</pkgmetadata>

@ -1,18 +0,0 @@
# Copyright 1999-2013 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: /var/cvsroot/gentoo-x86/app-text/pdfgrep/pdfgrep-1.2.ebuild,v 1.3 2013/03/17 16:09:51 dilfridge Exp $
EAPI=5
DESCRIPTION="A tool similar to grep which searches text in PDFs"
HOMEPAGE="http://pdfgrep.sourceforge.net/"
SRC_URI="mirror://sourceforge/${PN}/${P}.tar.gz"
SLOT="0"
LICENSE="GPL-2"
KEYWORDS="~amd64 ~x86"
IUSE=""
RDEPEND="app-text/poppler:="
DEPEND="${RDEPEND}
virtual/pkgconfig"

@ -2,3 +2,4 @@ DIST postgis-1.3.6.tar.gz 2227317 SHA256 d3b04d4a3439596a1f6368b0627f21762347cef
DIST postgis-1.4.2.tar.gz 3276515 SHA256 5ce49b83b4c8f62eccb7080157f05299ff0e49c6ba06c3e1fa1ecfa2682c4d4b SHA512 3c27e8ed9eeb0e884190cdd5e4731989f9752e2ba449cdfe45d09cd638bd5b600d5cef16140e072d5e328cac035b2ffcc18392651c7306dcc4b5401429efc73e WHIRLPOOL 34a92d15018c5c414f93bf16c7cccb53af0943564b378bf2ca49d1692ebe51b9935214a5b2e2bddee716734954be7aabe0b4ce8b9c6b7d9cfbb801fa177bf5c4
DIST postgis-1.5.8.tar.gz 3948219 SHA256 4896fdae2f814b88c3ca458b7d01d7eca7e9aca021599c817919f131a1b0d804 SHA512 30167c56083dcd2aa764ee82b5b124992bfca2ab4eb8753a80f0fe624b310a060411f0714a8e56a1aebc277c3fdf8e1157d13d91560d5a8ffbc64917e9f3c727 WHIRLPOOL c889546679f69bbfc6d015c245721323c39fc18b6da2cfc28e24c7c736be112274f5c43d7d2ce61ea11a49011123d66d1a8f3c79ec3356227c48325945bff72a
DIST postgis-2.0.3.tar.gz 5581619 SHA256 7f865a6fdf19afed7d2f3e7178cd504f7254a9e96f2ce6a07d0ea19edc1668a0 SHA512 e49232a0aebd202a053e2f6cb741551e932e49a8c535fadd22fe15c654e3823c2f43a4c78dc0340cddbbc7f9298651dc16e1737be3bfe0779cc4feede032facc WHIRLPOOL 9c7985ab6d50a4a8ffa4e8fa5ea69c7e365aae8d90a3ea70c978149e5a9efe4a29a29d11db5d2a6b5c830dcd5ba458a3263288f32a5af54665f5d1cab3357415
DIST postgis-2.1.0beta3.tar.gz 6514183 SHA256 00bf610724a7100cd3585b17e9eeb9700c76acc4a73a647e81bbd6fcc6e2f07f SHA512 11fc8e8ebba124551f290998ac05949eaedce2e937d1d41801df54247f67106edb3f3806a7e7df81c2b782325c9cd0a235cbc7b556f68b7188c497dec48fbcac WHIRLPOOL 3ee2808c880e618230c4bcefe30449999a965743e52d0082b7f673649af9a84b1a807f7e14e7a6a278210c7118291d86a4147665543655e1ba1e5134654d2d6b

@ -0,0 +1,122 @@
diff -Naurw postgis-2.1.0beta3.orig/configure.ac postgis-2.1.0beta3/configure.ac
--- postgis-2.1.0beta3.orig/configure.ac 2013-06-21 15:45:40.000000000 +0000
+++ postgis-2.1.0beta3/configure.ac 2013-06-23 22:47:31.914947086 +0000
@@ -743,65 +743,14 @@
dnl Detect if json-c installed
dnl ===========================================================================
-CHECK_JSON=yes
-HAVE_JSON=no
-AC_SUBST([HAVE_JSON])
-
-AC_ARG_WITH([json],
- [AS_HELP_STRING([--without-json], [build without json-c support])],
- [CHECK_JSON="$withval"], [])
-
-if test "$CHECK_JSON" != "no"; then dnl {
-
-AC_ARG_WITH([jsondir],
- [AS_HELP_STRING([--with-jsondir=PATH], [specify the json-c installation directory])],
- [JSONDIR="$withval"], [JSONDIR=])
-
-if test ! "x$JSONDIR" = "x"; then
- dnl Make sure that the directory exists
- if test "x$JSONDIR" = "xyes"; then
- AC_MSG_ERROR([you must specify a parameter to --with-jsondir, e.g. --with-jsondir=/path/to])
- else
- dnl We need (libjson.so OR libjson.a OR libjson.dll) AND json/json.h
- if test ! -e "${JSONDIR}/include/json/json.h" -o \
- ! \( -e "${JSONDIR}/lib/libjson.so" -o \
- -e "${JSONDIR}/lib/libjson.dll" -o \
- -e "${JSONDIR}/lib/libjson.dylib" -o \
- -e "${JSONDIR}/bin/libjson.dll" -o \
- -e "${JSONDIR}/lib/libjson.a" \)
- then
- AC_MSG_ERROR([Cannot find json dev files in "$JSONDIR"])
- fi
- AC_MSG_RESULT([Using user-specified json-c directory: $JSONDIR])
-
- dnl Add the include directory to JSON_CPPFLAGS
- JSON_CPPFLAGS="-I$JSONDIR/include"
- JSON_LDFLAGS="-L$JSONDIR/lib"
- fi
-fi
-
-dnl Check that we can find the json/json.h header file
-CPPFLAGS_SAVE="$CPPFLAGS"
-CPPFLAGS="$JSON_CPPFLAGS"
-AC_CHECK_HEADER([json/json.h], [HAVE_JSON=yes], [])
-CPPFLAGS="$CPPFLAGS_SAVE"
-
-dnl Ensure we can link against libjson
-LIBS_SAVE="$LIBS"
-LIBS="$JSON_LDFLAGS"
-AC_CHECK_LIB([json-c], [json_object_get], [HAVE_JSON=yes; JSON_LDFLAGS="${JSON_LDFLAGS} -ljson-c"], [
- AC_CHECK_LIB([json], [json_object_get], [HAVE_JSON=yes; JSON_LDFLAGS="${JSON_LDFLAGS} -ljson"], [], [])
-], [])
-LIBS="$LIBS_SAVE"
-
-if test "$HAVE_JSON" = "yes"; then
+PKG_CHECK_MODULES([JSON], [json],
+ [
+ HAVE_JSON=yes
AC_DEFINE([HAVE_LIBJSON], 1, [Define to 1 if libjson is present])
-fi
+ ],
+ [HAVE_JSON=no])
-AC_SUBST([JSON_CPPFLAGS])
-AC_SUBST([JSON_LDFLAGS])
-
-fi dnl }
+AC_SUBST([HAVE_JSON])
dnl ===========================================================================
dnl Detect GTK+2.0 for GUI
@@ -892,10 +841,10 @@
AC_DEFINE_UNQUOTED([POSTGIS_USE_STATS], [1], [Enable use of ANALYZE statistics])
-CPPFLAGS="$PGSQL_CPPFLAGS $GEOS_CPPFLAGS $PROJ_CPPFLAGS $XML2_CPPFLAGS $SFCGAL_CPPFLAGS"
+CPPFLAGS="$PGSQL_CPPFLAGS $GEOS_CPPFLAGS $PROJ_CPPFLAGS $XML2_CPPFLAGS $SFCGAL_CPPFLAGS $JSON_CFLAGS"
dnl AC_MSG_RESULT([CPPFLAGS: $CPPFLAGS])
-SHLIB_LINK="$PGSQL_LDFLAGS $GEOS_LDFLAGS $PROJ_LDFLAGS -lgeos_c -lproj $JSON_LDFLAGS $XML2_LDFLAGS $SFCGAL_LDFLAGS"
+SHLIB_LINK="$PGSQL_LDFLAGS $GEOS_LDFLAGS $PROJ_LDFLAGS -lgeos_c -lproj $JSON_LIBS $XML2_LDFLAGS $SFCGAL_LDFLAGS"
AC_SUBST([SHLIB_LINK])
dnl AC_MSG_RESULT([SHLIB_LINK: $SHLIB_LINK])
diff -Naurw postgis-2.1.0beta3.orig/liblwgeom/lwin_geojson.c postgis-2.1.0beta3/liblwgeom/lwin_geojson.c
--- postgis-2.1.0beta3.orig/liblwgeom/lwin_geojson.c 2013-02-28 17:42:49.000000000 +0000
+++ postgis-2.1.0beta3/liblwgeom/lwin_geojson.c 2013-06-23 22:49:06.427947772 +0000
@@ -17,8 +17,8 @@
#ifdef HAVE_LIBJSON
-#include <json/json.h>
-#include <json/json_object_private.h>
+#include <json.h>
+#include <json_object_private.h>
#include <string.h>
static void geojson_lwerror(char *msg, int error_code)
@@ -551,5 +551,3 @@
return lwgeom;
#endif /* HAVE_LIBJSON */
}
-
-
diff -Naurw postgis-2.1.0beta3.orig/liblwgeom/Makefile.in postgis-2.1.0beta3/liblwgeom/Makefile.in
--- postgis-2.1.0beta3.orig/liblwgeom/Makefile.in 2013-05-09 19:38:17.000000000 +0000
+++ postgis-2.1.0beta3/liblwgeom/Makefile.in 2013-06-23 22:53:56.715076184 +0000
@@ -11,8 +11,8 @@
# **********************************************************************
CC = @CC@
-CFLAGS = @CFLAGS@ @PICFLAGS@ @WARNFLAGS@ @GEOS_CPPFLAGS@ @PROJ_CPPFLAGS@ @JSON_CPPFLAGS@
-LDFLAGS = @LDFLAGS@ @GEOS_LDFLAGS@ -lgeos_c @PROJ_LDFLAGS@ -lproj @JSON_LDFLAGS@
+CFLAGS = @CFLAGS@ @PICFLAGS@ @WARNFLAGS@ @GEOS_CPPFLAGS@ @PROJ_CPPFLAGS@ @JSON_CFLAGS@
+LDFLAGS = @LDFLAGS@ @GEOS_LDFLAGS@ -lgeos_c @PROJ_LDFLAGS@ -lproj @JSON_LIBS@
NUMERICFLAGS = @NUMERICFLAGS@
top_builddir = @top_builddir@
prefix = @prefix@

@ -0,0 +1,312 @@
# Copyright 1999-2013 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: /var/cvsroot/gentoo-x86/dev-db/postgis/postgis-2.1.0_beta3.ebuild,v 1.1 2013/06/26 10:59:19 titanofold Exp $
EAPI="4"
PG_SLOT_MIN="9.0"
inherit autotools eutils versionator
MY_PV=$(replace_version_separator 3 '')
MY_P="${PN}-${MY_PV}"
S="${WORKDIR}/${MY_P}"
DESCRIPTION="Geographic Objects for PostgreSQL"
HOMEPAGE="http://postgis.net"
SRC_URI="http://download.osgeo.org/postgis/source/${MY_P}.tar.gz"
LICENSE="GPL-2"
SLOT="0"
KEYWORDS="~amd64 ~ppc ~x86 ~amd64-linux ~x86-linux"
IUSE="doc gtk static-libs"
RDEPEND="
|| (
dev-db/postgresql-server:9.3
dev-db/postgresql-server:9.2
dev-db/postgresql-server:9.1
dev-db/postgresql-server:9.0
)
dev-libs/json-c
dev-libs/libxml2:2
>=sci-libs/geos-3.3.8
>=sci-libs/proj-4.6.0
>=sci-libs/gdal-1.10.0
gtk? ( x11-libs/gtk+:2 )
"
DEPEND="${RDEPEND}
doc? (
app-text/docbook-xsl-stylesheets
app-text/docbook-xml-dtd:4.3
dev-libs/libxslt
|| (
media-gfx/imagemagick[png]
media-gfx/graphicsmagick[imagemagick,png]
)
)
virtual/pkgconfig
"
PGIS="$(get_version_component_range 1-2)"
RESTRICT="test"
# These modules are built using the same *FLAGS that were used to build
# dev-db/postgresql. The right thing to do is to ignore the current
# *FLAGS settings.
QA_FLAGS_IGNORED="usr/lib(64)?/(rt)?postgis-${PGIS}\.so"
# Because developers have been fooled into thinking recursive make is a
# good thing.
MAKEOPTS="-j1"
postgres_check_slot() {
local pg_slot="$(postgresql-config show) 2> /dev/null"
# If app-admin/eselect-postgresql is not installed, or the slot
# hasn't been set before pkg_pretend is called, skip the rest of
# this function.
if [[ -z ${pg_slot} || "${pg_slot}" = "(none)" ]] ; then
if [[ "$EBUILD_PHASE" = "pretend" ]] ; then
return 1
else
if [[ "${pg_slot}" = "(none)" ]] ; then
die "Please set a default slot with postgresql-config"
elif [[ -z ${pg_slot} ]] ; then
die "This isn't supposed to happen."
fi
fi
fi
if [[ -n $PG_SLOT_MIN && $PG_SLOT_MIN != -1 ]] ; then
if [[ ${pg_slot//.} < ${PG_SLOT_MIN//.} ]] ; then
eerror "You must build ${CATEGORY}/${PN} against PostgreSQL ${PG_SLOT_MIN} or higher."
eerror "Set an appropriate slot with postgresql-config."
die
fi
fi
if [[ -n $PG_SLOT_MAX && $PG_SLOT_MAX != -1 ]] ; then
if [[ ${pg_slot//.} > ${PG_SLOT_MAX//.} ]] ; then
eerror "You must build ${CATEGORY}/${PN} against PostgreSQL ${PG_SLOT_MAX} or lower."
eerror "Set an appropriate slot with postgresql-config."
fi
fi
if [[ -n $PG_SLOT_SOFT_MAX ]] ; then
if [[ ${pg_slot//.} > ${PG_SLOT_SOFT_MAX//.} ]] ; then
ewarn "You are building ${CATEGORY}/${PN} against a version of PostgreSQL greater than ${PG_SLOT_SOFT_MAX}."
ewarn "This is not supported here."
ewarn "Any bugs you encounter should be reported upstream."
fi
fi
}
pkg_pretend() {
postgres_check_slot
}
pkg_setup() {
postgres_check_slot
export PGSLOT="$(postgresql-config show)"
}
src_prepare() {
epatch "${FILESDIR}/${PN}-2.0-ldflags.patch" \
"${FILESDIR}/${PN}-2.0-arflags.patch" \
"${FILESDIR}/${PN}-2.1-pkgconfig-json.patch"
local AT_M4DIR="macros"
eautoreconf
}
src_configure() {
local myargs=""
use gtk && myargs+=" --with-gui"
econf ${myargs}
}
src_compile() {
# Occasionally, builds fail because of out of order compilation.
# Otherwise, it'd be fine.
emake
emake -C topology
if use doc ; then
emake comments
emake cheatsheets
emake -C doc html
fi
}
src_install() {
emake DESTDIR="${D}" install
use doc && emake DESTDIR="${D}" comments-install
emake -C topology DESTDIR="${D}" install
dobin ./utils/postgis_restore.pl
dodoc CREDITS TODO loader/README.* doc/*txt
use doc && dohtml -r doc/html/*
docinto topology
dodoc topology/{TODO,README}
insinto /etc
doins "${FILESDIR}/postgis_dbs"
}
pkg_postinst() {
postgresql-config update
elog "To finish installing or updating PostGIS edit:"
elog " ${EROOT%/}/etc/postgis_dbs"
elog
elog "Then, run:"
elog " emerge --config =${CATEGORY}/${PF}"
}
pkg_config(){
source "${EROOT%/}/etc/conf.d/postgresql-${PGSLOT}"
source "${EROOT%/}/etc/postgis_dbs"
local postgis_path="${EROOT%/}/usr/share/postgresql-${PGSLOT}/contrib/postgis-${PGIS}"
if [[ -n ${configured} ]] ; then
einfon "Password for PostgreSQL user '${pguser}': "
read -s PGPASSWORD
export PGPASSWORD
echo
else
eerror "You must edit:"
eerror " ${EROOT%/}/etc/postgis_dbs"
eerror "Before running 'emerge --config =${CATEGORY}/${PF}'"
eerror
die "Edit postgis_dbs"
fi
# The server we work with must be the same slot we built against.
local server_version
server_version=$(psql -U ${pguser} -d postgres -p ${PGPORT} \
-Aqwtc 'SELECT version()' 2> /dev/null)
if [[ $? = 0 ]] ; then
server_version=$(echo ${server_version} | cut -d " " -f 2 | \
cut -d "." -f -2 | tr -d .)
if [[ $server_version != ${PGSLOT//.} ]] ; then
unset PGPASSWORD
eerror "Server version must be ${PGSLOT}.x"
die "Server version isn't ${PGSLOT}.x"
fi
else
unset PGPASSWORD
eerror "Is the server running?"
die "Couldn't connect to server."
fi
local retval
safe_exit() {
unset PGPASSWORD
sed -e 's/\(configured\)/#\1/' -i "${EROOT%/}/etc/postgis_dbs"
eend $retval
eerror "All actions could not be performed."
eerror "Read above to see what failed."
eerror "Once you fix the issue, you'll need to edit:"
eerror " ${EROOT%/}/etc/postgis_dbs"
eerror "As some things may have succeeded."
eerror
die "All actions could not be performed"
}
local db
for db in ${databases[@]} ; do
ebegin "Performing CREATE LANGUAGE on ${db}"
createlang -U ${pguser} -p ${PGPORT} plpgsql ${db}
retval=$?
# In this case, only error code 1 is fatal
[[ $retval == 1 ]] && safe_exit || eend 0
ebegin "Enabling PostGIS on ${db}"
psql -q -U ${pguser} -p ${PGPORT} -d ${db} \
-f "${postgis_path}/postgis.sql"
retval=$?
[[ $retval == 0 ]] && eend 0 || safe_exit
done
for db in ${templates[@]} ; do
ebegin "Creating template database '${db}'"
createdb -p ${PGPORT} -U ${pguser} -O ${pguser} -T ${from_template} \
${db} "PostGIS Template"
retval=$?
[[ $retval != 0 ]] && safe_exit
psql -q -U ${pguser} -p ${PGPORT} -c \
"UPDATE pg_database \
SET datistemplate = TRUE, datallowconn = TRUE \
WHERE datname = '${db}'"
retval=$?
[[ $retval != 0 ]] && safe_exit
createlang -U ${pguser} -p ${PGPORT} plpgsql ${db}
retval=$?
# In this case, only error code 1 is fatal
[[ $retval == 1 ]] && safe_exit
psql -q -U ${pguser} -p ${PGPORT} -d ${db} \
-f "${postgis_path}/postgis.sql"
retval=$?
[[ $retval == 0 ]] && eend 0 || safe_exit
done
for db in ${epsg_databases[@]} ; do
ebegin "Adding EPSG to ${db}"
psql -q -U ${pguser} -p ${PGPORT} -d ${db} \
-f "${postgis_path}/spatial_ref_sys.sql"
retval=$?
[[ $retval == 0 ]] && eend 0 || safe_exit
done
for db in ${comment_databases[@]} ; do
ebegin "Adding comments on ${db}"
local comment_file
for comment_file in "${postgis_path}"/*_comments.sql ; do
psql -q -U ${pguser} -p ${PGPORT} -d ${db} -f "${comment_file}"
retval=$?
[[ $retval == 0 ]] && continue || safe_exit
done
eend 0
done
for db in ${upgrade_from_1_3[@]} ; do
ebegin "Upgrading from PostGIS 1.3 to ${PGIS} on ${db}"
psql -q -U ${pguser} -p ${PGPORT} -d ${db} \
-f "${postgis_path}/postgis_upgrade_13_to_${PGIS//.}.sql"
retval=$?
[[ $retval == 0 ]] && eend 0 || safe_exit
done
for db in ${upgrade_from_1_4[@]} ; do
ebegin "Upgrading from PostGIS 1.4 to ${PGIS} on ${db}"
psql -q -U ${pguser} -p ${PGPORT} -d ${db} \
-f "${postgis_path}/postgis_upgrade_14_to_${PGIS//.}.sql"
retval=$?
[[ $retval == 0 ]] && eend 0 || safe_exit
done
for db in ${upgrade_from_1_5[@]} ; do
ebegin "Minor upgrade for PostGIS ${PGIS} on ${db}"
psql -q -U ${pguser} -p ${PGPORT} -d ${db} \
-f "${postgis_path}/postgis_upgrade_${PGIS//.}_minor.sql"
retval=$?
[[ $retval == 0 ]] && eend 0 || safe_exit
done
# Clean up and make it so the user has to edit postgis_dbs again that
# way this script won't step on any toes due to user error.
unset PGPASSWORD
sed -e 's/\(configured\)/#\1/' -i "${EROOT%/}/etc/postgis_dbs"
einfo "PostgreSQL ${PGSLOT} is now PostGIS enabled."
einfo
einfo "To enable other databases, change the default slot:"
einfo " postgresql-config set <slot>"
einfo "Then, emerge this package again:"
einfo " emerge -av =${CATEGORY}/${PF}"
}

@ -1,6 +1,6 @@
# Copyright 1999-2013 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: /var/cvsroot/gentoo-x86/dev-lang/swig/swig-1.3.40-r2.ebuild,v 1.9 2013/06/26 08:49:35 ago Exp $
# $Header: /var/cvsroot/gentoo-x86/dev-lang/swig/swig-1.3.40-r2.ebuild,v 1.10 2013/06/26 11:54:48 ago Exp $
EAPI="3"
DESCRIPTION="Simplified Wrapper and Interface Generator"
@ -9,7 +9,7 @@ SRC_URI="mirror://sourceforge/${PN}/${P}.tar.gz"
LICENSE="BSD BSD-2"
SLOT="1"
KEYWORDS="alpha amd64 ~arm hppa ia64 ppc ppc64 ~s390 ~sh ~sparc x86 ~ppc-aix ~x86-fbsd ~ia64-hpux ~x86-interix ~amd64-linux ~x86-linux ~ppc-macos ~x64-macos ~x86-macos ~sparc-solaris ~x64-solaris ~x86-solaris"
KEYWORDS="alpha amd64 arm hppa ia64 ppc ppc64 ~s390 ~sh ~sparc x86 ~ppc-aix ~x86-fbsd ~ia64-hpux ~x86-interix ~amd64-linux ~x86-linux ~ppc-macos ~x64-macos ~x86-macos ~sparc-solaris ~x64-solaris ~x86-solaris"
IUSE="ccache doc"
RESTRICT="test"
DEPEND=""

@ -1,6 +1,6 @@
# Copyright 1999-2013 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: /var/cvsroot/gentoo-x86/dev-libs/jansson/jansson-2.4.ebuild,v 1.4 2013/06/25 12:54:56 ago Exp $
# $Header: /var/cvsroot/gentoo-x86/dev-libs/jansson/jansson-2.4.ebuild,v 1.6 2013/06/26 16:52:45 blueness Exp $
EAPI="4"
AUTOTOOLS_AUTORECONF=1
@ -13,7 +13,7 @@ SRC_URI="http://www.digip.org/jansson/releases/${P}.tar.gz"
LICENSE="MIT"
SLOT="0"
KEYWORDS="amd64 x86"
KEYWORDS="amd64 ~arm ~ppc ~ppc64 x86"
IUSE="doc static-libs"
DEPEND="doc? ( >=dev-python/sphinx-1.0.4 )"

@ -1,6 +1,6 @@
# Copyright 1999-2013 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: /var/cvsroot/gentoo-x86/dev-libs/libusb-compat/libusb-compat-0.1.5.ebuild,v 1.8 2013/06/26 08:54:27 ago Exp $
# $Header: /var/cvsroot/gentoo-x86/dev-libs/libusb-compat/libusb-compat-0.1.5.ebuild,v 1.9 2013/06/26 11:58:31 ago Exp $
EAPI=5
inherit eutils
@ -11,7 +11,7 @@ SRC_URI="mirror://sourceforge/${PN/-compat}/${P}.tar.bz2"
LICENSE="LGPL-2.1"
SLOT="0"
KEYWORDS="alpha amd64 ~arm hppa ia64 ~m68k ~mips ppc ppc64 ~s390 ~sh ~sparc x86 ~x86-fbsd ~amd64-linux ~x86-linux ~ppc-macos ~x64-macos ~x86-macos"
KEYWORDS="alpha amd64 arm hppa ia64 ~m68k ~mips ppc ppc64 ~s390 ~sh ~sparc x86 ~x86-fbsd ~amd64-linux ~x86-linux ~ppc-macos ~x64-macos ~x86-macos"
IUSE="debug static-libs"
RDEPEND="virtual/libusb:1

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save