parent
0f27d023e0
commit
a2f65af846
@ -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
|
||||
{
|
@ -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
|
@ -1,369 +0,0 @@
|
||||
|
||||
# HG changeset patch
|
||||
# User Ian Jackson <Ian.Jackson@eu.citrix.com>
|
||||
# Date 1351264255 -3600
|
||||
# Node ID 537776f51f79c5789d06f97b363596a197c3e71c
|
||||
# Parent 40ccbee890e1fc053de3046bbc3d13b8ff6f5d63
|
||||
libxc: builder: limit maximum size of kernel/ramdisk.
|
||||
|
||||
Allowing user supplied kernels of arbitrary sizes, especially during
|
||||
decompression, can swallow up dom0 memory leading to either virtual
|
||||
address space exhaustion in the builder process or allocation
|
||||
failures/OOM killing of both toolstack and unrelated processes.
|
||||
|
||||
We disable these checks when building in a stub domain for pvgrub
|
||||
since this uses the guest's own memory and is isolated.
|
||||
|
||||
Decompression of gzip compressed kernels and ramdisks has been safe
|
||||
since 14954:58205257517d (Xen 3.1.0 onwards).
|
||||
|
||||
This is XSA-25 / CVE-2012-4544.
|
||||
|
||||
Also make explicit checks for buffer overflows in various
|
||||
decompression routines. These were already ruled out due to other
|
||||
properties of the code but check them as a belt-and-braces measure.
|
||||
|
||||
Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
|
||||
diff -r 40ccbee890e1 -r 537776f51f79 stubdom/grub/kexec.c
|
||||
--- stubdom/grub/kexec.c Thu Oct 25 15:36:32 2012 +0200
|
||||
+++ stubdom/grub/kexec.c Fri Oct 26 16:10:55 2012 +0100
|
||||
@@ -137,6 +137,10 @@ void kexec(void *kernel, long kernel_siz
|
||||
dom = xc_dom_allocate(xc_handle, cmdline, features);
|
||||
dom->allocate = kexec_allocate;
|
||||
|
||||
+ /* We are using guest owned memory, therefore no limits. */
|
||||
+ xc_dom_kernel_max_size(dom, 0);
|
||||
+ xc_dom_ramdisk_max_size(dom, 0);
|
||||
+
|
||||
dom->kernel_blob = kernel;
|
||||
dom->kernel_size = kernel_size;
|
||||
|
||||
diff -r 40ccbee890e1 -r 537776f51f79 tools/libxc/xc_dom.h
|
||||
--- tools/libxc/xc_dom.h Thu Oct 25 15:36:32 2012 +0200
|
||||
+++ tools/libxc/xc_dom.h Fri Oct 26 16:10:55 2012 +0100
|
||||
@@ -55,6 +55,9 @@ struct xc_dom_image {
|
||||
void *ramdisk_blob;
|
||||
size_t ramdisk_size;
|
||||
|
||||
+ size_t max_kernel_size;
|
||||
+ size_t max_ramdisk_size;
|
||||
+
|
||||
/* arguments and parameters */
|
||||
char *cmdline;
|
||||
uint32_t f_requested[XENFEAT_NR_SUBMAPS];
|
||||
@@ -180,6 +183,23 @@ void xc_dom_release_phys(struct xc_dom_i
|
||||
void xc_dom_release(struct xc_dom_image *dom);
|
||||
int xc_dom_mem_init(struct xc_dom_image *dom, unsigned int mem_mb);
|
||||
|
||||
+/* Set this larger if you have enormous ramdisks/kernels. Note that
|
||||
+ * you should trust all kernels not to be maliciously large (e.g. to
|
||||
+ * exhaust all dom0 memory) if you do this (see CVE-2012-4544 /
|
||||
+ * XSA-25). You can also set the default independently for
|
||||
+ * ramdisks/kernels in xc_dom_allocate() or call
|
||||
+ * xc_dom_{kernel,ramdisk}_max_size.
|
||||
+ */
|
||||
+#ifndef XC_DOM_DECOMPRESS_MAX
|
||||
+#define XC_DOM_DECOMPRESS_MAX (1024*1024*1024) /* 1GB */
|
||||
+#endif
|
||||
+
|
||||
+int xc_dom_kernel_check_size(struct xc_dom_image *dom, size_t sz);
|
||||
+int xc_dom_kernel_max_size(struct xc_dom_image *dom, size_t sz);
|
||||
+
|
||||
+int xc_dom_ramdisk_check_size(struct xc_dom_image *dom, size_t sz);
|
||||
+int xc_dom_ramdisk_max_size(struct xc_dom_image *dom, size_t sz);
|
||||
+
|
||||
size_t xc_dom_check_gzip(xc_interface *xch,
|
||||
void *blob, size_t ziplen);
|
||||
int xc_dom_do_gunzip(xc_interface *xch,
|
||||
@@ -240,7 +260,8 @@ void xc_dom_log_memory_footprint(struct
|
||||
void *xc_dom_malloc(struct xc_dom_image *dom, size_t size);
|
||||
void *xc_dom_malloc_page_aligned(struct xc_dom_image *dom, size_t size);
|
||||
void *xc_dom_malloc_filemap(struct xc_dom_image *dom,
|
||||
- const char *filename, size_t * size);
|
||||
+ const char *filename, size_t * size,
|
||||
+ const size_t max_size);
|
||||
char *xc_dom_strdup(struct xc_dom_image *dom, const char *str);
|
||||
|
||||
/* --- alloc memory pool ------------------------------------------- */
|
||||
diff -r 40ccbee890e1 -r 537776f51f79 tools/libxc/xc_dom_bzimageloader.c
|
||||
--- tools/libxc/xc_dom_bzimageloader.c Thu Oct 25 15:36:32 2012 +0200
|
||||
+++ tools/libxc/xc_dom_bzimageloader.c Fri Oct 26 16:10:55 2012 +0100
|
||||
@@ -47,13 +47,19 @@ static int xc_try_bzip2_decode(
|
||||
char *out_buf;
|
||||
char *tmp_buf;
|
||||
int retval = -1;
|
||||
- int outsize;
|
||||
+ unsigned int outsize;
|
||||
uint64_t total;
|
||||
|
||||
stream.bzalloc = NULL;
|
||||
stream.bzfree = NULL;
|
||||
stream.opaque = NULL;
|
||||
|
||||
+ if ( dom->kernel_size == 0)
|
||||
+ {
|
||||
+ DOMPRINTF("BZIP2: Input is 0 size");
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
ret = BZ2_bzDecompressInit(&stream, 0, 0);
|
||||
if ( ret != BZ_OK )
|
||||
{
|
||||
@@ -66,6 +72,17 @@ static int xc_try_bzip2_decode(
|
||||
* the input buffer to start, and we'll realloc as needed.
|
||||
*/
|
||||
outsize = dom->kernel_size;
|
||||
+
|
||||
+ /*
|
||||
+ * stream.avail_in and outsize are unsigned int, while kernel_size
|
||||
+ * is a size_t. Check we aren't overflowing.
|
||||
+ */
|
||||
+ if ( outsize != dom->kernel_size )
|
||||
+ {
|
||||
+ DOMPRINTF("BZIP2: Input too large");
|
||||
+ goto bzip2_cleanup;
|
||||
+ }
|
||||
+
|
||||
out_buf = malloc(outsize);
|
||||
if ( out_buf == NULL )
|
||||
{
|
||||
@@ -98,13 +115,20 @@ static int xc_try_bzip2_decode(
|
||||
if ( stream.avail_out == 0 )
|
||||
{
|
||||
/* Protect against output buffer overflow */
|
||||
- if ( outsize > INT_MAX / 2 )
|
||||
+ if ( outsize > UINT_MAX / 2 )
|
||||
{
|
||||
DOMPRINTF("BZIP2: output buffer overflow");
|
||||
free(out_buf);
|
||||
goto bzip2_cleanup;
|
||||
}
|
||||
|
||||
+ if ( xc_dom_kernel_check_size(dom, outsize * 2) )
|
||||
+ {
|
||||
+ DOMPRINTF("BZIP2: output too large");
|
||||
+ free(out_buf);
|
||||
+ goto bzip2_cleanup;
|
||||
+ }
|
||||
+
|
||||
tmp_buf = realloc(out_buf, outsize * 2);
|
||||
if ( tmp_buf == NULL )
|
||||
{
|
||||
@@ -172,9 +196,15 @@ static int _xc_try_lzma_decode(
|
||||
unsigned char *out_buf;
|
||||
unsigned char *tmp_buf;
|
||||
int retval = -1;
|
||||
- int outsize;
|
||||
+ size_t outsize;
|
||||
const char *msg;
|
||||
|
||||
+ if ( dom->kernel_size == 0)
|
||||
+ {
|
||||
+ DOMPRINTF("%s: Input is 0 size", what);
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
/* sigh. We don't know up-front how much memory we are going to need
|
||||
* for the output buffer. Allocate the output buffer to be equal
|
||||
* the input buffer to start, and we'll realloc as needed.
|
||||
@@ -244,13 +274,20 @@ static int _xc_try_lzma_decode(
|
||||
if ( stream->avail_out == 0 )
|
||||
{
|
||||
/* Protect against output buffer overflow */
|
||||
- if ( outsize > INT_MAX / 2 )
|
||||
+ if ( outsize > SIZE_MAX / 2 )
|
||||
{
|
||||
DOMPRINTF("%s: output buffer overflow", what);
|
||||
free(out_buf);
|
||||
goto lzma_cleanup;
|
||||
}
|
||||
|
||||
+ if ( xc_dom_kernel_check_size(dom, outsize * 2) )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: output too large", what);
|
||||
+ free(out_buf);
|
||||
+ goto lzma_cleanup;
|
||||
+ }
|
||||
+
|
||||
tmp_buf = realloc(out_buf, outsize * 2);
|
||||
if ( tmp_buf == NULL )
|
||||
{
|
||||
@@ -359,6 +396,12 @@ static int xc_try_lzo1x_decode(
|
||||
0x89, 0x4c, 0x5a, 0x4f, 0x00, 0x0d, 0x0a, 0x1a, 0x0a
|
||||
};
|
||||
|
||||
+ /*
|
||||
+ * lzo_uint should match size_t. Check that this is the case to be
|
||||
+ * sure we won't overflow various lzo_uint fields.
|
||||
+ */
|
||||
+ XC_BUILD_BUG_ON(sizeof(lzo_uint) != sizeof(size_t));
|
||||
+
|
||||
ret = lzo_init();
|
||||
if ( ret != LZO_E_OK )
|
||||
{
|
||||
@@ -438,6 +481,14 @@ static int xc_try_lzo1x_decode(
|
||||
if ( src_len <= 0 || src_len > dst_len || src_len > left )
|
||||
break;
|
||||
|
||||
+ msg = "Output buffer overflow";
|
||||
+ if ( *size > SIZE_MAX - dst_len )
|
||||
+ break;
|
||||
+
|
||||
+ msg = "Decompressed image too large";
|
||||
+ if ( xc_dom_kernel_check_size(dom, *size + dst_len) )
|
||||
+ break;
|
||||
+
|
||||
msg = "Failed to (re)alloc memory";
|
||||
tmp_buf = realloc(out_buf, *size + dst_len);
|
||||
if ( tmp_buf == NULL )
|
||||
diff -r 40ccbee890e1 -r 537776f51f79 tools/libxc/xc_dom_core.c
|
||||
--- tools/libxc/xc_dom_core.c Thu Oct 25 15:36:32 2012 +0200
|
||||
+++ tools/libxc/xc_dom_core.c Fri Oct 26 16:10:55 2012 +0100
|
||||
@@ -159,7 +159,8 @@ void *xc_dom_malloc_page_aligned(struct
|
||||
}
|
||||
|
||||
void *xc_dom_malloc_filemap(struct xc_dom_image *dom,
|
||||
- const char *filename, size_t * size)
|
||||
+ const char *filename, size_t * size,
|
||||
+ const size_t max_size)
|
||||
{
|
||||
struct xc_dom_mem *block = NULL;
|
||||
int fd = -1;
|
||||
@@ -171,6 +172,13 @@ void *xc_dom_malloc_filemap(struct xc_do
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
*size = lseek(fd, 0, SEEK_END);
|
||||
|
||||
+ if ( max_size && *size > max_size )
|
||||
+ {
|
||||
+ xc_dom_panic(dom->xch, XC_OUT_OF_MEMORY,
|
||||
+ "tried to map file which is too large");
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
block = malloc(sizeof(*block));
|
||||
if ( block == NULL )
|
||||
goto err;
|
||||
@@ -222,6 +230,40 @@ char *xc_dom_strdup(struct xc_dom_image
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
+/* decompression buffer sizing */
|
||||
+int xc_dom_kernel_check_size(struct xc_dom_image *dom, size_t sz)
|
||||
+{
|
||||
+ /* No limit */
|
||||
+ if ( !dom->max_kernel_size )
|
||||
+ return 0;
|
||||
+
|
||||
+ if ( sz > dom->max_kernel_size )
|
||||
+ {
|
||||
+ xc_dom_panic(dom->xch, XC_INVALID_KERNEL,
|
||||
+ "kernel image too large");
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int xc_dom_ramdisk_check_size(struct xc_dom_image *dom, size_t sz)
|
||||
+{
|
||||
+ /* No limit */
|
||||
+ if ( !dom->max_ramdisk_size )
|
||||
+ return 0;
|
||||
+
|
||||
+ if ( sz > dom->max_ramdisk_size )
|
||||
+ {
|
||||
+ xc_dom_panic(dom->xch, XC_INVALID_KERNEL,
|
||||
+ "ramdisk image too large");
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/* ------------------------------------------------------------------------ */
|
||||
/* read files, copy memory blocks, with transparent gunzip */
|
||||
|
||||
size_t xc_dom_check_gzip(xc_interface *xch, void *blob, size_t ziplen)
|
||||
@@ -235,7 +277,7 @@ size_t xc_dom_check_gzip(xc_interface *x
|
||||
|
||||
gzlen = blob + ziplen - 4;
|
||||
unziplen = gzlen[3] << 24 | gzlen[2] << 16 | gzlen[1] << 8 | gzlen[0];
|
||||
- if ( (unziplen < 0) || (unziplen > (1024*1024*1024)) ) /* 1GB limit */
|
||||
+ if ( (unziplen < 0) || (unziplen > XC_DOM_DECOMPRESS_MAX) )
|
||||
{
|
||||
xc_dom_printf
|
||||
(xch,
|
||||
@@ -288,6 +330,9 @@ int xc_dom_try_gunzip(struct xc_dom_imag
|
||||
if ( unziplen == 0 )
|
||||
return 0;
|
||||
|
||||
+ if ( xc_dom_kernel_check_size(dom, unziplen) )
|
||||
+ return 0;
|
||||
+
|
||||
unzip = xc_dom_malloc(dom, unziplen);
|
||||
if ( unzip == NULL )
|
||||
return -1;
|
||||
@@ -588,6 +633,9 @@ struct xc_dom_image *xc_dom_allocate(xc_
|
||||
memset(dom, 0, sizeof(*dom));
|
||||
dom->xch = xch;
|
||||
|
||||
+ dom->max_kernel_size = XC_DOM_DECOMPRESS_MAX;
|
||||
+ dom->max_ramdisk_size = XC_DOM_DECOMPRESS_MAX;
|
||||
+
|
||||
if ( cmdline )
|
||||
dom->cmdline = xc_dom_strdup(dom, cmdline);
|
||||
if ( features )
|
||||
@@ -608,10 +656,25 @@ struct xc_dom_image *xc_dom_allocate(xc_
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+int xc_dom_kernel_max_size(struct xc_dom_image *dom, size_t sz)
|
||||
+{
|
||||
+ DOMPRINTF("%s: kernel_max_size=%zx", __FUNCTION__, sz);
|
||||
+ dom->max_kernel_size = sz;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int xc_dom_ramdisk_max_size(struct xc_dom_image *dom, size_t sz)
|
||||
+{
|
||||
+ DOMPRINTF("%s: ramdisk_max_size=%zx", __FUNCTION__, sz);
|
||||
+ dom->max_ramdisk_size = sz;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
int xc_dom_kernel_file(struct xc_dom_image *dom, const char *filename)
|
||||
{
|
||||
DOMPRINTF("%s: filename=\"%s\"", __FUNCTION__, filename);
|
||||
- dom->kernel_blob = xc_dom_malloc_filemap(dom, filename, &dom->kernel_size);
|
||||
+ dom->kernel_blob = xc_dom_malloc_filemap(dom, filename, &dom->kernel_size,
|
||||
+ dom->max_kernel_size);
|
||||
if ( dom->kernel_blob == NULL )
|
||||
return -1;
|
||||
return xc_dom_try_gunzip(dom, &dom->kernel_blob, &dom->kernel_size);
|
||||
@@ -621,7 +684,9 @@ int xc_dom_ramdisk_file(struct xc_dom_im
|
||||
{
|
||||
DOMPRINTF("%s: filename=\"%s\"", __FUNCTION__, filename);
|
||||
dom->ramdisk_blob =
|
||||
- xc_dom_malloc_filemap(dom, filename, &dom->ramdisk_size);
|
||||
+ xc_dom_malloc_filemap(dom, filename, &dom->ramdisk_size,
|
||||
+ dom->max_ramdisk_size);
|
||||
+
|
||||
if ( dom->ramdisk_blob == NULL )
|
||||
return -1;
|
||||
// return xc_dom_try_gunzip(dom, &dom->ramdisk_blob, &dom->ramdisk_size);
|
||||
@@ -781,7 +846,11 @@ int xc_dom_build_image(struct xc_dom_ima
|
||||
void *ramdiskmap;
|
||||
|
||||
unziplen = xc_dom_check_gzip(dom->xch, dom->ramdisk_blob, dom->ramdisk_size);
|
||||
+ if ( xc_dom_ramdisk_check_size(dom, unziplen) != 0 )
|
||||
+ unziplen = 0;
|
||||
+
|
||||
ramdisklen = unziplen ? unziplen : dom->ramdisk_size;
|
||||
+
|
||||
if ( xc_dom_alloc_segment(dom, &dom->ramdisk_seg, "ramdisk", 0,
|
||||
ramdisklen) != 0 )
|
||||
goto err;
|
||||
|
||||
|
@ -0,0 +1,417 @@
|
||||
From 9737484becab4a25159f1e985700eaee89690d34 Mon Sep 17 00:00:00 2001
|
||||
From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Date: Fri, 14 Jun 2013 16:43:15 +0100
|
||||
Subject: [PATCH 01/23] libelf: abolish libelf-relocate.c
|
||||
|
||||
This file is not actually used. It's not built in Xen's instance of
|
||||
libelf; in libxc's it's built but nothing in it is called. Do not
|
||||
compile it in libxc, and delete it.
|
||||
|
||||
This reduces the amount of work we need to do in forthcoming patches
|
||||
to libelf (particularly since as libelf-relocate.c is not used it is
|
||||
probably full of bugs).
|
||||
|
||||
This is part of the fix to a security issue, XSA-55.
|
||||
|
||||
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
---
|
||||
tools/libxc/Makefile | 2 +-
|
||||
xen/common/libelf/libelf-relocate.c | 372 -----------------------------------
|
||||
2 files changed, 1 insertions(+), 373 deletions(-)
|
||||
delete mode 100644 xen/common/libelf/libelf-relocate.c
|
||||
|
||||
diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile
|
||||
index ca38cbd..d8c6a60 100644
|
||||
--- a/tools/libxc/Makefile
|
||||
+++ b/tools/libxc/Makefile
|
||||
@@ -53,7 +53,7 @@ vpath %.c ../../xen/common/libelf
|
||||
CFLAGS += -I../../xen/common/libelf
|
||||
|
||||
GUEST_SRCS-y += libelf-tools.c libelf-loader.c
|
||||
-GUEST_SRCS-y += libelf-dominfo.c libelf-relocate.c
|
||||
+GUEST_SRCS-y += libelf-dominfo.c
|
||||
|
||||
# new domain builder
|
||||
GUEST_SRCS-y += xc_dom_core.c xc_dom_boot.c
|
||||
diff --git a/xen/common/libelf/libelf-relocate.c b/xen/common/libelf/libelf-relocate.c
|
||||
#deleted file mode 100644
|
||||
index 7ef4b01..0000000
|
||||
--- a/xen/common/libelf/libelf-relocate.c
|
||||
+++ /dev/null
|
||||
@@ -1,372 +0,0 @@
|
||||
-/*
|
||||
- * ELF relocation code (not used by xen kernel right now).
|
||||
- *
|
||||
- * This library is free software; you can redistribute it and/or
|
||||
- * modify it under the terms of the GNU Lesser General Public
|
||||
- * License as published by the Free Software Foundation;
|
||||
- * version 2.1 of the License.
|
||||
- *
|
||||
- * This library is distributed in the hope that it will be useful,
|
||||
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
- * Lesser General Public License for more details.
|
||||
- *
|
||||
- * You should have received a copy of the GNU Lesser General Public
|
||||
- * License along with this library; if not, write to the Free Software
|
||||
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
- */
|
||||
-
|
||||
-#include "libelf-private.h"
|
||||
-
|
||||
-/* ------------------------------------------------------------------------ */
|
||||
-
|
||||
-static const char *rel_names_i386[] = {
|
||||
- "R_386_NONE",
|
||||
- "R_386_32",
|
||||
- "R_386_PC32",
|
||||
- "R_386_GOT32",
|
||||
- "R_386_PLT32",
|
||||
- "R_386_COPY",
|
||||
- "R_386_GLOB_DAT",
|
||||
- "R_386_JMP_SLOT",
|
||||
- "R_386_RELATIVE",
|
||||
- "R_386_GOTOFF",
|
||||
- "R_386_GOTPC",
|
||||
- "R_386_32PLT",
|
||||
- "R_386_TLS_TPOFF",
|
||||
- "R_386_TLS_IE",
|
||||
- "R_386_TLS_GOTIE",
|
||||
- "R_386_TLS_LE",
|
||||
- "R_386_TLS_GD",
|
||||
- "R_386_TLS_LDM",
|
||||
- "R_386_16",
|
||||
- "R_386_PC16",
|
||||
- "R_386_8",
|
||||
- "R_386_PC8",
|
||||
- "R_386_TLS_GD_32",
|
||||
- "R_386_TLS_GD_PUSH",
|
||||
- "R_386_TLS_GD_CALL",
|
||||
- "R_386_TLS_GD_POP",
|
||||
- "R_386_TLS_LDM_32",
|
||||
- "R_386_TLS_LDM_PUSH",
|
||||
- "R_386_TLS_LDM_CALL",
|
||||
- "R_386_TLS_LDM_POP",
|
||||
- "R_386_TLS_LDO_32",
|
||||
- "R_386_TLS_IE_32",
|
||||
- "R_386_TLS_LE_32",
|
||||
- "R_386_TLS_DTPMOD32",
|
||||
- "R_386_TLS_DTPOFF32",
|
||||
- "R_386_TLS_TPOFF32",
|
||||
-};
|
||||
-
|
||||
-static int elf_reloc_i386(struct elf_binary *elf, int type,
|
||||
- uint64_t addr, uint64_t value)
|
||||
-{
|
||||
- void *ptr = elf_get_ptr(elf, addr);
|
||||
- uint32_t *u32;
|
||||
-
|
||||
- switch ( type )
|
||||
- {
|
||||
- case 1 /* R_386_32 */ :
|
||||
- u32 = ptr;
|
||||
- *u32 += elf->reloc_offset;
|
||||
- break;
|
||||
- case 2 /* R_386_PC32 */ :
|
||||
- /* nothing */
|
||||
- break;
|
||||
- default:
|
||||
- return -1;
|
||||
- }
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-/* ------------------------------------------------------------------------ */
|
||||
-
|
||||
-static const char *rel_names_x86_64[] = {
|
||||
- "R_X86_64_NONE",
|
||||
- "R_X86_64_64",
|
||||
- "R_X86_64_PC32",
|
||||
- "R_X86_64_GOT32",
|
||||
- "R_X86_64_PLT32",
|
||||
- "R_X86_64_COPY",
|
||||
- "R_X86_64_GLOB_DAT",
|
||||
- "R_X86_64_JUMP_SLOT",
|
||||
- "R_X86_64_RELATIVE",
|
||||
- "R_X86_64_GOTPCREL",
|
||||
- "R_X86_64_32",
|
||||
- "R_X86_64_32S",
|
||||
- "R_X86_64_16",
|
||||
- "R_X86_64_PC16",
|
||||
- "R_X86_64_8",
|
||||
- "R_X86_64_PC8",
|
||||
- "R_X86_64_DTPMOD64",
|
||||
- "R_X86_64_DTPOFF64",
|
||||
- "R_X86_64_TPOFF64",
|
||||
- "R_X86_64_TLSGD",
|
||||
- "R_X86_64_TLSLD",
|
||||
- "R_X86_64_DTPOFF32",
|
||||
- "R_X86_64_GOTTPOFF",
|
||||
- "R_X86_64_TPOFF32",
|
||||
-};
|
||||
-
|
||||
-static int elf_reloc_x86_64(struct elf_binary *elf, int type,
|
||||
- uint64_t addr, uint64_t value)
|
||||
-{
|
||||
- void *ptr = elf_get_ptr(elf, addr);
|
||||
- uint64_t *u64;
|
||||
- uint32_t *u32;
|
||||
- int32_t *s32;
|
||||
-
|
||||
- switch ( type )
|
||||
- {
|
||||
- case 1 /* R_X86_64_64 */ :
|
||||
- u64 = ptr;
|
||||
- value += elf->reloc_offset;
|
||||
- *u64 = value;
|
||||
- break;
|
||||
- case 2 /* R_X86_64_PC32 */ :
|
||||
- u32 = ptr;
|
||||
- *u32 = value - addr;
|
||||
- if ( *u32 != (uint32_t)(value - addr) )
|
||||
- {
|
||||
- elf_err(elf, "R_X86_64_PC32 overflow: 0x%" PRIx32
|
||||
- " != 0x%" PRIx32 "\n",
|
||||
- *u32, (uint32_t) (value - addr));
|
||||
- return -1;
|
||||
- }
|
||||
- break;
|
||||
- case 10 /* R_X86_64_32 */ :
|
||||
- u32 = ptr;
|
||||
- value += elf->reloc_offset;
|
||||
- *u32 = value;
|
||||
- if ( *u32 != value )
|
||||
- {
|
||||
- elf_err(elf, "R_X86_64_32 overflow: 0x%" PRIx32
|
||||
- " != 0x%" PRIx64 "\n",
|
||||
- *u32, value);
|
||||
- return -1;
|
||||
- }
|
||||
- break;
|
||||
- case 11 /* R_X86_64_32S */ :
|
||||
- s32 = ptr;
|
||||
- value += elf->reloc_offset;
|
||||
- *s32 = value;
|
||||
- if ( *s32 != (int64_t) value )
|
||||
- {
|
||||
- elf_err(elf, "R_X86_64_32S overflow: 0x%" PRIx32
|
||||
- " != 0x%" PRIx64 "\n",
|
||||
- *s32, (int64_t) value);
|
||||
- return -1;
|
||||
- }
|
||||
- break;
|
||||
- default:
|
||||
- return -1;
|
||||
- }
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-/* ------------------------------------------------------------------------ */
|
||||
-
|
||||
-static struct relocs {
|
||||
- const char **names;
|
||||
- int count;
|
||||
- int (*func) (struct elf_binary * elf, int type, uint64_t addr,
|
||||
- uint64_t value);
|
||||
-} relocs[] =
|
||||
-/* *INDENT-OFF* */
|
||||
-{
|
||||
- [EM_386] = {
|
||||
- .names = rel_names_i386,
|
||||
- .count = sizeof(rel_names_i386) / sizeof(rel_names_i386[0]),
|
||||
- .func = elf_reloc_i386,
|
||||
- },
|
||||
- [EM_X86_64] = {
|
||||
- .names = rel_names_x86_64,
|
||||
- .count = sizeof(rel_names_x86_64) / sizeof(rel_names_x86_64[0]),
|
||||
- .func = elf_reloc_x86_64,
|
||||
- }
|
||||
-};
|
||||
-/* *INDENT-ON* */
|
||||
-
|
||||
-/* ------------------------------------------------------------------------ */
|
||||
-
|
||||
-static const char *rela_name(int machine, int type)
|
||||
-{
|
||||
- if ( machine > sizeof(relocs) / sizeof(relocs[0]) )
|
||||
- return "unknown mach";
|
||||
- if ( !relocs[machine].names )
|
||||
- return "unknown mach";
|
||||
- if ( type > relocs[machine].count )
|
||||
- return "unknown rela";
|
||||
- return relocs[machine].names[type];
|
||||
-}
|
||||
-
|
||||
-static int elf_reloc_section(struct elf_binary *elf,
|
||||
- const elf_shdr * rels,
|
||||
- const elf_shdr * sect, const elf_shdr * syms)
|
||||
-{
|
||||
- const void *ptr, *end;
|
||||
- const elf_shdr *shdr;
|
||||
- const elf_rela *rela;
|
||||
- const elf_rel *rel;
|
||||
- const elf_sym *sym;
|
||||
- uint64_t s_type;
|
||||
- uint64_t r_offset;
|
||||
- uint64_t r_info;
|
||||
- uint64_t r_addend;
|
||||
- int r_type, r_sym;
|
||||
- size_t rsize;
|
||||
- uint64_t shndx, sbase, addr, value;
|
||||
- const char *sname;
|
||||
- int machine;
|
||||
-
|
||||
- machine = elf_uval(elf, elf->ehdr, e_machine);
|
||||
- if ( (machine >= (sizeof(relocs) / sizeof(relocs[0]))) ||
|
||||
- (relocs[machine].func == NULL) )
|
||||
- {
|
||||
- elf_err(elf, "%s: can't handle machine %d\n",
|
||||
- __FUNCTION__, machine);
|
||||
- return -1;
|
||||
- }
|
||||
- if ( elf_swap(elf) )
|
||||
- {
|
||||
- elf_err(elf, "%s: non-native byte order, relocation not supported\n",
|
||||
- __FUNCTION__);
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
- s_type = elf_uval(elf, rels, sh_type);
|
||||
- rsize = (SHT_REL == s_type) ? elf_size(elf, rel) : elf_size(elf, rela);
|
||||
- ptr = elf_section_start(elf, rels);
|
||||
- end = elf_section_end(elf, rels);
|
||||
-
|
||||
- for ( ; ptr < end; ptr += rsize )
|
||||
- {
|
||||
- switch ( s_type )
|
||||
- {
|
||||
- case SHT_REL:
|
||||
- rel = ptr;
|
||||
- r_offset = elf_uval(elf, rel, r_offset);
|
||||
- r_info = elf_uval(elf, rel, r_info);
|
||||
- r_addend = 0;
|
||||
- break;
|
||||
- case SHT_RELA:
|
||||
- rela = ptr;
|
||||
- r_offset = elf_uval(elf, rela, r_offset);
|
||||
- r_info = elf_uval(elf, rela, r_info);
|
||||
- r_addend = elf_uval(elf, rela, r_addend);
|
||||
- break;
|
||||
- default:
|
||||
- /* can't happen */
|
||||
- return -1;
|
||||
- }
|
||||
- if ( elf_64bit(elf) )
|
||||
- {
|
||||
- r_type = ELF64_R_TYPE(r_info);
|
||||
- r_sym = ELF64_R_SYM(r_info);
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- r_type = ELF32_R_TYPE(r_info);
|
||||
- r_sym = ELF32_R_SYM(r_info);
|
||||
- }
|
||||
-
|
||||
- sym = elf_sym_by_index(elf, r_sym);
|
||||
- shndx = elf_uval(elf, sym, st_shndx);
|
||||
- switch ( shndx )
|
||||
- {
|
||||
- case SHN_UNDEF:
|
||||
- sname = "*UNDEF*";
|
||||
- sbase = 0;
|
||||
- break;
|
||||
- case SHN_COMMON:
|
||||
- elf_err(elf, "%s: invalid section: %" PRId64 "\n",
|
||||
- __FUNCTION__, shndx);
|
||||
- return -1;
|
||||
- case SHN_ABS:
|
||||
- sname = "*ABS*";
|
||||
- sbase = 0;
|
||||
- break;
|
||||
- default:
|
||||
- shdr = elf_shdr_by_index(elf, shndx);
|
||||
- if ( shdr == NULL )
|
||||
- {
|
||||
- elf_err(elf, "%s: invalid section: %" PRId64 "\n",
|
||||
- __FUNCTION__, shndx);
|
||||
- return -1;
|
||||
- }
|
||||
- sname = elf_section_name(elf, shdr);
|
||||
- sbase = elf_uval(elf, shdr, sh_addr);
|
||||
- }
|
||||
-
|
||||
- addr = r_offset;
|
||||
- value = elf_uval(elf, sym, st_value);
|
||||
- value += r_addend;
|
||||
-
|
||||
- if ( elf->log_callback && (elf->verbose > 1) )
|
||||
- {
|
||||
- uint64_t st_name = elf_uval(elf, sym, st_name);
|
||||
- const char *name = st_name ? elf->sym_strtab + st_name : "*NONE*";
|
||||
-
|
||||
- elf_msg(elf,
|
||||
- "%s: type %s [%d], off 0x%" PRIx64 ", add 0x%" PRIx64 ","
|
||||
- " sym %s [0x%" PRIx64 "], sec %s [0x%" PRIx64 "]"
|
||||
- " -> addr 0x%" PRIx64 " value 0x%" PRIx64 "\n",
|
||||
- __FUNCTION__, rela_name(machine, r_type), r_type, r_offset,
|
||||
- r_addend, name, elf_uval(elf, sym, st_value), sname, sbase,
|
||||
- addr, value);
|
||||
- }
|
||||
-
|
||||
- if ( relocs[machine].func(elf, r_type, addr, value) == -1 )
|
||||
- {
|
||||
- elf_err(elf, "%s: unknown/unsupported reloc type %s [%d]\n",
|
||||
- __FUNCTION__, rela_name(machine, r_type), r_type);
|
||||
- return -1;
|
||||
- }
|
||||
- }
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-int elf_reloc(struct elf_binary *elf)
|
||||
-{
|
||||
- const elf_shdr *rels, *sect, *syms;
|
||||
- uint64_t i, count, type;
|
||||
-
|
||||
- count = elf_shdr_count(elf);
|
||||
- for ( i = 0; i < count; i++ )
|
||||
- {
|
||||
- rels = elf_shdr_by_index(elf, i);
|
||||
- type = elf_uval(elf, rels, sh_type);
|
||||
- if ( (type != SHT_REL) && (type != SHT_RELA) )
|
||||
- continue;
|
||||
-
|
||||
- sect = elf_shdr_by_index(elf, elf_uval(elf, rels, sh_info));
|
||||
- syms = elf_shdr_by_index(elf, elf_uval(elf, rels, sh_link));
|
||||
- if ( NULL == sect || NULL == syms )
|
||||
- continue;
|
||||
-
|
||||
- if ( !(elf_uval(elf, sect, sh_flags) & SHF_ALLOC) )
|
||||
- {
|
||||
- elf_msg(elf, "%s: relocations for %s, skipping\n",
|
||||
- __FUNCTION__, elf_section_name(elf, sect));
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- elf_msg(elf, "%s: relocations for %s @ 0x%" PRIx64 "\n",
|
||||
- __FUNCTION__, elf_section_name(elf, sect),
|
||||
- elf_uval(elf, sect, sh_addr));
|
||||
- if ( elf_reloc_section(elf, rels, sect, syms) != 0 )
|
||||
- return -1;
|
||||
- }
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-/*
|
||||
- * Local variables:
|
||||
- * mode: C
|
||||
- * c-set-style: "BSD"
|
||||
- * c-basic-offset: 4
|
||||
- * tab-width: 4
|
||||
- * indent-tabs-mode: nil
|
||||
- * End:
|
||||
- */
|
||||
--
|
||||
#1.7.2.5
|
||||
|
@ -0,0 +1,788 @@
|
||||
From cc8761371aac432318530c2ddfe2c8234bc0621f Mon Sep 17 00:00:00 2001
|
||||
From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Date: Fri, 14 Jun 2013 16:43:17 +0100
|
||||
Subject: [PATCH 11/23] libelf: check all pointer accesses
|
||||
|
||||
We change the ELF_PTRVAL and ELF_HANDLE types and associated macros:
|
||||
|
||||
* PTRVAL becomes a uintptr_t, for which we provide a typedef
|
||||
elf_ptrval. This means no arithmetic done on it can overflow so
|
||||
the compiler cannot do any malicious invalid pointer arithmetic
|
||||
"optimisations". It also means that any places where we
|
||||
dereference one of these pointers without using the appropriate
|
||||
macros or functions become a compilation error.
|
||||
|
||||
So we can be sure that we won't miss any memory accesses.
|
||||
|
||||
All the PTRVAL variables were previously void* or char*, so
|
||||
the actual address calculations are unchanged.
|
||||
|
||||
* ELF_HANDLE becomes a union, one half of which keeps the pointer
|
||||
value and the other half of which is just there to record the
|
||||
type.
|
||||
|
||||
The new type is not a pointer type so there can be no address
|
||||
calculations on it whose meaning would change. Every assignment or
|
||||
access has to go through one of our macros.
|
||||
|
||||
* The distinction between const and non-const pointers and char*s
|
||||
and void*s in libelf goes away. This was not important (and
|
||||
anyway libelf tended to cast away const in various places).
|
||||
|
||||
* The fields elf->image and elf->dest are renamed. That proves
|
||||
that we haven't missed any unchecked uses of these actual
|
||||
pointer values.
|
||||
|
||||
* The caller may fill in elf->caller_xdest_base and _size to
|
||||
specify another range of memory which is safe for libelf to
|
||||
access, besides the input and output images.
|
||||
|
||||
* When accesses fail due to being out of range, we mark the elf
|
||||
"broken". This will be checked and used for diagnostics in
|
||||
a following patch.
|
||||
|
||||
We do not check for write accesses to the input image. This is
|
||||
because libelf actually does this in a number of places. So we
|
||||
simply permit that.
|
||||
|
||||
* Each caller of libelf which used to set dest now sets
|
||||
dest_base and dest_size.
|
||||
|
||||
* In xc_dom_load_elf_symtab we provide a new actual-pointer
|
||||
value hdr_ptr which we get from mapping the guest's kernel
|
||||
area and use (checking carefully) as the caller_xdest area.
|
||||
|
||||
* The STAR(h) macro in libelf-dominfo.c now uses elf_access_unsigned.
|
||||
|
||||
* elf-init uses the new elf_uval_3264 accessor to access the 32-bit
|
||||
fields, rather than an unchecked field access (ie, unchecked
|
||||
pointer access).
|
||||
|
||||
* elf_uval has been reworked to use elf_uval_3264. Both of these
|
||||
macros are essentially new in this patch (although they are derived
|
||||
from the old elf_uval) and need careful review.
|
||||
|
||||
* ELF_ADVANCE_DEST is now safe in the sense that you can use it to
|
||||
chop parts off the front of the dest area but if you chop more than
|
||||
is available, the dest area is simply set to be empty, preventing
|
||||
future accesses.
|
||||
|
||||
* We introduce some #defines for memcpy, memset, memmove and strcpy:
|
||||
- We provide elf_memcpy_safe and elf_memset_safe which take
|
||||
PTRVALs and do checking on the supplied pointers.
|
||||
- Users inside libelf must all be changed to either
|
||||
elf_mem*_unchecked (which are just like mem*), or
|
||||
elf_mem*_safe (which take PTRVALs) and are checked. Any
|
||||
unchanged call sites become compilation errors.
|
||||
|
||||
* We do _not_ at this time fix elf_access_unsigned so that it doesn't
|
||||
make unaligned accesses. We hope that unaligned accesses are OK on
|
||||
every supported architecture. But it does check the supplied
|
||||
pointer for validity.
|
||||
|
||||
This is part of the fix to a security issue, XSA-55.
|
||||
|
||||
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
---
|
||||
tools/libxc/xc_dom_elfloader.c | 49 ++++++++--
|
||||
tools/libxc/xc_hvm_build_x86.c | 10 +-
|
||||
xen/arch/x86/domain_build.c | 3 +-
|
||||
xen/common/libelf/libelf-dominfo.c | 2 +-
|
||||
xen/common/libelf/libelf-loader.c | 16 ++--
|
||||
xen/common/libelf/libelf-private.h | 13 +++
|
||||
xen/common/libelf/libelf-tools.c | 106 ++++++++++++++++++-
|
||||
xen/include/xen/libelf.h | 198 +++++++++++++++++++++++++-----------
|
||||
8 files changed, 312 insertions(+), 85 deletions(-)
|
||||
|
||||
diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c
|
||||
index cc0f206..b82a08c 100644
|
||||
--- a/tools/libxc/xc_dom_elfloader.c
|
||||
+++ b/tools/libxc/xc_dom_elfloader.c
|
||||
@@ -130,20 +130,30 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
|
||||
if ( load )
|
||||
{
|
||||
- size_t allow_size; /* will be used in a forthcoming XSA-55 patch */
|
||||
+ char *hdr_ptr;
|
||||
+ size_t allow_size;
|
||||
+
|
||||
if ( !dom->bsd_symtab_start )
|
||||
return 0;
|
||||
size = dom->kernel_seg.vend - dom->bsd_symtab_start;
|
||||
- hdr = xc_dom_vaddr_to_ptr(dom, dom->bsd_symtab_start, &allow_size);
|
||||
- *(int *)hdr = size - sizeof(int);
|
||||
+ hdr_ptr = xc_dom_vaddr_to_ptr(dom, dom->bsd_symtab_start, &allow_size);
|
||||
+ elf->caller_xdest_base = hdr_ptr;
|
||||
+ elf->caller_xdest_size = allow_size;
|
||||
+ hdr = ELF_REALPTR2PTRVAL(hdr_ptr);
|
||||
+ elf_store_val(elf, int, hdr, size - sizeof(int));
|
||||
}
|
||||
else
|
||||
{
|
||||
+ char *hdr_ptr;
|
||||
+
|
||||
size = sizeof(int) + elf_size(elf, elf->ehdr) +
|
||||
elf_shdr_count(elf) * elf_size(elf, shdr);
|
||||
- hdr = xc_dom_malloc(dom, size);
|
||||
- if ( hdr == NULL )
|
||||
+ hdr_ptr = xc_dom_malloc(dom, size);
|
||||
+ if ( hdr_ptr == NULL )
|
||||
return 0;
|
||||
+ elf->caller_xdest_base = hdr_ptr;
|
||||
+ elf->caller_xdest_size = size;
|
||||
+ hdr = ELF_REALPTR2PTRVAL(hdr_ptr);
|
||||
dom->bsd_symtab_start = elf_round_up(elf, dom->kernel_seg.vend);
|
||||
}
|
||||
|
||||
@@ -171,9 +181,32 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
ehdr->e_shoff = elf_size(elf, elf->ehdr);
|
||||
ehdr->e_shstrndx = SHN_UNDEF;
|
||||
}
|
||||
- if ( elf_init(&syms, hdr + sizeof(int), size - sizeof(int)) )
|
||||
+ if ( elf->caller_xdest_size < sizeof(int) )
|
||||
+ {
|
||||
+ DOMPRINTF("%s/%s: header size %"PRIx64" too small",
|
||||
+ __FUNCTION__, load ? "load" : "parse",
|
||||
+ (uint64_t)elf->caller_xdest_size);
|
||||
+ return -1;
|
||||
+ }
|
||||
+ if ( elf_init(&syms, elf->caller_xdest_base + sizeof(int),
|
||||
+ elf->caller_xdest_size - sizeof(int)) )
|
||||
return -1;
|
||||
|
||||
+ /*
|
||||
+ * The caller_xdest_{base,size} and dest_{base,size} need to
|
||||
+ * remain valid so long as each struct elf_image does. The
|
||||
+ * principle we adopt is that these values are set when the
|
||||
+ * memory is allocated or mapped, and cleared when (and if)
|
||||
+ * they are unmapped.
|
||||
+ *
|
||||
+ * Mappings of the guest are normally undone by xc_dom_unmap_all
|
||||
+ * (directly or via xc_dom_release). We do not explicitly clear
|
||||
+ * these because in fact that happens only at the end of
|
||||
+ * xc_dom_boot_image, at which time all of these ELF loading
|
||||
+ * functions have returned. No relevant struct elf_binary*
|
||||
+ * escapes this file.
|
||||
+ */
|
||||
+
|
||||
xc_elf_set_logfile(dom->xch, &syms, 1);
|
||||
|
||||
symtab = dom->bsd_symtab_start + sizeof(int);
|
||||
@@ -312,8 +345,10 @@ static int xc_dom_load_elf_kernel(struct xc_dom_image *dom)
|
||||
{
|
||||
struct elf_binary *elf = dom->private_loader;
|
||||
int rc;
|
||||
+ xen_pfn_t pages;
|
||||
|
||||
- elf->dest = xc_dom_seg_to_ptr(dom, &dom->kernel_seg);
|
||||
+ elf->dest_base = xc_dom_seg_to_ptr_pages(dom, &dom->kernel_seg, &pages);
|
||||
+ elf->dest_size = pages * XC_DOM_PAGE_SIZE(dom);
|
||||
rc = elf_load_binary(elf);
|
||||
if ( rc < 0 )
|
||||
{
|
||||
diff --git a/tools/libxc/xc_hvm_build_x86.c b/tools/libxc/xc_hvm_build_x86.c
|
||||
index 15b603d..ccfd8b5 100644
|
||||
--- a/tools/libxc/xc_hvm_build_x86.c
|
||||
+++ b/tools/libxc/xc_hvm_build_x86.c
|
||||
@@ -104,11 +104,12 @@ static int loadelfimage(
|
||||
for ( i = 0; i < pages; i++ )
|
||||
entries[i].mfn = parray[(elf->pstart >> PAGE_SHIFT) + i];
|
||||
|
||||
- elf->dest = xc_map_foreign_ranges(
|
||||
+ elf->dest_base = xc_map_foreign_ranges(
|
||||
xch, dom, pages << PAGE_SHIFT, PROT_READ | PROT_WRITE, 1 << PAGE_SHIFT,
|
||||
entries, pages);
|
||||
- if ( elf->dest == NULL )
|
||||
+ if ( elf->dest_base == NULL )
|
||||
goto err;
|
||||
+ elf->dest_size = pages * PAGE_SIZE;
|
||||
|
||||
ELF_ADVANCE_DEST(elf, elf->pstart & (PAGE_SIZE - 1));
|
||||
|
||||
@@ -117,8 +118,9 @@ static int loadelfimage(
|
||||
if ( rc < 0 )
|
||||
PERROR("Failed to load elf binary\n");
|
||||
|
||||
- munmap(elf->dest, pages << PAGE_SHIFT);
|
||||
- elf->dest = NULL;
|
||||
+ munmap(elf->dest_base, pages << PAGE_SHIFT);
|
||||
+ elf->dest_base = NULL;
|
||||
+ elf->dest_size = 0;
|
||||
|
||||
err:
|
||||
free(entries);
|
||||
diff --git a/xen/arch/x86/domain_build.c b/xen/arch/x86/domain_build.c
|
||||
index 469d363..a655b21 100644
|
||||
--- a/xen/arch/x86/domain_build.c
|
||||
+++ b/xen/arch/x86/domain_build.c
|
||||
@@ -908,7 +908,8 @@ int __init construct_dom0(
|
||||
write_ptbase(v);
|
||||
|
||||
/* Copy the OS image and free temporary buffer. */
|
||||
- elf.dest = (void*)vkern_start;
|
||||
+ elf.dest_base = (void*)vkern_start;
|
||||
+ elf.dest_size = vkern_end - vkern_start;
|
||||
rc = elf_load_binary(&elf);
|
||||
if ( rc < 0 )
|
||||
{
|
||||
diff --git a/xen/common/libelf/libelf-dominfo.c b/xen/common/libelf/libelf-dominfo.c
|
||||
index b217f8f..98c80dc 100644
|
||||
--- a/xen/common/libelf/libelf-dominfo.c
|
||||
+++ b/xen/common/libelf/libelf-dominfo.c
|
||||
@@ -254,7 +254,7 @@ int elf_xen_parse_guest_info(struct elf_binary *elf,
|
||||
int len;
|
||||
|
||||
h = parms->guest_info;
|
||||
-#define STAR(h) (*(h))
|
||||
+#define STAR(h) (elf_access_unsigned(elf, (h), 0, 1))
|
||||
while ( STAR(h) )
|
||||
{
|
||||
elf_memset_unchecked(name, 0, sizeof(name));
|
||||
diff --git a/xen/common/libelf/libelf-loader.c b/xen/common/libelf/libelf-loader.c
|
||||
index 0fef84c..a3310e7 100644
|
||||
--- a/xen/common/libelf/libelf-loader.c
|
||||
+++ b/xen/common/libelf/libelf-loader.c
|
||||
@@ -24,23 +24,25 @@
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
-int elf_init(struct elf_binary *elf, const char *image, size_t size)
|
||||
+int elf_init(struct elf_binary *elf, const char *image_input, size_t size)
|
||||
{
|
||||
ELF_HANDLE_DECL(elf_shdr) shdr;
|
||||
uint64_t i, count, section, offset;
|
||||
|
||||
- if ( !elf_is_elfbinary(image) )
|
||||
+ if ( !elf_is_elfbinary(image_input) )
|
||||
{
|
||||
elf_err(elf, "%s: not an ELF binary\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
elf_memset_unchecked(elf, 0, sizeof(*elf));
|
||||
- elf->image = image;
|
||||
+ elf->image_base = image_input;
|
||||
elf->size = size;
|
||||
- elf->ehdr = (elf_ehdr *)image;
|
||||
- elf->class = elf->ehdr->e32.e_ident[EI_CLASS];
|
||||
- elf->data = elf->ehdr->e32.e_ident[EI_DATA];
|
||||
+ elf->ehdr = ELF_MAKE_HANDLE(elf_ehdr, (elf_ptrval)image_input);
|
||||
+ elf->class = elf_uval_3264(elf, elf->ehdr, e32.e_ident[EI_CLASS]);
|
||||
+ elf->data = elf_uval_3264(elf, elf->ehdr, e32.e_ident[EI_DATA]);
|
||||
+ elf->caller_xdest_base = NULL;
|
||||
+ elf->caller_xdest_size = 0;
|
||||
|
||||
/* Sanity check phdr. */
|
||||
offset = elf_uval(elf, elf->ehdr, e_phoff) +
|
||||
@@ -300,7 +302,7 @@ int elf_load_binary(struct elf_binary *elf)
|
||||
|
||||
ELF_PTRVAL_VOID elf_get_ptr(struct elf_binary *elf, unsigned long addr)
|
||||
{
|
||||
- return elf->dest + addr - elf->pstart;
|
||||
+ return ELF_REALPTR2PTRVAL(elf->dest_base) + addr - elf->pstart;
|
||||
}
|
||||
|
||||
uint64_t elf_lookup_addr(struct elf_binary * elf, const char *symbol)
|
||||
diff --git a/xen/common/libelf/libelf-private.h b/xen/common/libelf/libelf-private.h
|
||||
index 3ef753c..280dfd1 100644
|
||||
--- a/xen/common/libelf/libelf-private.h
|
||||
+++ b/xen/common/libelf/libelf-private.h
|
||||
@@ -86,6 +86,19 @@ do { strncpy((d),(s),sizeof((d))-1); \
|
||||
|
||||
#endif
|
||||
|
||||
+#undef memcpy
|
||||
+#undef memset
|
||||
+#undef memmove
|
||||
+#undef strcpy
|
||||
+
|
||||
+#define memcpy MISTAKE_unspecified_memcpy
|
||||
+#define memset MISTAKE_unspecified_memset
|
||||
+#define memmove MISTAKE_unspecified_memmove
|
||||
+#define strcpy MISTAKE_unspecified_strcpy
|
||||
+ /* This prevents libelf from using these undecorated versions
|
||||
+ * of memcpy, memset, memmove and strcpy. Every call site
|
||||
+ * must either use elf_mem*_unchecked, or elf_mem*_safe. */
|
||||
+
|
||||
#endif /* __LIBELF_PRIVATE_H_ */
|
||||
|
||||
/*
|
||||
diff --git a/xen/common/libelf/libelf-tools.c b/xen/common/libelf/libelf-tools.c
|
||||
index 3a0cde1..46ca553 100644
|
||||
--- a/xen/common/libelf/libelf-tools.c
|
||||
+++ b/xen/common/libelf/libelf-tools.c
|
||||
@@ -20,28 +20,100 @@
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
-uint64_t elf_access_unsigned(struct elf_binary * elf, const void *ptr,
|
||||
- uint64_t offset, size_t size)
|
||||
+void elf_mark_broken(struct elf_binary *elf, const char *msg)
|
||||
{
|
||||
+ if ( elf->broken == NULL )
|
||||
+ elf->broken = msg;
|
||||
+}
|
||||
+
|
||||
+const char *elf_check_broken(const struct elf_binary *elf)
|
||||
+{
|
||||
+ return elf->broken;
|
||||
+}
|
||||
+
|
||||
+static int elf_ptrval_in_range(elf_ptrval ptrval, uint64_t size,
|
||||
+ const void *region, uint64_t regionsize)
|
||||
+ /*
|
||||
+ * Returns true if the putative memory area [ptrval,ptrval+size>
|
||||
+ * is completely inside the region [region,region+regionsize>.
|
||||
+ *
|
||||
+ * ptrval and size are the untrusted inputs to be checked.
|
||||
+ * region and regionsize are trusted and must be correct and valid,
|
||||
+ * although it is OK for region to perhaps be maliciously NULL
|
||||
+ * (but not some other malicious value).
|
||||
+ */
|
||||
+{
|
||||
+ elf_ptrval regionp = (elf_ptrval)region;
|
||||
+
|
||||
+ if ( (region == NULL) ||
|
||||
+ (ptrval < regionp) || /* start is before region */
|
||||
+ (ptrval > regionp + regionsize) || /* start is after region */
|
||||
+ (size > regionsize - (ptrval - regionp)) ) /* too big */
|
||||
+ return 0;
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+int elf_access_ok(struct elf_binary * elf,
|
||||
+ uint64_t ptrval, size_t size)
|
||||
+{
|
||||
+ if ( elf_ptrval_in_range(ptrval, size, elf->image_base, elf->size) )
|
||||
+ return 1;
|
||||
+ if ( elf_ptrval_in_range(ptrval, size, elf->dest_base, elf->dest_size) )
|
||||
+ return 1;
|
||||
+ if ( elf_ptrval_in_range(ptrval, size,
|
||||
+ elf->caller_xdest_base, elf->caller_xdest_size) )
|
||||
+ return 1;
|
||||
+ elf_mark_broken(elf, "out of range access");
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+void elf_memcpy_safe(struct elf_binary *elf, elf_ptrval dst,
|
||||
+ elf_ptrval src, size_t size)
|
||||
+{
|
||||
+ if ( elf_access_ok(elf, dst, size) &&
|
||||
+ elf_access_ok(elf, src, size) )
|
||||
+ {
|
||||
+ /* use memmove because these checks do not prove that the
|
||||
+ * regions don't overlap and overlapping regions grant
|
||||
+ * permission for compiler malice */
|
||||
+ elf_memmove_unchecked(ELF_UNSAFE_PTR(dst), ELF_UNSAFE_PTR(src), size);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+void elf_memset_safe(struct elf_binary *elf, elf_ptrval dst, int c, size_t size)
|
||||
+{
|
||||
+ if ( elf_access_ok(elf, dst, size) )
|
||||
+ {
|
||||
+ elf_memset_unchecked(ELF_UNSAFE_PTR(dst), c, size);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+uint64_t elf_access_unsigned(struct elf_binary * elf, elf_ptrval base,
|
||||
+ uint64_t moreoffset, size_t size)
|
||||
+{
|
||||
+ elf_ptrval ptrval = base + moreoffset;
|
||||
int need_swap = elf_swap(elf);
|
||||
const uint8_t *u8;
|
||||
const uint16_t *u16;
|
||||
const uint32_t *u32;
|
||||
const uint64_t *u64;
|
||||
|
||||
+ if ( !elf_access_ok(elf, ptrval, size) )
|
||||
+ return 0;
|
||||
+
|
||||
switch ( size )
|
||||
{
|
||||
case 1:
|
||||
- u8 = ptr + offset;
|
||||
+ u8 = (const void*)ptrval;
|
||||
return *u8;
|
||||
case 2:
|
||||
- u16 = ptr + offset;
|
||||
+ u16 = (const void*)ptrval;
|
||||
return need_swap ? bswap_16(*u16) : *u16;
|
||||
case 4:
|
||||
- u32 = ptr + offset;
|
||||
+ u32 = (const void*)ptrval;
|
||||
return need_swap ? bswap_32(*u32) : *u32;
|
||||
case 8:
|
||||
- u64 = ptr + offset;
|
||||
+ u64 = (const void*)ptrval;
|
||||
return need_swap ? bswap_64(*u64) : *u64;
|
||||
default:
|
||||
return 0;
|
||||
@@ -122,6 +194,28 @@ const char *elf_section_name(struct elf_binary *elf,
|
||||
return elf_strval(elf, elf->sec_strtab + elf_uval(elf, shdr, sh_name));
|
||||
}
|
||||
|
||||
+const char *elf_strval(struct elf_binary *elf, elf_ptrval start)
|
||||
+{
|
||||
+ uint64_t length;
|
||||
+
|
||||
+ for ( length = 0; ; length++ ) {
|
||||
+ if ( !elf_access_ok(elf, start + length, 1) )
|
||||
+ return NULL;
|
||||
+ if ( !elf_access_unsigned(elf, start, length, 1) )
|
||||
+ /* ok */
|
||||
+ return ELF_UNSAFE_PTR(start);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+const char *elf_strfmt(struct elf_binary *elf, elf_ptrval start)
|
||||
+{
|
||||
+ const char *str = elf_strval(elf, start);
|
||||
+
|
||||
+ if ( str == NULL )
|
||||
+ return "(invalid)";
|
||||
+ return str;
|
||||
+}
|
||||
+
|
||||
ELF_PTRVAL_CONST_VOID elf_section_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr)
|
||||
{
|
||||
return ELF_IMAGE_BASE(elf) + elf_uval(elf, shdr, sh_offset);
|
||||
diff --git a/xen/include/xen/libelf.h b/xen/include/xen/libelf.h
|
||||
index af5b5c5..ddc3ed7 100644
|
||||
--- a/xen/include/xen/libelf.h
|
||||
+++ b/xen/include/xen/libelf.h
|
||||
@@ -57,8 +57,9 @@ typedef void elf_log_callback(struct elf_binary*, void *caller_data,
|
||||
* on this.
|
||||
* This replaces variables which were char*,void*
|
||||
* and their const versions, so we provide four
|
||||
- * different declaration macros:
|
||||
+ * different obsolete declaration macros:
|
||||
* ELF_PTRVAL_{,CONST}{VOID,CHAR}
|
||||
+ * New code can simply use the elf_ptrval typedef.
|
||||
* HANDLE A pointer to a struct. There is one of these types
|
||||
* for each pointer type - that is, for each "structname".
|
||||
* In the arguments to the various HANDLE macros, structname
|
||||
@@ -67,54 +68,66 @@ typedef void elf_log_callback(struct elf_binary*, void *caller_data,
|
||||
* pointers. In the current code attempts to do so will
|
||||
* compile, but in the next patch this will become a
|
||||
* compile error.
|
||||
- * We provide two declaration macros for const and
|
||||
- * non-const pointers.
|
||||
+ * We also provide a second declaration macro for
|
||||
+ * pointers which were to const; this is obsolete.
|
||||
*/
|
||||
|
||||
-#define ELF_REALPTR2PTRVAL(realpointer) (realpointer)
|
||||
+typedef uintptr_t elf_ptrval;
|
||||
+
|
||||
+#define ELF_REALPTR2PTRVAL(realpointer) ((elf_ptrval)(realpointer))
|
||||
/* Converts an actual C pointer into a PTRVAL */
|
||||
|
||||
-#define ELF_HANDLE_DECL_NONCONST(structname) structname *
|
||||
-#define ELF_HANDLE_DECL(structname) const structname *
|
||||
+#define ELF_HANDLE_DECL_NONCONST(structname) structname##_handle /*obsolete*/
|
||||
+#define ELF_HANDLE_DECL(structname) structname##_handle
|
||||
/* Provides a type declaration for a HANDLE. */
|
||||
- /* May only be used to declare ONE variable at a time */
|
||||
|
||||
-#define ELF_PTRVAL_VOID void *
|
||||
-#define ELF_PTRVAL_CHAR char *
|
||||
-#define ELF_PTRVAL_CONST_VOID const void *
|
||||
-#define ELF_PTRVAL_CONST_CHAR const char *
|
||||
- /* Provides a type declaration for a PTRVAL. */
|
||||
- /* May only be used to declare ONE variable at a time */
|
||||
+#define ELF_PTRVAL_VOID elf_ptrval /*obsolete*/
|
||||
+#define ELF_PTRVAL_CHAR elf_ptrval /*obsolete*/
|
||||
+#define ELF_PTRVAL_CONST_VOID elf_ptrval /*obsolete*/
|
||||
+#define ELF_PTRVAL_CONST_CHAR elf_ptrval /*obsolete*/
|
||||
+
|
||||
+#ifdef __XEN__
|
||||
+# define ELF_PRPTRVAL "lu"
|
||||
+ /*
|
||||
+ * PRIuPTR is misdefined in xen/include/xen/inttypes.h, on 32-bit,
|
||||
+ * to "u", when in fact uintptr_t is an unsigned long.
|
||||
+ */
|
||||
+#else
|
||||
+# define ELF_PRPTRVAL PRIuPTR
|
||||
+#endif
|
||||
+ /* printf format a la PRId... for a PTRVAL */
|
||||
|
||||
-#define ELF_DEFINE_HANDLE(structname) /* empty */
|
||||
+#define ELF_DEFINE_HANDLE(structname) \
|
||||
+ typedef union { \
|
||||
+ elf_ptrval ptrval; \
|
||||
+ const structname *typeonly; /* for sizeof, offsetof, &c only */ \
|
||||
+ } structname##_handle;
|
||||
/*
|
||||
* This must be invoked for each HANDLE type to define
|
||||
* the actual C type used for that kind of HANDLE.
|
||||
*/
|
||||
|
||||
-#define ELF_PRPTRVAL "p"
|
||||
- /* printf format a la PRId... for a PTRVAL */
|
||||
-
|
||||
-#define ELF_MAKE_HANDLE(structname, ptrval) (ptrval)
|
||||
+#define ELF_MAKE_HANDLE(structname, ptrval) ((structname##_handle){ ptrval })
|
||||
/* Converts a PTRVAL to a HANDLE */
|
||||
|
||||
-#define ELF_IMAGE_BASE(elf) ((elf)->image)
|
||||
+#define ELF_IMAGE_BASE(elf) ((elf_ptrval)(elf)->image_base)
|
||||
/* Returns the base of the image as a PTRVAL. */
|
||||
|
||||
-#define ELF_HANDLE_PTRVAL(handleval) ((void*)(handleval))
|
||||
+#define ELF_HANDLE_PTRVAL(handleval) ((handleval).ptrval)
|
||||
/* Converts a HANDLE to a PTRVAL. */
|
||||
|
||||
-#define ELF_OBSOLETE_VOIDP_CAST (void*)(uintptr_t)
|
||||
+#define ELF_OBSOLETE_VOIDP_CAST /*empty*/
|
||||
/*
|
||||
- * In some places the existing code needs to
|
||||
+ * In some places the old code used to need to
|
||||
* - cast away const (the existing code uses const a fair
|
||||
* bit but actually sometimes wants to write to its input)
|
||||
* from a PTRVAL.
|
||||
* - convert an integer representing a pointer to a PTRVAL
|
||||
- * This macro provides a suitable cast.
|
||||
+ * Nowadays all of these re uintptr_ts so there is no const problem
|
||||
+ * and no need for any casting.
|
||||
*/
|
||||
|
||||
-#define ELF_UNSAFE_PTR(ptrval) ((void*)(uintptr_t)(ptrval))
|
||||
+#define ELF_UNSAFE_PTR(ptrval) ((void*)(elf_ptrval)(ptrval))
|
||||
/*
|
||||
* Turns a PTRVAL into an actual C pointer. Before this is done
|
||||
* the caller must have ensured that the PTRVAL does in fact point
|
||||
@@ -122,18 +135,21 @@ typedef void elf_log_callback(struct elf_binary*, void *caller_data,
|
||||
*/
|
||||
|
||||
/* PTRVALs can be INVALID (ie, NULL). */
|
||||
-#define ELF_INVALID_PTRVAL (NULL) /* returns NULL PTRVAL */
|
||||
+#define ELF_INVALID_PTRVAL ((elf_ptrval)0) /* returns NULL PTRVAL */
|
||||
#define ELF_INVALID_HANDLE(structname) /* returns NULL handle */ \
|
||||
ELF_MAKE_HANDLE(structname, ELF_INVALID_PTRVAL)
|
||||
-#define ELF_PTRVAL_VALID(ptrval) (ptrval) /* } */
|
||||
-#define ELF_HANDLE_VALID(handleval) (handleval) /* } predicates */
|
||||
-#define ELF_PTRVAL_INVALID(ptrval) ((ptrval) == NULL) /* } */
|
||||
+#define ELF_PTRVAL_VALID(ptrval) (!!(ptrval)) /* } */
|
||||
+#define ELF_HANDLE_VALID(handleval) (!!(handleval).ptrval) /* } predicates */
|
||||
+#define ELF_PTRVAL_INVALID(ptrval) (!ELF_PTRVAL_VALID((ptrval))) /* } */
|
||||
+
|
||||
+#define ELF_MAX_PTRVAL (~(elf_ptrval)0)
|
||||
+ /* PTRVAL value guaranteed to compare > to any valid PTRVAL */
|
||||
|
||||
/* For internal use by other macros here */
|
||||
#define ELF__HANDLE_FIELD_TYPE(handleval, elm) \
|
||||
- typeof((handleval)->elm)
|
||||
+ typeof((handleval).typeonly->elm)
|
||||
#define ELF__HANDLE_FIELD_OFFSET(handleval, elm) \
|
||||
- offsetof(typeof(*(handleval)),elm)
|
||||
+ offsetof(typeof(*(handleval).typeonly),elm)
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
@@ -182,7 +198,7 @@ ELF_DEFINE_HANDLE(elf_note)
|
||||
|
||||
struct elf_binary {
|
||||
/* elf binary */
|
||||
- const char *image;
|
||||
+ const void *image_base;
|
||||
size_t size;
|
||||
char class;
|
||||
char data;
|
||||
@@ -190,10 +206,16 @@ struct elf_binary {
|
||||
ELF_HANDLE_DECL(elf_ehdr) ehdr;
|
||||
ELF_PTRVAL_CONST_CHAR sec_strtab;
|
||||
ELF_HANDLE_DECL(elf_shdr) sym_tab;
|
||||
- ELF_PTRVAL_CONST_CHAR sym_strtab;
|
||||
+ uint64_t sym_strtab;
|
||||
|
||||
/* loaded to */
|
||||
- char *dest;
|
||||
+ /*
|
||||
+ * dest_base and dest_size are trusted and must be correct;
|
||||
+ * whenever dest_size is not 0, both of these must be valid
|
||||
+ * so long as the struct elf_binary is in use.
|
||||
+ */
|
||||
+ char *dest_base;
|
||||
+ size_t dest_size;
|
||||
uint64_t pstart;
|
||||
uint64_t pend;
|
||||
uint64_t reloc_offset;
|
||||
@@ -201,12 +223,22 @@ struct elf_binary {
|
||||
uint64_t bsd_symtab_pstart;
|
||||
uint64_t bsd_symtab_pend;
|
||||
|
||||
+ /*
|
||||
+ * caller's other acceptable destination
|
||||
+ *
|
||||
+ * Again, these are trusted and must be valid (or 0) so long
|
||||
+ * as the struct elf_binary is in use.
|
||||
+ */
|
||||
+ void *caller_xdest_base;
|
||||
+ uint64_t caller_xdest_size;
|
||||
+
|
||||
#ifndef __XEN__
|
||||
/* misc */
|
||||
elf_log_callback *log_callback;
|
||||
void *log_caller_data;
|
||||
#endif
|
||||
int verbose;
|
||||
+ const char *broken;
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
@@ -224,22 +256,27 @@ struct elf_binary {
|
||||
#define elf_lsb(elf) (ELFDATA2LSB == (elf)->data)
|
||||
#define elf_swap(elf) (NATIVE_ELFDATA != (elf)->data)
|
||||
|
||||
-#define elf_uval(elf, str, elem) \
|
||||
- ((ELFCLASS64 == (elf)->class) \
|
||||
- ? elf_access_unsigned((elf), (str), \
|
||||
- offsetof(typeof(*(str)),e64.elem), \
|
||||
- sizeof((str)->e64.elem)) \
|
||||
- : elf_access_unsigned((elf), (str), \
|
||||
- offsetof(typeof(*(str)),e32.elem), \
|
||||
- sizeof((str)->e32.elem)))
|
||||
+#define elf_uval_3264(elf, handle, elem) \
|
||||
+ elf_access_unsigned((elf), (handle).ptrval, \
|
||||
+ offsetof(typeof(*(handle).typeonly),elem), \
|
||||
+ sizeof((handle).typeonly->elem))
|
||||
+
|
||||
+#define elf_uval(elf, handle, elem) \
|
||||
+ ((ELFCLASS64 == (elf)->class) \
|
||||
+ ? elf_uval_3264(elf, handle, e64.elem) \
|
||||
+ : elf_uval_3264(elf, handle, e32.elem))
|
||||
/*
|
||||
* Reads an unsigned field in a header structure in the ELF.
|
||||
* str is a HANDLE, and elem is the field name in it.
|
||||
*/
|
||||
|
||||
-#define elf_size(elf, str) \
|
||||
+
|
||||
+#define elf_size(elf, handle_or_handletype) ({ \
|
||||
+ typeof(handle_or_handletype) elf_size__dummy; \
|
||||
((ELFCLASS64 == (elf)->class) \
|
||||
- ? sizeof((str)->e64) : sizeof((str)->e32))
|
||||
+ ? sizeof(elf_size__dummy.typeonly->e64) \
|
||||
+ : sizeof(elf_size__dummy.typeonly->e32)); \
|
||||
+})
|
||||
/*
|
||||
* Returns the size of the substructure for the appropriate 32/64-bitness.
|
||||
* str should be a HANDLE.
|
||||
@@ -251,23 +288,37 @@ uint64_t elf_access_unsigned(struct elf_binary *elf, ELF_PTRVAL_CONST_VOID ptr,
|
||||
|
||||
uint64_t elf_round_up(struct elf_binary *elf, uint64_t addr);
|
||||
|
||||
+const char *elf_strval(struct elf_binary *elf, elf_ptrval start);
|
||||
+ /* may return NULL if the string is out of range etc. */
|
||||
|
||||
-#define elf_strval(elf,x) ((const char*)(x)) /* may return NULL in the future */
|
||||
-#define elf_strfmt(elf,x) ((const char*)(x)) /* will return (invalid) instead */
|
||||
+const char *elf_strfmt(struct elf_binary *elf, elf_ptrval start);
|
||||
+ /* like elf_strval but returns "(invalid)" instead of NULL */
|
||||
|
||||
-#define elf_memcpy_safe(elf, dst, src, sz) memcpy((dst),(src),(sz))
|
||||
-#define elf_memset_safe(elf, dst, c, sz) memset((dst),(c),(sz))
|
||||
+void elf_memcpy_safe(struct elf_binary*, elf_ptrval dst, elf_ptrval src, size_t);
|
||||
+void elf_memset_safe(struct elf_binary*, elf_ptrval dst, int c, size_t);
|
||||
/*
|
||||
- * Versions of memcpy and memset which will (in the next patch)
|
||||
- * arrange never to write outside permitted areas.
|
||||
+ * Versions of memcpy and memset which arrange never to write
|
||||
+ * outside permitted areas.
|
||||
*/
|
||||
|
||||
-#define elf_store_val(elf, type, ptr, val) (*(type*)(ptr) = (val))
|
||||
+int elf_access_ok(struct elf_binary * elf,
|
||||
+ uint64_t ptrval, size_t size);
|
||||
+
|
||||
+#define elf_store_val(elf, type, ptr, val) \
|
||||
+ ({ \
|
||||
+ typeof(type) elf_store__val = (val); \
|
||||
+ elf_ptrval elf_store__targ = ptr; \
|
||||
+ if (elf_access_ok((elf), elf_store__targ, \
|
||||
+ sizeof(elf_store__val))) { \
|
||||
+ elf_memcpy_unchecked((void*)elf_store__targ, &elf_store__val, \
|
||||
+ sizeof(elf_store__val)); \
|
||||
+ } \
|
||||
+ }) \
|
||||
/* Stores a value at a particular PTRVAL. */
|
||||
|
||||
-#define elf_store_field(elf, hdr, elm, val) \
|
||||
- (elf_store_val((elf), ELF__HANDLE_FIELD_TYPE(hdr, elm), \
|
||||
- &((hdr)->elm), \
|
||||
+#define elf_store_field(elf, hdr, elm, val) \
|
||||
+ (elf_store_val((elf), ELF__HANDLE_FIELD_TYPE(hdr, elm), \
|
||||
+ ELF_HANDLE_PTRVAL(hdr) + ELF__HANDLE_FIELD_OFFSET(hdr, elm), \
|
||||
(val)))
|
||||
/* Stores a 32/64-bit field. hdr is a HANDLE and elm is the field name. */
|
||||
|
||||
@@ -306,6 +357,10 @@ int elf_phdr_is_loadable(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr)
|
||||
/* xc_libelf_loader.c */
|
||||
|
||||
int elf_init(struct elf_binary *elf, const char *image, size_t size);
|
||||
+ /*
|
||||
+ * image and size must be correct. They will be recorded in
|
||||
+ * *elf, and must remain valid while the elf is in use.
|
||||
+ */
|
||||
#ifdef __XEN__
|
||||
void elf_set_verbose(struct elf_binary *elf);
|
||||
#else
|
||||
@@ -321,6 +376,9 @@ uint64_t elf_lookup_addr(struct elf_binary *elf, const char *symbol);
|
||||
|
||||
void elf_parse_bsdsyms(struct elf_binary *elf, uint64_t pstart); /* private */
|
||||
|
||||
+void elf_mark_broken(struct elf_binary *elf, const char *msg);
|
||||
+const char *elf_check_broken(const struct elf_binary *elf); /* NULL means OK */
|
||||
+
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* xc_libelf_relocate.c */
|
||||
|
||||
@@ -395,16 +453,38 @@ int elf_xen_parse_guest_info(struct elf_binary *elf,
|
||||
int elf_xen_parse(struct elf_binary *elf,
|
||||
struct elf_dom_parms *parms);
|
||||
|
||||
-#define elf_memcpy_unchecked memcpy
|
||||
-#define elf_memset_unchecked memset
|
||||
+static inline void *elf_memcpy_unchecked(void *dest, const void *src, size_t n)
|
||||
+ { return memcpy(dest, src, n); }
|
||||
+static inline void *elf_memmove_unchecked(void *dest, const void *src, size_t n)
|
||||
+ { return memmove(dest, src, n); }
|
||||
+static inline void *elf_memset_unchecked(void *s, int c, size_t n)
|
||||
+ { return memset(s, c, n); }
|
||||
/*
|
||||
- * Unsafe versions of memcpy and memset which take actual C
|
||||
- * pointers. These are just like real memcpy and memset.
|
||||
+ * Unsafe versions of memcpy, memmove memset which take actual C
|
||||
+ * pointers. These are just like the real functions.
|
||||
+ * We provide these so that in libelf-private.h we can #define
|
||||
+ * memcpy, memset and memmove to undefined MISTAKE things.
|
||||
*/
|
||||
|
||||
|
||||
-#define ELF_ADVANCE_DEST(elf, amount) elf->dest += (amount)
|
||||
- /* Advances past amount bytes of the current destination area. */
|
||||
+/* Advances past amount bytes of the current destination area. */
|
||||
+static inline void ELF_ADVANCE_DEST(struct elf_binary *elf, uint64_t amount)
|
||||
+{
|
||||
+ if ( elf->dest_base == NULL )
|
||||
+ {
|
||||
+ elf_mark_broken(elf, "advancing in null image");
|
||||
+ }
|
||||
+ else if ( elf->dest_size >= amount )
|
||||
+ {
|
||||
+ elf->dest_base += amount;
|
||||
+ elf->dest_size -= amount;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ elf->dest_size = 0;
|
||||
+ elf_mark_broken(elf, "advancing past end (image very short?)");
|
||||
+ }
|
||||
+}
|
||||
|
||||
|
||||
#endif /* __XEN_LIBELF_H__ */
|
||||
--
|
||||
1.7.2.5
|
||||
|
@ -0,0 +1,371 @@
|
||||
From d0790bdad7496e720416b2d4a04563c4c27e7b95 Mon Sep 17 00:00:00 2001
|
||||
From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Date: Fri, 14 Jun 2013 16:43:17 +0100
|
||||
Subject: [PATCH 12/23] libelf: Check pointer references in elf_is_elfbinary
|
||||
|
||||
elf_is_elfbinary didn't take a length parameter and could potentially
|
||||
access out of range when provided with a very short image.
|
||||
|
||||
We only need to check the size is enough for the actual dereference in
|
||||
elf_is_elfbinary; callers are just using it to check the magic number
|
||||
and do their own checks (usually via the new elf_ptrval system) before
|
||||
dereferencing other parts of the header.
|
||||
|
||||
This is part of the fix to a security issue, XSA-55.
|
||||
|
||||
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
|
||||
---
|
||||
tools/libxc/xc_dom_elfloader.c | 2 +-
|
||||
xen/arch/x86/bzimage.c | 4 ++--
|
||||
xen/common/libelf/libelf-loader.c | 2 +-
|
||||
xen/common/libelf/libelf-tools.c | 9 ++++++---
|
||||
xen/include/xen/libelf.h | 4 +++-
|
||||
5 files changed, 13 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c
|
||||
index b82a08c..ea45886 100644
|
||||
--- a/tools/libxc/xc_dom_elfloader.c
|
||||
+++ b/tools/libxc/xc_dom_elfloader.c
|
||||
@@ -95,7 +95,7 @@ static int check_elf_kernel(struct xc_dom_image *dom, int verbose)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
- if ( !elf_is_elfbinary(dom->kernel_blob) )
|
||||
+ if ( !elf_is_elfbinary(dom->kernel_blob, dom->kernel_size) )
|
||||
{
|
||||
if ( verbose )
|
||||
xc_dom_panic(dom->xch,
|
||||
diff --git a/xen/arch/x86/bzimage.c b/xen/arch/x86/bzimage.c
|
||||
index 5adc223..3600dca 100644
|
||||
--- a/xen/arch/x86/bzimage.c
|
||||
+++ b/xen/arch/x86/bzimage.c
|
||||
@@ -220,7 +220,7 @@ unsigned long __init bzimage_headroom(char *image_start,
|
||||
image_length = hdr->payload_length;
|
||||
}
|
||||
|
||||
- if ( elf_is_elfbinary(image_start) )
|
||||
+ if ( elf_is_elfbinary(image_start, image_length) )
|
||||
return 0;
|
||||
|
||||
orig_image_len = image_length;
|
||||
@@ -251,7 +251,7 @@ int __init bzimage_parse(char *image_base, char **image_start, unsigned long *im
|
||||
*image_len = hdr->payload_length;
|
||||
}
|
||||
|
||||
- if ( elf_is_elfbinary(*image_start) )
|
||||
+ if ( elf_is_elfbinary(*image_start, *image_len) )
|
||||
return 0;
|
||||
|
||||
BUG_ON(!(image_base < *image_start));
|
||||
diff --git a/xen/common/libelf/libelf-loader.c b/xen/common/libelf/libelf-loader.c
|
||||
index a3310e7..f8be635 100644
|
||||
--- a/xen/common/libelf/libelf-loader.c
|
||||
+++ b/xen/common/libelf/libelf-loader.c
|
||||
@@ -29,7 +29,7 @@ int elf_init(struct elf_binary *elf, const char *image_input, size_t size)
|
||||
ELF_HANDLE_DECL(elf_shdr) shdr;
|
||||
uint64_t i, count, section, offset;
|
||||
|
||||
- if ( !elf_is_elfbinary(image_input) )
|
||||
+ if ( !elf_is_elfbinary(image_input, size) )
|
||||
{
|
||||
elf_err(elf, "%s: not an ELF binary\n", __FUNCTION__);
|
||||
return -1;
|
||||
diff --git a/xen/common/libelf/libelf-tools.c b/xen/common/libelf/libelf-tools.c
|
||||
index 46ca553..744027e 100644
|
||||
--- a/xen/common/libelf/libelf-tools.c
|
||||
+++ b/xen/common/libelf/libelf-tools.c
|
||||
@@ -332,11 +332,14 @@ ELF_HANDLE_DECL(elf_note) elf_note_next(struct elf_binary *elf, ELF_HANDLE_DECL(
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
-int elf_is_elfbinary(const void *image)
|
||||
+int elf_is_elfbinary(const void *image_start, size_t image_size)
|
||||
{
|
||||
- const Elf32_Ehdr *ehdr = image;
|
||||
+ const Elf32_Ehdr *ehdr = image_start;
|
||||
|
||||
- return IS_ELF(*ehdr); /* fixme unchecked */
|
||||
+ if ( image_size < sizeof(*ehdr) )
|
||||
+ return 0;
|
||||
+
|
||||
+ return IS_ELF(*ehdr);
|
||||
}
|
||||
|
||||
int elf_phdr_is_loadable(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr)
|
||||
diff --git a/xen/include/xen/libelf.h b/xen/include/xen/libelf.h
|
||||
index ddc3ed7..ac93858 100644
|
||||
--- a/xen/include/xen/libelf.h
|
||||
+++ b/xen/include/xen/libelf.h
|
||||
@@ -350,7 +350,9 @@ uint64_t elf_note_numeric_array(struct elf_binary *, ELF_HANDLE_DECL(elf_note),
|
||||
unsigned int unitsz, unsigned int idx);
|
||||
ELF_HANDLE_DECL(elf_note) elf_note_next(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
|
||||
|
||||
-int elf_is_elfbinary(const void *image);
|
||||
+/* (Only) checks that the image has the right magic number. */
|
||||
+int elf_is_elfbinary(const void *image_start, size_t image_size);
|
||||
+
|
||||
int elf_phdr_is_loadable(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr);
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
--
|
||||
1.7.2.5
|
||||
#From a965b8f80388603d439ae2b8ee7b9b018a079f90 Mon Sep 17 00:00:00 2001
|
||||
#From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
#Date: Fri, 14 Jun 2013 16:43:17 +0100
|
||||
#Subject: [PATCH 13/23] libelf: Make all callers call elf_check_broken
|
||||
#
|
||||
#This arranges that if the new pointer reference error checking
|
||||
#tripped, we actually get a message about it. In this patch these
|
||||
#messages do not change the actual return values from the various
|
||||
#functions: so pointer reference errors do not prevent loading. This
|
||||
#is for fear that some existing kernels might cause the code to make
|
||||
#these wild references, which would then break, which is not a good
|
||||
#thing in a security patch.
|
||||
#
|
||||
#In xen/arch/x86/domain_build.c we have to introduce an "out" label and
|
||||
#change all of the "return rc" beyond the relevant point into "goto
|
||||
#out".
|
||||
#
|
||||
#Difference in the 4.2 series, compared to unstable:
|
||||
#
|
||||
#* tools/libxc/xc_hvm_build_x86.c:setup_guest and
|
||||
# xen/arch/arm/kernel.c:kernel_try_elf_prepare have different
|
||||
# error handling in 4.2 to unstable; patch adjusted accordingly.
|
||||
#
|
||||
#This is part of the fix to a security issue, XSA-55.
|
||||
#
|
||||
#Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
#
|
||||
#xen-unstable version Reviewed-by: George Dunlap <george.dunlap@eu.citrix.com>
|
||||
#---
|
||||
# tools/libxc/xc_dom_elfloader.c | 25 +++++++++++++++++++++----
|
||||
# tools/libxc/xc_hvm_build_x86.c | 5 +++++
|
||||
# tools/xcutils/readnotes.c | 3 +++
|
||||
# xen/arch/arm/kernel.c | 15 ++++++++++++++-
|
||||
# xen/arch/x86/domain_build.c | 28 +++++++++++++++++++++-------
|
||||
# 5 files changed, 64 insertions(+), 12 deletions(-)
|
||||
#
|
||||
diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c
|
||||
index ea45886..4fb4da2 100644
|
||||
--- a/tools/libxc/xc_dom_elfloader.c
|
||||
+++ b/tools/libxc/xc_dom_elfloader.c
|
||||
@@ -276,6 +276,13 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
elf_store_field(elf, shdr, e32.sh_name, 0);
|
||||
}
|
||||
|
||||
+ if ( elf_check_broken(&syms) )
|
||||
+ DOMPRINTF("%s: symbols ELF broken: %s", __FUNCTION__,
|
||||
+ elf_check_broken(&syms));
|
||||
+ if ( elf_check_broken(elf) )
|
||||
+ DOMPRINTF("%s: ELF broken: %s", __FUNCTION__,
|
||||
+ elf_check_broken(elf));
|
||||
+
|
||||
if ( tables == 0 )
|
||||
{
|
||||
DOMPRINTF("%s: no symbol table present", __FUNCTION__);
|
||||
@@ -312,19 +319,23 @@ static int xc_dom_parse_elf_kernel(struct xc_dom_image *dom)
|
||||
{
|
||||
xc_dom_panic(dom->xch, XC_INVALID_KERNEL, "%s: ELF image"
|
||||
" has no shstrtab", __FUNCTION__);
|
||||
- return -EINVAL;
|
||||
+ rc = -EINVAL;
|
||||
+ goto out;
|
||||
}
|
||||
|
||||
/* parse binary and get xen meta info */
|
||||
elf_parse_binary(elf);
|
||||
if ( (rc = elf_xen_parse(elf, &dom->parms)) != 0 )
|
||||
- return rc;
|
||||
+ {
|
||||
+ goto out;
|
||||
+ }
|
||||
|
||||
if ( elf_xen_feature_get(XENFEAT_dom0, dom->parms.f_required) )
|
||||
{
|
||||
xc_dom_panic(dom->xch, XC_INVALID_KERNEL, "%s: Kernel does not"
|
||||
" support unprivileged (DomU) operation", __FUNCTION__);
|
||||
- return -EINVAL;
|
||||
+ rc = -EINVAL;
|
||||
+ goto out;
|
||||
}
|
||||
|
||||
/* find kernel segment */
|
||||
@@ -338,7 +349,13 @@ static int xc_dom_parse_elf_kernel(struct xc_dom_image *dom)
|
||||
DOMPRINTF("%s: %s: 0x%" PRIx64 " -> 0x%" PRIx64 "",
|
||||
__FUNCTION__, dom->guest_type,
|
||||
dom->kernel_seg.vstart, dom->kernel_seg.vend);
|
||||
- return 0;
|
||||
+ rc = 0;
|
||||
+out:
|
||||
+ if ( elf_check_broken(elf) )
|
||||
+ DOMPRINTF("%s: ELF broken: %s", __FUNCTION__,
|
||||
+ elf_check_broken(elf));
|
||||
+
|
||||
+ return rc;
|
||||
}
|
||||
|
||||
static int xc_dom_load_elf_kernel(struct xc_dom_image *dom)
|
||||
diff --git a/tools/libxc/xc_hvm_build_x86.c b/tools/libxc/xc_hvm_build_x86.c
|
||||
index ccfd8b5..8165287 100644
|
||||
--- a/tools/libxc/xc_hvm_build_x86.c
|
||||
+++ b/tools/libxc/xc_hvm_build_x86.c
|
||||
@@ -403,11 +403,16 @@ static int setup_guest(xc_interface *xch,
|
||||
munmap(page0, PAGE_SIZE);
|
||||
}
|
||||
|
||||
+ if ( elf_check_broken(&elf) )
|
||||
+ ERROR("HVM ELF broken: %s", elf_check_broken(&elf));
|
||||
+
|
||||
free(page_array);
|
||||
return 0;
|
||||
|
||||
error_out:
|
||||
free(page_array);
|
||||
+ if ( elf_check_broken(&elf) )
|
||||
+ ERROR("HVM ELF broken, failing: %s", elf_check_broken(&elf));
|
||||
return -1;
|
||||
}
|
||||
|
||||
diff --git a/tools/xcutils/readnotes.c b/tools/xcutils/readnotes.c
|
||||
index cfae994..d1f7a30 100644
|
||||
--- a/tools/xcutils/readnotes.c
|
||||
+++ b/tools/xcutils/readnotes.c
|
||||
@@ -301,6 +301,9 @@ int main(int argc, char **argv)
|
||||
printf("__xen_guest: %s\n",
|
||||
elf_strfmt(&elf, elf_section_start(&elf, shdr)));
|
||||
|
||||
+ if (elf_check_broken(&elf))
|
||||
+ printf("warning: broken ELF: %s\n", elf_check_broken(&elf));
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
diff --git a/xen/arch/arm/kernel.c b/xen/arch/arm/kernel.c
|
||||
index 2d56130..dec0519 100644
|
||||
--- a/xen/arch/arm/kernel.c
|
||||
+++ b/xen/arch/arm/kernel.c
|
||||
@@ -146,6 +146,8 @@ static int kernel_try_elf_prepare(struct kernel_info *info)
|
||||
{
|
||||
int rc;
|
||||
|
||||
+ memset(&info->elf.elf, 0, sizeof(info->elf.elf));
|
||||
+
|
||||
info->kernel_order = get_order_from_bytes(KERNEL_FLASH_SIZE);
|
||||
info->kernel_img = alloc_xenheap_pages(info->kernel_order, 0);
|
||||
if ( info->kernel_img == NULL )
|
||||
@@ -160,7 +162,7 @@ static int kernel_try_elf_prepare(struct kernel_info *info)
|
||||
#endif
|
||||
elf_parse_binary(&info->elf.elf);
|
||||
if ( (rc = elf_xen_parse(&info->elf.elf, &info->elf.parms)) != 0 )
|
||||
- return rc;
|
||||
+ goto err;
|
||||
|
||||
/*
|
||||
* TODO: can the ELF header be used to find the physical address
|
||||
@@ -169,7 +171,18 @@ static int kernel_try_elf_prepare(struct kernel_info *info)
|
||||
info->entry = info->elf.parms.virt_entry;
|
||||
info->load = kernel_elf_load;
|
||||
|
||||
+ if ( elf_check_broken(&info->elf.elf) )
|
||||
+ printk("Xen: warning: ELF kernel broken: %s\n",
|
||||
+ elf_check_broken(&info->elf.elf));
|
||||
+
|
||||
return 0;
|
||||
+
|
||||
+err:
|
||||
+ if ( elf_check_broken(&info->elf.elf) )
|
||||
+ printk("Xen: ELF kernel broken: %s\n",
|
||||
+ elf_check_broken(&info->elf.elf));
|
||||
+
|
||||
+ return rc;
|
||||
}
|
||||
|
||||
int kernel_prepare(struct kernel_info *info)
|
||||
diff --git a/xen/arch/x86/domain_build.c b/xen/arch/x86/domain_build.c
|
||||
index a655b21..0dbec96 100644
|
||||
--- a/xen/arch/x86/domain_build.c
|
||||
+++ b/xen/arch/x86/domain_build.c
|
||||
@@ -374,7 +374,7 @@ int __init construct_dom0(
|
||||
#endif
|
||||
elf_parse_binary(&elf);
|
||||
if ( (rc = elf_xen_parse(&elf, &parms)) != 0 )
|
||||
- return rc;
|
||||
+ goto out;
|
||||
|
||||
/* compatibility check */
|
||||
compatible = 0;
|
||||
@@ -413,14 +413,16 @@ int __init construct_dom0(
|
||||
if ( !compatible )
|
||||
{
|
||||
printk("Mismatch between Xen and DOM0 kernel\n");
|
||||
- return -EINVAL;
|
||||
+ rc = -EINVAL;
|
||||
+ goto out;
|
||||
}
|
||||
|
||||
if ( parms.elf_notes[XEN_ELFNOTE_SUPPORTED_FEATURES].type != XEN_ENT_NONE &&
|
||||
!test_bit(XENFEAT_dom0, parms.f_supported) )
|
||||
{
|
||||
printk("Kernel does not support Dom0 operation\n");
|
||||
- return -EINVAL;
|
||||
+ rc = -EINVAL;
|
||||
+ goto out;
|
||||
}
|
||||
|
||||
#if defined(__x86_64__)
|
||||
@@ -734,7 +736,8 @@ int __init construct_dom0(
|
||||
(v_end > HYPERVISOR_COMPAT_VIRT_START(d)) )
|
||||
{
|
||||
printk("DOM0 image overlaps with Xen private area.\n");
|
||||
- return -EINVAL;
|
||||
+ rc = -EINVAL;
|
||||
+ goto out;
|
||||
}
|
||||
|
||||
if ( is_pv_32on64_domain(d) )
|
||||
@@ -914,7 +917,7 @@ int __init construct_dom0(
|
||||
if ( rc < 0 )
|
||||
{
|
||||
printk("Failed to load the kernel binary\n");
|
||||
- return rc;
|
||||
+ goto out;
|
||||
}
|
||||
bootstrap_map(NULL);
|
||||
|
||||
@@ -925,7 +928,8 @@ int __init construct_dom0(
|
||||
{
|
||||
write_ptbase(current);
|
||||
printk("Invalid HYPERCALL_PAGE field in ELF notes.\n");
|
||||
- return -1;
|
||||
+ rc = -1;
|
||||
+ goto out;
|
||||
}
|
||||
hypercall_page_initialise(
|
||||
d, (void *)(unsigned long)parms.virt_hypercall);
|
||||
@@ -1272,9 +1276,19 @@ int __init construct_dom0(
|
||||
|
||||
BUG_ON(rc != 0);
|
||||
|
||||
- iommu_dom0_init(dom0);
|
||||
+ if ( elf_check_broken(&elf) )
|
||||
+ printk(" Xen warning: dom0 kernel broken ELF: %s\n",
|
||||
+ elf_check_broken(&elf));
|
||||
|
||||
+ iommu_dom0_init(dom0);
|
||||
return 0;
|
||||
+
|
||||
+out:
|
||||
+ if ( elf_check_broken(&elf) )
|
||||
+ printk(" Xen dom0 kernel broken ELF: %s\n",
|
||||
+ elf_check_broken(&elf));
|
||||
+
|
||||
+ return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
--
|
||||
1.7.2.5
|
||||
|
||||
|
@ -0,0 +1,252 @@
|
||||
From 3fb6ccf2faccaf5e22e33a3155ccc72d732896d8 Mon Sep 17 00:00:00 2001
|
||||
From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Date: Fri, 14 Jun 2013 16:43:18 +0100
|
||||
Subject: [PATCH 14/23] libelf: use C99 bool for booleans
|
||||
|
||||
We want to remove uses of "int" because signed integers have
|
||||
undesirable undefined behaviours on overflow. Malicious compilers can
|
||||
turn apparently-correct code into code with security vulnerabilities
|
||||
etc.
|
||||
|
||||
In this patch we change all the booleans in libelf to C99 bool,
|
||||
from <stdbool.h>.
|
||||
|
||||
For the one visible libelf boolean in libxc's public interface we
|
||||
retain the use of int to avoid changing the ABI; libxc converts it to
|
||||
a bool for consumption by libelf.
|
||||
|
||||
It is OK to change all values only ever used as booleans to _Bool
|
||||
(bool) because conversion from any scalar type to a _Bool works the
|
||||
same as the boolean test in if() or ?: and is always defined (C99
|
||||
6.3.1.2). But we do need to check that all these variables really are
|
||||
only ever used that way. (It is theoretically possible that the old
|
||||
code truncated some 64-bit values to 32-bit ints which might become
|
||||
zero depending on the value, which would mean a behavioural change in
|
||||
this patch, but it seems implausible that treating 0x????????00000000
|
||||
as false could have been intended.)
|
||||
|
||||
This is part of the fix to a security issue, XSA-55.
|
||||
|
||||
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Acked-by: George Dunlap <george.dunlap@eu.citrix.com>
|
||||
---
|
||||
tools/libxc/xc_dom_elfloader.c | 8 ++++----
|
||||
xen/common/libelf/libelf-dominfo.c | 2 +-
|
||||
xen/common/libelf/libelf-loader.c | 4 ++--
|
||||
xen/common/libelf/libelf-private.h | 2 +-
|
||||
xen/common/libelf/libelf-tools.c | 10 +++++-----
|
||||
xen/include/xen/libelf.h | 18 ++++++++++--------
|
||||
6 files changed, 23 insertions(+), 21 deletions(-)
|
||||
|
||||
diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c
|
||||
index 4fb4da2..9ba64ae 100644
|
||||
--- a/tools/libxc/xc_dom_elfloader.c
|
||||
+++ b/tools/libxc/xc_dom_elfloader.c
|
||||
@@ -34,7 +34,7 @@
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
static void log_callback(struct elf_binary *elf, void *caller_data,
|
||||
- int iserr, const char *fmt, va_list al) {
|
||||
+ bool iserr, const char *fmt, va_list al) {
|
||||
xc_interface *xch = caller_data;
|
||||
|
||||
xc_reportv(xch,
|
||||
@@ -46,7 +46,7 @@ static void log_callback(struct elf_binary *elf, void *caller_data,
|
||||
|
||||
void xc_elf_set_logfile(xc_interface *xch, struct elf_binary *elf,
|
||||
int verbose) {
|
||||
- elf_set_log(elf, log_callback, xch, verbose);
|
||||
+ elf_set_log(elf, log_callback, xch, verbose /* convert to bool */);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
@@ -84,7 +84,7 @@ static char *xc_dom_guest_type(struct xc_dom_image *dom,
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* parse elf binary */
|
||||
|
||||
-static int check_elf_kernel(struct xc_dom_image *dom, int verbose)
|
||||
+static int check_elf_kernel(struct xc_dom_image *dom, bool verbose)
|
||||
{
|
||||
if ( dom->kernel_blob == NULL )
|
||||
{
|
||||
@@ -112,7 +112,7 @@ static int xc_dom_probe_elf_kernel(struct xc_dom_image *dom)
|
||||
}
|
||||
|
||||
static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
- struct elf_binary *elf, int load)
|
||||
+ struct elf_binary *elf, bool load)
|
||||
{
|
||||
struct elf_binary syms;
|
||||
ELF_HANDLE_DECL_NONCONST(elf_shdr) shdr; ELF_HANDLE_DECL(elf_shdr) shdr2;
|
||||
diff --git a/xen/common/libelf/libelf-dominfo.c b/xen/common/libelf/libelf-dominfo.c
|
||||
index 98c80dc..12b6c2a 100644
|
||||
--- a/xen/common/libelf/libelf-dominfo.c
|
||||
+++ b/xen/common/libelf/libelf-dominfo.c
|
||||
@@ -101,7 +101,7 @@ int elf_xen_parse_note(struct elf_binary *elf,
|
||||
/* *INDENT-OFF* */
|
||||
static const struct {
|
||||
char *name;
|
||||
- int str;
|
||||
+ bool str;
|
||||
} note_desc[] = {
|
||||
[XEN_ELFNOTE_ENTRY] = { "ENTRY", 0},
|
||||
[XEN_ELFNOTE_HYPERCALL_PAGE] = { "HYPERCALL_PAGE", 0},
|
||||
diff --git a/xen/common/libelf/libelf-loader.c b/xen/common/libelf/libelf-loader.c
|
||||
index f8be635..0dccd4d 100644
|
||||
--- a/xen/common/libelf/libelf-loader.c
|
||||
+++ b/xen/common/libelf/libelf-loader.c
|
||||
@@ -92,7 +92,7 @@ int elf_init(struct elf_binary *elf, const char *image_input, size_t size)
|
||||
}
|
||||
|
||||
#ifndef __XEN__
|
||||
-void elf_call_log_callback(struct elf_binary *elf, int iserr,
|
||||
+void elf_call_log_callback(struct elf_binary *elf, bool iserr,
|
||||
const char *fmt,...) {
|
||||
va_list al;
|
||||
|
||||
@@ -107,7 +107,7 @@ void elf_call_log_callback(struct elf_binary *elf, int iserr,
|
||||
}
|
||||
|
||||
void elf_set_log(struct elf_binary *elf, elf_log_callback *log_callback,
|
||||
- void *log_caller_data, int verbose)
|
||||
+ void *log_caller_data, bool verbose)
|
||||
{
|
||||
elf->log_callback = log_callback;
|
||||
elf->log_caller_data = log_caller_data;
|
||||
diff --git a/xen/common/libelf/libelf-private.h b/xen/common/libelf/libelf-private.h
|
||||
index 280dfd1..277be04 100644
|
||||
--- a/xen/common/libelf/libelf-private.h
|
||||
+++ b/xen/common/libelf/libelf-private.h
|
||||
@@ -77,7 +77,7 @@
|
||||
#define elf_err(elf, fmt, args ... ) \
|
||||
elf_call_log_callback(elf, 1, fmt , ## args );
|
||||
|
||||
-void elf_call_log_callback(struct elf_binary*, int iserr, const char *fmt,...);
|
||||
+void elf_call_log_callback(struct elf_binary*, bool iserr, const char *fmt,...);
|
||||
|
||||
#define safe_strcpy(d,s) \
|
||||
do { strncpy((d),(s),sizeof((d))-1); \
|
||||
diff --git a/xen/common/libelf/libelf-tools.c b/xen/common/libelf/libelf-tools.c
|
||||
index 744027e..fa58f76 100644
|
||||
--- a/xen/common/libelf/libelf-tools.c
|
||||
+++ b/xen/common/libelf/libelf-tools.c
|
||||
@@ -31,7 +31,7 @@ const char *elf_check_broken(const struct elf_binary *elf)
|
||||
return elf->broken;
|
||||
}
|
||||
|
||||
-static int elf_ptrval_in_range(elf_ptrval ptrval, uint64_t size,
|
||||
+static bool elf_ptrval_in_range(elf_ptrval ptrval, uint64_t size,
|
||||
const void *region, uint64_t regionsize)
|
||||
/*
|
||||
* Returns true if the putative memory area [ptrval,ptrval+size>
|
||||
@@ -53,7 +53,7 @@ static int elf_ptrval_in_range(elf_ptrval ptrval, uint64_t size,
|
||||
return 1;
|
||||
}
|
||||
|
||||
-int elf_access_ok(struct elf_binary * elf,
|
||||
+bool elf_access_ok(struct elf_binary * elf,
|
||||
uint64_t ptrval, size_t size)
|
||||
{
|
||||
if ( elf_ptrval_in_range(ptrval, size, elf->image_base, elf->size) )
|
||||
@@ -92,7 +92,7 @@ uint64_t elf_access_unsigned(struct elf_binary * elf, elf_ptrval base,
|
||||
uint64_t moreoffset, size_t size)
|
||||
{
|
||||
elf_ptrval ptrval = base + moreoffset;
|
||||
- int need_swap = elf_swap(elf);
|
||||
+ bool need_swap = elf_swap(elf);
|
||||
const uint8_t *u8;
|
||||
const uint16_t *u16;
|
||||
const uint32_t *u32;
|
||||
@@ -332,7 +332,7 @@ ELF_HANDLE_DECL(elf_note) elf_note_next(struct elf_binary *elf, ELF_HANDLE_DECL(
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
-int elf_is_elfbinary(const void *image_start, size_t image_size)
|
||||
+bool elf_is_elfbinary(const void *image_start, size_t image_size)
|
||||
{
|
||||
const Elf32_Ehdr *ehdr = image_start;
|
||||
|
||||
@@ -342,7 +342,7 @@ int elf_is_elfbinary(const void *image_start, size_t image_size)
|
||||
return IS_ELF(*ehdr);
|
||||
}
|
||||
|
||||
-int elf_phdr_is_loadable(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr)
|
||||
+bool elf_phdr_is_loadable(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr)
|
||||
{
|
||||
uint64_t p_type = elf_uval(elf, phdr, p_type);
|
||||
uint64_t p_flags = elf_uval(elf, phdr, p_flags);
|
||||
diff --git a/xen/include/xen/libelf.h b/xen/include/xen/libelf.h
|
||||
index ac93858..951430f 100644
|
||||
--- a/xen/include/xen/libelf.h
|
||||
+++ b/xen/include/xen/libelf.h
|
||||
@@ -29,6 +29,8 @@
|
||||
#error define architectural endianness
|
||||
#endif
|
||||
|
||||
+#include <stdbool.h>
|
||||
+
|
||||
#undef ELFSIZE
|
||||
#include "elfstructs.h"
|
||||
#ifdef __XEN__
|
||||
@@ -42,7 +44,7 @@
|
||||
|
||||
struct elf_binary;
|
||||
typedef void elf_log_callback(struct elf_binary*, void *caller_data,
|
||||
- int iserr, const char *fmt, va_list al);
|
||||
+ bool iserr, const char *fmt, va_list al);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -237,7 +239,7 @@ struct elf_binary {
|
||||
elf_log_callback *log_callback;
|
||||
void *log_caller_data;
|
||||
#endif
|
||||
- int verbose;
|
||||
+ bool verbose;
|
||||
const char *broken;
|
||||
};
|
||||
|
||||
@@ -301,8 +303,8 @@ void elf_memset_safe(struct elf_binary*, elf_ptrval dst, int c, size_t);
|
||||
* outside permitted areas.
|
||||
*/
|
||||
|
||||
-int elf_access_ok(struct elf_binary * elf,
|
||||
- uint64_t ptrval, size_t size);
|
||||
+bool elf_access_ok(struct elf_binary * elf,
|
||||
+ uint64_t ptrval, size_t size);
|
||||
|
||||
#define elf_store_val(elf, type, ptr, val) \
|
||||
({ \
|
||||
@@ -351,9 +353,9 @@ uint64_t elf_note_numeric_array(struct elf_binary *, ELF_HANDLE_DECL(elf_note),
|
||||
ELF_HANDLE_DECL(elf_note) elf_note_next(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
|
||||
|
||||
/* (Only) checks that the image has the right magic number. */
|
||||
-int elf_is_elfbinary(const void *image_start, size_t image_size);
|
||||
+bool elf_is_elfbinary(const void *image_start, size_t image_size);
|
||||
|
||||
-int elf_phdr_is_loadable(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr);
|
||||
+bool elf_phdr_is_loadable(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr);
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* xc_libelf_loader.c */
|
||||
@@ -367,7 +369,7 @@ int elf_init(struct elf_binary *elf, const char *image, size_t size);
|
||||
void elf_set_verbose(struct elf_binary *elf);
|
||||
#else
|
||||
void elf_set_log(struct elf_binary *elf, elf_log_callback*,
|
||||
- void *log_caller_pointer, int verbose);
|
||||
+ void *log_caller_pointer, bool verbose);
|
||||
#endif
|
||||
|
||||
void elf_parse_binary(struct elf_binary *elf);
|
||||
@@ -419,7 +421,7 @@ struct elf_dom_parms {
|
||||
char xen_ver[16];
|
||||
char loader[16];
|
||||
int pae;
|
||||
- int bsd_symtab;
|
||||
+ bool bsd_symtab;
|
||||
uint64_t virt_base;
|
||||
uint64_t virt_entry;
|
||||
uint64_t virt_hypercall;
|
||||
--
|
||||
1.7.2.5
|
||||
|
@ -0,0 +1,759 @@
|
||||
From e673ca50127b6c1263727aa31de0b8bb966ca7a2 Mon Sep 17 00:00:00 2001
|
||||
From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Date: Fri, 14 Jun 2013 16:43:18 +0100
|
||||
Subject: [PATCH 15/23] libelf: use only unsigned integers
|
||||
|
||||
Signed integers have undesirable undefined behaviours on overflow.
|
||||
Malicious compilers can turn apparently-correct code into code with
|
||||
security vulnerabilities etc.
|
||||
|
||||
So use only unsigned integers. Exceptions are booleans (which we have
|
||||
already changed) and error codes.
|
||||
|
||||
We _do_ change all the chars which aren't fixed constants from our own
|
||||
text segment, but not the char*s. This is because it is safe to
|
||||
access an arbitrary byte through a char*, but not necessarily safe to
|
||||
convert an arbitrary value to a char.
|
||||
|
||||
As a consequence we need to compile libelf with -Wno-pointer-sign.
|
||||
|
||||
It is OK to change all the signed integers to unsigned because all the
|
||||
inequalities in libelf are in contexts where we don't "expect"
|
||||
negative numbers.
|
||||
|
||||
In libelf-dominfo.c:elf_xen_parse we rename a variable "rc" to
|
||||
"more_notes" as it actually contains a note count derived from the
|
||||
input image. The "error" return value from elf_xen_parse_notes is
|
||||
changed from -1 to ~0U.
|
||||
|
||||
grepping shows only one occurrence of "PRId" or "%d" or "%ld" in
|
||||
libelf and xc_dom_elfloader.c (a "%d" which becomes "%u").
|
||||
|
||||
This is part of the fix to a security issue, XSA-55.
|
||||
|
||||
For those concerned about unintentional functional changes, the
|
||||
following rune produces a version of the patch which is much smaller
|
||||
and eliminates only non-functional changes:
|
||||
|
||||
GIT_EXTERNAL_DIFF=.../unsigned-differ git-diff <before>..<after>
|
||||
|
||||
where <before> and <after> are git refs for the code before and after
|
||||
this patch, and unsigned-differ is this shell script:
|
||||
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
seddery () {
|
||||
perl -pe 's/\b(?:elf_errorstatus|elf_negerrnoval)\b/int/g'
|
||||
}
|
||||
|
||||
path="$1"
|
||||
in="$2"
|
||||
out="$5"
|
||||
|
||||
set +e
|
||||
diff -pu --label "$path~" <(seddery <"$in") --label "$path" <(seddery <"$out")
|
||||
rc=$?
|
||||
set -e
|
||||
if [ $rc = 1 ]; then rc=0; fi
|
||||
exit $rc
|
||||
|
||||
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
---
|
||||
tools/libxc/Makefile | 9 +++++-
|
||||
tools/libxc/xc_dom.h | 7 +++--
|
||||
tools/libxc/xc_dom_elfloader.c | 42 ++++++++++++++++-------------
|
||||
tools/xcutils/readnotes.c | 15 +++++-----
|
||||
xen/common/libelf/Makefile | 2 +
|
||||
xen/common/libelf/libelf-dominfo.c | 52 ++++++++++++++++++-----------------
|
||||
xen/common/libelf/libelf-loader.c | 20 +++++++-------
|
||||
xen/common/libelf/libelf-tools.c | 24 ++++++++--------
|
||||
xen/include/xen/libelf.h | 21 ++++++++------
|
||||
9 files changed, 105 insertions(+), 87 deletions(-)
|
||||
|
||||
diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile
|
||||
index d8c6a60..a3fd90c 100644
|
||||
--- a/tools/libxc/Makefile
|
||||
+++ b/tools/libxc/Makefile
|
||||
@@ -52,8 +52,13 @@ endif
|
||||
vpath %.c ../../xen/common/libelf
|
||||
CFLAGS += -I../../xen/common/libelf
|
||||
|
||||
-GUEST_SRCS-y += libelf-tools.c libelf-loader.c
|
||||
-GUEST_SRCS-y += libelf-dominfo.c
|
||||
+ELF_SRCS-y += libelf-tools.c libelf-loader.c
|
||||
+ELF_SRCS-y += libelf-dominfo.c
|
||||
+
|
||||
+GUEST_SRCS-y += $(ELF_SRCS-y)
|
||||
+
|
||||
+$(patsubst %.c,%.o,$(ELF_SRCS-y)): CFLAGS += -Wno-pointer-sign
|
||||
+$(patsubst %.c,%.opic,$(ELF_SRCS-y)): CFLAGS += -Wno-pointer-sign
|
||||
|
||||
# new domain builder
|
||||
GUEST_SRCS-y += xc_dom_core.c xc_dom_boot.c
|
||||
diff --git a/tools/libxc/xc_dom.h b/tools/libxc/xc_dom.h
|
||||
index 9f8037e..0161459 100644
|
||||
--- a/tools/libxc/xc_dom.h
|
||||
+++ b/tools/libxc/xc_dom.h
|
||||
@@ -140,9 +140,10 @@ struct xc_dom_image {
|
||||
|
||||
struct xc_dom_loader {
|
||||
char *name;
|
||||
- int (*probe) (struct xc_dom_image * dom);
|
||||
- int (*parser) (struct xc_dom_image * dom);
|
||||
- int (*loader) (struct xc_dom_image * dom);
|
||||
+ /* Sadly the error returns from these functions are not consistent: */
|
||||
+ elf_negerrnoval (*probe) (struct xc_dom_image * dom);
|
||||
+ elf_negerrnoval (*parser) (struct xc_dom_image * dom);
|
||||
+ elf_errorstatus (*loader) (struct xc_dom_image * dom);
|
||||
|
||||
struct xc_dom_loader *next;
|
||||
};
|
||||
diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c
|
||||
index 9ba64ae..62a0d3b 100644
|
||||
--- a/tools/libxc/xc_dom_elfloader.c
|
||||
+++ b/tools/libxc/xc_dom_elfloader.c
|
||||
@@ -84,7 +84,7 @@ static char *xc_dom_guest_type(struct xc_dom_image *dom,
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* parse elf binary */
|
||||
|
||||
-static int check_elf_kernel(struct xc_dom_image *dom, bool verbose)
|
||||
+static elf_negerrnoval check_elf_kernel(struct xc_dom_image *dom, bool verbose)
|
||||
{
|
||||
if ( dom->kernel_blob == NULL )
|
||||
{
|
||||
@@ -106,12 +106,12 @@ static int check_elf_kernel(struct xc_dom_image *dom, bool verbose)
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int xc_dom_probe_elf_kernel(struct xc_dom_image *dom)
|
||||
+static elf_negerrnoval xc_dom_probe_elf_kernel(struct xc_dom_image *dom)
|
||||
{
|
||||
return check_elf_kernel(dom, 0);
|
||||
}
|
||||
|
||||
-static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
+static elf_errorstatus xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
struct elf_binary *elf, bool load)
|
||||
{
|
||||
struct elf_binary syms;
|
||||
@@ -119,7 +119,7 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
xen_vaddr_t symtab, maxaddr;
|
||||
ELF_PTRVAL_CHAR hdr;
|
||||
size_t size;
|
||||
- int h, count, type, i, tables = 0;
|
||||
+ unsigned h, count, type, i, tables = 0;
|
||||
|
||||
if ( elf_swap(elf) )
|
||||
{
|
||||
@@ -140,13 +140,13 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
elf->caller_xdest_base = hdr_ptr;
|
||||
elf->caller_xdest_size = allow_size;
|
||||
hdr = ELF_REALPTR2PTRVAL(hdr_ptr);
|
||||
- elf_store_val(elf, int, hdr, size - sizeof(int));
|
||||
+ elf_store_val(elf, unsigned, hdr, size - sizeof(unsigned));
|
||||
}
|
||||
else
|
||||
{
|
||||
char *hdr_ptr;
|
||||
|
||||
- size = sizeof(int) + elf_size(elf, elf->ehdr) +
|
||||
+ size = sizeof(unsigned) + elf_size(elf, elf->ehdr) +
|
||||
elf_shdr_count(elf) * elf_size(elf, shdr);
|
||||
hdr_ptr = xc_dom_malloc(dom, size);
|
||||
if ( hdr_ptr == NULL )
|
||||
@@ -157,15 +157,15 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
dom->bsd_symtab_start = elf_round_up(elf, dom->kernel_seg.vend);
|
||||
}
|
||||
|
||||
- elf_memcpy_safe(elf, hdr + sizeof(int),
|
||||
+ elf_memcpy_safe(elf, hdr + sizeof(unsigned),
|
||||
ELF_IMAGE_BASE(elf),
|
||||
elf_size(elf, elf->ehdr));
|
||||
- elf_memcpy_safe(elf, hdr + sizeof(int) + elf_size(elf, elf->ehdr),
|
||||
+ elf_memcpy_safe(elf, hdr + sizeof(unsigned) + elf_size(elf, elf->ehdr),
|
||||
ELF_IMAGE_BASE(elf) + elf_uval(elf, elf->ehdr, e_shoff),
|
||||
elf_shdr_count(elf) * elf_size(elf, shdr));
|
||||
if ( elf_64bit(elf) )
|
||||
{
|
||||
- Elf64_Ehdr *ehdr = (Elf64_Ehdr *)(hdr + sizeof(int));
|
||||
+ Elf64_Ehdr *ehdr = (Elf64_Ehdr *)(hdr + sizeof(unsigned));
|
||||
ehdr->e_phoff = 0;
|
||||
ehdr->e_phentsize = 0;
|
||||
ehdr->e_phnum = 0;
|
||||
@@ -174,22 +174,22 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
}
|
||||
else
|
||||
{
|
||||
- Elf32_Ehdr *ehdr = (Elf32_Ehdr *)(hdr + sizeof(int));
|
||||
+ Elf32_Ehdr *ehdr = (Elf32_Ehdr *)(hdr + sizeof(unsigned));
|
||||
ehdr->e_phoff = 0;
|
||||
ehdr->e_phentsize = 0;
|
||||
ehdr->e_phnum = 0;
|
||||
ehdr->e_shoff = elf_size(elf, elf->ehdr);
|
||||
ehdr->e_shstrndx = SHN_UNDEF;
|
||||
}
|
||||
- if ( elf->caller_xdest_size < sizeof(int) )
|
||||
+ if ( elf->caller_xdest_size < sizeof(unsigned) )
|
||||
{
|
||||
DOMPRINTF("%s/%s: header size %"PRIx64" too small",
|
||||
__FUNCTION__, load ? "load" : "parse",
|
||||
(uint64_t)elf->caller_xdest_size);
|
||||
return -1;
|
||||
}
|
||||
- if ( elf_init(&syms, elf->caller_xdest_base + sizeof(int),
|
||||
- elf->caller_xdest_size - sizeof(int)) )
|
||||
+ if ( elf_init(&syms, elf->caller_xdest_base + sizeof(unsigned),
|
||||
+ elf->caller_xdest_size - sizeof(unsigned)) )
|
||||
return -1;
|
||||
|
||||
/*
|
||||
@@ -209,7 +209,7 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
|
||||
xc_elf_set_logfile(dom->xch, &syms, 1);
|
||||
|
||||
- symtab = dom->bsd_symtab_start + sizeof(int);
|
||||
+ symtab = dom->bsd_symtab_start + sizeof(unsigned);
|
||||
maxaddr = elf_round_up(&syms, symtab + elf_size(&syms, syms.ehdr) +
|
||||
elf_shdr_count(&syms) * elf_size(&syms, shdr));
|
||||
|
||||
@@ -255,7 +255,7 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
size = elf_uval(&syms, shdr, sh_size);
|
||||
maxaddr = elf_round_up(&syms, maxaddr + size);
|
||||
tables++;
|
||||
- DOMPRINTF("%s: h=%d %s, size=0x%zx, maxaddr=0x%" PRIx64 "",
|
||||
+ DOMPRINTF("%s: h=%u %s, size=0x%zx, maxaddr=0x%" PRIx64 "",
|
||||
__FUNCTION__, h,
|
||||
type == SHT_SYMTAB ? "symtab" : "strtab",
|
||||
size, maxaddr);
|
||||
@@ -294,10 +294,14 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int xc_dom_parse_elf_kernel(struct xc_dom_image *dom)
|
||||
+static elf_errorstatus xc_dom_parse_elf_kernel(struct xc_dom_image *dom)
|
||||
+ /*
|
||||
+ * This function sometimes returns -1 for error and sometimes
|
||||
+ * an errno value. ?!?!
|
||||
+ */
|
||||
{
|
||||
struct elf_binary *elf;
|
||||
- int rc;
|
||||
+ elf_errorstatus rc;
|
||||
|
||||
rc = check_elf_kernel(dom, 1);
|
||||
if ( rc != 0 )
|
||||
@@ -358,10 +362,10 @@ out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
-static int xc_dom_load_elf_kernel(struct xc_dom_image *dom)
|
||||
+static elf_errorstatus xc_dom_load_elf_kernel(struct xc_dom_image *dom)
|
||||
{
|
||||
struct elf_binary *elf = dom->private_loader;
|
||||
- int rc;
|
||||
+ elf_errorstatus rc;
|
||||
xen_pfn_t pages;
|
||||
|
||||
elf->dest_base = xc_dom_seg_to_ptr_pages(dom, &dom->kernel_seg, &pages);
|
||||
diff --git a/tools/xcutils/readnotes.c b/tools/xcutils/readnotes.c
|
||||
index d1f7a30..2ca7732 100644
|
||||
--- a/tools/xcutils/readnotes.c
|
||||
+++ b/tools/xcutils/readnotes.c
|
||||
@@ -70,7 +70,7 @@ static void print_numeric_note(const char *prefix, struct elf_binary *elf,
|
||||
ELF_HANDLE_DECL(elf_note) note)
|
||||
{
|
||||
uint64_t value = elf_note_numeric(elf, note);
|
||||
- int descsz = elf_uval(elf, note, descsz);
|
||||
+ unsigned descsz = elf_uval(elf, note, descsz);
|
||||
|
||||
printf("%s: %#*" PRIx64 " (%d bytes)\n",
|
||||
prefix, 2+2*descsz, value, descsz);
|
||||
@@ -79,7 +79,7 @@ static void print_numeric_note(const char *prefix, struct elf_binary *elf,
|
||||
static void print_l1_mfn_valid_note(const char *prefix, struct elf_binary *elf,
|
||||
ELF_HANDLE_DECL(elf_note) note)
|
||||
{
|
||||
- int descsz = elf_uval(elf, note, descsz);
|
||||
+ unsigned descsz = elf_uval(elf, note, descsz);
|
||||
ELF_PTRVAL_CONST_VOID desc = elf_note_desc(elf, note);
|
||||
|
||||
/* XXX should be able to cope with a list of values. */
|
||||
@@ -99,10 +99,10 @@ static void print_l1_mfn_valid_note(const char *prefix, struct elf_binary *elf,
|
||||
|
||||
}
|
||||
|
||||
-static int print_notes(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) start, ELF_HANDLE_DECL(elf_note) end)
|
||||
+static unsigned print_notes(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) start, ELF_HANDLE_DECL(elf_note) end)
|
||||
{
|
||||
ELF_HANDLE_DECL(elf_note) note;
|
||||
- int notes_found = 0;
|
||||
+ unsigned notes_found = 0;
|
||||
const char *this_note_name;
|
||||
|
||||
for ( note = start; ELF_HANDLE_PTRVAL(note) < ELF_HANDLE_PTRVAL(end); note = elf_note_next(elf, note) )
|
||||
@@ -161,7 +161,7 @@ static int print_notes(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) start,
|
||||
break;
|
||||
default:
|
||||
printf("unknown note type %#x\n",
|
||||
- (int)elf_uval(elf, note, type));
|
||||
+ (unsigned)elf_uval(elf, note, type));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -171,12 +171,13 @@ static int print_notes(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) start,
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char *f;
|
||||
- int fd,h,size,usize,count;
|
||||
+ int fd;
|
||||
+ unsigned h,size,usize,count;
|
||||
void *image,*tmp;
|
||||
struct stat st;
|
||||
struct elf_binary elf;
|
||||
ELF_HANDLE_DECL(elf_shdr) shdr;
|
||||
- int notes_found = 0;
|
||||
+ unsigned notes_found = 0;
|
||||
|
||||
struct setup_header *hdr;
|
||||
uint64_t payload_offset, payload_length;
|
||||
diff --git a/xen/common/libelf/Makefile b/xen/common/libelf/Makefile
|
||||
index 18dc8e2..5bf8f76 100644
|
||||
--- a/xen/common/libelf/Makefile
|
||||
+++ b/xen/common/libelf/Makefile
|
||||
@@ -2,6 +2,8 @@ obj-bin-y := libelf.o
|
||||
|
||||
SECTIONS := text data $(SPECIAL_DATA_SECTIONS)
|
||||
|
||||
+CFLAGS += -Wno-pointer-sign
|
||||
+
|
||||
libelf.o: libelf-temp.o Makefile
|
||||
$(OBJCOPY) $(foreach s,$(SECTIONS),--rename-section .$(s)=.init.$(s)) $< $@
|
||||
|
||||
diff --git a/xen/common/libelf/libelf-dominfo.c b/xen/common/libelf/libelf-dominfo.c
|
||||
index 12b6c2a..cdd0d31 100644
|
||||
--- a/xen/common/libelf/libelf-dominfo.c
|
||||
+++ b/xen/common/libelf/libelf-dominfo.c
|
||||
@@ -29,15 +29,15 @@ static const char *const elf_xen_feature_names[] = {
|
||||
[XENFEAT_pae_pgdir_above_4gb] = "pae_pgdir_above_4gb",
|
||||
[XENFEAT_dom0] = "dom0"
|
||||
};
|
||||
-static const int elf_xen_features =
|
||||
+static const unsigned elf_xen_features =
|
||||
sizeof(elf_xen_feature_names) / sizeof(elf_xen_feature_names[0]);
|
||||
|
||||
-int elf_xen_parse_features(const char *features,
|
||||
+elf_errorstatus elf_xen_parse_features(const char *features,
|
||||
uint32_t *supported,
|
||||
uint32_t *required)
|
||||
{
|
||||
- char feature[64];
|
||||
- int pos, len, i;
|
||||
+ unsigned char feature[64];
|
||||
+ unsigned pos, len, i;
|
||||
|
||||
if ( features == NULL )
|
||||
return 0;
|
||||
@@ -94,7 +94,7 @@ int elf_xen_parse_features(const char *features,
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* xen elf notes */
|
||||
|
||||
-int elf_xen_parse_note(struct elf_binary *elf,
|
||||
+elf_errorstatus elf_xen_parse_note(struct elf_binary *elf,
|
||||
struct elf_dom_parms *parms,
|
||||
ELF_HANDLE_DECL(elf_note) note)
|
||||
{
|
||||
@@ -125,7 +125,7 @@ int elf_xen_parse_note(struct elf_binary *elf,
|
||||
const char *str = NULL;
|
||||
uint64_t val = 0;
|
||||
unsigned int i;
|
||||
- int type = elf_uval(elf, note, type);
|
||||
+ unsigned type = elf_uval(elf, note, type);
|
||||
|
||||
if ( (type >= sizeof(note_desc) / sizeof(note_desc[0])) ||
|
||||
(note_desc[type].name == NULL) )
|
||||
@@ -216,12 +216,14 @@ int elf_xen_parse_note(struct elf_binary *elf,
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int elf_xen_parse_notes(struct elf_binary *elf,
|
||||
+#define ELF_NOTE_INVALID (~0U)
|
||||
+
|
||||
+static unsigned elf_xen_parse_notes(struct elf_binary *elf,
|
||||
struct elf_dom_parms *parms,
|
||||
ELF_PTRVAL_CONST_VOID start,
|
||||
ELF_PTRVAL_CONST_VOID end)
|
||||
{
|
||||
- int xen_elfnotes = 0;
|
||||
+ unsigned xen_elfnotes = 0;
|
||||
ELF_HANDLE_DECL(elf_note) note;
|
||||
const char *note_name;
|
||||
|
||||
@@ -237,7 +239,7 @@ static int elf_xen_parse_notes(struct elf_binary *elf,
|
||||
if ( strcmp(note_name, "Xen") )
|
||||
continue;
|
||||
if ( elf_xen_parse_note(elf, parms, note) )
|
||||
- return -1;
|
||||
+ return ELF_NOTE_INVALID;
|
||||
xen_elfnotes++;
|
||||
}
|
||||
return xen_elfnotes;
|
||||
@@ -246,12 +248,12 @@ static int elf_xen_parse_notes(struct elf_binary *elf,
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* __xen_guest section */
|
||||
|
||||
-int elf_xen_parse_guest_info(struct elf_binary *elf,
|
||||
+elf_errorstatus elf_xen_parse_guest_info(struct elf_binary *elf,
|
||||
struct elf_dom_parms *parms)
|
||||
{
|
||||
ELF_PTRVAL_CONST_CHAR h;
|
||||
- char name[32], value[128];
|
||||
- int len;
|
||||
+ unsigned char name[32], value[128];
|
||||
+ unsigned len;
|
||||
|
||||
h = parms->guest_info;
|
||||
#define STAR(h) (elf_access_unsigned(elf, (h), 0, 1))
|
||||
@@ -334,13 +336,13 @@ int elf_xen_parse_guest_info(struct elf_binary *elf,
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* sanity checks */
|
||||
|
||||
-static int elf_xen_note_check(struct elf_binary *elf,
|
||||
+static elf_errorstatus elf_xen_note_check(struct elf_binary *elf,
|
||||
struct elf_dom_parms *parms)
|
||||
{
|
||||
if ( (ELF_PTRVAL_INVALID(parms->elf_note_start)) &&
|
||||
(ELF_PTRVAL_INVALID(parms->guest_info)) )
|
||||
{
|
||||
- int machine = elf_uval(elf, elf->ehdr, e_machine);
|
||||
+ unsigned machine = elf_uval(elf, elf->ehdr, e_machine);
|
||||
if ( (machine == EM_386) || (machine == EM_X86_64) )
|
||||
{
|
||||
elf_err(elf, "%s: ERROR: Not a Xen-ELF image: "
|
||||
@@ -378,7 +380,7 @@ static int elf_xen_note_check(struct elf_binary *elf,
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int elf_xen_addr_calc_check(struct elf_binary *elf,
|
||||
+static elf_errorstatus elf_xen_addr_calc_check(struct elf_binary *elf,
|
||||
struct elf_dom_parms *parms)
|
||||
{
|
||||
if ( (parms->elf_paddr_offset != UNSET_ADDR) &&
|
||||
@@ -464,13 +466,13 @@ static int elf_xen_addr_calc_check(struct elf_binary *elf,
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* glue it all together ... */
|
||||
|
||||
-int elf_xen_parse(struct elf_binary *elf,
|
||||
+elf_errorstatus elf_xen_parse(struct elf_binary *elf,
|
||||
struct elf_dom_parms *parms)
|
||||
{
|
||||
ELF_HANDLE_DECL(elf_shdr) shdr;
|
||||
ELF_HANDLE_DECL(elf_phdr) phdr;
|
||||
- int xen_elfnotes = 0;
|
||||
- int i, count, rc;
|
||||
+ unsigned xen_elfnotes = 0;
|
||||
+ unsigned i, count, more_notes;
|
||||
|
||||
elf_memset_unchecked(parms, 0, sizeof(*parms));
|
||||
parms->virt_base = UNSET_ADDR;
|
||||
@@ -495,13 +497,13 @@ int elf_xen_parse(struct elf_binary *elf,
|
||||
if (elf_uval(elf, phdr, p_offset) == 0)
|
||||
continue;
|
||||
|
||||
- rc = elf_xen_parse_notes(elf, parms,
|
||||
+ more_notes = elf_xen_parse_notes(elf, parms,
|
||||
elf_segment_start(elf, phdr),
|
||||
elf_segment_end(elf, phdr));
|
||||
- if ( rc == -1 )
|
||||
+ if ( more_notes == ELF_NOTE_INVALID )
|
||||
return -1;
|
||||
|
||||
- xen_elfnotes += rc;
|
||||
+ xen_elfnotes += more_notes;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -518,17 +520,17 @@ int elf_xen_parse(struct elf_binary *elf,
|
||||
if ( elf_uval(elf, shdr, sh_type) != SHT_NOTE )
|
||||
continue;
|
||||
|
||||
- rc = elf_xen_parse_notes(elf, parms,
|
||||
+ more_notes = elf_xen_parse_notes(elf, parms,
|
||||
elf_section_start(elf, shdr),
|
||||
elf_section_end(elf, shdr));
|
||||
|
||||
- if ( rc == -1 )
|
||||
+ if ( more_notes == ELF_NOTE_INVALID )
|
||||
return -1;
|
||||
|
||||
- if ( xen_elfnotes == 0 && rc > 0 )
|
||||
+ if ( xen_elfnotes == 0 && more_notes > 0 )
|
||||
elf_msg(elf, "%s: using notes from SHT_NOTE section\n", __FUNCTION__);
|
||||
|
||||
- xen_elfnotes += rc;
|
||||
+ xen_elfnotes += more_notes;
|
||||
}
|
||||
|
||||
}
|
||||
diff --git a/xen/common/libelf/libelf-loader.c b/xen/common/libelf/libelf-loader.c
|
||||
index 0dccd4d..c3a9e51 100644
|
||||
--- a/xen/common/libelf/libelf-loader.c
|
||||
+++ b/xen/common/libelf/libelf-loader.c
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
-int elf_init(struct elf_binary *elf, const char *image_input, size_t size)
|
||||
+elf_errorstatus elf_init(struct elf_binary *elf, const char *image_input, size_t size)
|
||||
{
|
||||
ELF_HANDLE_DECL(elf_shdr) shdr;
|
||||
uint64_t i, count, section, offset;
|
||||
@@ -114,7 +114,7 @@ void elf_set_log(struct elf_binary *elf, elf_log_callback *log_callback,
|
||||
elf->verbose = verbose;
|
||||
}
|
||||
|
||||
-static int elf_load_image(struct elf_binary *elf,
|
||||
+static elf_errorstatus elf_load_image(struct elf_binary *elf,
|
||||
ELF_PTRVAL_VOID dst, ELF_PTRVAL_CONST_VOID src,
|
||||
uint64_t filesz, uint64_t memsz)
|
||||
{
|
||||
@@ -129,9 +129,9 @@ void elf_set_verbose(struct elf_binary *elf)
|
||||
elf->verbose = 1;
|
||||
}
|
||||
|
||||
-static int elf_load_image(struct elf_binary *elf, ELF_PTRVAL_VOID dst, ELF_PTRVAL_CONST_VOID src, uint64_t filesz, uint64_t memsz)
|
||||
+static elf_errorstatus elf_load_image(struct elf_binary *elf, ELF_PTRVAL_VOID dst, ELF_PTRVAL_CONST_VOID src, uint64_t filesz, uint64_t memsz)
|
||||
{
|
||||
- int rc;
|
||||
+ elf_errorstatus rc;
|
||||
if ( filesz > ULONG_MAX || memsz > ULONG_MAX )
|
||||
return -1;
|
||||
/* We trust the dom0 kernel image completely, so we don't care
|
||||
@@ -151,7 +151,7 @@ void elf_parse_bsdsyms(struct elf_binary *elf, uint64_t pstart)
|
||||
{
|
||||
uint64_t sz;
|
||||
ELF_HANDLE_DECL(elf_shdr) shdr;
|
||||
- int i, type;
|
||||
+ unsigned i, type;
|
||||
|
||||
if ( !ELF_HANDLE_VALID(elf->sym_tab) )
|
||||
return;
|
||||
@@ -187,7 +187,7 @@ static void elf_load_bsdsyms(struct elf_binary *elf)
|
||||
ELF_PTRVAL_VOID symbase;
|
||||
ELF_PTRVAL_VOID symtab_addr;
|
||||
ELF_HANDLE_DECL_NONCONST(elf_shdr) shdr;
|
||||
- int i, type;
|
||||
+ unsigned i, type;
|
||||
|
||||
if ( !elf->bsd_symtab_pstart )
|
||||
return;
|
||||
@@ -220,7 +220,7 @@ do { \
|
||||
elf_memcpy_safe(elf, ELF_HANDLE_PTRVAL(shdr),
|
||||
ELF_IMAGE_BASE(elf) + elf_uval(elf, elf->ehdr, e_shoff),
|
||||
sz);
|
||||
- maxva = ELF_OBSOLETE_VOIDP_CAST elf_round_up(elf, (long)maxva + sz);
|
||||
+ maxva = ELF_OBSOLETE_VOIDP_CAST elf_round_up(elf, (unsigned long)maxva + sz);
|
||||
|
||||
for ( i = 0; i < elf_shdr_count(elf); i++ )
|
||||
{
|
||||
@@ -233,10 +233,10 @@ do { \
|
||||
elf_memcpy_safe(elf, maxva, elf_section_start(elf, shdr), sz);
|
||||
/* Mangled to be based on ELF header location. */
|
||||
elf_hdr_elm(elf, shdr, sh_offset, maxva - symtab_addr);
|
||||
- maxva = ELF_OBSOLETE_VOIDP_CAST elf_round_up(elf, (long)maxva + sz);
|
||||
+ maxva = ELF_OBSOLETE_VOIDP_CAST elf_round_up(elf, (unsigned long)maxva + sz);
|
||||
}
|
||||
shdr = ELF_MAKE_HANDLE(elf_shdr, ELF_HANDLE_PTRVAL(shdr) +
|
||||
- (long)elf_uval(elf, elf->ehdr, e_shentsize));
|
||||
+ (unsigned long)elf_uval(elf, elf->ehdr, e_shentsize));
|
||||
}
|
||||
|
||||
/* Write down the actual sym size. */
|
||||
@@ -273,7 +273,7 @@ void elf_parse_binary(struct elf_binary *elf)
|
||||
__FUNCTION__, elf->pstart, elf->pend);
|
||||
}
|
||||
|
||||
-int elf_load_binary(struct elf_binary *elf)
|
||||
+elf_errorstatus elf_load_binary(struct elf_binary *elf)
|
||||
{
|
||||
ELF_HANDLE_DECL(elf_phdr) phdr;
|
||||
uint64_t i, count, paddr, offset, filesz, memsz;
|
||||
diff --git a/xen/common/libelf/libelf-tools.c b/xen/common/libelf/libelf-tools.c
|
||||
index fa58f76..46d4ab1 100644
|
||||
--- a/xen/common/libelf/libelf-tools.c
|
||||
+++ b/xen/common/libelf/libelf-tools.c
|
||||
@@ -122,19 +122,19 @@ uint64_t elf_access_unsigned(struct elf_binary * elf, elf_ptrval base,
|
||||
|
||||
uint64_t elf_round_up(struct elf_binary *elf, uint64_t addr)
|
||||
{
|
||||
- int elf_round = (elf_64bit(elf) ? 8 : 4) - 1;
|
||||
+ uint64_t elf_round = (elf_64bit(elf) ? 8 : 4) - 1;
|
||||
|
||||
return (addr + elf_round) & ~elf_round;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
-int elf_shdr_count(struct elf_binary *elf)
|
||||
+unsigned elf_shdr_count(struct elf_binary *elf)
|
||||
{
|
||||
return elf_uval(elf, elf->ehdr, e_shnum);
|
||||
}
|
||||
|
||||
-int elf_phdr_count(struct elf_binary *elf)
|
||||
+unsigned elf_phdr_count(struct elf_binary *elf)
|
||||
{
|
||||
return elf_uval(elf, elf->ehdr, e_phnum);
|
||||
}
|
||||
@@ -144,7 +144,7 @@ ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_name(struct elf_binary *elf, const char *n
|
||||
uint64_t count = elf_shdr_count(elf);
|
||||
ELF_HANDLE_DECL(elf_shdr) shdr;
|
||||
const char *sname;
|
||||
- int i;
|
||||
+ unsigned i;
|
||||
|
||||
for ( i = 0; i < count; i++ )
|
||||
{
|
||||
@@ -156,7 +156,7 @@ ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_name(struct elf_binary *elf, const char *n
|
||||
return ELF_INVALID_HANDLE(elf_shdr);
|
||||
}
|
||||
|
||||
-ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_index(struct elf_binary *elf, int index)
|
||||
+ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_index(struct elf_binary *elf, unsigned index)
|
||||
{
|
||||
uint64_t count = elf_shdr_count(elf);
|
||||
ELF_PTRVAL_CONST_VOID ptr;
|
||||
@@ -170,7 +170,7 @@ ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_index(struct elf_binary *elf, int index)
|
||||
return ELF_MAKE_HANDLE(elf_shdr, ptr);
|
||||
}
|
||||
|
||||
-ELF_HANDLE_DECL(elf_phdr) elf_phdr_by_index(struct elf_binary *elf, int index)
|
||||
+ELF_HANDLE_DECL(elf_phdr) elf_phdr_by_index(struct elf_binary *elf, unsigned index)
|
||||
{
|
||||
uint64_t count = elf_uval(elf, elf->ehdr, e_phnum);
|
||||
ELF_PTRVAL_CONST_VOID ptr;
|
||||
@@ -264,7 +264,7 @@ ELF_HANDLE_DECL(elf_sym) elf_sym_by_name(struct elf_binary *elf, const char *sym
|
||||
return ELF_INVALID_HANDLE(elf_sym);
|
||||
}
|
||||
|
||||
-ELF_HANDLE_DECL(elf_sym) elf_sym_by_index(struct elf_binary *elf, int index)
|
||||
+ELF_HANDLE_DECL(elf_sym) elf_sym_by_index(struct elf_binary *elf, unsigned index)
|
||||
{
|
||||
ELF_PTRVAL_CONST_VOID ptr = elf_section_start(elf, elf->sym_tab);
|
||||
ELF_HANDLE_DECL(elf_sym) sym;
|
||||
@@ -280,7 +280,7 @@ const char *elf_note_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note
|
||||
|
||||
ELF_PTRVAL_CONST_VOID elf_note_desc(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note)
|
||||
{
|
||||
- int namesz = (elf_uval(elf, note, namesz) + 3) & ~3;
|
||||
+ unsigned namesz = (elf_uval(elf, note, namesz) + 3) & ~3;
|
||||
|
||||
return ELF_HANDLE_PTRVAL(note) + elf_size(elf, note) + namesz;
|
||||
}
|
||||
@@ -288,7 +288,7 @@ ELF_PTRVAL_CONST_VOID elf_note_desc(struct elf_binary *elf, ELF_HANDLE_DECL(elf_
|
||||
uint64_t elf_note_numeric(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note)
|
||||
{
|
||||
ELF_PTRVAL_CONST_VOID desc = elf_note_desc(elf, note);
|
||||
- int descsz = elf_uval(elf, note, descsz);
|
||||
+ unsigned descsz = elf_uval(elf, note, descsz);
|
||||
|
||||
switch (descsz)
|
||||
{
|
||||
@@ -306,7 +306,7 @@ uint64_t elf_note_numeric_array(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note
|
||||
unsigned int unitsz, unsigned int idx)
|
||||
{
|
||||
ELF_PTRVAL_CONST_VOID desc = elf_note_desc(elf, note);
|
||||
- int descsz = elf_uval(elf, note, descsz);
|
||||
+ unsigned descsz = elf_uval(elf, note, descsz);
|
||||
|
||||
if ( descsz % unitsz || idx >= descsz / unitsz )
|
||||
return 0;
|
||||
@@ -324,8 +324,8 @@ uint64_t elf_note_numeric_array(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note
|
||||
|
||||
ELF_HANDLE_DECL(elf_note) elf_note_next(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note)
|
||||
{
|
||||
- int namesz = (elf_uval(elf, note, namesz) + 3) & ~3;
|
||||
- int descsz = (elf_uval(elf, note, descsz) + 3) & ~3;
|
||||
+ unsigned namesz = (elf_uval(elf, note, namesz) + 3) & ~3;
|
||||
+ unsigned descsz = (elf_uval(elf, note, descsz) + 3) & ~3;
|
||||
|
||||
return ELF_MAKE_HANDLE(elf_note, ELF_HANDLE_PTRVAL(note) + elf_size(elf, note) + namesz + descsz);
|
||||
}
|
||||
diff --git a/xen/include/xen/libelf.h b/xen/include/xen/libelf.h
|
||||
index 951430f..87e126a 100644
|
||||
--- a/xen/include/xen/libelf.h
|
||||
+++ b/xen/include/xen/libelf.h
|
||||
@@ -31,6 +31,9 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
+typedef int elf_errorstatus; /* 0: ok; -ve (normally -1): error */
|
||||
+typedef int elf_negerrnoval; /* 0: ok; -EFOO: error */
|
||||
+
|
||||
#undef ELFSIZE
|
||||
#include "elfstructs.h"
|
||||
#ifdef __XEN__
|
||||
@@ -328,12 +331,12 @@ bool elf_access_ok(struct elf_binary * elf,
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* xc_libelf_tools.c */
|
||||
|
||||
-int elf_shdr_count(struct elf_binary *elf);
|
||||
-int elf_phdr_count(struct elf_binary *elf);
|
||||
+unsigned elf_shdr_count(struct elf_binary *elf);
|
||||
+unsigned elf_phdr_count(struct elf_binary *elf);
|
||||
|
||||
ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_name(struct elf_binary *elf, const char *name);
|
||||
-ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_index(struct elf_binary *elf, int index);
|
||||
-ELF_HANDLE_DECL(elf_phdr) elf_phdr_by_index(struct elf_binary *elf, int index);
|
||||
+ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_index(struct elf_binary *elf, unsigned index);
|
||||
+ELF_HANDLE_DECL(elf_phdr) elf_phdr_by_index(struct elf_binary *elf, unsigned index);
|
||||
|
||||
const char *elf_section_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr); /* might return NULL if inputs are invalid */
|
||||
ELF_PTRVAL_CONST_VOID elf_section_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr);
|
||||
@@ -343,7 +346,7 @@ ELF_PTRVAL_CONST_VOID elf_segment_start(struct elf_binary *elf, ELF_HANDLE_DECL(
|
||||
ELF_PTRVAL_CONST_VOID elf_segment_end(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr);
|
||||
|
||||
ELF_HANDLE_DECL(elf_sym) elf_sym_by_name(struct elf_binary *elf, const char *symbol);
|
||||
-ELF_HANDLE_DECL(elf_sym) elf_sym_by_index(struct elf_binary *elf, int index);
|
||||
+ELF_HANDLE_DECL(elf_sym) elf_sym_by_index(struct elf_binary *elf, unsigned index);
|
||||
|
||||
const char *elf_note_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note); /* may return NULL */
|
||||
ELF_PTRVAL_CONST_VOID elf_note_desc(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
|
||||
@@ -360,7 +363,7 @@ bool elf_phdr_is_loadable(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* xc_libelf_loader.c */
|
||||
|
||||
-int elf_init(struct elf_binary *elf, const char *image, size_t size);
|
||||
+elf_errorstatus elf_init(struct elf_binary *elf, const char *image, size_t size);
|
||||
/*
|
||||
* image and size must be correct. They will be recorded in
|
||||
* *elf, and must remain valid while the elf is in use.
|
||||
@@ -373,7 +376,7 @@ void elf_set_log(struct elf_binary *elf, elf_log_callback*,
|
||||
#endif
|
||||
|
||||
void elf_parse_binary(struct elf_binary *elf);
|
||||
-int elf_load_binary(struct elf_binary *elf);
|
||||
+elf_errorstatus elf_load_binary(struct elf_binary *elf);
|
||||
|
||||
ELF_PTRVAL_VOID elf_get_ptr(struct elf_binary *elf, unsigned long addr);
|
||||
uint64_t elf_lookup_addr(struct elf_binary *elf, const char *symbol);
|
||||
@@ -386,7 +389,7 @@ const char *elf_check_broken(const struct elf_binary *elf); /* NULL means OK */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* xc_libelf_relocate.c */
|
||||
|
||||
-int elf_reloc(struct elf_binary *elf);
|
||||
+elf_errorstatus elf_reloc(struct elf_binary *elf);
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* xc_libelf_dominfo.c */
|
||||
@@ -420,7 +423,7 @@ struct elf_dom_parms {
|
||||
char guest_ver[16];
|
||||
char xen_ver[16];
|
||||
char loader[16];
|
||||
- int pae;
|
||||
+ int pae; /* some kind of enum apparently */
|
||||
bool bsd_symtab;
|
||||
uint64_t virt_base;
|
||||
uint64_t virt_entry;
|
||||
--
|
||||
1.7.2.5
|
||||
|
@ -0,0 +1,409 @@
|
||||
From 52d8cc2dd3bb3e0f6d51e00280da934e8d91653a Mon Sep 17 00:00:00 2001
|
||||
From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Date: Fri, 14 Jun 2013 16:43:18 +0100
|
||||
Subject: [PATCH 16/23] libelf: check loops for running away
|
||||
|
||||
Ensure that libelf does not have any loops which can run away
|
||||
indefinitely even if the input is bogus. (Grepped for \bfor, \bwhile
|
||||
and \bgoto in libelf and xc_dom_*loader*.c.)
|
||||
|
||||
Changes needed:
|
||||
* elf_note_next uses the note's unchecked alleged length, which might
|
||||
wrap round. If it does, return ELF_MAX_PTRVAL (0xfff..fff) instead,
|
||||
which will be beyond the end of the section and so terminate the
|
||||
caller's loop. Also check that the returned psuedopointer is sane.
|
||||
* In various loops over section and program headers, check that the
|
||||
calculated header pointer is still within the image, and quit the
|
||||
loop if it isn't.
|
||||
* Some fixed limits to avoid potentially O(image_size^2) loops:
|
||||
- maximum length of strings: 4K (longer ones ignored totally)
|
||||
- maximum total number of ELF notes: 65536 (any more are ignored)
|
||||
* Check that the total program contents (text, data) we copy or
|
||||
initialise doesn't exceed twice the output image area size.
|
||||
* Remove an entirely useless loop from elf_xen_parse (!)
|
||||
* Replace a nested search loop in in xc_dom_load_elf_symtab in
|
||||
xc_dom_elfloader.c by a precomputation of a bitmap of referenced
|
||||
symtabs.
|
||||
|
||||
We have not changed loops which might, in principle, iterate over the
|
||||
whole image - even if they might do so one byte at a time with a
|
||||
nontrivial access check function in the middle.
|
||||
|
||||
This is part of the fix to a security issue, XSA-55.
|
||||
|
||||
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
---
|
||||
tools/libxc/xc_dom_elfloader.c | 33 ++++++++++++++++++-------
|
||||
xen/common/libelf/libelf-dominfo.c | 43 ++++++++++++++++++++------------
|
||||
xen/common/libelf/libelf-loader.c | 47 ++++++++++++++++++++++++++++++++++-
|
||||
xen/common/libelf/libelf-tools.c | 28 ++++++++++++++++++++-
|
||||
xen/include/xen/libelf.h | 13 ++++++++++
|
||||
5 files changed, 135 insertions(+), 29 deletions(-)
|
||||
|
||||
diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c
|
||||
index 62a0d3b..c5014d2 100644
|
||||
--- a/tools/libxc/xc_dom_elfloader.c
|
||||
+++ b/tools/libxc/xc_dom_elfloader.c
|
||||
@@ -28,6 +28,7 @@
|
||||
|
||||
#include "xg_private.h"
|
||||
#include "xc_dom.h"
|
||||
+#include "xc_bitops.h"
|
||||
|
||||
#define XEN_VER "xen-3.0"
|
||||
|
||||
@@ -120,6 +121,7 @@ static elf_errorstatus xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
ELF_PTRVAL_CHAR hdr;
|
||||
size_t size;
|
||||
unsigned h, count, type, i, tables = 0;
|
||||
+ unsigned long *strtab_referenced = NULL;
|
||||
|
||||
if ( elf_swap(elf) )
|
||||
{
|
||||
@@ -220,22 +222,35 @@ static elf_errorstatus xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
symtab, maxaddr);
|
||||
|
||||
count = elf_shdr_count(&syms);
|
||||
+ /* elf_shdr_count guarantees that count is reasonable */
|
||||
+
|
||||
+ strtab_referenced = xc_dom_malloc(dom, bitmap_size(count));
|
||||
+ if ( strtab_referenced == NULL )
|
||||
+ return -1;
|
||||
+ bitmap_clear(strtab_referenced, count);
|
||||
+ /* Note the symtabs @h linked to by any strtab @i. */
|
||||
+ for ( i = 0; i < count; i++ )
|
||||
+ {
|
||||
+ shdr2 = elf_shdr_by_index(&syms, i);
|
||||
+ if ( elf_uval(&syms, shdr2, sh_type) == SHT_SYMTAB )
|
||||
+ {
|
||||
+ h = elf_uval(&syms, shdr2, sh_link);
|
||||
+ if (h < count)
|
||||
+ set_bit(h, strtab_referenced);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
for ( h = 0; h < count; h++ )
|
||||
{
|
||||
shdr = ELF_OBSOLETE_VOIDP_CAST elf_shdr_by_index(&syms, h);
|
||||
+ if ( !elf_access_ok(elf, ELF_HANDLE_PTRVAL(shdr), 1) )
|
||||
+ /* input has an insane section header count field */
|
||||
+ break;
|
||||
type = elf_uval(&syms, shdr, sh_type);
|
||||
if ( type == SHT_STRTAB )
|
||||
{
|
||||
- /* Look for a strtab @i linked to symtab @h. */
|
||||
- for ( i = 0; i < count; i++ )
|
||||
- {
|
||||
- shdr2 = elf_shdr_by_index(&syms, i);
|
||||
- if ( (elf_uval(&syms, shdr2, sh_type) == SHT_SYMTAB) &&
|
||||
- (elf_uval(&syms, shdr2, sh_link) == h) )
|
||||
- break;
|
||||
- }
|
||||
/* Skip symtab @h if we found no corresponding strtab @i. */
|
||||
- if ( i == count )
|
||||
+ if ( !test_bit(h, strtab_referenced) )
|
||||
{
|
||||
if ( elf_64bit(&syms) )
|
||||
elf_store_field(elf, shdr, e64.sh_offset, 0);
|
||||
diff --git a/xen/common/libelf/libelf-dominfo.c b/xen/common/libelf/libelf-dominfo.c
|
||||
index cdd0d31..25a10d7 100644
|
||||
--- a/xen/common/libelf/libelf-dominfo.c
|
||||
+++ b/xen/common/libelf/libelf-dominfo.c
|
||||
@@ -221,7 +221,8 @@ elf_errorstatus elf_xen_parse_note(struct elf_binary *elf,
|
||||
static unsigned elf_xen_parse_notes(struct elf_binary *elf,
|
||||
struct elf_dom_parms *parms,
|
||||
ELF_PTRVAL_CONST_VOID start,
|
||||
- ELF_PTRVAL_CONST_VOID end)
|
||||
+ ELF_PTRVAL_CONST_VOID end,
|
||||
+ unsigned *total_note_count)
|
||||
{
|
||||
unsigned xen_elfnotes = 0;
|
||||
ELF_HANDLE_DECL(elf_note) note;
|
||||
@@ -233,6 +234,12 @@ static unsigned elf_xen_parse_notes(struct elf_binary *elf,
|
||||
ELF_HANDLE_PTRVAL(note) < parms->elf_note_end;
|
||||
note = elf_note_next(elf, note) )
|
||||
{
|
||||
+ if ( *total_note_count >= ELF_MAX_TOTAL_NOTE_COUNT )
|
||||
+ {
|
||||
+ elf_mark_broken(elf, "too many ELF notes");
|
||||
+ break;
|
||||
+ }
|
||||
+ (*total_note_count)++;
|
||||
note_name = elf_note_name(elf, note);
|
||||
if ( note_name == NULL )
|
||||
continue;
|
||||
@@ -473,6 +480,7 @@ elf_errorstatus elf_xen_parse(struct elf_binary *elf,
|
||||
ELF_HANDLE_DECL(elf_phdr) phdr;
|
||||
unsigned xen_elfnotes = 0;
|
||||
unsigned i, count, more_notes;
|
||||
+ unsigned total_note_count = 0;
|
||||
|
||||
elf_memset_unchecked(parms, 0, sizeof(*parms));
|
||||
parms->virt_base = UNSET_ADDR;
|
||||
@@ -487,6 +495,9 @@ elf_errorstatus elf_xen_parse(struct elf_binary *elf,
|
||||
for ( i = 0; i < count; i++ )
|
||||
{
|
||||
phdr = elf_phdr_by_index(elf, i);
|
||||
+ if ( !elf_access_ok(elf, ELF_HANDLE_PTRVAL(phdr), 1) )
|
||||
+ /* input has an insane program header count field */
|
||||
+ break;
|
||||
if ( elf_uval(elf, phdr, p_type) != PT_NOTE )
|
||||
continue;
|
||||
|
||||
@@ -499,7 +510,8 @@ elf_errorstatus elf_xen_parse(struct elf_binary *elf,
|
||||
|
||||
more_notes = elf_xen_parse_notes(elf, parms,
|
||||
elf_segment_start(elf, phdr),
|
||||
- elf_segment_end(elf, phdr));
|
||||
+ elf_segment_end(elf, phdr),
|
||||
+ &total_note_count);
|
||||
if ( more_notes == ELF_NOTE_INVALID )
|
||||
return -1;
|
||||
|
||||
@@ -516,13 +528,17 @@ elf_errorstatus elf_xen_parse(struct elf_binary *elf,
|
||||
for ( i = 0; i < count; i++ )
|
||||
{
|
||||
shdr = elf_shdr_by_index(elf, i);
|
||||
+ if ( !elf_access_ok(elf, ELF_HANDLE_PTRVAL(shdr), 1) )
|
||||
+ /* input has an insane section header count field */
|
||||
+ break;
|
||||
|
||||
if ( elf_uval(elf, shdr, sh_type) != SHT_NOTE )
|
||||
continue;
|
||||
|
||||
more_notes = elf_xen_parse_notes(elf, parms,
|
||||
elf_section_start(elf, shdr),
|
||||
- elf_section_end(elf, shdr));
|
||||
+ elf_section_end(elf, shdr),
|
||||
+ &total_note_count);
|
||||
|
||||
if ( more_notes == ELF_NOTE_INVALID )
|
||||
return -1;
|
||||
@@ -540,20 +556,15 @@ elf_errorstatus elf_xen_parse(struct elf_binary *elf,
|
||||
*/
|
||||
if ( xen_elfnotes == 0 )
|
||||
{
|
||||
- count = elf_shdr_count(elf);
|
||||
- for ( i = 0; i < count; i++ )
|
||||
+ shdr = elf_shdr_by_name(elf, "__xen_guest");
|
||||
+ if ( ELF_HANDLE_VALID(shdr) )
|
||||
{
|
||||
- shdr = elf_shdr_by_name(elf, "__xen_guest");
|
||||
- if ( ELF_HANDLE_VALID(shdr) )
|
||||
- {
|
||||
- parms->guest_info = elf_section_start(elf, shdr);
|
||||
- parms->elf_note_start = ELF_INVALID_PTRVAL;
|
||||
- parms->elf_note_end = ELF_INVALID_PTRVAL;
|
||||
- elf_msg(elf, "%s: __xen_guest: \"%s\"\n", __FUNCTION__,
|
||||
- elf_strfmt(elf, parms->guest_info));
|
||||
- elf_xen_parse_guest_info(elf, parms);
|
||||
- break;
|
||||
- }
|
||||
+ parms->guest_info = elf_section_start(elf, shdr);
|
||||
+ parms->elf_note_start = ELF_INVALID_PTRVAL;
|
||||
+ parms->elf_note_end = ELF_INVALID_PTRVAL;
|
||||
+ elf_msg(elf, "%s: __xen_guest: \"%s\"\n", __FUNCTION__,
|
||||
+ elf_strfmt(elf, parms->guest_info));
|
||||
+ elf_xen_parse_guest_info(elf, parms);
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/xen/common/libelf/libelf-loader.c b/xen/common/libelf/libelf-loader.c
|
||||
index c3a9e51..06799af 100644
|
||||
--- a/xen/common/libelf/libelf-loader.c
|
||||
+++ b/xen/common/libelf/libelf-loader.c
|
||||
@@ -75,6 +75,9 @@ elf_errorstatus elf_init(struct elf_binary *elf, const char *image_input, size_t
|
||||
for ( i = 0; i < count; i++ )
|
||||
{
|
||||
shdr = elf_shdr_by_index(elf, i);
|
||||
+ if ( !elf_access_ok(elf, ELF_HANDLE_PTRVAL(shdr), 1) )
|
||||
+ /* input has an insane section header count field */
|
||||
+ break;
|
||||
if ( elf_uval(elf, shdr, sh_type) != SHT_SYMTAB )
|
||||
continue;
|
||||
elf->sym_tab = shdr;
|
||||
@@ -170,6 +173,9 @@ void elf_parse_bsdsyms(struct elf_binary *elf, uint64_t pstart)
|
||||
for ( i = 0; i < elf_shdr_count(elf); i++ )
|
||||
{
|
||||
shdr = elf_shdr_by_index(elf, i);
|
||||
+ if ( !elf_access_ok(elf, ELF_HANDLE_PTRVAL(shdr), 1) )
|
||||
+ /* input has an insane section header count field */
|
||||
+ break;
|
||||
type = elf_uval(elf, shdr, sh_type);
|
||||
if ( (type == SHT_STRTAB) || (type == SHT_SYMTAB) )
|
||||
sz = elf_round_up(elf, sz + elf_uval(elf, shdr, sh_size));
|
||||
@@ -224,6 +230,9 @@ do { \
|
||||
|
||||
for ( i = 0; i < elf_shdr_count(elf); i++ )
|
||||
{
|
||||
+ elf_ptrval old_shdr_p;
|
||||
+ elf_ptrval new_shdr_p;
|
||||
+
|
||||
type = elf_uval(elf, shdr, sh_type);
|
||||
if ( (type == SHT_STRTAB) || (type == SHT_SYMTAB) )
|
||||
{
|
||||
@@ -235,8 +244,16 @@ do { \
|
||||
elf_hdr_elm(elf, shdr, sh_offset, maxva - symtab_addr);
|
||||
maxva = ELF_OBSOLETE_VOIDP_CAST elf_round_up(elf, (unsigned long)maxva + sz);
|
||||
}
|
||||
- shdr = ELF_MAKE_HANDLE(elf_shdr, ELF_HANDLE_PTRVAL(shdr) +
|
||||
- (unsigned long)elf_uval(elf, elf->ehdr, e_shentsize));
|
||||
+ old_shdr_p = ELF_HANDLE_PTRVAL(shdr);
|
||||
+ new_shdr_p = old_shdr_p + elf_uval(elf, elf->ehdr, e_shentsize);
|
||||
+ if ( new_shdr_p <= old_shdr_p ) /* wrapped or stuck */
|
||||
+ {
|
||||
+ elf_mark_broken(elf, "bad section header length");
|
||||
+ break;
|
||||
+ }
|
||||
+ if ( !elf_access_ok(elf, new_shdr_p, 1) ) /* outside image */
|
||||
+ break;
|
||||
+ shdr = ELF_MAKE_HANDLE(elf_shdr, new_shdr_p);
|
||||
}
|
||||
|
||||
/* Write down the actual sym size. */
|
||||
@@ -256,6 +273,9 @@ void elf_parse_binary(struct elf_binary *elf)
|
||||
for ( i = 0; i < count; i++ )
|
||||
{
|
||||
phdr = elf_phdr_by_index(elf, i);
|
||||
+ if ( !elf_access_ok(elf, ELF_HANDLE_PTRVAL(phdr), 1) )
|
||||
+ /* input has an insane program header count field */
|
||||
+ break;
|
||||
if ( !elf_phdr_is_loadable(elf, phdr) )
|
||||
continue;
|
||||
paddr = elf_uval(elf, phdr, p_paddr);
|
||||
@@ -278,11 +298,20 @@ elf_errorstatus elf_load_binary(struct elf_binary *elf)
|
||||
ELF_HANDLE_DECL(elf_phdr) phdr;
|
||||
uint64_t i, count, paddr, offset, filesz, memsz;
|
||||
ELF_PTRVAL_VOID dest;
|
||||
+ /*
|
||||
+ * Let bizarre ELFs write the output image up to twice; this
|
||||
+ * calculation is just to ensure our copying loop is no worse than
|
||||
+ * O(domain_size).
|
||||
+ */
|
||||
+ uint64_t remain_allow_copy = (uint64_t)elf->dest_size * 2;
|
||||
|
||||
count = elf_uval(elf, elf->ehdr, e_phnum);
|
||||
for ( i = 0; i < count; i++ )
|
||||
{
|
||||
phdr = elf_phdr_by_index(elf, i);
|
||||
+ if ( !elf_access_ok(elf, ELF_HANDLE_PTRVAL(phdr), 1) )
|
||||
+ /* input has an insane program header count field */
|
||||
+ break;
|
||||
if ( !elf_phdr_is_loadable(elf, phdr) )
|
||||
continue;
|
||||
paddr = elf_uval(elf, phdr, p_paddr);
|
||||
@@ -290,6 +319,20 @@ elf_errorstatus elf_load_binary(struct elf_binary *elf)
|
||||
filesz = elf_uval(elf, phdr, p_filesz);
|
||||
memsz = elf_uval(elf, phdr, p_memsz);
|
||||
dest = elf_get_ptr(elf, paddr);
|
||||
+
|
||||
+ /*
|
||||
+ * We need to check that the input image doesn't have us copy
|
||||
+ * the whole image zillions of times, as that could lead to
|
||||
+ * O(n^2) time behaviour and possible DoS by a malicous ELF.
|
||||
+ */
|
||||
+ if ( remain_allow_copy < memsz )
|
||||
+ {
|
||||
+ elf_mark_broken(elf, "program segments total to more"
|
||||
+ " than the input image size");
|
||||
+ break;
|
||||
+ }
|
||||
+ remain_allow_copy -= memsz;
|
||||
+
|
||||
elf_msg(elf, "%s: phdr %" PRIu64 " at 0x%"ELF_PRPTRVAL" -> 0x%"ELF_PRPTRVAL"\n",
|
||||
__func__, i, dest, (ELF_PTRVAL_VOID)(dest + filesz));
|
||||
if ( elf_load_image(elf, dest, ELF_IMAGE_BASE(elf) + offset, filesz, memsz) != 0 )
|
||||
diff --git a/xen/common/libelf/libelf-tools.c b/xen/common/libelf/libelf-tools.c
|
||||
index 46d4ab1..4a83133 100644
|
||||
--- a/xen/common/libelf/libelf-tools.c
|
||||
+++ b/xen/common/libelf/libelf-tools.c
|
||||
@@ -131,7 +131,16 @@ uint64_t elf_round_up(struct elf_binary *elf, uint64_t addr)
|
||||
|
||||
unsigned elf_shdr_count(struct elf_binary *elf)
|
||||
{
|
||||
- return elf_uval(elf, elf->ehdr, e_shnum);
|
||||
+ unsigned count = elf_uval(elf, elf->ehdr, e_shnum);
|
||||
+ uint64_t max = elf->size / sizeof(Elf32_Shdr);
|
||||
+ if (max > ~(unsigned)0)
|
||||
+ max = ~(unsigned)0; /* Xen doesn't have limits.h :-/ */
|
||||
+ if (count > max)
|
||||
+ {
|
||||
+ elf_mark_broken(elf, "far too many section headers");
|
||||
+ count = max;
|
||||
+ }
|
||||
+ return count;
|
||||
}
|
||||
|
||||
unsigned elf_phdr_count(struct elf_binary *elf)
|
||||
@@ -149,6 +158,9 @@ ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_name(struct elf_binary *elf, const char *n
|
||||
for ( i = 0; i < count; i++ )
|
||||
{
|
||||
shdr = elf_shdr_by_index(elf, i);
|
||||
+ if ( !elf_access_ok(elf, ELF_HANDLE_PTRVAL(shdr), 1) )
|
||||
+ /* input has an insane section header count field */
|
||||
+ break;
|
||||
sname = elf_section_name(elf, shdr);
|
||||
if ( sname && !strcmp(sname, name) )
|
||||
return shdr;
|
||||
@@ -204,6 +216,11 @@ const char *elf_strval(struct elf_binary *elf, elf_ptrval start)
|
||||
if ( !elf_access_unsigned(elf, start, length, 1) )
|
||||
/* ok */
|
||||
return ELF_UNSAFE_PTR(start);
|
||||
+ if ( length >= ELF_MAX_STRING_LENGTH )
|
||||
+ {
|
||||
+ elf_mark_broken(elf, "excessively long string");
|
||||
+ return NULL;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -327,7 +344,14 @@ ELF_HANDLE_DECL(elf_note) elf_note_next(struct elf_binary *elf, ELF_HANDLE_DECL(
|
||||
unsigned namesz = (elf_uval(elf, note, namesz) + 3) & ~3;
|
||||
unsigned descsz = (elf_uval(elf, note, descsz) + 3) & ~3;
|
||||
|
||||
- return ELF_MAKE_HANDLE(elf_note, ELF_HANDLE_PTRVAL(note) + elf_size(elf, note) + namesz + descsz);
|
||||
+ elf_ptrval ptrval = ELF_HANDLE_PTRVAL(note)
|
||||
+ + elf_size(elf, note) + namesz + descsz;
|
||||
+
|
||||
+ if ( ( ptrval <= ELF_HANDLE_PTRVAL(note) || /* wrapped or stuck */
|
||||
+ !elf_access_ok(elf, ELF_HANDLE_PTRVAL(note), 1) ) )
|
||||
+ ptrval = ELF_MAX_PTRVAL; /* terminate caller's loop */
|
||||
+
|
||||
+ return ELF_MAKE_HANDLE(elf_note, ptrval);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
diff --git a/xen/include/xen/libelf.h b/xen/include/xen/libelf.h
|
||||
index 87e126a..f95fe88 100644
|
||||
--- a/xen/include/xen/libelf.h
|
||||
+++ b/xen/include/xen/libelf.h
|
||||
@@ -51,6 +51,9 @@ typedef void elf_log_callback(struct elf_binary*, void *caller_data,
|
||||
|
||||
#endif
|
||||
|
||||
+#define ELF_MAX_STRING_LENGTH 4096
|
||||
+#define ELF_MAX_TOTAL_NOTE_COUNT 65536
|
||||
+
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
/* Macros for accessing the input image and output area. */
|
||||
@@ -353,6 +356,16 @@ ELF_PTRVAL_CONST_VOID elf_note_desc(struct elf_binary *elf, ELF_HANDLE_DECL(elf_
|
||||
uint64_t elf_note_numeric(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
|
||||
uint64_t elf_note_numeric_array(struct elf_binary *, ELF_HANDLE_DECL(elf_note),
|
||||
unsigned int unitsz, unsigned int idx);
|
||||
+
|
||||
+/*
|
||||
+ * If you use elf_note_next in a loop, you must put a nontrivial upper
|
||||
+ * bound on the returned value as part of your loop condition. In
|
||||
+ * some cases elf_note_next will substitute ELF_PTRVAL_MAX as return
|
||||
+ * value to indicate that the iteration isn't going well (for example,
|
||||
+ * the putative "next" value would be earlier in memory). In this
|
||||
+ * case the caller's loop must terminate. Checking against the
|
||||
+ * end of the notes segment with a strict inequality is sufficient.
|
||||
+ */
|
||||
ELF_HANDLE_DECL(elf_note) elf_note_next(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
|
||||
|
||||
/* (Only) checks that the image has the right magic number. */
|
||||
--
|
||||
1.7.2.5
|
||||
|
@ -0,0 +1,406 @@
|
||||
From 3baaa4ffcd3e7dd6227f9bdf817f90e5b75aeda2 Mon Sep 17 00:00:00 2001
|
||||
From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Date: Fri, 14 Jun 2013 16:43:19 +0100
|
||||
Subject: [PATCH 17/23] libelf: abolish obsolete macros
|
||||
|
||||
Abolish ELF_PTRVAL_[CONST_]{CHAR,VOID}; change uses to elf_ptrval.
|
||||
Abolish ELF_HANDLE_DECL_NONCONST; change uses to ELF_HANDLE_DECL.
|
||||
Abolish ELF_OBSOLETE_VOIDP_CAST; simply remove all uses.
|
||||
|
||||
No functional change. (Verified by diffing assembler output.)
|
||||
|
||||
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
|
||||
v2: New patch.
|
||||
---
|
||||
tools/libxc/xc_dom_elfloader.c | 8 +++---
|
||||
tools/xcutils/readnotes.c | 2 +-
|
||||
xen/common/libelf/libelf-dominfo.c | 6 ++--
|
||||
xen/common/libelf/libelf-loader.c | 24 +++++++++---------
|
||||
xen/common/libelf/libelf-tools.c | 24 +++++++++---------
|
||||
xen/include/xen/libelf.h | 48 +++++++++---------------------------
|
||||
6 files changed, 44 insertions(+), 68 deletions(-)
|
||||
|
||||
diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c
|
||||
index c5014d2..9fc4b94 100644
|
||||
--- a/tools/libxc/xc_dom_elfloader.c
|
||||
+++ b/tools/libxc/xc_dom_elfloader.c
|
||||
@@ -116,9 +116,9 @@ static elf_errorstatus xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
struct elf_binary *elf, bool load)
|
||||
{
|
||||
struct elf_binary syms;
|
||||
- ELF_HANDLE_DECL_NONCONST(elf_shdr) shdr; ELF_HANDLE_DECL(elf_shdr) shdr2;
|
||||
+ ELF_HANDLE_DECL(elf_shdr) shdr; ELF_HANDLE_DECL(elf_shdr) shdr2;
|
||||
xen_vaddr_t symtab, maxaddr;
|
||||
- ELF_PTRVAL_CHAR hdr;
|
||||
+ elf_ptrval hdr;
|
||||
size_t size;
|
||||
unsigned h, count, type, i, tables = 0;
|
||||
unsigned long *strtab_referenced = NULL;
|
||||
@@ -242,7 +242,7 @@ static elf_errorstatus xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
|
||||
for ( h = 0; h < count; h++ )
|
||||
{
|
||||
- shdr = ELF_OBSOLETE_VOIDP_CAST elf_shdr_by_index(&syms, h);
|
||||
+ shdr = elf_shdr_by_index(&syms, h);
|
||||
if ( !elf_access_ok(elf, ELF_HANDLE_PTRVAL(shdr), 1) )
|
||||
/* input has an insane section header count field */
|
||||
break;
|
||||
@@ -278,7 +278,7 @@ static elf_errorstatus xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
if ( load )
|
||||
{
|
||||
shdr2 = elf_shdr_by_index(elf, h);
|
||||
- elf_memcpy_safe(elf, ELF_OBSOLETE_VOIDP_CAST elf_section_start(&syms, shdr),
|
||||
+ elf_memcpy_safe(elf, elf_section_start(&syms, shdr),
|
||||
elf_section_start(elf, shdr2),
|
||||
size);
|
||||
}
|
||||
diff --git a/tools/xcutils/readnotes.c b/tools/xcutils/readnotes.c
|
||||
index 2ca7732..5fa445e 100644
|
||||
--- a/tools/xcutils/readnotes.c
|
||||
+++ b/tools/xcutils/readnotes.c
|
||||
@@ -80,7 +80,7 @@ static void print_l1_mfn_valid_note(const char *prefix, struct elf_binary *elf,
|
||||
ELF_HANDLE_DECL(elf_note) note)
|
||||
{
|
||||
unsigned descsz = elf_uval(elf, note, descsz);
|
||||
- ELF_PTRVAL_CONST_VOID desc = elf_note_desc(elf, note);
|
||||
+ elf_ptrval desc = elf_note_desc(elf, note);
|
||||
|
||||
/* XXX should be able to cope with a list of values. */
|
||||
switch ( descsz / 2 )
|
||||
diff --git a/xen/common/libelf/libelf-dominfo.c b/xen/common/libelf/libelf-dominfo.c
|
||||
index 25a10d7..412ea70 100644
|
||||
--- a/xen/common/libelf/libelf-dominfo.c
|
||||
+++ b/xen/common/libelf/libelf-dominfo.c
|
||||
@@ -220,8 +220,8 @@ elf_errorstatus elf_xen_parse_note(struct elf_binary *elf,
|
||||
|
||||
static unsigned elf_xen_parse_notes(struct elf_binary *elf,
|
||||
struct elf_dom_parms *parms,
|
||||
- ELF_PTRVAL_CONST_VOID start,
|
||||
- ELF_PTRVAL_CONST_VOID end,
|
||||
+ elf_ptrval start,
|
||||
+ elf_ptrval end,
|
||||
unsigned *total_note_count)
|
||||
{
|
||||
unsigned xen_elfnotes = 0;
|
||||
@@ -258,7 +258,7 @@ static unsigned elf_xen_parse_notes(struct elf_binary *elf,
|
||||
elf_errorstatus elf_xen_parse_guest_info(struct elf_binary *elf,
|
||||
struct elf_dom_parms *parms)
|
||||
{
|
||||
- ELF_PTRVAL_CONST_CHAR h;
|
||||
+ elf_ptrval h;
|
||||
unsigned char name[32], value[128];
|
||||
unsigned len;
|
||||
|
||||
diff --git a/xen/common/libelf/libelf-loader.c b/xen/common/libelf/libelf-loader.c
|
||||
index 06799af..e2e75af 100644
|
||||
--- a/xen/common/libelf/libelf-loader.c
|
||||
+++ b/xen/common/libelf/libelf-loader.c
|
||||
@@ -118,7 +118,7 @@ void elf_set_log(struct elf_binary *elf, elf_log_callback *log_callback,
|
||||
}
|
||||
|
||||
static elf_errorstatus elf_load_image(struct elf_binary *elf,
|
||||
- ELF_PTRVAL_VOID dst, ELF_PTRVAL_CONST_VOID src,
|
||||
+ elf_ptrval dst, elf_ptrval src,
|
||||
uint64_t filesz, uint64_t memsz)
|
||||
{
|
||||
elf_memcpy_safe(elf, dst, src, filesz);
|
||||
@@ -132,7 +132,7 @@ void elf_set_verbose(struct elf_binary *elf)
|
||||
elf->verbose = 1;
|
||||
}
|
||||
|
||||
-static elf_errorstatus elf_load_image(struct elf_binary *elf, ELF_PTRVAL_VOID dst, ELF_PTRVAL_CONST_VOID src, uint64_t filesz, uint64_t memsz)
|
||||
+static elf_errorstatus elf_load_image(struct elf_binary *elf, elf_ptrval dst, elf_ptrval src, uint64_t filesz, uint64_t memsz)
|
||||
{
|
||||
elf_errorstatus rc;
|
||||
if ( filesz > ULONG_MAX || memsz > ULONG_MAX )
|
||||
@@ -187,12 +187,12 @@ void elf_parse_bsdsyms(struct elf_binary *elf, uint64_t pstart)
|
||||
|
||||
static void elf_load_bsdsyms(struct elf_binary *elf)
|
||||
{
|
||||
- ELF_HANDLE_DECL_NONCONST(elf_ehdr) sym_ehdr;
|
||||
+ ELF_HANDLE_DECL(elf_ehdr) sym_ehdr;
|
||||
unsigned long sz;
|
||||
- ELF_PTRVAL_VOID maxva;
|
||||
- ELF_PTRVAL_VOID symbase;
|
||||
- ELF_PTRVAL_VOID symtab_addr;
|
||||
- ELF_HANDLE_DECL_NONCONST(elf_shdr) shdr;
|
||||
+ elf_ptrval maxva;
|
||||
+ elf_ptrval symbase;
|
||||
+ elf_ptrval symtab_addr;
|
||||
+ ELF_HANDLE_DECL(elf_shdr) shdr;
|
||||
unsigned i, type;
|
||||
|
||||
if ( !elf->bsd_symtab_pstart )
|
||||
@@ -226,7 +226,7 @@ do { \
|
||||
elf_memcpy_safe(elf, ELF_HANDLE_PTRVAL(shdr),
|
||||
ELF_IMAGE_BASE(elf) + elf_uval(elf, elf->ehdr, e_shoff),
|
||||
sz);
|
||||
- maxva = ELF_OBSOLETE_VOIDP_CAST elf_round_up(elf, (unsigned long)maxva + sz);
|
||||
+ maxva = elf_round_up(elf, (unsigned long)maxva + sz);
|
||||
|
||||
for ( i = 0; i < elf_shdr_count(elf); i++ )
|
||||
{
|
||||
@@ -242,7 +242,7 @@ do { \
|
||||
elf_memcpy_safe(elf, maxva, elf_section_start(elf, shdr), sz);
|
||||
/* Mangled to be based on ELF header location. */
|
||||
elf_hdr_elm(elf, shdr, sh_offset, maxva - symtab_addr);
|
||||
- maxva = ELF_OBSOLETE_VOIDP_CAST elf_round_up(elf, (unsigned long)maxva + sz);
|
||||
+ maxva = elf_round_up(elf, (unsigned long)maxva + sz);
|
||||
}
|
||||
old_shdr_p = ELF_HANDLE_PTRVAL(shdr);
|
||||
new_shdr_p = old_shdr_p + elf_uval(elf, elf->ehdr, e_shentsize);
|
||||
@@ -297,7 +297,7 @@ elf_errorstatus elf_load_binary(struct elf_binary *elf)
|
||||
{
|
||||
ELF_HANDLE_DECL(elf_phdr) phdr;
|
||||
uint64_t i, count, paddr, offset, filesz, memsz;
|
||||
- ELF_PTRVAL_VOID dest;
|
||||
+ elf_ptrval dest;
|
||||
/*
|
||||
* Let bizarre ELFs write the output image up to twice; this
|
||||
* calculation is just to ensure our copying loop is no worse than
|
||||
@@ -334,7 +334,7 @@ elf_errorstatus elf_load_binary(struct elf_binary *elf)
|
||||
remain_allow_copy -= memsz;
|
||||
|
||||
elf_msg(elf, "%s: phdr %" PRIu64 " at 0x%"ELF_PRPTRVAL" -> 0x%"ELF_PRPTRVAL"\n",
|
||||
- __func__, i, dest, (ELF_PTRVAL_VOID)(dest + filesz));
|
||||
+ __func__, i, dest, (elf_ptrval)(dest + filesz));
|
||||
if ( elf_load_image(elf, dest, ELF_IMAGE_BASE(elf) + offset, filesz, memsz) != 0 )
|
||||
return -1;
|
||||
}
|
||||
@@ -343,7 +343,7 @@ elf_errorstatus elf_load_binary(struct elf_binary *elf)
|
||||
return 0;
|
||||
}
|
||||
|
||||
-ELF_PTRVAL_VOID elf_get_ptr(struct elf_binary *elf, unsigned long addr)
|
||||
+elf_ptrval elf_get_ptr(struct elf_binary *elf, unsigned long addr)
|
||||
{
|
||||
return ELF_REALPTR2PTRVAL(elf->dest_base) + addr - elf->pstart;
|
||||
}
|
||||
diff --git a/xen/common/libelf/libelf-tools.c b/xen/common/libelf/libelf-tools.c
|
||||
index 4a83133..e202249 100644
|
||||
--- a/xen/common/libelf/libelf-tools.c
|
||||
+++ b/xen/common/libelf/libelf-tools.c
|
||||
@@ -171,7 +171,7 @@ ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_name(struct elf_binary *elf, const char *n
|
||||
ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_index(struct elf_binary *elf, unsigned index)
|
||||
{
|
||||
uint64_t count = elf_shdr_count(elf);
|
||||
- ELF_PTRVAL_CONST_VOID ptr;
|
||||
+ elf_ptrval ptr;
|
||||
|
||||
if ( index >= count )
|
||||
return ELF_INVALID_HANDLE(elf_shdr);
|
||||
@@ -185,7 +185,7 @@ ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_index(struct elf_binary *elf, unsigned ind
|
||||
ELF_HANDLE_DECL(elf_phdr) elf_phdr_by_index(struct elf_binary *elf, unsigned index)
|
||||
{
|
||||
uint64_t count = elf_uval(elf, elf->ehdr, e_phnum);
|
||||
- ELF_PTRVAL_CONST_VOID ptr;
|
||||
+ elf_ptrval ptr;
|
||||
|
||||
if ( index >= count )
|
||||
return ELF_INVALID_HANDLE(elf_phdr);
|
||||
@@ -233,24 +233,24 @@ const char *elf_strfmt(struct elf_binary *elf, elf_ptrval start)
|
||||
return str;
|
||||
}
|
||||
|
||||
-ELF_PTRVAL_CONST_VOID elf_section_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr)
|
||||
+elf_ptrval elf_section_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr)
|
||||
{
|
||||
return ELF_IMAGE_BASE(elf) + elf_uval(elf, shdr, sh_offset);
|
||||
}
|
||||
|
||||
-ELF_PTRVAL_CONST_VOID elf_section_end(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr)
|
||||
+elf_ptrval elf_section_end(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr)
|
||||
{
|
||||
return ELF_IMAGE_BASE(elf)
|
||||
+ elf_uval(elf, shdr, sh_offset) + elf_uval(elf, shdr, sh_size);
|
||||
}
|
||||
|
||||
-ELF_PTRVAL_CONST_VOID elf_segment_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr)
|
||||
+elf_ptrval elf_segment_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr)
|
||||
{
|
||||
return ELF_IMAGE_BASE(elf)
|
||||
+ elf_uval(elf, phdr, p_offset);
|
||||
}
|
||||
|
||||
-ELF_PTRVAL_CONST_VOID elf_segment_end(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr)
|
||||
+elf_ptrval elf_segment_end(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr)
|
||||
{
|
||||
return ELF_IMAGE_BASE(elf)
|
||||
+ elf_uval(elf, phdr, p_offset) + elf_uval(elf, phdr, p_filesz);
|
||||
@@ -258,8 +258,8 @@ ELF_PTRVAL_CONST_VOID elf_segment_end(struct elf_binary *elf, ELF_HANDLE_DECL(el
|
||||
|
||||
ELF_HANDLE_DECL(elf_sym) elf_sym_by_name(struct elf_binary *elf, const char *symbol)
|
||||
{
|
||||
- ELF_PTRVAL_CONST_VOID ptr = elf_section_start(elf, elf->sym_tab);
|
||||
- ELF_PTRVAL_CONST_VOID end = elf_section_end(elf, elf->sym_tab);
|
||||
+ elf_ptrval ptr = elf_section_start(elf, elf->sym_tab);
|
||||
+ elf_ptrval end = elf_section_end(elf, elf->sym_tab);
|
||||
ELF_HANDLE_DECL(elf_sym) sym;
|
||||
uint64_t info, name;
|
||||
const char *sym_name;
|
||||
@@ -283,7 +283,7 @@ ELF_HANDLE_DECL(elf_sym) elf_sym_by_name(struct elf_binary *elf, const char *sym
|
||||
|
||||
ELF_HANDLE_DECL(elf_sym) elf_sym_by_index(struct elf_binary *elf, unsigned index)
|
||||
{
|
||||
- ELF_PTRVAL_CONST_VOID ptr = elf_section_start(elf, elf->sym_tab);
|
||||
+ elf_ptrval ptr = elf_section_start(elf, elf->sym_tab);
|
||||
ELF_HANDLE_DECL(elf_sym) sym;
|
||||
|
||||
sym = ELF_MAKE_HANDLE(elf_sym, ptr + index * elf_size(elf, sym));
|
||||
@@ -295,7 +295,7 @@ const char *elf_note_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note
|
||||
return elf_strval(elf, ELF_HANDLE_PTRVAL(note) + elf_size(elf, note));
|
||||
}
|
||||
|
||||
-ELF_PTRVAL_CONST_VOID elf_note_desc(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note)
|
||||
+elf_ptrval elf_note_desc(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note)
|
||||
{
|
||||
unsigned namesz = (elf_uval(elf, note, namesz) + 3) & ~3;
|
||||
|
||||
@@ -304,7 +304,7 @@ ELF_PTRVAL_CONST_VOID elf_note_desc(struct elf_binary *elf, ELF_HANDLE_DECL(elf_
|
||||
|
||||
uint64_t elf_note_numeric(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note)
|
||||
{
|
||||
- ELF_PTRVAL_CONST_VOID desc = elf_note_desc(elf, note);
|
||||
+ elf_ptrval desc = elf_note_desc(elf, note);
|
||||
unsigned descsz = elf_uval(elf, note, descsz);
|
||||
|
||||
switch (descsz)
|
||||
@@ -322,7 +322,7 @@ uint64_t elf_note_numeric(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note
|
||||
uint64_t elf_note_numeric_array(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note,
|
||||
unsigned int unitsz, unsigned int idx)
|
||||
{
|
||||
- ELF_PTRVAL_CONST_VOID desc = elf_note_desc(elf, note);
|
||||
+ elf_ptrval desc = elf_note_desc(elf, note);
|
||||
unsigned descsz = elf_uval(elf, note, descsz);
|
||||
|
||||
if ( descsz % unitsz || idx >= descsz / unitsz )
|
||||
diff --git a/xen/include/xen/libelf.h b/xen/include/xen/libelf.h
|
||||
index f95fe88..174f8da 100644
|
||||
--- a/xen/include/xen/libelf.h
|
||||
+++ b/xen/include/xen/libelf.h
|
||||
@@ -61,13 +61,8 @@ typedef void elf_log_callback(struct elf_binary*, void *caller_data,
|
||||
/*
|
||||
* We abstract away the pointerness of these pointers, replacing
|
||||
* various void*, char* and struct* with the following:
|
||||
- * PTRVAL A pointer to a byte; one can do pointer arithmetic
|
||||
+ * elf_ptrval A pointer to a byte; one can do pointer arithmetic
|
||||
* on this.
|
||||
- * This replaces variables which were char*,void*
|
||||
- * and their const versions, so we provide four
|
||||
- * different obsolete declaration macros:
|
||||
- * ELF_PTRVAL_{,CONST}{VOID,CHAR}
|
||||
- * New code can simply use the elf_ptrval typedef.
|
||||
* HANDLE A pointer to a struct. There is one of these types
|
||||
* for each pointer type - that is, for each "structname".
|
||||
* In the arguments to the various HANDLE macros, structname
|
||||
@@ -76,8 +71,6 @@ typedef void elf_log_callback(struct elf_binary*, void *caller_data,
|
||||
* pointers. In the current code attempts to do so will
|
||||
* compile, but in the next patch this will become a
|
||||
* compile error.
|
||||
- * We also provide a second declaration macro for
|
||||
- * pointers which were to const; this is obsolete.
|
||||
*/
|
||||
|
||||
typedef uintptr_t elf_ptrval;
|
||||
@@ -85,15 +78,9 @@ typedef uintptr_t elf_ptrval;
|
||||
#define ELF_REALPTR2PTRVAL(realpointer) ((elf_ptrval)(realpointer))
|
||||
/* Converts an actual C pointer into a PTRVAL */
|
||||
|
||||
-#define ELF_HANDLE_DECL_NONCONST(structname) structname##_handle /*obsolete*/
|
||||
#define ELF_HANDLE_DECL(structname) structname##_handle
|
||||
/* Provides a type declaration for a HANDLE. */
|
||||
|
||||
-#define ELF_PTRVAL_VOID elf_ptrval /*obsolete*/
|
||||
-#define ELF_PTRVAL_CHAR elf_ptrval /*obsolete*/
|
||||
-#define ELF_PTRVAL_CONST_VOID elf_ptrval /*obsolete*/
|
||||
-#define ELF_PTRVAL_CONST_CHAR elf_ptrval /*obsolete*/
|
||||
-
|
||||
#ifdef __XEN__
|
||||
# define ELF_PRPTRVAL "lu"
|
||||
/*
|
||||
@@ -124,17 +111,6 @@ typedef uintptr_t elf_ptrval;
|
||||
#define ELF_HANDLE_PTRVAL(handleval) ((handleval).ptrval)
|
||||
/* Converts a HANDLE to a PTRVAL. */
|
||||
|
||||
-#define ELF_OBSOLETE_VOIDP_CAST /*empty*/
|
||||
- /*
|
||||
- * In some places the old code used to need to
|
||||
- * - cast away const (the existing code uses const a fair
|
||||
- * bit but actually sometimes wants to write to its input)
|
||||
- * from a PTRVAL.
|
||||
- * - convert an integer representing a pointer to a PTRVAL
|
||||
- * Nowadays all of these re uintptr_ts so there is no const problem
|
||||
- * and no need for any casting.
|
||||
- */
|
||||
-
|
||||
#define ELF_UNSAFE_PTR(ptrval) ((void*)(elf_ptrval)(ptrval))
|
||||
/*
|
||||
* Turns a PTRVAL into an actual C pointer. Before this is done
|
||||
@@ -212,7 +188,7 @@ struct elf_binary {
|
||||
char data;
|
||||
|
||||
ELF_HANDLE_DECL(elf_ehdr) ehdr;
|
||||
- ELF_PTRVAL_CONST_CHAR sec_strtab;
|
||||
+ elf_ptrval sec_strtab;
|
||||
ELF_HANDLE_DECL(elf_shdr) sym_tab;
|
||||
uint64_t sym_strtab;
|
||||
|
||||
@@ -290,7 +266,7 @@ struct elf_binary {
|
||||
* str should be a HANDLE.
|
||||
*/
|
||||
|
||||
-uint64_t elf_access_unsigned(struct elf_binary *elf, ELF_PTRVAL_CONST_VOID ptr,
|
||||
+uint64_t elf_access_unsigned(struct elf_binary *elf, elf_ptrval ptr,
|
||||
uint64_t offset, size_t size);
|
||||
/* Reads a field at arbitrary offset and alignemnt */
|
||||
|
||||
@@ -342,17 +318,17 @@ ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_index(struct elf_binary *elf, unsigned ind
|
||||
ELF_HANDLE_DECL(elf_phdr) elf_phdr_by_index(struct elf_binary *elf, unsigned index);
|
||||
|
||||
const char *elf_section_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr); /* might return NULL if inputs are invalid */
|
||||
-ELF_PTRVAL_CONST_VOID elf_section_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr);
|
||||
-ELF_PTRVAL_CONST_VOID elf_section_end(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr);
|
||||
+elf_ptrval elf_section_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr);
|
||||
+elf_ptrval elf_section_end(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr);
|
||||
|
||||
-ELF_PTRVAL_CONST_VOID elf_segment_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr);
|
||||
-ELF_PTRVAL_CONST_VOID elf_segment_end(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr);
|
||||
+elf_ptrval elf_segment_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr);
|
||||
+elf_ptrval elf_segment_end(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr);
|
||||
|
||||
ELF_HANDLE_DECL(elf_sym) elf_sym_by_name(struct elf_binary *elf, const char *symbol);
|
||||
ELF_HANDLE_DECL(elf_sym) elf_sym_by_index(struct elf_binary *elf, unsigned index);
|
||||
|
||||
const char *elf_note_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note); /* may return NULL */
|
||||
-ELF_PTRVAL_CONST_VOID elf_note_desc(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
|
||||
+elf_ptrval elf_note_desc(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
|
||||
uint64_t elf_note_numeric(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
|
||||
uint64_t elf_note_numeric_array(struct elf_binary *, ELF_HANDLE_DECL(elf_note),
|
||||
unsigned int unitsz, unsigned int idx);
|
||||
@@ -391,7 +367,7 @@ void elf_set_log(struct elf_binary *elf, elf_log_callback*,
|
||||
void elf_parse_binary(struct elf_binary *elf);
|
||||
elf_errorstatus elf_load_binary(struct elf_binary *elf);
|
||||
|
||||
-ELF_PTRVAL_VOID elf_get_ptr(struct elf_binary *elf, unsigned long addr);
|
||||
+elf_ptrval elf_get_ptr(struct elf_binary *elf, unsigned long addr);
|
||||
uint64_t elf_lookup_addr(struct elf_binary *elf, const char *symbol);
|
||||
|
||||
void elf_parse_bsdsyms(struct elf_binary *elf, uint64_t pstart); /* private */
|
||||
@@ -426,9 +402,9 @@ struct xen_elfnote {
|
||||
|
||||
struct elf_dom_parms {
|
||||
/* raw */
|
||||
- ELF_PTRVAL_CONST_CHAR guest_info;
|
||||
- ELF_PTRVAL_CONST_VOID elf_note_start;
|
||||
- ELF_PTRVAL_CONST_VOID elf_note_end;
|
||||
+ elf_ptrval guest_info;
|
||||
+ elf_ptrval elf_note_start;
|
||||
+ elf_ptrval elf_note_end;
|
||||
struct xen_elfnote elf_notes[XEN_ELFNOTE_MAX + 1];
|
||||
|
||||
/* parsed */
|
||||
--
|
||||
1.7.2.5
|
||||
|
@ -0,0 +1,450 @@
|
||||
From b06e277b1fc08c7da3befeb3ac3950e1d941585d Mon Sep 17 00:00:00 2001
|
||||
From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Date: Fri, 14 Jun 2013 16:43:19 +0100
|
||||
Subject: [PATCH 18/23] libxc: Add range checking to xc_dom_binloader
|
||||
|
||||
This is a simple binary image loader with its own metadata format.
|
||||
However, it is too careless with image-supplied values.
|
||||
|
||||
Add the following checks:
|
||||
|
||||
* That the image is bigger than the metadata table; otherwise the
|
||||
pointer arithmetic to calculate the metadata table location may
|
||||
yield undefined and dangerous values.
|
||||
|
||||
* When clamping the end of the region to search, that we do not
|
||||
calculate pointers beyond the end of the image. The C
|
||||
specification does not permit this and compilers are becoming ever
|
||||
more determined to miscompile code when they can "prove" various
|
||||
falsehoods based on assertions from the C spec.
|
||||
|
||||
* That the supplied image is big enough for the text we are allegedly
|
||||
copying from it. Otherwise we might have a read overrun and copy
|
||||
the results (perhaps a lot of secret data) into the guest.
|
||||
|
||||
This is part of the fix to a security issue, XSA-55.
|
||||
|
||||
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
---
|
||||
tools/libxc/xc_dom_binloader.c | 15 +++++++++++++--
|
||||
1 files changed, 13 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/tools/libxc/xc_dom_binloader.c b/tools/libxc/xc_dom_binloader.c
|
||||
index bde93f7..8596a28 100644
|
||||
--- a/tools/libxc/xc_dom_binloader.c
|
||||
+++ b/tools/libxc/xc_dom_binloader.c
|
||||
@@ -123,10 +123,13 @@ static struct xen_bin_image_table *find_table(struct xc_dom_image *dom)
|
||||
uint32_t *probe_ptr;
|
||||
uint32_t *probe_end;
|
||||
|
||||
+ if ( dom->kernel_size < sizeof(*table) )
|
||||
+ return NULL;
|
||||
probe_ptr = dom->kernel_blob;
|
||||
- probe_end = dom->kernel_blob + dom->kernel_size - sizeof(*table);
|
||||
- if ( (void*)probe_end > (dom->kernel_blob + 8192) )
|
||||
+ if ( dom->kernel_size > (8192 + sizeof(*table)) )
|
||||
probe_end = dom->kernel_blob + 8192;
|
||||
+ else
|
||||
+ probe_end = dom->kernel_blob + dom->kernel_size - sizeof(*table);
|
||||
|
||||
for ( table = NULL; probe_ptr < probe_end; probe_ptr++ )
|
||||
{
|
||||
@@ -282,6 +285,14 @@ static int xc_dom_load_bin_kernel(struct xc_dom_image *dom)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
+ if ( image_size < skip ||
|
||||
+ image_size - skip < text_size )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: image is too small for declared text size",
|
||||
+ __FUNCTION__);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
memcpy(dest, image + skip, text_size);
|
||||
memset(dest + text_size, 0, bss_size);
|
||||
|
||||
--
|
||||
1.7.2.5
|
||||
#From 77c0829fa751f052f7b8ec08287aef6e7ba97bc5 Mon Sep 17 00:00:00 2001
|
||||
#From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
#Date: Fri, 14 Jun 2013 16:43:19 +0100
|
||||
#Subject: [PATCH 19/23] libxc: check failure of xc_dom_*_to_ptr, xc_map_foreign_range
|
||||
#
|
||||
#The return values from xc_dom_*_to_ptr and xc_map_foreign_range are
|
||||
#sometimes dereferenced, or subjected to pointer arithmetic, without
|
||||
#checking whether the relevant function failed and returned NULL.
|
||||
#
|
||||
#Add an appropriate error check at every call site.
|
||||
#
|
||||
#Changes in the 4.2 backport of this series:
|
||||
#* Fix tools/libxc/xc_dom_x86.c:setup_pgtables_x86_32.
|
||||
#* Fix tools/libxc/xc_dom_ia64.c:start_info_ia64.
|
||||
#* Fix tools/libxc/ia64/xc_ia64_dom_fwloader.c:xc_dom_load_fw_kernel.
|
||||
#
|
||||
#This is part of the fix to a security issue, XSA-55.
|
||||
#
|
||||
#Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
#---
|
||||
# tools/libxc/ia64/xc_ia64_dom_fwloader.c | 2 +
|
||||
# tools/libxc/xc_dom_binloader.c | 6 +++
|
||||
# tools/libxc/xc_dom_core.c | 6 +++
|
||||
# tools/libxc/xc_dom_elfloader.c | 13 +++++++
|
||||
# tools/libxc/xc_dom_ia64.c | 6 +++
|
||||
# tools/libxc/xc_dom_x86.c | 55 +++++++++++++++++++++++++++++++
|
||||
# tools/libxc/xc_domain_restore.c | 27 +++++++++++++++
|
||||
# tools/libxc/xc_offline_page.c | 5 +++
|
||||
# 8 files changed, 120 insertions(+), 0 deletions(-)
|
||||
#
|
||||
diff --git a/tools/libxc/ia64/xc_ia64_dom_fwloader.c b/tools/libxc/ia64/xc_ia64_dom_fwloader.c
|
||||
index cdf3333..dbd3349 100644
|
||||
--- a/tools/libxc/ia64/xc_ia64_dom_fwloader.c
|
||||
+++ b/tools/libxc/ia64/xc_ia64_dom_fwloader.c
|
||||
@@ -60,6 +60,8 @@ static int xc_dom_load_fw_kernel(struct xc_dom_image *dom)
|
||||
unsigned long i;
|
||||
|
||||
dest = xc_dom_vaddr_to_ptr(dom, dom->kernel_seg.vstart);
|
||||
+ if ( dest == NULL )
|
||||
+ return -1;
|
||||
memcpy(dest, dom->kernel_blob, FW_SIZE);
|
||||
|
||||
/* Synchronize cache. */
|
||||
diff --git a/tools/libxc/xc_dom_binloader.c b/tools/libxc/xc_dom_binloader.c
|
||||
index 8596a28..553b366 100644
|
||||
--- a/tools/libxc/xc_dom_binloader.c
|
||||
+++ b/tools/libxc/xc_dom_binloader.c
|
||||
@@ -277,6 +277,12 @@ static int xc_dom_load_bin_kernel(struct xc_dom_image *dom)
|
||||
DOMPRINTF(" bss_size: 0x%" PRIx32 "", bss_size);
|
||||
|
||||
dest = xc_dom_vaddr_to_ptr(dom, dom->kernel_seg.vstart, &dest_size);
|
||||
+ if ( dest == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: xc_dom_vaddr_to_ptr(dom, dom->kernel_seg.vstart)"
|
||||
+ " => NULL", __FUNCTION__);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
|
||||
if ( dest_size < text_size ||
|
||||
dest_size - text_size < bss_size )
|
||||
diff --git a/tools/libxc/xc_dom_core.c b/tools/libxc/xc_dom_core.c
|
||||
index 8913e41..a54ddae 100644
|
||||
--- a/tools/libxc/xc_dom_core.c
|
||||
+++ b/tools/libxc/xc_dom_core.c
|
||||
@@ -868,6 +868,12 @@ int xc_dom_build_image(struct xc_dom_image *dom)
|
||||
ramdisklen) != 0 )
|
||||
goto err;
|
||||
ramdiskmap = xc_dom_seg_to_ptr(dom, &dom->ramdisk_seg);
|
||||
+ if ( ramdiskmap == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: xc_dom_seg_to_ptr(dom, &dom->ramdisk_seg) => NULL",
|
||||
+ __FUNCTION__);
|
||||
+ goto err;
|
||||
+ }
|
||||
if ( unziplen )
|
||||
{
|
||||
if ( xc_dom_do_gunzip(dom->xch,
|
||||
diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c
|
||||
index 9fc4b94..61b5798 100644
|
||||
--- a/tools/libxc/xc_dom_elfloader.c
|
||||
+++ b/tools/libxc/xc_dom_elfloader.c
|
||||
@@ -139,6 +139,12 @@ static elf_errorstatus xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
return 0;
|
||||
size = dom->kernel_seg.vend - dom->bsd_symtab_start;
|
||||
hdr_ptr = xc_dom_vaddr_to_ptr(dom, dom->bsd_symtab_start, &allow_size);
|
||||
+ if ( hdr_ptr == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s/load: xc_dom_vaddr_to_ptr(dom,dom->bsd_symtab_start"
|
||||
+ " => NULL", __FUNCTION__);
|
||||
+ return -1;
|
||||
+ }
|
||||
elf->caller_xdest_base = hdr_ptr;
|
||||
elf->caller_xdest_size = allow_size;
|
||||
hdr = ELF_REALPTR2PTRVAL(hdr_ptr);
|
||||
@@ -384,7 +390,14 @@ static elf_errorstatus xc_dom_load_elf_kernel(struct xc_dom_image *dom)
|
||||
xen_pfn_t pages;
|
||||
|
||||
elf->dest_base = xc_dom_seg_to_ptr_pages(dom, &dom->kernel_seg, &pages);
|
||||
+ if ( elf->dest_base == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: xc_dom_vaddr_to_ptr(dom,dom->kernel_seg)"
|
||||
+ " => NULL", __FUNCTION__);
|
||||
+ return -1;
|
||||
+ }
|
||||
elf->dest_size = pages * XC_DOM_PAGE_SIZE(dom);
|
||||
+
|
||||
rc = elf_load_binary(elf);
|
||||
if ( rc < 0 )
|
||||
{
|
||||
diff --git a/tools/libxc/xc_dom_ia64.c b/tools/libxc/xc_dom_ia64.c
|
||||
index dcd1523..7c0eff1 100644
|
||||
--- a/tools/libxc/xc_dom_ia64.c
|
||||
+++ b/tools/libxc/xc_dom_ia64.c
|
||||
@@ -60,6 +60,12 @@ int start_info_ia64(struct xc_dom_image *dom)
|
||||
|
||||
DOMPRINTF_CALLED(dom->xch);
|
||||
|
||||
+ if ( start_info == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: xc_dom_pfn_to_ptr failed on start_info", __FUNCTION__);
|
||||
+ return -1; /* our caller throws away our return value :-/ */
|
||||
+ }
|
||||
+
|
||||
memset(start_info, 0, sizeof(*start_info));
|
||||
sprintf(start_info->magic, dom->guest_type);
|
||||
start_info->flags = dom->flags;
|
||||
diff --git a/tools/libxc/xc_dom_x86.c b/tools/libxc/xc_dom_x86.c
|
||||
index 0cf1687..75d6b83 100644
|
||||
--- a/tools/libxc/xc_dom_x86.c
|
||||
+++ b/tools/libxc/xc_dom_x86.c
|
||||
@@ -144,6 +144,9 @@ static int setup_pgtables_x86_32(struct xc_dom_image *dom)
|
||||
xen_vaddr_t addr;
|
||||
xen_pfn_t pgpfn;
|
||||
|
||||
+ if ( l2tab == NULL )
|
||||
+ goto pfn_error;
|
||||
+
|
||||
for ( addr = dom->parms.virt_base; addr < dom->virt_pgtab_end;
|
||||
addr += PAGE_SIZE_X86 )
|
||||
{
|
||||
@@ -151,6 +154,8 @@ static int setup_pgtables_x86_32(struct xc_dom_image *dom)
|
||||
{
|
||||
/* get L1 tab, make L2 entry */
|
||||
l1tab = xc_dom_pfn_to_ptr(dom, l1pfn, 1);
|
||||
+ if ( l1tab == NULL )
|
||||
+ goto pfn_error;
|
||||
l2off = l2_table_offset_i386(addr);
|
||||
l2tab[l2off] =
|
||||
pfn_to_paddr(xc_dom_p2m_guest(dom, l1pfn)) | L2_PROT;
|
||||
@@ -169,6 +174,11 @@ static int setup_pgtables_x86_32(struct xc_dom_image *dom)
|
||||
l1tab = NULL;
|
||||
}
|
||||
return 0;
|
||||
+
|
||||
+pfn_error:
|
||||
+ xc_dom_panic(dom->xch, XC_INTERNAL_ERROR,
|
||||
+ "%s: xc_dom_pfn_to_ptr failed", __FUNCTION__);
|
||||
+ return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -219,6 +229,12 @@ static xen_pfn_t move_l3_below_4G(struct xc_dom_image *dom,
|
||||
goto out;
|
||||
|
||||
l3tab = xc_dom_pfn_to_ptr(dom, l3pfn, 1);
|
||||
+ if ( l3tab == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: xc_dom_pfn_to_ptr(dom, l3pfn, 1) => NULL",
|
||||
+ __FUNCTION__);
|
||||
+ return l3mfn; /* our one call site will call xc_dom_panic and fail */
|
||||
+ }
|
||||
memset(l3tab, 0, XC_DOM_PAGE_SIZE(dom));
|
||||
|
||||
DOMPRINTF("%s: successfully relocated L3 below 4G. "
|
||||
@@ -262,6 +278,8 @@ static int setup_pgtables_x86_32_pae(struct xc_dom_image *dom)
|
||||
}
|
||||
|
||||
l3tab = xc_dom_pfn_to_ptr(dom, l3pfn, 1);
|
||||
+ if ( l3tab == NULL )
|
||||
+ goto pfn_error;
|
||||
|
||||
for ( addr = dom->parms.virt_base; addr < dom->virt_pgtab_end;
|
||||
addr += PAGE_SIZE_X86 )
|
||||
@@ -270,6 +288,8 @@ static int setup_pgtables_x86_32_pae(struct xc_dom_image *dom)
|
||||
{
|
||||
/* get L2 tab, make L3 entry */
|
||||
l2tab = xc_dom_pfn_to_ptr(dom, l2pfn, 1);
|
||||
+ if ( l2tab == NULL )
|
||||
+ goto pfn_error;
|
||||
l3off = l3_table_offset_pae(addr);
|
||||
l3tab[l3off] =
|
||||
pfn_to_paddr(xc_dom_p2m_guest(dom, l2pfn)) | L3_PROT;
|
||||
@@ -280,6 +300,8 @@ static int setup_pgtables_x86_32_pae(struct xc_dom_image *dom)
|
||||
{
|
||||
/* get L1 tab, make L2 entry */
|
||||
l1tab = xc_dom_pfn_to_ptr(dom, l1pfn, 1);
|
||||
+ if ( l1tab == NULL )
|
||||
+ goto pfn_error;
|
||||
l2off = l2_table_offset_pae(addr);
|
||||
l2tab[l2off] =
|
||||
pfn_to_paddr(xc_dom_p2m_guest(dom, l1pfn)) | L2_PROT;
|
||||
@@ -306,6 +328,11 @@ static int setup_pgtables_x86_32_pae(struct xc_dom_image *dom)
|
||||
l3tab[3] = pfn_to_paddr(xc_dom_p2m_guest(dom, l2pfn)) | L3_PROT;
|
||||
}
|
||||
return 0;
|
||||
+
|
||||
+pfn_error:
|
||||
+ xc_dom_panic(dom->xch, XC_INTERNAL_ERROR,
|
||||
+ "%s: xc_dom_pfn_to_ptr failed", __FUNCTION__);
|
||||
+ return -EINVAL;
|
||||
}
|
||||
|
||||
#undef L1_PROT
|
||||
@@ -344,6 +371,9 @@ static int setup_pgtables_x86_64(struct xc_dom_image *dom)
|
||||
uint64_t addr;
|
||||
xen_pfn_t pgpfn;
|
||||
|
||||
+ if ( l4tab == NULL )
|
||||
+ goto pfn_error;
|
||||
+
|
||||
for ( addr = dom->parms.virt_base; addr < dom->virt_pgtab_end;
|
||||
addr += PAGE_SIZE_X86 )
|
||||
{
|
||||
@@ -351,6 +381,8 @@ static int setup_pgtables_x86_64(struct xc_dom_image *dom)
|
||||
{
|
||||
/* get L3 tab, make L4 entry */
|
||||
l3tab = xc_dom_pfn_to_ptr(dom, l3pfn, 1);
|
||||
+ if ( l3tab == NULL )
|
||||
+ goto pfn_error;
|
||||
l4off = l4_table_offset_x86_64(addr);
|
||||
l4tab[l4off] =
|
||||
pfn_to_paddr(xc_dom_p2m_guest(dom, l3pfn)) | L4_PROT;
|
||||
@@ -361,6 +393,8 @@ static int setup_pgtables_x86_64(struct xc_dom_image *dom)
|
||||
{
|
||||
/* get L2 tab, make L3 entry */
|
||||
l2tab = xc_dom_pfn_to_ptr(dom, l2pfn, 1);
|
||||
+ if ( l2tab == NULL )
|
||||
+ goto pfn_error;
|
||||
l3off = l3_table_offset_x86_64(addr);
|
||||
l3tab[l3off] =
|
||||
pfn_to_paddr(xc_dom_p2m_guest(dom, l2pfn)) | L3_PROT;
|
||||
@@ -373,6 +407,8 @@ static int setup_pgtables_x86_64(struct xc_dom_image *dom)
|
||||
{
|
||||
/* get L1 tab, make L2 entry */
|
||||
l1tab = xc_dom_pfn_to_ptr(dom, l1pfn, 1);
|
||||
+ if ( l1tab == NULL )
|
||||
+ goto pfn_error;
|
||||
l2off = l2_table_offset_x86_64(addr);
|
||||
l2tab[l2off] =
|
||||
pfn_to_paddr(xc_dom_p2m_guest(dom, l1pfn)) | L2_PROT;
|
||||
@@ -393,6 +429,11 @@ static int setup_pgtables_x86_64(struct xc_dom_image *dom)
|
||||
l1tab = NULL;
|
||||
}
|
||||
return 0;
|
||||
+
|
||||
+pfn_error:
|
||||
+ xc_dom_panic(dom->xch, XC_INTERNAL_ERROR,
|
||||
+ "%s: xc_dom_pfn_to_ptr failed", __FUNCTION__);
|
||||
+ return -EINVAL;
|
||||
}
|
||||
|
||||
#undef L1_PROT
|
||||
@@ -410,6 +451,8 @@ static int alloc_magic_pages(struct xc_dom_image *dom)
|
||||
if ( xc_dom_alloc_segment(dom, &dom->p2m_seg, "phys2mach", 0, p2m_size) )
|
||||
return -1;
|
||||
dom->p2m_guest = xc_dom_seg_to_ptr(dom, &dom->p2m_seg);
|
||||
+ if ( dom->p2m_guest == NULL )
|
||||
+ return -1;
|
||||
|
||||
/* allocate special pages */
|
||||
dom->start_info_pfn = xc_dom_alloc_page(dom, "start info");
|
||||
@@ -434,6 +477,12 @@ static int start_info_x86_32(struct xc_dom_image *dom)
|
||||
|
||||
DOMPRINTF_CALLED(dom->xch);
|
||||
|
||||
+ if ( start_info == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: xc_dom_pfn_to_ptr failed on start_info", __FUNCTION__);
|
||||
+ return -1; /* our caller throws away our return value :-/ */
|
||||
+ }
|
||||
+
|
||||
memset(start_info, 0, sizeof(*start_info));
|
||||
strncpy(start_info->magic, dom->guest_type, sizeof(start_info->magic));
|
||||
start_info->magic[sizeof(start_info->magic) - 1] = '\0';
|
||||
@@ -474,6 +523,12 @@ static int start_info_x86_64(struct xc_dom_image *dom)
|
||||
|
||||
DOMPRINTF_CALLED(dom->xch);
|
||||
|
||||
+ if ( start_info == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: xc_dom_pfn_to_ptr failed on start_info", __FUNCTION__);
|
||||
+ return -1; /* our caller throws away our return value :-/ */
|
||||
+ }
|
||||
+
|
||||
memset(start_info, 0, sizeof(*start_info));
|
||||
strncpy(start_info->magic, dom->guest_type, sizeof(start_info->magic));
|
||||
start_info->magic[sizeof(start_info->magic) - 1] = '\0';
|
||||
diff --git a/tools/libxc/xc_domain_restore.c b/tools/libxc/xc_domain_restore.c
|
||||
index b4c0b10..3994f8f 100644
|
||||
--- a/tools/libxc/xc_domain_restore.c
|
||||
+++ b/tools/libxc/xc_domain_restore.c
|
||||
@@ -1556,6 +1556,12 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
|
||||
mfn = ctx->p2m[pfn];
|
||||
buf = xc_map_foreign_range(xch, dom, PAGE_SIZE,
|
||||
PROT_READ | PROT_WRITE, mfn);
|
||||
+ if ( buf == NULL )
|
||||
+ {
|
||||
+ ERROR("xc_map_foreign_range for generation id"
|
||||
+ " buffer failed");
|
||||
+ goto out;
|
||||
+ }
|
||||
|
||||
generationid = *(unsigned long long *)(buf + offset);
|
||||
*(unsigned long long *)(buf + offset) = generationid + 1;
|
||||
@@ -1713,6 +1719,11 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
|
||||
l3tab = (uint64_t *)
|
||||
xc_map_foreign_range(xch, dom, PAGE_SIZE,
|
||||
PROT_READ, ctx->p2m[i]);
|
||||
+ if ( l3tab == NULL )
|
||||
+ {
|
||||
+ PERROR("xc_map_foreign_range failed (for l3tab)");
|
||||
+ goto out;
|
||||
+ }
|
||||
|
||||
for ( j = 0; j < 4; j++ )
|
||||
l3ptes[j] = l3tab[j];
|
||||
@@ -1739,6 +1750,11 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
|
||||
l3tab = (uint64_t *)
|
||||
xc_map_foreign_range(xch, dom, PAGE_SIZE,
|
||||
PROT_READ | PROT_WRITE, ctx->p2m[i]);
|
||||
+ if ( l3tab == NULL )
|
||||
+ {
|
||||
+ PERROR("xc_map_foreign_range failed (for l3tab, 2nd)");
|
||||
+ goto out;
|
||||
+ }
|
||||
|
||||
for ( j = 0; j < 4; j++ )
|
||||
l3tab[j] = l3ptes[j];
|
||||
@@ -1909,6 +1925,12 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
|
||||
SET_FIELD(ctxt, user_regs.edx, mfn);
|
||||
start_info = xc_map_foreign_range(
|
||||
xch, dom, PAGE_SIZE, PROT_READ | PROT_WRITE, mfn);
|
||||
+ if ( start_info == NULL )
|
||||
+ {
|
||||
+ PERROR("xc_map_foreign_range failed (for start_info)");
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
SET_FIELD(start_info, nr_pages, dinfo->p2m_size);
|
||||
SET_FIELD(start_info, shared_info, shared_info_frame<<PAGE_SHIFT);
|
||||
SET_FIELD(start_info, flags, 0);
|
||||
@@ -2056,6 +2078,11 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
|
||||
/* Restore contents of shared-info page. No checking needed. */
|
||||
new_shared_info = xc_map_foreign_range(
|
||||
xch, dom, PAGE_SIZE, PROT_WRITE, shared_info_frame);
|
||||
+ if ( new_shared_info == NULL )
|
||||
+ {
|
||||
+ PERROR("xc_map_foreign_range failed (for new_shared_info)");
|
||||
+ goto out;
|
||||
+ }
|
||||
|
||||
/* restore saved vcpu_info and arch specific info */
|
||||
MEMCPY_FIELD(new_shared_info, old_shared_info, vcpu_info);
|
||||
diff --git a/tools/libxc/xc_offline_page.c b/tools/libxc/xc_offline_page.c
|
||||
index 089a361..36b9812 100644
|
||||
--- a/tools/libxc/xc_offline_page.c
|
||||
+++ b/tools/libxc/xc_offline_page.c
|
||||
@@ -714,6 +714,11 @@ int xc_exchange_page(xc_interface *xch, int domid, xen_pfn_t mfn)
|
||||
|
||||
new_p = xc_map_foreign_range(xch, domid, PAGE_SIZE,
|
||||
PROT_READ|PROT_WRITE, new_mfn);
|
||||
+ if ( new_p == NULL )
|
||||
+ {
|
||||
+ ERROR("failed to map new_p for copy, guest may be broken?");
|
||||
+ goto failed;
|
||||
+ }
|
||||
memcpy(new_p, backup, PAGE_SIZE);
|
||||
munmap(new_p, PAGE_SIZE);
|
||||
mops.arg1.mfn = new_mfn;
|
||||
--
|
||||
1.7.2.5
|
||||
|
@ -0,0 +1,56 @@
|
||||
From a672da4b2d58ef12be9d7407160e9fb43cac75d9 Mon Sep 17 00:00:00 2001
|
||||
From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Date: Fri, 14 Jun 2013 16:43:16 +0100
|
||||
Subject: [PATCH 02/23] libxc: introduce xc_dom_seg_to_ptr_pages
|
||||
|
||||
Provide a version of xc_dom_seg_to_ptr which returns the number of
|
||||
guest pages it has actually mapped. This is useful for callers who
|
||||
want to do range checking; we will use this later in this series.
|
||||
|
||||
This is part of the fix to a security issue, XSA-55.
|
||||
|
||||
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
|
||||
---
|
||||
tools/libxc/xc_dom.h | 19 ++++++++++++++++---
|
||||
1 files changed, 16 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/tools/libxc/xc_dom.h b/tools/libxc/xc_dom.h
|
||||
index 6a72aa9..9af2195 100644
|
||||
--- a/tools/libxc/xc_dom.h
|
||||
+++ b/tools/libxc/xc_dom.h
|
||||
@@ -278,14 +278,27 @@ void *xc_dom_pfn_to_ptr(struct xc_dom_image *dom, xen_pfn_t first,
|
||||
void xc_dom_unmap_one(struct xc_dom_image *dom, xen_pfn_t pfn);
|
||||
void xc_dom_unmap_all(struct xc_dom_image *dom);
|
||||
|
||||
-static inline void *xc_dom_seg_to_ptr(struct xc_dom_image *dom,
|
||||
- struct xc_dom_seg *seg)
|
||||
+static inline void *xc_dom_seg_to_ptr_pages(struct xc_dom_image *dom,
|
||||
+ struct xc_dom_seg *seg,
|
||||
+ xen_pfn_t *pages_out)
|
||||
{
|
||||
xen_vaddr_t segsize = seg->vend - seg->vstart;
|
||||
unsigned int page_size = XC_DOM_PAGE_SIZE(dom);
|
||||
xen_pfn_t pages = (segsize + page_size - 1) / page_size;
|
||||
+ void *retval;
|
||||
+
|
||||
+ retval = xc_dom_pfn_to_ptr(dom, seg->pfn, pages);
|
||||
+
|
||||
+ *pages_out = retval ? pages : 0;
|
||||
+ return retval;
|
||||
+}
|
||||
+
|
||||
+static inline void *xc_dom_seg_to_ptr(struct xc_dom_image *dom,
|
||||
+ struct xc_dom_seg *seg)
|
||||
+{
|
||||
+ xen_pfn_t dummy;
|
||||
|
||||
- return xc_dom_pfn_to_ptr(dom, seg->pfn, pages);
|
||||
+ return xc_dom_seg_to_ptr_pages(dom, seg, &dummy);
|
||||
}
|
||||
|
||||
static inline void *xc_dom_vaddr_to_ptr(struct xc_dom_image *dom,
|
||||
--
|
||||
1.7.2.5
|
||||
|
@ -0,0 +1,381 @@
|
||||
From 8dc90d163650ce8aa36ae0b46debab83cc61edb6 Mon Sep 17 00:00:00 2001
|
||||
From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Date: Fri, 14 Jun 2013 16:43:19 +0100
|
||||
Subject: [PATCH 20/23] libxc: check return values from malloc
|
||||
|
||||
A sufficiently malformed input to libxc (such as a malformed input ELF
|
||||
or other guest-controlled data) might cause one of libxc's malloc() to
|
||||
fail. In this case we need to make sure we don't dereference or do
|
||||
pointer arithmetic on the result.
|
||||
|
||||
Search for all occurrences of \b(m|c|re)alloc in libxc, and all
|
||||
functions which call them, and add appropriate error checking where
|
||||
missing.
|
||||
|
||||
This includes the functions xc_dom_malloc*, which now print a message
|
||||
when they fail so that callers don't have to do so.
|
||||
|
||||
The function xc_cpuid_to_str wasn't provided with a sane return value
|
||||
and has a pretty strange API, which now becomes a little stranger.
|
||||
There are no in-tree callers.
|
||||
|
||||
Changes in the Xen 4.2 version of this series:
|
||||
* No need to fix code relating to ARM.
|
||||
* No need to fix code relating to superpage support.
|
||||
* Additionally fix `dom->p2m_host = xc_dom_malloc...' in xc_dom_ia64.c.
|
||||
|
||||
This is part of the fix to a security issue, XSA-55.
|
||||
|
||||
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
---
|
||||
tools/libxc/xc_cpuid_x86.c | 20 ++++++++++++++++++--
|
||||
tools/libxc/xc_dom_core.c | 13 +++++++++++++
|
||||
tools/libxc/xc_dom_elfloader.c | 2 ++
|
||||
tools/libxc/xc_dom_ia64.c | 6 ++++++
|
||||
tools/libxc/xc_dom_x86.c | 3 +++
|
||||
tools/libxc/xc_domain_restore.c | 5 +++++
|
||||
tools/libxc/xc_linux_osdep.c | 4 ++++
|
||||
tools/libxc/xc_private.c | 2 ++
|
||||
tools/libxc/xenctrl.h | 2 +-
|
||||
9 files changed, 54 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/tools/libxc/xc_cpuid_x86.c b/tools/libxc/xc_cpuid_x86.c
|
||||
index 0882ce6..da435ce 100644
|
||||
--- a/tools/libxc/xc_cpuid_x86.c
|
||||
+++ b/tools/libxc/xc_cpuid_x86.c
|
||||
@@ -589,6 +589,8 @@ static int xc_cpuid_do_domctl(
|
||||
static char *alloc_str(void)
|
||||
{
|
||||
char *s = malloc(33);
|
||||
+ if ( s == NULL )
|
||||
+ return s;
|
||||
memset(s, 0, 33);
|
||||
return s;
|
||||
}
|
||||
@@ -600,6 +602,8 @@ void xc_cpuid_to_str(const unsigned int *regs, char **strs)
|
||||
for ( i = 0; i < 4; i++ )
|
||||
{
|
||||
strs[i] = alloc_str();
|
||||
+ if ( strs[i] == NULL )
|
||||
+ continue;
|
||||
for ( j = 0; j < 32; j++ )
|
||||
strs[i][j] = !!((regs[i] & (1U << (31 - j)))) ? '1' : '0';
|
||||
}
|
||||
@@ -680,7 +684,7 @@ int xc_cpuid_check(
|
||||
const char **config,
|
||||
char **config_transformed)
|
||||
{
|
||||
- int i, j;
|
||||
+ int i, j, rc;
|
||||
unsigned int regs[4];
|
||||
|
||||
memset(config_transformed, 0, 4 * sizeof(*config_transformed));
|
||||
@@ -692,6 +696,11 @@ int xc_cpuid_check(
|
||||
if ( config[i] == NULL )
|
||||
continue;
|
||||
config_transformed[i] = alloc_str();
|
||||
+ if ( config_transformed[i] == NULL )
|
||||
+ {
|
||||
+ rc = -ENOMEM;
|
||||
+ goto fail_rc;
|
||||
+ }
|
||||
for ( j = 0; j < 32; j++ )
|
||||
{
|
||||
unsigned char val = !!((regs[i] & (1U << (31 - j))));
|
||||
@@ -708,12 +717,14 @@ int xc_cpuid_check(
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
+ rc = -EPERM;
|
||||
+ fail_rc:
|
||||
for ( i = 0; i < 4; i++ )
|
||||
{
|
||||
free(config_transformed[i]);
|
||||
config_transformed[i] = NULL;
|
||||
}
|
||||
- return -EPERM;
|
||||
+ return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -758,6 +769,11 @@ int xc_cpuid_set(
|
||||
}
|
||||
|
||||
config_transformed[i] = alloc_str();
|
||||
+ if ( config_transformed[i] == NULL )
|
||||
+ {
|
||||
+ rc = -ENOMEM;
|
||||
+ goto fail;
|
||||
+ }
|
||||
|
||||
for ( j = 0; j < 32; j++ )
|
||||
{
|
||||
diff --git a/tools/libxc/xc_dom_core.c b/tools/libxc/xc_dom_core.c
|
||||
index a54ddae..3cbf9f7 100644
|
||||
--- a/tools/libxc/xc_dom_core.c
|
||||
+++ b/tools/libxc/xc_dom_core.c
|
||||
@@ -120,9 +120,17 @@ void *xc_dom_malloc(struct xc_dom_image *dom, size_t size)
|
||||
{
|
||||
struct xc_dom_mem *block;
|
||||
|
||||
+ if ( size > SIZE_MAX - sizeof(*block) )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: unreasonable allocation size", __FUNCTION__);
|
||||
+ return NULL;
|
||||
+ }
|
||||
block = malloc(sizeof(*block) + size);
|
||||
if ( block == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: allocation failed", __FUNCTION__);
|
||||
return NULL;
|
||||
+ }
|
||||
memset(block, 0, sizeof(*block) + size);
|
||||
block->next = dom->memblocks;
|
||||
dom->memblocks = block;
|
||||
@@ -138,7 +146,10 @@ void *xc_dom_malloc_page_aligned(struct xc_dom_image *dom, size_t size)
|
||||
|
||||
block = malloc(sizeof(*block));
|
||||
if ( block == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: allocation failed", __FUNCTION__);
|
||||
return NULL;
|
||||
+ }
|
||||
memset(block, 0, sizeof(*block));
|
||||
block->mmap_len = size;
|
||||
block->mmap_ptr = mmap(NULL, block->mmap_len,
|
||||
@@ -146,6 +157,7 @@ void *xc_dom_malloc_page_aligned(struct xc_dom_image *dom, size_t size)
|
||||
-1, 0);
|
||||
if ( block->mmap_ptr == MAP_FAILED )
|
||||
{
|
||||
+ DOMPRINTF("%s: mmap failed", __FUNCTION__);
|
||||
free(block);
|
||||
return NULL;
|
||||
}
|
||||
@@ -202,6 +214,7 @@ void *xc_dom_malloc_filemap(struct xc_dom_image *dom,
|
||||
close(fd);
|
||||
if ( block != NULL )
|
||||
free(block);
|
||||
+ DOMPRINTF("%s: failed (on file `%s')", __FUNCTION__, filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c
|
||||
index 61b5798..be58276 100644
|
||||
--- a/tools/libxc/xc_dom_elfloader.c
|
||||
+++ b/tools/libxc/xc_dom_elfloader.c
|
||||
@@ -329,6 +329,8 @@ static elf_errorstatus xc_dom_parse_elf_kernel(struct xc_dom_image *dom)
|
||||
return rc;
|
||||
|
||||
elf = xc_dom_malloc(dom, sizeof(*elf));
|
||||
+ if ( elf == NULL )
|
||||
+ return -1;
|
||||
dom->private_loader = elf;
|
||||
rc = elf_init(elf, dom->kernel_blob, dom->kernel_size);
|
||||
xc_elf_set_logfile(dom->xch, elf, 1);
|
||||
diff --git a/tools/libxc/xc_dom_ia64.c b/tools/libxc/xc_dom_ia64.c
|
||||
index 7c0eff1..076821c 100644
|
||||
--- a/tools/libxc/xc_dom_ia64.c
|
||||
+++ b/tools/libxc/xc_dom_ia64.c
|
||||
@@ -188,6 +188,12 @@ int arch_setup_meminit(struct xc_dom_image *dom)
|
||||
|
||||
/* setup initial p2m */
|
||||
dom->p2m_host = xc_dom_malloc(dom, sizeof(xen_pfn_t) * nbr);
|
||||
+ if ( dom->p2m_host == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: xc_dom_malloc failed for p2m_host",
|
||||
+ __FUNCTION__);
|
||||
+ return -1;
|
||||
+ }
|
||||
for ( pfn = 0; pfn < nbr; pfn++ )
|
||||
dom->p2m_host[pfn] = start + pfn;
|
||||
|
||||
diff --git a/tools/libxc/xc_dom_x86.c b/tools/libxc/xc_dom_x86.c
|
||||
index 75d6b83..448d9a1 100644
|
||||
--- a/tools/libxc/xc_dom_x86.c
|
||||
+++ b/tools/libxc/xc_dom_x86.c
|
||||
@@ -780,6 +780,9 @@ int arch_setup_meminit(struct xc_dom_image *dom)
|
||||
}
|
||||
|
||||
dom->p2m_host = xc_dom_malloc(dom, sizeof(xen_pfn_t) * dom->total_pages);
|
||||
+ if ( dom->p2m_host == NULL )
|
||||
+ return -EINVAL;
|
||||
+
|
||||
if ( dom->superpages )
|
||||
{
|
||||
int count = dom->total_pages >> SUPERPAGE_PFN_SHIFT;
|
||||
diff --git a/tools/libxc/xc_domain_restore.c b/tools/libxc/xc_domain_restore.c
|
||||
index 3994f8f..f9ed6b2 100644
|
||||
--- a/tools/libxc/xc_domain_restore.c
|
||||
+++ b/tools/libxc/xc_domain_restore.c
|
||||
@@ -1180,6 +1180,11 @@ static int apply_batch(xc_interface *xch, uint32_t dom, struct restore_ctx *ctx,
|
||||
|
||||
/* Map relevant mfns */
|
||||
pfn_err = calloc(j, sizeof(*pfn_err));
|
||||
+ if ( pfn_err == NULL )
|
||||
+ {
|
||||
+ PERROR("allocation for pfn_err failed");
|
||||
+ return -1;
|
||||
+ }
|
||||
region_base = xc_map_foreign_bulk(
|
||||
xch, dom, PROT_WRITE, region_mfn, pfn_err, j);
|
||||
|
||||
diff --git a/tools/libxc/xc_linux_osdep.c b/tools/libxc/xc_linux_osdep.c
|
||||
index 787e742..98e041c 100644
|
||||
--- a/tools/libxc/xc_linux_osdep.c
|
||||
+++ b/tools/libxc/xc_linux_osdep.c
|
||||
@@ -378,6 +378,8 @@ static void *linux_privcmd_map_foreign_range(xc_interface *xch, xc_osdep_handle
|
||||
|
||||
num = (size + XC_PAGE_SIZE - 1) >> XC_PAGE_SHIFT;
|
||||
arr = calloc(num, sizeof(xen_pfn_t));
|
||||
+ if ( arr == NULL )
|
||||
+ return NULL;
|
||||
|
||||
for ( i = 0; i < num; i++ )
|
||||
arr[i] = mfn + i;
|
||||
@@ -402,6 +404,8 @@ static void *linux_privcmd_map_foreign_ranges(xc_interface *xch, xc_osdep_handle
|
||||
num_per_entry = chunksize >> XC_PAGE_SHIFT;
|
||||
num = num_per_entry * nentries;
|
||||
arr = calloc(num, sizeof(xen_pfn_t));
|
||||
+ if ( arr == NULL )
|
||||
+ return NULL;
|
||||
|
||||
for ( i = 0; i < nentries; i++ )
|
||||
for ( j = 0; j < num_per_entry; j++ )
|
||||
diff --git a/tools/libxc/xc_private.c b/tools/libxc/xc_private.c
|
||||
index 3e03a91..848ceed 100644
|
||||
--- a/tools/libxc/xc_private.c
|
||||
+++ b/tools/libxc/xc_private.c
|
||||
@@ -771,6 +771,8 @@ const char *xc_strerror(xc_interface *xch, int errcode)
|
||||
errbuf = pthread_getspecific(errbuf_pkey);
|
||||
if (errbuf == NULL) {
|
||||
errbuf = malloc(XS_BUFSIZE);
|
||||
+ if ( errbuf == NULL )
|
||||
+ return "(failed to allocate errbuf)";
|
||||
pthread_setspecific(errbuf_pkey, errbuf);
|
||||
}
|
||||
|
||||
diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h
|
||||
index b7741ca..8952048 100644
|
||||
--- a/tools/libxc/xenctrl.h
|
||||
+++ b/tools/libxc/xenctrl.h
|
||||
@@ -1778,7 +1778,7 @@ int xc_cpuid_set(xc_interface *xch,
|
||||
int xc_cpuid_apply_policy(xc_interface *xch,
|
||||
domid_t domid);
|
||||
void xc_cpuid_to_str(const unsigned int *regs,
|
||||
- char **strs);
|
||||
+ char **strs); /* some strs[] may be NULL if ENOMEM */
|
||||
int xc_mca_op(xc_interface *xch, struct xen_mc *mc);
|
||||
#endif
|
||||
|
||||
--
|
||||
1.7.2.5
|
||||
#From 052a689aa526ca51fd70528d4b0f83dfb2de99c1 Mon Sep 17 00:00:00 2001
|
||||
#From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
#Date: Fri, 14 Jun 2013 16:43:19 +0100
|
||||
#Subject: [PATCH 21/23] libxc: range checks in xc_dom_p2m_host and _guest
|
||||
#
|
||||
#These functions take guest pfns and look them up in the p2m. They did
|
||||
#no range checking.
|
||||
#
|
||||
#However, some callers, notably xc_dom_boot.c:setup_hypercall_page want
|
||||
#to pass untrusted guest-supplied value(s). It is most convenient to
|
||||
#detect this here and return INVALID_MFN.
|
||||
#
|
||||
#This is part of the fix to a security issue, XSA-55.
|
||||
#
|
||||
#Changes from Xen 4.2 version of this patch:
|
||||
#* 4.2 lacks dom->rambase_pfn, so don't add/subtract/check it.
|
||||
#
|
||||
#Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
#---
|
||||
# tools/libxc/xc_dom.h | 4 ++++
|
||||
# 1 files changed, 4 insertions(+), 0 deletions(-)
|
||||
#
|
||||
diff --git a/tools/libxc/xc_dom.h b/tools/libxc/xc_dom.h
|
||||
index 0161459..d801f66 100644
|
||||
--- a/tools/libxc/xc_dom.h
|
||||
+++ b/tools/libxc/xc_dom.h
|
||||
@@ -331,6 +331,8 @@ static inline xen_pfn_t xc_dom_p2m_host(struct xc_dom_image *dom, xen_pfn_t pfn)
|
||||
{
|
||||
if (dom->shadow_enabled)
|
||||
return pfn;
|
||||
+ if (pfn >= dom->total_pages)
|
||||
+ return INVALID_MFN;
|
||||
return dom->p2m_host[pfn];
|
||||
}
|
||||
|
||||
@@ -339,6 +341,8 @@ static inline xen_pfn_t xc_dom_p2m_guest(struct xc_dom_image *dom,
|
||||
{
|
||||
if (xc_dom_feature_translated(dom))
|
||||
return pfn;
|
||||
+ if (pfn >= dom->total_pages)
|
||||
+ return INVALID_MFN;
|
||||
return dom->p2m_host[pfn];
|
||||
}
|
||||
|
||||
--
|
||||
1.7.2.5
|
||||
#From 2a548e22915535ac13694eb38222903bca7245e3 Mon Sep 17 00:00:00 2001
|
||||
#From: Matthew Daley <mattjd@gmail.com>
|
||||
#Date: Fri, 14 Jun 2013 16:43:19 +0100
|
||||
#Subject: [PATCH 22/23] libxc: check blob size before proceeding in xc_dom_check_gzip
|
||||
#
|
||||
#This is part of the fix to a security issue, XSA-55.
|
||||
#
|
||||
#Signed-off-by: Matthew Daley <mattjd@gmail.com>
|
||||
#---
|
||||
# tools/libxc/xc_dom_core.c | 5 +++++
|
||||
# 1 files changed, 5 insertions(+), 0 deletions(-)
|
||||
#
|
||||
diff --git a/tools/libxc/xc_dom_core.c b/tools/libxc/xc_dom_core.c
|
||||
index 3cbf9f7..f8d1b08 100644
|
||||
--- a/tools/libxc/xc_dom_core.c
|
||||
+++ b/tools/libxc/xc_dom_core.c
|
||||
@@ -284,6 +284,11 @@ size_t xc_dom_check_gzip(xc_interface *xch, void *blob, size_t ziplen)
|
||||
unsigned char *gzlen;
|
||||
size_t unziplen;
|
||||
|
||||
+ if ( ziplen < 6 )
|
||||
+ /* Too small. We need (i.e. the subsequent code relies on)
|
||||
+ * 2 bytes for the magic number plus 4 bytes length. */
|
||||
+ return 0;
|
||||
+
|
||||
if ( strncmp(blob, "\037\213", 2) )
|
||||
/* not gzipped */
|
||||
return 0;
|
||||
--
|
||||
1.7.2.5
|
||||
#From d21d36e84354c04638b60a739a5f7c3d9f8adaf8 Mon Sep 17 00:00:00 2001
|
||||
#From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
#Date: Fri, 14 Jun 2013 16:43:19 +0100
|
||||
#Subject: [PATCH 23/23] libxc: Better range check in xc_dom_alloc_segment
|
||||
#
|
||||
#If seg->pfn is too large, the arithmetic in the range check might
|
||||
#overflow, defeating the range check.
|
||||
#
|
||||
#This is part of the fix to a security issue, XSA-55.
|
||||
#
|
||||
#Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
#Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
|
||||
#---
|
||||
# tools/libxc/xc_dom_core.c | 3 ++-
|
||||
# 1 files changed, 2 insertions(+), 1 deletions(-)
|
||||
#
|
||||
diff --git a/tools/libxc/xc_dom_core.c b/tools/libxc/xc_dom_core.c
|
||||
index f8d1b08..e79e38d 100644
|
||||
--- a/tools/libxc/xc_dom_core.c
|
||||
+++ b/tools/libxc/xc_dom_core.c
|
||||
@@ -509,7 +509,8 @@ int xc_dom_alloc_segment(struct xc_dom_image *dom,
|
||||
seg->vstart = start;
|
||||
seg->pfn = (seg->vstart - dom->parms.virt_base) / page_size;
|
||||
|
||||
- if ( pages > dom->total_pages || /* double test avoids overflow probs */
|
||||
+ if ( pages > dom->total_pages || /* multiple test avoids overflow probs */
|
||||
+ seg->pfn > dom->total_pages ||
|
||||
pages > dom->total_pages - seg->pfn)
|
||||
{
|
||||
xc_dom_panic(dom->xch, XC_OUT_OF_MEMORY,
|
||||
--
|
||||
1.7.2.5
|
||||
|
||||
|
@ -0,0 +1,156 @@
|
||||
From 8c738fa5c1f3cfcd935b6191b3526f7ac8b2a5bd Mon Sep 17 00:00:00 2001
|
||||
From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Date: Fri, 14 Jun 2013 16:43:16 +0100
|
||||
Subject: [PATCH 03/23] libxc: Fix range checking in xc_dom_pfn_to_ptr etc.
|
||||
|
||||
* Ensure that xc_dom_pfn_to_ptr (when called with count==0) does not
|
||||
return a previously-allocated block which is entirely before the
|
||||
requested pfn (!)
|
||||
|
||||
* Provide a version of xc_dom_pfn_to_ptr, xc_dom_pfn_to_ptr_retcount,
|
||||
which provides the length of the mapped region via an out parameter.
|
||||
|
||||
* Change xc_dom_vaddr_to_ptr to always provide the length of the
|
||||
mapped region and change the call site in xc_dom_binloader.c to
|
||||
check it. The call site in xc_dom_load_elf_symtab will be corrected
|
||||
in a forthcoming patch, and for now ignores the returned length.
|
||||
|
||||
This is part of the fix to a security issue, XSA-55.
|
||||
|
||||
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
---
|
||||
tools/libxc/xc_dom.h | 16 +++++++++++++---
|
||||
tools/libxc/xc_dom_binloader.c | 11 ++++++++++-
|
||||
tools/libxc/xc_dom_core.c | 13 +++++++++++++
|
||||
tools/libxc/xc_dom_elfloader.c | 3 ++-
|
||||
4 files changed, 38 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/tools/libxc/xc_dom.h b/tools/libxc/xc_dom.h
|
||||
index 9af2195..9f8037e 100644
|
||||
--- a/tools/libxc/xc_dom.h
|
||||
+++ b/tools/libxc/xc_dom.h
|
||||
@@ -275,6 +275,8 @@ int xc_dom_alloc_segment(struct xc_dom_image *dom,
|
||||
|
||||
void *xc_dom_pfn_to_ptr(struct xc_dom_image *dom, xen_pfn_t first,
|
||||
xen_pfn_t count);
|
||||
+void *xc_dom_pfn_to_ptr_retcount(struct xc_dom_image *dom, xen_pfn_t first,
|
||||
+ xen_pfn_t count, xen_pfn_t *count_out);
|
||||
void xc_dom_unmap_one(struct xc_dom_image *dom, xen_pfn_t pfn);
|
||||
void xc_dom_unmap_all(struct xc_dom_image *dom);
|
||||
|
||||
@@ -302,13 +304,21 @@ static inline void *xc_dom_seg_to_ptr(struct xc_dom_image *dom,
|
||||
}
|
||||
|
||||
static inline void *xc_dom_vaddr_to_ptr(struct xc_dom_image *dom,
|
||||
- xen_vaddr_t vaddr)
|
||||
+ xen_vaddr_t vaddr,
|
||||
+ size_t *safe_region_out)
|
||||
{
|
||||
unsigned int page_size = XC_DOM_PAGE_SIZE(dom);
|
||||
xen_pfn_t page = (vaddr - dom->parms.virt_base) / page_size;
|
||||
unsigned int offset = (vaddr - dom->parms.virt_base) % page_size;
|
||||
- void *ptr = xc_dom_pfn_to_ptr(dom, page, 0);
|
||||
- return (ptr ? (ptr + offset) : NULL);
|
||||
+ xen_pfn_t safe_region_count;
|
||||
+ void *ptr;
|
||||
+
|
||||
+ *safe_region_out = 0;
|
||||
+ ptr = xc_dom_pfn_to_ptr_retcount(dom, page, 0, &safe_region_count);
|
||||
+ if ( ptr == NULL )
|
||||
+ return ptr;
|
||||
+ *safe_region_out = (safe_region_count << XC_DOM_PAGE_SHIFT(dom)) - offset;
|
||||
+ return ptr;
|
||||
}
|
||||
|
||||
static inline int xc_dom_feature_translated(struct xc_dom_image *dom)
|
||||
diff --git a/tools/libxc/xc_dom_binloader.c b/tools/libxc/xc_dom_binloader.c
|
||||
index 769e97d..bde93f7 100644
|
||||
--- a/tools/libxc/xc_dom_binloader.c
|
||||
+++ b/tools/libxc/xc_dom_binloader.c
|
||||
@@ -249,6 +249,7 @@ static int xc_dom_load_bin_kernel(struct xc_dom_image *dom)
|
||||
char *image = dom->kernel_blob;
|
||||
char *dest;
|
||||
size_t image_size = dom->kernel_size;
|
||||
+ size_t dest_size;
|
||||
uint32_t start_addr;
|
||||
uint32_t load_end_addr;
|
||||
uint32_t bss_end_addr;
|
||||
@@ -272,7 +273,15 @@ static int xc_dom_load_bin_kernel(struct xc_dom_image *dom)
|
||||
DOMPRINTF(" text_size: 0x%" PRIx32 "", text_size);
|
||||
DOMPRINTF(" bss_size: 0x%" PRIx32 "", bss_size);
|
||||
|
||||
- dest = xc_dom_vaddr_to_ptr(dom, dom->kernel_seg.vstart);
|
||||
+ dest = xc_dom_vaddr_to_ptr(dom, dom->kernel_seg.vstart, &dest_size);
|
||||
+
|
||||
+ if ( dest_size < text_size ||
|
||||
+ dest_size - text_size < bss_size )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: mapped region is too small for image", __FUNCTION__);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
memcpy(dest, image + skip, text_size);
|
||||
memset(dest + text_size, 0, bss_size);
|
||||
|
||||
diff --git a/tools/libxc/xc_dom_core.c b/tools/libxc/xc_dom_core.c
|
||||
index 2a01d7c..8913e41 100644
|
||||
--- a/tools/libxc/xc_dom_core.c
|
||||
+++ b/tools/libxc/xc_dom_core.c
|
||||
@@ -351,10 +351,19 @@ int xc_dom_try_gunzip(struct xc_dom_image *dom, void **blob, size_t * size)
|
||||
void *xc_dom_pfn_to_ptr(struct xc_dom_image *dom, xen_pfn_t pfn,
|
||||
xen_pfn_t count)
|
||||
{
|
||||
+ xen_pfn_t count_out_dummy;
|
||||
+ return xc_dom_pfn_to_ptr_retcount(dom, pfn, count, &count_out_dummy);
|
||||
+}
|
||||
+
|
||||
+void *xc_dom_pfn_to_ptr_retcount(struct xc_dom_image *dom, xen_pfn_t pfn,
|
||||
+ xen_pfn_t count, xen_pfn_t *count_out)
|
||||
+{
|
||||
struct xc_dom_phys *phys;
|
||||
unsigned int page_shift = XC_DOM_PAGE_SHIFT(dom);
|
||||
char *mode = "unset";
|
||||
|
||||
+ *count_out = 0;
|
||||
+
|
||||
if ( pfn > dom->total_pages || /* multiple checks to avoid overflows */
|
||||
count > dom->total_pages ||
|
||||
pfn > dom->total_pages - count )
|
||||
@@ -384,6 +393,7 @@ void *xc_dom_pfn_to_ptr(struct xc_dom_image *dom, xen_pfn_t pfn,
|
||||
phys->count);
|
||||
return NULL;
|
||||
}
|
||||
+ *count_out = count;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -391,6 +401,9 @@ void *xc_dom_pfn_to_ptr(struct xc_dom_image *dom, xen_pfn_t pfn,
|
||||
just hand out a pointer to it */
|
||||
if ( pfn < phys->first )
|
||||
continue;
|
||||
+ if ( pfn >= phys->first + phys->count )
|
||||
+ continue;
|
||||
+ *count_out = phys->count - (pfn - phys->first);
|
||||
}
|
||||
return phys->ptr + ((pfn - phys->first) << page_shift);
|
||||
}
|
||||
diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c
|
||||
index 2e69559..031b5b6 100644
|
||||
--- a/tools/libxc/xc_dom_elfloader.c
|
||||
+++ b/tools/libxc/xc_dom_elfloader.c
|
||||
@@ -130,10 +130,11 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
|
||||
if ( load )
|
||||
{
|
||||
+ size_t allow_size; /* will be used in a forthcoming XSA-55 patch */
|
||||
if ( !dom->bsd_symtab_start )
|
||||
return 0;
|
||||
size = dom->kernel_seg.vend - dom->bsd_symtab_start;
|
||||
- hdr = xc_dom_vaddr_to_ptr(dom, dom->bsd_symtab_start);
|
||||
+ hdr = xc_dom_vaddr_to_ptr(dom, dom->bsd_symtab_start, &allow_size);
|
||||
*(int *)hdr = size - sizeof(int);
|
||||
}
|
||||
else
|
||||
--
|
||||
1.7.2.5
|
||||
|
@ -0,0 +1,55 @@
|
||||
From 035634047d10c678cbb8801c4263747bdaf4e5b1 Mon Sep 17 00:00:00 2001
|
||||
From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Date: Fri, 14 Jun 2013 16:43:16 +0100
|
||||
Subject: [PATCH 04/23] libelf: add `struct elf_binary*' parameter to elf_load_image
|
||||
|
||||
The meat of this function is going to need a copy of the elf pointer,
|
||||
in forthcoming patches.
|
||||
|
||||
No functional change in this patch.
|
||||
|
||||
This is part of the fix to a security issue, XSA-55.
|
||||
|
||||
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
|
||||
---
|
||||
xen/common/libelf/libelf-loader.c | 8 +++++---
|
||||
1 files changed, 5 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/xen/common/libelf/libelf-loader.c b/xen/common/libelf/libelf-loader.c
|
||||
index ab58b8b..0559d88 100644
|
||||
--- a/xen/common/libelf/libelf-loader.c
|
||||
+++ b/xen/common/libelf/libelf-loader.c
|
||||
@@ -108,7 +108,8 @@ void elf_set_log(struct elf_binary *elf, elf_log_callback *log_callback,
|
||||
elf->verbose = verbose;
|
||||
}
|
||||
|
||||
-static int elf_load_image(void *dst, const void *src, uint64_t filesz, uint64_t memsz)
|
||||
+static int elf_load_image(struct elf_binary *elf,
|
||||
+ void *dst, const void *src, uint64_t filesz, uint64_t memsz)
|
||||
{
|
||||
memcpy(dst, src, filesz);
|
||||
memset(dst + filesz, 0, memsz - filesz);
|
||||
@@ -122,7 +123,8 @@ void elf_set_verbose(struct elf_binary *elf)
|
||||
elf->verbose = 1;
|
||||
}
|
||||
|
||||
-static int elf_load_image(void *dst, const void *src, uint64_t filesz, uint64_t memsz)
|
||||
+static int elf_load_image(struct elf_binary *elf,
|
||||
+ void *dst, const void *src, uint64_t filesz, uint64_t memsz)
|
||||
{
|
||||
int rc;
|
||||
if ( filesz > ULONG_MAX || memsz > ULONG_MAX )
|
||||
@@ -279,7 +281,7 @@ int elf_load_binary(struct elf_binary *elf)
|
||||
dest = elf_get_ptr(elf, paddr);
|
||||
elf_msg(elf, "%s: phdr %" PRIu64 " at 0x%p -> 0x%p\n",
|
||||
__func__, i, dest, dest + filesz);
|
||||
- if ( elf_load_image(dest, elf->image + offset, filesz, memsz) != 0 )
|
||||
+ if ( elf_load_image(elf, dest, elf->image + offset, filesz, memsz) != 0 )
|
||||
return -1;
|
||||
}
|
||||
|
||||
--
|
||||
1.7.2.5
|
||||
|
@ -0,0 +1,174 @@
|
||||
From 83ec905922b496e1a5756e3a88405eb6c2c6ba88 Mon Sep 17 00:00:00 2001
|
||||
From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Date: Fri, 14 Jun 2013 16:43:16 +0100
|
||||
Subject: [PATCH 05/23] libelf: abolish elf_sval and elf_access_signed
|
||||
|
||||
These are not used anywhere.
|
||||
|
||||
This is part of the fix to a security issue, XSA-55.
|
||||
|
||||
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
---
|
||||
xen/common/libelf/libelf-tools.c | 28 ----------------------------
|
||||
xen/include/xen/libelf.h | 11 -----------
|
||||
2 files changed, 0 insertions(+), 39 deletions(-)
|
||||
|
||||
diff --git a/xen/common/libelf/libelf-tools.c b/xen/common/libelf/libelf-tools.c
|
||||
index cb97908..2f54142 100644
|
||||
--- a/xen/common/libelf/libelf-tools.c
|
||||
+++ b/xen/common/libelf/libelf-tools.c
|
||||
@@ -48,34 +48,6 @@ uint64_t elf_access_unsigned(struct elf_binary * elf, const void *ptr,
|
||||
}
|
||||
}
|
||||
|
||||
-int64_t elf_access_signed(struct elf_binary *elf, const void *ptr,
|
||||
- uint64_t offset, size_t size)
|
||||
-{
|
||||
- int need_swap = elf_swap(elf);
|
||||
- const int8_t *s8;
|
||||
- const int16_t *s16;
|
||||
- const int32_t *s32;
|
||||
- const int64_t *s64;
|
||||
-
|
||||
- switch ( size )
|
||||
- {
|
||||
- case 1:
|
||||
- s8 = ptr + offset;
|
||||
- return *s8;
|
||||
- case 2:
|
||||
- s16 = ptr + offset;
|
||||
- return need_swap ? bswap_16(*s16) : *s16;
|
||||
- case 4:
|
||||
- s32 = ptr + offset;
|
||||
- return need_swap ? bswap_32(*s32) : *s32;
|
||||
- case 8:
|
||||
- s64 = ptr + offset;
|
||||
- return need_swap ? bswap_64(*s64) : *s64;
|
||||
- default:
|
||||
- return 0;
|
||||
- }
|
||||
-}
|
||||
-
|
||||
uint64_t elf_round_up(struct elf_binary *elf, uint64_t addr)
|
||||
{
|
||||
int elf_round = (elf_64bit(elf) ? 8 : 4) - 1;
|
||||
diff --git a/xen/include/xen/libelf.h b/xen/include/xen/libelf.h
|
||||
index e8f6508..38e490c 100644
|
||||
--- a/xen/include/xen/libelf.h
|
||||
+++ b/xen/include/xen/libelf.h
|
||||
@@ -136,23 +136,12 @@ struct elf_binary {
|
||||
offsetof(typeof(*(str)),e32.elem), \
|
||||
sizeof((str)->e32.elem)))
|
||||
|
||||
-#define elf_sval(elf, str, elem) \
|
||||
- ((ELFCLASS64 == (elf)->class) \
|
||||
- ? elf_access_signed((elf), (str), \
|
||||
- offsetof(typeof(*(str)),e64.elem), \
|
||||
- sizeof((str)->e64.elem)) \
|
||||
- : elf_access_signed((elf), (str), \
|
||||
- offsetof(typeof(*(str)),e32.elem), \
|
||||
- sizeof((str)->e32.elem)))
|
||||
-
|
||||
#define elf_size(elf, str) \
|
||||
((ELFCLASS64 == (elf)->class) \
|
||||
? sizeof((str)->e64) : sizeof((str)->e32))
|
||||
|
||||
uint64_t elf_access_unsigned(struct elf_binary *elf, const void *ptr,
|
||||
uint64_t offset, size_t size);
|
||||
-int64_t elf_access_signed(struct elf_binary *elf, const void *ptr,
|
||||
- uint64_t offset, size_t size);
|
||||
|
||||
uint64_t elf_round_up(struct elf_binary *elf, uint64_t addr);
|
||||
|
||||
--
|
||||
1.7.2.5
|
||||
#From 682a04488e7b3bd6c3448ab60599566eb7c6177a Mon Sep 17 00:00:00 2001
|
||||
#From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
#Date: Fri, 14 Jun 2013 16:43:16 +0100
|
||||
#Subject: [PATCH 06/23] libelf: move include of <asm/guest_access.h> to top of file
|
||||
#
|
||||
#libelf-loader.c #includes <asm/guest_access.h>, when being compiled
|
||||
#for Xen. Currently it does this in the middle of the file.
|
||||
#
|
||||
#Move this #include to the top of the file, before libelf-private.h.
|
||||
#This is necessary because in forthcoming patches we will introduce
|
||||
#private #defines of memcpy etc. which would interfere with definitions
|
||||
#in headers #included from guest_access.h.
|
||||
#
|
||||
#No semantic or functional change in this patch.
|
||||
#
|
||||
#This is part of the fix to a security issue, XSA-55.
|
||||
#
|
||||
#Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
#Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
#Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
|
||||
#---
|
||||
# xen/common/libelf/libelf-loader.c | 5 ++++-
|
||||
# 1 files changed, 4 insertions(+), 1 deletions(-)
|
||||
#
|
||||
diff --git a/xen/common/libelf/libelf-loader.c b/xen/common/libelf/libelf-loader.c
|
||||
index 0559d88..ec0706b 100644
|
||||
--- a/xen/common/libelf/libelf-loader.c
|
||||
+++ b/xen/common/libelf/libelf-loader.c
|
||||
@@ -16,6 +16,10 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
+#ifdef __XEN__
|
||||
+#include <asm/guest_access.h>
|
||||
+#endif
|
||||
+
|
||||
#include "libelf-private.h"
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
@@ -116,7 +120,6 @@ static int elf_load_image(struct elf_binary *elf,
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
-#include <asm/guest_access.h>
|
||||
|
||||
void elf_set_verbose(struct elf_binary *elf)
|
||||
{
|
||||
--
|
||||
1.7.2.5
|
||||
#From de9089b449d2508b1ba05590905c7ebaee00c8c4 Mon Sep 17 00:00:00 2001
|
||||
#From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
#Date: Fri, 14 Jun 2013 16:43:16 +0100
|
||||
#Subject: [PATCH 07/23] libelf/xc_dom_load_elf_symtab: Do not use "syms" uninitialised
|
||||
#
|
||||
#xc_dom_load_elf_symtab (with load==0) calls elf_round_up, but it
|
||||
#mistakenly used the uninitialised variable "syms" when calculating
|
||||
#dom->bsd_symtab_start. This should be a reference to "elf".
|
||||
#
|
||||
#This change might have the effect of rounding the value differently.
|
||||
#Previously if the uninitialised value (a single byte on the stack) was
|
||||
#ELFCLASS64 (ie, 2), the alignment would be to 8 bytes, otherwise to 4.
|
||||
#
|
||||
#However, the value is calculated from dom->kernel_seg.vend so this
|
||||
#could only make a difference if that value wasn't already aligned to 8
|
||||
#bytes.
|
||||
#
|
||||
#This is part of the fix to a security issue, XSA-55.
|
||||
#
|
||||
#Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
#Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
#---
|
||||
# tools/libxc/xc_dom_elfloader.c | 2 +-
|
||||
# 1 files changed, 1 insertions(+), 1 deletions(-)
|
||||
#
|
||||
diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c
|
||||
index 031b5b6..e82f6e9 100644
|
||||
--- a/tools/libxc/xc_dom_elfloader.c
|
||||
+++ b/tools/libxc/xc_dom_elfloader.c
|
||||
@@ -144,7 +144,7 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
hdr = xc_dom_malloc(dom, size);
|
||||
if ( hdr == NULL )
|
||||
return 0;
|
||||
- dom->bsd_symtab_start = elf_round_up(&syms, dom->kernel_seg.vend);
|
||||
+ dom->bsd_symtab_start = elf_round_up(elf, dom->kernel_seg.vend);
|
||||
}
|
||||
|
||||
memcpy(hdr + sizeof(int),
|
||||
--
|
||||
1.7.2.5
|
@ -0,0 +1,252 @@
|
||||
From 3fb6ccf2faccaf5e22e33a3155ccc72d732896d8 Mon Sep 17 00:00:00 2001
|
||||
From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Date: Fri, 14 Jun 2013 16:43:18 +0100
|
||||
Subject: [PATCH 14/23] libelf: use C99 bool for booleans
|
||||
|
||||
We want to remove uses of "int" because signed integers have
|
||||
undesirable undefined behaviours on overflow. Malicious compilers can
|
||||
turn apparently-correct code into code with security vulnerabilities
|
||||
etc.
|
||||
|
||||
In this patch we change all the booleans in libelf to C99 bool,
|
||||
from <stdbool.h>.
|
||||
|
||||
For the one visible libelf boolean in libxc's public interface we
|
||||
retain the use of int to avoid changing the ABI; libxc converts it to
|
||||
a bool for consumption by libelf.
|
||||
|
||||
It is OK to change all values only ever used as booleans to _Bool
|
||||
(bool) because conversion from any scalar type to a _Bool works the
|
||||
same as the boolean test in if() or ?: and is always defined (C99
|
||||
6.3.1.2). But we do need to check that all these variables really are
|
||||
only ever used that way. (It is theoretically possible that the old
|
||||
code truncated some 64-bit values to 32-bit ints which might become
|
||||
zero depending on the value, which would mean a behavioural change in
|
||||
this patch, but it seems implausible that treating 0x????????00000000
|
||||
as false could have been intended.)
|
||||
|
||||
This is part of the fix to a security issue, XSA-55.
|
||||
|
||||
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Acked-by: George Dunlap <george.dunlap@eu.citrix.com>
|
||||
---
|
||||
tools/libxc/xc_dom_elfloader.c | 8 ++++----
|
||||
xen/common/libelf/libelf-dominfo.c | 2 +-
|
||||
xen/common/libelf/libelf-loader.c | 4 ++--
|
||||
xen/common/libelf/libelf-private.h | 2 +-
|
||||
xen/common/libelf/libelf-tools.c | 10 +++++-----
|
||||
xen/include/xen/libelf.h | 18 ++++++++++--------
|
||||
6 files changed, 23 insertions(+), 21 deletions(-)
|
||||
|
||||
diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c
|
||||
index 4fb4da2..9ba64ae 100644
|
||||
--- a/tools/libxc/xc_dom_elfloader.c
|
||||
+++ b/tools/libxc/xc_dom_elfloader.c
|
||||
@@ -34,7 +34,7 @@
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
static void log_callback(struct elf_binary *elf, void *caller_data,
|
||||
- int iserr, const char *fmt, va_list al) {
|
||||
+ bool iserr, const char *fmt, va_list al) {
|
||||
xc_interface *xch = caller_data;
|
||||
|
||||
xc_reportv(xch,
|
||||
@@ -46,7 +46,7 @@ static void log_callback(struct elf_binary *elf, void *caller_data,
|
||||
|
||||
void xc_elf_set_logfile(xc_interface *xch, struct elf_binary *elf,
|
||||
int verbose) {
|
||||
- elf_set_log(elf, log_callback, xch, verbose);
|
||||
+ elf_set_log(elf, log_callback, xch, verbose /* convert to bool */);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
@@ -84,7 +84,7 @@ static char *xc_dom_guest_type(struct xc_dom_image *dom,
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* parse elf binary */
|
||||
|
||||
-static int check_elf_kernel(struct xc_dom_image *dom, int verbose)
|
||||
+static int check_elf_kernel(struct xc_dom_image *dom, bool verbose)
|
||||
{
|
||||
if ( dom->kernel_blob == NULL )
|
||||
{
|
||||
@@ -112,7 +112,7 @@ static int xc_dom_probe_elf_kernel(struct xc_dom_image *dom)
|
||||
}
|
||||
|
||||
static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
- struct elf_binary *elf, int load)
|
||||
+ struct elf_binary *elf, bool load)
|
||||
{
|
||||
struct elf_binary syms;
|
||||
ELF_HANDLE_DECL_NONCONST(elf_shdr) shdr; ELF_HANDLE_DECL(elf_shdr) shdr2;
|
||||
diff --git a/xen/common/libelf/libelf-dominfo.c b/xen/common/libelf/libelf-dominfo.c
|
||||
index 98c80dc..12b6c2a 100644
|
||||
--- a/xen/common/libelf/libelf-dominfo.c
|
||||
+++ b/xen/common/libelf/libelf-dominfo.c
|
||||
@@ -101,7 +101,7 @@ int elf_xen_parse_note(struct elf_binary *elf,
|
||||
/* *INDENT-OFF* */
|
||||
static const struct {
|
||||
char *name;
|
||||
- int str;
|
||||
+ bool str;
|
||||
} note_desc[] = {
|
||||
[XEN_ELFNOTE_ENTRY] = { "ENTRY", 0},
|
||||
[XEN_ELFNOTE_HYPERCALL_PAGE] = { "HYPERCALL_PAGE", 0},
|
||||
diff --git a/xen/common/libelf/libelf-loader.c b/xen/common/libelf/libelf-loader.c
|
||||
index f8be635..0dccd4d 100644
|
||||
--- a/xen/common/libelf/libelf-loader.c
|
||||
+++ b/xen/common/libelf/libelf-loader.c
|
||||
@@ -92,7 +92,7 @@ int elf_init(struct elf_binary *elf, const char *image_input, size_t size)
|
||||
}
|
||||
|
||||
#ifndef __XEN__
|
||||
-void elf_call_log_callback(struct elf_binary *elf, int iserr,
|
||||
+void elf_call_log_callback(struct elf_binary *elf, bool iserr,
|
||||
const char *fmt,...) {
|
||||
va_list al;
|
||||
|
||||
@@ -107,7 +107,7 @@ void elf_call_log_callback(struct elf_binary *elf, int iserr,
|
||||
}
|
||||
|
||||
void elf_set_log(struct elf_binary *elf, elf_log_callback *log_callback,
|
||||
- void *log_caller_data, int verbose)
|
||||
+ void *log_caller_data, bool verbose)
|
||||
{
|
||||
elf->log_callback = log_callback;
|
||||
elf->log_caller_data = log_caller_data;
|
||||
diff --git a/xen/common/libelf/libelf-private.h b/xen/common/libelf/libelf-private.h
|
||||
index 280dfd1..277be04 100644
|
||||
--- a/xen/common/libelf/libelf-private.h
|
||||
+++ b/xen/common/libelf/libelf-private.h
|
||||
@@ -77,7 +77,7 @@
|
||||
#define elf_err(elf, fmt, args ... ) \
|
||||
elf_call_log_callback(elf, 1, fmt , ## args );
|
||||
|
||||
-void elf_call_log_callback(struct elf_binary*, int iserr, const char *fmt,...);
|
||||
+void elf_call_log_callback(struct elf_binary*, bool iserr, const char *fmt,...);
|
||||
|
||||
#define safe_strcpy(d,s) \
|
||||
do { strncpy((d),(s),sizeof((d))-1); \
|
||||
diff --git a/xen/common/libelf/libelf-tools.c b/xen/common/libelf/libelf-tools.c
|
||||
index 744027e..fa58f76 100644
|
||||
--- a/xen/common/libelf/libelf-tools.c
|
||||
+++ b/xen/common/libelf/libelf-tools.c
|
||||
@@ -31,7 +31,7 @@ const char *elf_check_broken(const struct elf_binary *elf)
|
||||
return elf->broken;
|
||||
}
|
||||
|
||||
-static int elf_ptrval_in_range(elf_ptrval ptrval, uint64_t size,
|
||||
+static bool elf_ptrval_in_range(elf_ptrval ptrval, uint64_t size,
|
||||
const void *region, uint64_t regionsize)
|
||||
/*
|
||||
* Returns true if the putative memory area [ptrval,ptrval+size>
|
||||
@@ -53,7 +53,7 @@ static int elf_ptrval_in_range(elf_ptrval ptrval, uint64_t size,
|
||||
return 1;
|
||||
}
|
||||
|
||||
-int elf_access_ok(struct elf_binary * elf,
|
||||
+bool elf_access_ok(struct elf_binary * elf,
|
||||
uint64_t ptrval, size_t size)
|
||||
{
|
||||
if ( elf_ptrval_in_range(ptrval, size, elf->image_base, elf->size) )
|
||||
@@ -92,7 +92,7 @@ uint64_t elf_access_unsigned(struct elf_binary * elf, elf_ptrval base,
|
||||
uint64_t moreoffset, size_t size)
|
||||
{
|
||||
elf_ptrval ptrval = base + moreoffset;
|
||||
- int need_swap = elf_swap(elf);
|
||||
+ bool need_swap = elf_swap(elf);
|
||||
const uint8_t *u8;
|
||||
const uint16_t *u16;
|
||||
const uint32_t *u32;
|
||||
@@ -332,7 +332,7 @@ ELF_HANDLE_DECL(elf_note) elf_note_next(struct elf_binary *elf, ELF_HANDLE_DECL(
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
-int elf_is_elfbinary(const void *image_start, size_t image_size)
|
||||
+bool elf_is_elfbinary(const void *image_start, size_t image_size)
|
||||
{
|
||||
const Elf32_Ehdr *ehdr = image_start;
|
||||
|
||||
@@ -342,7 +342,7 @@ int elf_is_elfbinary(const void *image_start, size_t image_size)
|
||||
return IS_ELF(*ehdr);
|
||||
}
|
||||
|
||||
-int elf_phdr_is_loadable(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr)
|
||||
+bool elf_phdr_is_loadable(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr)
|
||||
{
|
||||
uint64_t p_type = elf_uval(elf, phdr, p_type);
|
||||
uint64_t p_flags = elf_uval(elf, phdr, p_flags);
|
||||
diff --git a/xen/include/xen/libelf.h b/xen/include/xen/libelf.h
|
||||
index ac93858..951430f 100644
|
||||
--- a/xen/include/xen/libelf.h
|
||||
+++ b/xen/include/xen/libelf.h
|
||||
@@ -29,6 +29,8 @@
|
||||
#error define architectural endianness
|
||||
#endif
|
||||
|
||||
+#include <stdbool.h>
|
||||
+
|
||||
#undef ELFSIZE
|
||||
#include "elfstructs.h"
|
||||
#ifdef __XEN__
|
||||
@@ -42,7 +44,7 @@
|
||||
|
||||
struct elf_binary;
|
||||
typedef void elf_log_callback(struct elf_binary*, void *caller_data,
|
||||
- int iserr, const char *fmt, va_list al);
|
||||
+ bool iserr, const char *fmt, va_list al);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -237,7 +239,7 @@ struct elf_binary {
|
||||
elf_log_callback *log_callback;
|
||||
void *log_caller_data;
|
||||
#endif
|
||||
- int verbose;
|
||||
+ bool verbose;
|
||||
const char *broken;
|
||||
};
|
||||
|
||||
@@ -301,8 +303,8 @@ void elf_memset_safe(struct elf_binary*, elf_ptrval dst, int c, size_t);
|
||||
* outside permitted areas.
|
||||
*/
|
||||
|
||||
-int elf_access_ok(struct elf_binary * elf,
|
||||
- uint64_t ptrval, size_t size);
|
||||
+bool elf_access_ok(struct elf_binary * elf,
|
||||
+ uint64_t ptrval, size_t size);
|
||||
|
||||
#define elf_store_val(elf, type, ptr, val) \
|
||||
({ \
|
||||
@@ -351,9 +353,9 @@ uint64_t elf_note_numeric_array(struct elf_binary *, ELF_HANDLE_DECL(elf_note),
|
||||
ELF_HANDLE_DECL(elf_note) elf_note_next(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
|
||||
|
||||
/* (Only) checks that the image has the right magic number. */
|
||||
-int elf_is_elfbinary(const void *image_start, size_t image_size);
|
||||
+bool elf_is_elfbinary(const void *image_start, size_t image_size);
|
||||
|
||||
-int elf_phdr_is_loadable(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr);
|
||||
+bool elf_phdr_is_loadable(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr);
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* xc_libelf_loader.c */
|
||||
@@ -367,7 +369,7 @@ int elf_init(struct elf_binary *elf, const char *image, size_t size);
|
||||
void elf_set_verbose(struct elf_binary *elf);
|
||||
#else
|
||||
void elf_set_log(struct elf_binary *elf, elf_log_callback*,
|
||||
- void *log_caller_pointer, int verbose);
|
||||
+ void *log_caller_pointer, bool verbose);
|
||||
#endif
|
||||
|
||||
void elf_parse_binary(struct elf_binary *elf);
|
||||
@@ -419,7 +421,7 @@ struct elf_dom_parms {
|
||||
char xen_ver[16];
|
||||
char loader[16];
|
||||
int pae;
|
||||
- int bsd_symtab;
|
||||
+ bool bsd_symtab;
|
||||
uint64_t virt_base;
|
||||
uint64_t virt_entry;
|
||||
uint64_t virt_hypercall;
|
||||
--
|
||||
1.7.2.5
|
||||
|
@ -0,0 +1,382 @@
|
||||
From 77c0829fa751f052f7b8ec08287aef6e7ba97bc5 Mon Sep 17 00:00:00 2001
|
||||
From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Date: Fri, 14 Jun 2013 16:43:19 +0100
|
||||
Subject: [PATCH 19/23] libxc: check failure of xc_dom_*_to_ptr, xc_map_foreign_range
|
||||
|
||||
The return values from xc_dom_*_to_ptr and xc_map_foreign_range are
|
||||
sometimes dereferenced, or subjected to pointer arithmetic, without
|
||||
checking whether the relevant function failed and returned NULL.
|
||||
|
||||
Add an appropriate error check at every call site.
|
||||
|
||||
Changes in the 4.2 backport of this series:
|
||||
* Fix tools/libxc/xc_dom_x86.c:setup_pgtables_x86_32.
|
||||
* Fix tools/libxc/xc_dom_ia64.c:start_info_ia64.
|
||||
* Fix tools/libxc/ia64/xc_ia64_dom_fwloader.c:xc_dom_load_fw_kernel.
|
||||
|
||||
This is part of the fix to a security issue, XSA-55.
|
||||
|
||||
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
---
|
||||
tools/libxc/ia64/xc_ia64_dom_fwloader.c | 2 +
|
||||
tools/libxc/xc_dom_binloader.c | 6 +++
|
||||
tools/libxc/xc_dom_core.c | 6 +++
|
||||
tools/libxc/xc_dom_elfloader.c | 13 +++++++
|
||||
tools/libxc/xc_dom_ia64.c | 6 +++
|
||||
tools/libxc/xc_dom_x86.c | 55 +++++++++++++++++++++++++++++++
|
||||
tools/libxc/xc_domain_restore.c | 27 +++++++++++++++
|
||||
tools/libxc/xc_offline_page.c | 5 +++
|
||||
8 files changed, 120 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/tools/libxc/ia64/xc_ia64_dom_fwloader.c b/tools/libxc/ia64/xc_ia64_dom_fwloader.c
|
||||
index cdf3333..dbd3349 100644
|
||||
--- a/tools/libxc/ia64/xc_ia64_dom_fwloader.c
|
||||
+++ b/tools/libxc/ia64/xc_ia64_dom_fwloader.c
|
||||
@@ -60,6 +60,8 @@ static int xc_dom_load_fw_kernel(struct xc_dom_image *dom)
|
||||
unsigned long i;
|
||||
|
||||
dest = xc_dom_vaddr_to_ptr(dom, dom->kernel_seg.vstart);
|
||||
+ if ( dest == NULL )
|
||||
+ return -1;
|
||||
memcpy(dest, dom->kernel_blob, FW_SIZE);
|
||||
|
||||
/* Synchronize cache. */
|
||||
diff --git a/tools/libxc/xc_dom_binloader.c b/tools/libxc/xc_dom_binloader.c
|
||||
index 8596a28..553b366 100644
|
||||
--- a/tools/libxc/xc_dom_binloader.c
|
||||
+++ b/tools/libxc/xc_dom_binloader.c
|
||||
@@ -277,6 +277,12 @@ static int xc_dom_load_bin_kernel(struct xc_dom_image *dom)
|
||||
DOMPRINTF(" bss_size: 0x%" PRIx32 "", bss_size);
|
||||
|
||||
dest = xc_dom_vaddr_to_ptr(dom, dom->kernel_seg.vstart, &dest_size);
|
||||
+ if ( dest == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: xc_dom_vaddr_to_ptr(dom, dom->kernel_seg.vstart)"
|
||||
+ " => NULL", __FUNCTION__);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
|
||||
if ( dest_size < text_size ||
|
||||
dest_size - text_size < bss_size )
|
||||
diff --git a/tools/libxc/xc_dom_core.c b/tools/libxc/xc_dom_core.c
|
||||
index 8913e41..a54ddae 100644
|
||||
--- a/tools/libxc/xc_dom_core.c
|
||||
+++ b/tools/libxc/xc_dom_core.c
|
||||
@@ -868,6 +868,12 @@ int xc_dom_build_image(struct xc_dom_image *dom)
|
||||
ramdisklen) != 0 )
|
||||
goto err;
|
||||
ramdiskmap = xc_dom_seg_to_ptr(dom, &dom->ramdisk_seg);
|
||||
+ if ( ramdiskmap == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: xc_dom_seg_to_ptr(dom, &dom->ramdisk_seg) => NULL",
|
||||
+ __FUNCTION__);
|
||||
+ goto err;
|
||||
+ }
|
||||
if ( unziplen )
|
||||
{
|
||||
if ( xc_dom_do_gunzip(dom->xch,
|
||||
diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c
|
||||
index 9fc4b94..61b5798 100644
|
||||
--- a/tools/libxc/xc_dom_elfloader.c
|
||||
+++ b/tools/libxc/xc_dom_elfloader.c
|
||||
@@ -139,6 +139,12 @@ static elf_errorstatus xc_dom_load_elf_symtab(struct xc_dom_image *dom,
|
||||
return 0;
|
||||
size = dom->kernel_seg.vend - dom->bsd_symtab_start;
|
||||
hdr_ptr = xc_dom_vaddr_to_ptr(dom, dom->bsd_symtab_start, &allow_size);
|
||||
+ if ( hdr_ptr == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s/load: xc_dom_vaddr_to_ptr(dom,dom->bsd_symtab_start"
|
||||
+ " => NULL", __FUNCTION__);
|
||||
+ return -1;
|
||||
+ }
|
||||
elf->caller_xdest_base = hdr_ptr;
|
||||
elf->caller_xdest_size = allow_size;
|
||||
hdr = ELF_REALPTR2PTRVAL(hdr_ptr);
|
||||
@@ -384,7 +390,14 @@ static elf_errorstatus xc_dom_load_elf_kernel(struct xc_dom_image *dom)
|
||||
xen_pfn_t pages;
|
||||
|
||||
elf->dest_base = xc_dom_seg_to_ptr_pages(dom, &dom->kernel_seg, &pages);
|
||||
+ if ( elf->dest_base == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: xc_dom_vaddr_to_ptr(dom,dom->kernel_seg)"
|
||||
+ " => NULL", __FUNCTION__);
|
||||
+ return -1;
|
||||
+ }
|
||||
elf->dest_size = pages * XC_DOM_PAGE_SIZE(dom);
|
||||
+
|
||||
rc = elf_load_binary(elf);
|
||||
if ( rc < 0 )
|
||||
{
|
||||
diff --git a/tools/libxc/xc_dom_ia64.c b/tools/libxc/xc_dom_ia64.c
|
||||
index dcd1523..7c0eff1 100644
|
||||
--- a/tools/libxc/xc_dom_ia64.c
|
||||
+++ b/tools/libxc/xc_dom_ia64.c
|
||||
@@ -60,6 +60,12 @@ int start_info_ia64(struct xc_dom_image *dom)
|
||||
|
||||
DOMPRINTF_CALLED(dom->xch);
|
||||
|
||||
+ if ( start_info == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: xc_dom_pfn_to_ptr failed on start_info", __FUNCTION__);
|
||||
+ return -1; /* our caller throws away our return value :-/ */
|
||||
+ }
|
||||
+
|
||||
memset(start_info, 0, sizeof(*start_info));
|
||||
sprintf(start_info->magic, dom->guest_type);
|
||||
start_info->flags = dom->flags;
|
||||
diff --git a/tools/libxc/xc_dom_x86.c b/tools/libxc/xc_dom_x86.c
|
||||
index 0cf1687..75d6b83 100644
|
||||
--- a/tools/libxc/xc_dom_x86.c
|
||||
+++ b/tools/libxc/xc_dom_x86.c
|
||||
@@ -144,6 +144,9 @@ static int setup_pgtables_x86_32(struct xc_dom_image *dom)
|
||||
xen_vaddr_t addr;
|
||||
xen_pfn_t pgpfn;
|
||||
|
||||
+ if ( l2tab == NULL )
|
||||
+ goto pfn_error;
|
||||
+
|
||||
for ( addr = dom->parms.virt_base; addr < dom->virt_pgtab_end;
|
||||
addr += PAGE_SIZE_X86 )
|
||||
{
|
||||
@@ -151,6 +154,8 @@ static int setup_pgtables_x86_32(struct xc_dom_image *dom)
|
||||
{
|
||||
/* get L1 tab, make L2 entry */
|
||||
l1tab = xc_dom_pfn_to_ptr(dom, l1pfn, 1);
|
||||
+ if ( l1tab == NULL )
|
||||
+ goto pfn_error;
|
||||
l2off = l2_table_offset_i386(addr);
|
||||
l2tab[l2off] =
|
||||
pfn_to_paddr(xc_dom_p2m_guest(dom, l1pfn)) | L2_PROT;
|
||||
@@ -169,6 +174,11 @@ static int setup_pgtables_x86_32(struct xc_dom_image *dom)
|
||||
l1tab = NULL;
|
||||
}
|
||||
return 0;
|
||||
+
|
||||
+pfn_error:
|
||||
+ xc_dom_panic(dom->xch, XC_INTERNAL_ERROR,
|
||||
+ "%s: xc_dom_pfn_to_ptr failed", __FUNCTION__);
|
||||
+ return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -219,6 +229,12 @@ static xen_pfn_t move_l3_below_4G(struct xc_dom_image *dom,
|
||||
goto out;
|
||||
|
||||
l3tab = xc_dom_pfn_to_ptr(dom, l3pfn, 1);
|
||||
+ if ( l3tab == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: xc_dom_pfn_to_ptr(dom, l3pfn, 1) => NULL",
|
||||
+ __FUNCTION__);
|
||||
+ return l3mfn; /* our one call site will call xc_dom_panic and fail */
|
||||
+ }
|
||||
memset(l3tab, 0, XC_DOM_PAGE_SIZE(dom));
|
||||
|
||||
DOMPRINTF("%s: successfully relocated L3 below 4G. "
|
||||
@@ -262,6 +278,8 @@ static int setup_pgtables_x86_32_pae(struct xc_dom_image *dom)
|
||||
}
|
||||
|
||||
l3tab = xc_dom_pfn_to_ptr(dom, l3pfn, 1);
|
||||
+ if ( l3tab == NULL )
|
||||
+ goto pfn_error;
|
||||
|
||||
for ( addr = dom->parms.virt_base; addr < dom->virt_pgtab_end;
|
||||
addr += PAGE_SIZE_X86 )
|
||||
@@ -270,6 +288,8 @@ static int setup_pgtables_x86_32_pae(struct xc_dom_image *dom)
|
||||
{
|
||||
/* get L2 tab, make L3 entry */
|
||||
l2tab = xc_dom_pfn_to_ptr(dom, l2pfn, 1);
|
||||
+ if ( l2tab == NULL )
|
||||
+ goto pfn_error;
|
||||
l3off = l3_table_offset_pae(addr);
|
||||
l3tab[l3off] =
|
||||
pfn_to_paddr(xc_dom_p2m_guest(dom, l2pfn)) | L3_PROT;
|
||||
@@ -280,6 +300,8 @@ static int setup_pgtables_x86_32_pae(struct xc_dom_image *dom)
|
||||
{
|
||||
/* get L1 tab, make L2 entry */
|
||||
l1tab = xc_dom_pfn_to_ptr(dom, l1pfn, 1);
|
||||
+ if ( l1tab == NULL )
|
||||
+ goto pfn_error;
|
||||
l2off = l2_table_offset_pae(addr);
|
||||
l2tab[l2off] =
|
||||
pfn_to_paddr(xc_dom_p2m_guest(dom, l1pfn)) | L2_PROT;
|
||||
@@ -306,6 +328,11 @@ static int setup_pgtables_x86_32_pae(struct xc_dom_image *dom)
|
||||
l3tab[3] = pfn_to_paddr(xc_dom_p2m_guest(dom, l2pfn)) | L3_PROT;
|
||||
}
|
||||
return 0;
|
||||
+
|
||||
+pfn_error:
|
||||
+ xc_dom_panic(dom->xch, XC_INTERNAL_ERROR,
|
||||
+ "%s: xc_dom_pfn_to_ptr failed", __FUNCTION__);
|
||||
+ return -EINVAL;
|
||||
}
|
||||
|
||||
#undef L1_PROT
|
||||
@@ -344,6 +371,9 @@ static int setup_pgtables_x86_64(struct xc_dom_image *dom)
|
||||
uint64_t addr;
|
||||
xen_pfn_t pgpfn;
|
||||
|
||||
+ if ( l4tab == NULL )
|
||||
+ goto pfn_error;
|
||||
+
|
||||
for ( addr = dom->parms.virt_base; addr < dom->virt_pgtab_end;
|
||||
addr += PAGE_SIZE_X86 )
|
||||
{
|
||||
@@ -351,6 +381,8 @@ static int setup_pgtables_x86_64(struct xc_dom_image *dom)
|
||||
{
|
||||
/* get L3 tab, make L4 entry */
|
||||
l3tab = xc_dom_pfn_to_ptr(dom, l3pfn, 1);
|
||||
+ if ( l3tab == NULL )
|
||||
+ goto pfn_error;
|
||||
l4off = l4_table_offset_x86_64(addr);
|
||||
l4tab[l4off] =
|
||||
pfn_to_paddr(xc_dom_p2m_guest(dom, l3pfn)) | L4_PROT;
|
||||
@@ -361,6 +393,8 @@ static int setup_pgtables_x86_64(struct xc_dom_image *dom)
|
||||
{
|
||||
/* get L2 tab, make L3 entry */
|
||||
l2tab = xc_dom_pfn_to_ptr(dom, l2pfn, 1);
|
||||
+ if ( l2tab == NULL )
|
||||
+ goto pfn_error;
|
||||
l3off = l3_table_offset_x86_64(addr);
|
||||
l3tab[l3off] =
|
||||
pfn_to_paddr(xc_dom_p2m_guest(dom, l2pfn)) | L3_PROT;
|
||||
@@ -373,6 +407,8 @@ static int setup_pgtables_x86_64(struct xc_dom_image *dom)
|
||||
{
|
||||
/* get L1 tab, make L2 entry */
|
||||
l1tab = xc_dom_pfn_to_ptr(dom, l1pfn, 1);
|
||||
+ if ( l1tab == NULL )
|
||||
+ goto pfn_error;
|
||||
l2off = l2_table_offset_x86_64(addr);
|
||||
l2tab[l2off] =
|
||||
pfn_to_paddr(xc_dom_p2m_guest(dom, l1pfn)) | L2_PROT;
|
||||
@@ -393,6 +429,11 @@ static int setup_pgtables_x86_64(struct xc_dom_image *dom)
|
||||
l1tab = NULL;
|
||||
}
|
||||
return 0;
|
||||
+
|
||||
+pfn_error:
|
||||
+ xc_dom_panic(dom->xch, XC_INTERNAL_ERROR,
|
||||
+ "%s: xc_dom_pfn_to_ptr failed", __FUNCTION__);
|
||||
+ return -EINVAL;
|
||||
}
|
||||
|
||||
#undef L1_PROT
|
||||
@@ -410,6 +451,8 @@ static int alloc_magic_pages(struct xc_dom_image *dom)
|
||||
if ( xc_dom_alloc_segment(dom, &dom->p2m_seg, "phys2mach", 0, p2m_size) )
|
||||
return -1;
|
||||
dom->p2m_guest = xc_dom_seg_to_ptr(dom, &dom->p2m_seg);
|
||||
+ if ( dom->p2m_guest == NULL )
|
||||
+ return -1;
|
||||
|
||||
/* allocate special pages */
|
||||
dom->start_info_pfn = xc_dom_alloc_page(dom, "start info");
|
||||
@@ -434,6 +477,12 @@ static int start_info_x86_32(struct xc_dom_image *dom)
|
||||
|
||||
DOMPRINTF_CALLED(dom->xch);
|
||||
|
||||
+ if ( start_info == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: xc_dom_pfn_to_ptr failed on start_info", __FUNCTION__);
|
||||
+ return -1; /* our caller throws away our return value :-/ */
|
||||
+ }
|
||||
+
|
||||
memset(start_info, 0, sizeof(*start_info));
|
||||
strncpy(start_info->magic, dom->guest_type, sizeof(start_info->magic));
|
||||
start_info->magic[sizeof(start_info->magic) - 1] = '\0';
|
||||
@@ -474,6 +523,12 @@ static int start_info_x86_64(struct xc_dom_image *dom)
|
||||
|
||||
DOMPRINTF_CALLED(dom->xch);
|
||||
|
||||
+ if ( start_info == NULL )
|
||||
+ {
|
||||
+ DOMPRINTF("%s: xc_dom_pfn_to_ptr failed on start_info", __FUNCTION__);
|
||||
+ return -1; /* our caller throws away our return value :-/ */
|
||||
+ }
|
||||
+
|
||||
memset(start_info, 0, sizeof(*start_info));
|
||||
strncpy(start_info->magic, dom->guest_type, sizeof(start_info->magic));
|
||||
start_info->magic[sizeof(start_info->magic) - 1] = '\0';
|
||||
diff --git a/tools/libxc/xc_domain_restore.c b/tools/libxc/xc_domain_restore.c
|
||||
index b4c0b10..3994f8f 100644
|
||||
--- a/tools/libxc/xc_domain_restore.c
|
||||
+++ b/tools/libxc/xc_domain_restore.c
|
||||
@@ -1556,6 +1556,12 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
|
||||
mfn = ctx->p2m[pfn];
|
||||
buf = xc_map_foreign_range(xch, dom, PAGE_SIZE,
|
||||
PROT_READ | PROT_WRITE, mfn);
|
||||
+ if ( buf == NULL )
|
||||
+ {
|
||||
+ ERROR("xc_map_foreign_range for generation id"
|
||||
+ " buffer failed");
|
||||
+ goto out;
|
||||
+ }
|
||||
|
||||
generationid = *(unsigned long long *)(buf + offset);
|
||||
*(unsigned long long *)(buf + offset) = generationid + 1;
|
||||
@@ -1713,6 +1719,11 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
|
||||
l3tab = (uint64_t *)
|
||||
xc_map_foreign_range(xch, dom, PAGE_SIZE,
|
||||
PROT_READ, ctx->p2m[i]);
|
||||
+ if ( l3tab == NULL )
|
||||
+ {
|
||||
+ PERROR("xc_map_foreign_range failed (for l3tab)");
|
||||
+ goto out;
|
||||
+ }
|
||||
|
||||
for ( j = 0; j < 4; j++ )
|
||||
l3ptes[j] = l3tab[j];
|
||||
@@ -1739,6 +1750,11 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
|
||||
l3tab = (uint64_t *)
|
||||
xc_map_foreign_range(xch, dom, PAGE_SIZE,
|
||||
PROT_READ | PROT_WRITE, ctx->p2m[i]);
|
||||
+ if ( l3tab == NULL )
|
||||
+ {
|
||||
+ PERROR("xc_map_foreign_range failed (for l3tab, 2nd)");
|
||||
+ goto out;
|
||||
+ }
|
||||
|
||||
for ( j = 0; j < 4; j++ )
|
||||
l3tab[j] = l3ptes[j];
|
||||
@@ -1909,6 +1925,12 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
|
||||
SET_FIELD(ctxt, user_regs.edx, mfn);
|
||||
start_info = xc_map_foreign_range(
|
||||
xch, dom, PAGE_SIZE, PROT_READ | PROT_WRITE, mfn);
|
||||
+ if ( start_info == NULL )
|
||||
+ {
|
||||
+ PERROR("xc_map_foreign_range failed (for start_info)");
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
SET_FIELD(start_info, nr_pages, dinfo->p2m_size);
|
||||
SET_FIELD(start_info, shared_info, shared_info_frame<<PAGE_SHIFT);
|
||||
SET_FIELD(start_info, flags, 0);
|
||||
@@ -2056,6 +2078,11 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
|
||||
/* Restore contents of shared-info page. No checking needed. */
|
||||
new_shared_info = xc_map_foreign_range(
|
||||
xch, dom, PAGE_SIZE, PROT_WRITE, shared_info_frame);
|
||||
+ if ( new_shared_info == NULL )
|
||||
+ {
|
||||
+ PERROR("xc_map_foreign_range failed (for new_shared_info)");
|
||||
+ goto out;
|
||||
+ }
|
||||
|
||||
/* restore saved vcpu_info and arch specific info */
|
||||
MEMCPY_FIELD(new_shared_info, old_shared_info, vcpu_info);
|
||||
diff --git a/tools/libxc/xc_offline_page.c b/tools/libxc/xc_offline_page.c
|
||||
index 089a361..36b9812 100644
|
||||
--- a/tools/libxc/xc_offline_page.c
|
||||
+++ b/tools/libxc/xc_offline_page.c
|
||||
@@ -714,6 +714,11 @@ int xc_exchange_page(xc_interface *xch, int domid, xen_pfn_t mfn)
|
||||
|
||||
new_p = xc_map_foreign_range(xch, domid, PAGE_SIZE,
|
||||
PROT_READ|PROT_WRITE, new_mfn);
|
||||
+ if ( new_p == NULL )
|
||||
+ {
|
||||
+ ERROR("failed to map new_p for copy, guest may be broken?");
|
||||
+ goto failed;
|
||||
+ }
|
||||
memcpy(new_p, backup, PAGE_SIZE);
|
||||
munmap(new_p, PAGE_SIZE);
|
||||
mops.arg1.mfn = new_mfn;
|
||||
--
|
||||
1.7.2.5
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,261 @@
|
||||
From 59f66d58180832af6b99a9e4489031b5c2f627ab Mon Sep 17 00:00:00 2001
|
||||
From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Date: Fri, 14 Jun 2013 16:43:17 +0100
|
||||
Subject: [PATCH 09/23] tools/xcutils/readnotes: adjust print_l1_mfn_valid_note
|
||||
|
||||
Use the new PTRVAL macros and elf_access_unsigned in
|
||||
print_l1_mfn_valid_note.
|
||||
|
||||
No functional change unless the input is wrong, or we are reading a
|
||||
file for a different endianness.
|
||||
|
||||
Separated out from the previous patch because this change does produce
|
||||
a difference in the generated code.
|
||||
|
||||
This is part of the fix to a security issue, XSA-55.
|
||||
|
||||
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
---
|
||||
tools/xcutils/readnotes.c | 11 ++++++-----
|
||||
1 files changed, 6 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/tools/xcutils/readnotes.c b/tools/xcutils/readnotes.c
|
||||
index 2af047d..7ff2530 100644
|
||||
--- a/tools/xcutils/readnotes.c
|
||||
+++ b/tools/xcutils/readnotes.c
|
||||
@@ -77,22 +77,23 @@ static void print_numeric_note(const char *prefix, struct elf_binary *elf,
|
||||
}
|
||||
|
||||
static void print_l1_mfn_valid_note(const char *prefix, struct elf_binary *elf,
|
||||
- const elf_note *note)
|
||||
+ ELF_HANDLE_DECL(elf_note) note)
|
||||
{
|
||||
int descsz = elf_uval(elf, note, descsz);
|
||||
- const uint32_t *desc32 = elf_note_desc(elf, note);
|
||||
- const uint64_t *desc64 = elf_note_desc(elf, note);
|
||||
+ ELF_PTRVAL_CONST_VOID desc = elf_note_desc(elf, note);
|
||||
|
||||
/* XXX should be able to cope with a list of values. */
|
||||
switch ( descsz / 2 )
|
||||
{
|
||||
case 8:
|
||||
printf("%s: mask=%#"PRIx64" value=%#"PRIx64"\n", prefix,
|
||||
- desc64[0], desc64[1]);
|
||||
+ elf_access_unsigned(elf, desc, 0, 8),
|
||||
+ elf_access_unsigned(elf, desc, 8, 8));
|
||||
break;
|
||||
case 4:
|
||||
printf("%s: mask=%#"PRIx32" value=%#"PRIx32"\n", prefix,
|
||||
- desc32[0],desc32[1]);
|
||||
+ (uint32_t)elf_access_unsigned(elf, desc, 0, 4),
|
||||
+ (uint32_t)elf_access_unsigned(elf, desc, 4, 4));
|
||||
break;
|
||||
}
|
||||
|
||||
--
|
||||
1.7.2.5
|
||||
#From db14d5bd9b6508adfcd2b910f454fae12fa4ba00 Mon Sep 17 00:00:00 2001
|
||||
#From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
#Date: Fri, 14 Jun 2013 16:43:17 +0100
|
||||
#Subject: [PATCH 10/23] libelf: check nul-terminated strings properly
|
||||
#
|
||||
#It is not safe to simply take pointers into the ELF and use them as C
|
||||
#pointers. They might not be properly nul-terminated (and the pointers
|
||||
#might be wild).
|
||||
#
|
||||
#So we are going to introduce a new function elf_strval for safely
|
||||
#getting strings. This will check that the addresses are in range and
|
||||
#that there is a proper nul-terminated string. Of course it might
|
||||
#discover that there isn't. In that case, it will be made to fail.
|
||||
#This means that elf_note_name might fail, too.
|
||||
#
|
||||
#For the benefit of call sites which are just going to pass the value
|
||||
#to a printf-like function, we provide elf_strfmt which returns
|
||||
#"(invalid)" on failure rather than NULL.
|
||||
#
|
||||
#In this patch we introduce dummy definitions of these functions. We
|
||||
#introduce calls to elf_strval and elf_strfmt everywhere, and update
|
||||
#all the call sites with appropriate error checking.
|
||||
#
|
||||
#There is not yet any semantic change, since before this patch all the
|
||||
#places where we introduce elf_strval dereferenced the value anyway, so
|
||||
#it mustn't have been NULL.
|
||||
#
|
||||
#In future patches, when elf_strval is made able return NULL, when it
|
||||
#does so it will mark the elf "broken" so that an appropriate
|
||||
#diagnostic can be printed.
|
||||
#
|
||||
#This is part of the fix to a security issue, XSA-55.
|
||||
#
|
||||
#Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
#Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
#Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
|
||||
#---
|
||||
# tools/xcutils/readnotes.c | 11 ++++++++---
|
||||
# xen/common/libelf/libelf-dominfo.c | 13 ++++++++++---
|
||||
# xen/common/libelf/libelf-tools.c | 10 +++++++---
|
||||
# xen/include/xen/libelf.h | 7 +++++--
|
||||
# 4 files changed, 30 insertions(+), 11 deletions(-)
|
||||
#
|
||||
diff --git a/tools/xcutils/readnotes.c b/tools/xcutils/readnotes.c
|
||||
index 7ff2530..cfae994 100644
|
||||
--- a/tools/xcutils/readnotes.c
|
||||
+++ b/tools/xcutils/readnotes.c
|
||||
@@ -63,7 +63,7 @@ struct setup_header {
|
||||
static void print_string_note(const char *prefix, struct elf_binary *elf,
|
||||
ELF_HANDLE_DECL(elf_note) note)
|
||||
{
|
||||
- printf("%s: %s\n", prefix, (char*)elf_note_desc(elf, note));
|
||||
+ printf("%s: %s\n", prefix, elf_strfmt(elf, elf_note_desc(elf, note)));
|
||||
}
|
||||
|
||||
static void print_numeric_note(const char *prefix, struct elf_binary *elf,
|
||||
@@ -103,10 +103,14 @@ static int print_notes(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) start,
|
||||
{
|
||||
ELF_HANDLE_DECL(elf_note) note;
|
||||
int notes_found = 0;
|
||||
+ const char *this_note_name;
|
||||
|
||||
for ( note = start; ELF_HANDLE_PTRVAL(note) < ELF_HANDLE_PTRVAL(end); note = elf_note_next(elf, note) )
|
||||
{
|
||||
- if (0 != strcmp(elf_note_name(elf, note), "Xen"))
|
||||
+ this_note_name = elf_note_name(elf, note);
|
||||
+ if (NULL == this_note_name)
|
||||
+ continue;
|
||||
+ if (0 != strcmp(this_note_name, "Xen"))
|
||||
continue;
|
||||
|
||||
notes_found++;
|
||||
@@ -294,7 +298,8 @@ int main(int argc, char **argv)
|
||||
|
||||
shdr = elf_shdr_by_name(&elf, "__xen_guest");
|
||||
if (ELF_HANDLE_VALID(shdr))
|
||||
- printf("__xen_guest: %s\n", (char*)elf_section_start(&elf, shdr));
|
||||
+ printf("__xen_guest: %s\n",
|
||||
+ elf_strfmt(&elf, elf_section_start(&elf, shdr)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
diff --git a/xen/common/libelf/libelf-dominfo.c b/xen/common/libelf/libelf-dominfo.c
|
||||
index 7140d59..b217f8f 100644
|
||||
--- a/xen/common/libelf/libelf-dominfo.c
|
||||
+++ b/xen/common/libelf/libelf-dominfo.c
|
||||
@@ -137,7 +137,10 @@ int elf_xen_parse_note(struct elf_binary *elf,
|
||||
|
||||
if ( note_desc[type].str )
|
||||
{
|
||||
- str = elf_note_desc(elf, note);
|
||||
+ str = elf_strval(elf, elf_note_desc(elf, note));
|
||||
+ if (str == NULL)
|
||||
+ /* elf_strval will mark elf broken if it fails so no need to log */
|
||||
+ return 0;
|
||||
elf_msg(elf, "%s: %s = \"%s\"\n", __FUNCTION__,
|
||||
note_desc[type].name, str);
|
||||
parms->elf_notes[type].type = XEN_ENT_STR;
|
||||
@@ -220,6 +223,7 @@ static int elf_xen_parse_notes(struct elf_binary *elf,
|
||||
{
|
||||
int xen_elfnotes = 0;
|
||||
ELF_HANDLE_DECL(elf_note) note;
|
||||
+ const char *note_name;
|
||||
|
||||
parms->elf_note_start = start;
|
||||
parms->elf_note_end = end;
|
||||
@@ -227,7 +231,10 @@ static int elf_xen_parse_notes(struct elf_binary *elf,
|
||||
ELF_HANDLE_PTRVAL(note) < parms->elf_note_end;
|
||||
note = elf_note_next(elf, note) )
|
||||
{
|
||||
- if ( strcmp(elf_note_name(elf, note), "Xen") )
|
||||
+ note_name = elf_note_name(elf, note);
|
||||
+ if ( note_name == NULL )
|
||||
+ continue;
|
||||
+ if ( strcmp(note_name, "Xen") )
|
||||
continue;
|
||||
if ( elf_xen_parse_note(elf, parms, note) )
|
||||
return -1;
|
||||
@@ -541,7 +548,7 @@ int elf_xen_parse(struct elf_binary *elf,
|
||||
parms->elf_note_start = ELF_INVALID_PTRVAL;
|
||||
parms->elf_note_end = ELF_INVALID_PTRVAL;
|
||||
elf_msg(elf, "%s: __xen_guest: \"%s\"\n", __FUNCTION__,
|
||||
- parms->guest_info);
|
||||
+ elf_strfmt(elf, parms->guest_info));
|
||||
elf_xen_parse_guest_info(elf, parms);
|
||||
break;
|
||||
}
|
||||
diff --git a/xen/common/libelf/libelf-tools.c b/xen/common/libelf/libelf-tools.c
|
||||
index f1fd886..3a0cde1 100644
|
||||
--- a/xen/common/libelf/libelf-tools.c
|
||||
+++ b/xen/common/libelf/libelf-tools.c
|
||||
@@ -119,7 +119,7 @@ const char *elf_section_name(struct elf_binary *elf,
|
||||
if ( ELF_PTRVAL_INVALID(elf->sec_strtab) )
|
||||
return "unknown";
|
||||
|
||||
- return elf->sec_strtab + elf_uval(elf, shdr, sh_name);
|
||||
+ return elf_strval(elf, elf->sec_strtab + elf_uval(elf, shdr, sh_name));
|
||||
}
|
||||
|
||||
ELF_PTRVAL_CONST_VOID elf_section_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr)
|
||||
@@ -151,6 +151,7 @@ ELF_HANDLE_DECL(elf_sym) elf_sym_by_name(struct elf_binary *elf, const char *sym
|
||||
ELF_PTRVAL_CONST_VOID end = elf_section_end(elf, elf->sym_tab);
|
||||
ELF_HANDLE_DECL(elf_sym) sym;
|
||||
uint64_t info, name;
|
||||
+ const char *sym_name;
|
||||
|
||||
for ( ; ptr < end; ptr += elf_size(elf, sym) )
|
||||
{
|
||||
@@ -159,7 +160,10 @@ ELF_HANDLE_DECL(elf_sym) elf_sym_by_name(struct elf_binary *elf, const char *sym
|
||||
name = elf_uval(elf, sym, st_name);
|
||||
if ( ELF32_ST_BIND(info) != STB_GLOBAL )
|
||||
continue;
|
||||
- if ( strcmp(elf->sym_strtab + name, symbol) )
|
||||
+ sym_name = elf_strval(elf, elf->sym_strtab + name);
|
||||
+ if ( sym_name == NULL ) /* out of range, oops */
|
||||
+ return ELF_INVALID_HANDLE(elf_sym);
|
||||
+ if ( strcmp(sym_name, symbol) )
|
||||
continue;
|
||||
return sym;
|
||||
}
|
||||
@@ -177,7 +181,7 @@ ELF_HANDLE_DECL(elf_sym) elf_sym_by_index(struct elf_binary *elf, int index)
|
||||
|
||||
const char *elf_note_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note)
|
||||
{
|
||||
- return ELF_HANDLE_PTRVAL(note) + elf_size(elf, note);
|
||||
+ return elf_strval(elf, ELF_HANDLE_PTRVAL(note) + elf_size(elf, note));
|
||||
}
|
||||
|
||||
ELF_PTRVAL_CONST_VOID elf_note_desc(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note)
|
||||
diff --git a/xen/include/xen/libelf.h b/xen/include/xen/libelf.h
|
||||
index cefd3d3..af5b5c5 100644
|
||||
--- a/xen/include/xen/libelf.h
|
||||
+++ b/xen/include/xen/libelf.h
|
||||
@@ -252,6 +252,9 @@ uint64_t elf_access_unsigned(struct elf_binary *elf, ELF_PTRVAL_CONST_VOID ptr,
|
||||
uint64_t elf_round_up(struct elf_binary *elf, uint64_t addr);
|
||||
|
||||
|
||||
+#define elf_strval(elf,x) ((const char*)(x)) /* may return NULL in the future */
|
||||
+#define elf_strfmt(elf,x) ((const char*)(x)) /* will return (invalid) instead */
|
||||
+
|
||||
#define elf_memcpy_safe(elf, dst, src, sz) memcpy((dst),(src),(sz))
|
||||
#define elf_memset_safe(elf, dst, c, sz) memset((dst),(c),(sz))
|
||||
/*
|
||||
@@ -279,7 +282,7 @@ ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_name(struct elf_binary *elf, const char *n
|
||||
ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_index(struct elf_binary *elf, int index);
|
||||
ELF_HANDLE_DECL(elf_phdr) elf_phdr_by_index(struct elf_binary *elf, int index);
|
||||
|
||||
-const char *elf_section_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr);
|
||||
+const char *elf_section_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr); /* might return NULL if inputs are invalid */
|
||||
ELF_PTRVAL_CONST_VOID elf_section_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr);
|
||||
ELF_PTRVAL_CONST_VOID elf_section_end(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr);
|
||||
|
||||
@@ -289,7 +292,7 @@ ELF_PTRVAL_CONST_VOID elf_segment_end(struct elf_binary *elf, ELF_HANDLE_DECL(el
|
||||
ELF_HANDLE_DECL(elf_sym) elf_sym_by_name(struct elf_binary *elf, const char *symbol);
|
||||
ELF_HANDLE_DECL(elf_sym) elf_sym_by_index(struct elf_binary *elf, int index);
|
||||
|
||||
-const char *elf_note_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
|
||||
+const char *elf_note_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note); /* may return NULL */
|
||||
ELF_PTRVAL_CONST_VOID elf_note_desc(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
|
||||
uint64_t elf_note_numeric(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
|
||||
uint64_t elf_note_numeric_array(struct elf_binary *, ELF_HANDLE_DECL(elf_note),
|
||||
--
|
||||
1.7.2.5
|
||||
|
@ -1,116 +0,0 @@
|
||||
# Patch Makefile to patch insource newlib,
|
||||
# Prevent internal downloading of external packages
|
||||
diff -ur xen-4.2.0.orig/stubdom/Makefile xen-4.2.0/stubdom/Makefile
|
||||
--- stubdom/Makefile 2012-09-17 18:21:17.000000000 +0800
|
||||
+++ stubdom/Makefile 2012-12-05 14:01:10.694260256 +0800
|
||||
@@ -8,30 +8,30 @@
|
||||
include $(XEN_ROOT)/Config.mk
|
||||
|
||||
#ZLIB_URL?=http://www.zlib.net
|
||||
-ZLIB_URL=$(XEN_EXTFILES_URL)
|
||||
+ZLIB_URL=/mnt/gen2/TmpDir/portage/app-emulation/xen-pvgrub-4.2.0/distdir
|
||||
ZLIB_VERSION=1.2.3
|
||||
|
||||
#LIBPCI_URL?=http://www.kernel.org/pub/software/utils/pciutils
|
||||
-LIBPCI_URL?=$(XEN_EXTFILES_URL)
|
||||
+LIBPCI_URL?=/mnt/gen2/TmpDir/portage/app-emulation/xen-pvgrub-4.2.0/distdir
|
||||
LIBPCI_VERSION=2.2.9
|
||||
|
||||
#NEWLIB_URL?=ftp://sources.redhat.com/pub/newlib
|
||||
-NEWLIB_URL?=$(XEN_EXTFILES_URL)
|
||||
+NEWLIB_URL?=/mnt/gen2/TmpDir/portage/app-emulation/xen-pvgrub-4.2.0/distdir
|
||||
NEWLIB_VERSION=1.16.0
|
||||
|
||||
#LWIP_URL?=http://download.savannah.gnu.org/releases/lwip
|
||||
-LWIP_URL?=$(XEN_EXTFILES_URL)
|
||||
+LWIP_URL?=/mnt/gen2/TmpDir/portage/app-emulation/xen-pvgrub-4.2.0/distdir
|
||||
LWIP_VERSION=1.3.0
|
||||
|
||||
#GRUB_URL?=http://alpha.gnu.org/gnu/grub
|
||||
-GRUB_URL?=$(XEN_EXTFILES_URL)
|
||||
+GRUB_URL?=/mnt/gen2/TmpDir/portage/app-emulation/xen-pvgrub-4.2.0/distdir
|
||||
GRUB_VERSION=0.97
|
||||
|
||||
-#OCAML_URL?=$(XEN_EXTFILES_URL)
|
||||
+#OCAML_URL?=/mnt/gen2/TmpDir/portage/app-emulation/xen-pvgrub-4.2.0/distdir
|
||||
OCAML_URL?=http://caml.inria.fr/pub/distrib/ocaml-3.11
|
||||
OCAML_VERSION=3.11.0
|
||||
|
||||
-WGET=wget -c
|
||||
+WGET=cp -t .
|
||||
|
||||
GNU_TARGET_ARCH:=$(XEN_TARGET_ARCH)
|
||||
ifeq ($(XEN_TARGET_ARCH),x86_32)
|
||||
@@ -95,12 +95,12 @@
|
||||
##############
|
||||
|
||||
newlib-$(NEWLIB_VERSION).tar.gz:
|
||||
- $(WGET) $(NEWLIB_URL)/$@
|
||||
|
||||
newlib-$(NEWLIB_VERSION): newlib-$(NEWLIB_VERSION).tar.gz
|
||||
tar xzf $<
|
||||
patch -d $@ -p0 < newlib.patch
|
||||
patch -d $@ -p0 < newlib-chk.patch
|
||||
+ patch -d $@ -p0 < newlib-implicits.patch
|
||||
patch -d $@ -p1 < newlib-stdint-size_max-fix-from-1.17.0.patch
|
||||
find $@ -type f | xargs perl -i.bak \
|
||||
-pe 's/\b_(tzname|daylight|timezone)\b/$$1/g'
|
||||
@@ -112,7 +112,7 @@
|
||||
$(NEWLIB_STAMPFILE): mk-headers-$(XEN_TARGET_ARCH) newlib-$(NEWLIB_VERSION)
|
||||
mkdir -p newlib-$(XEN_TARGET_ARCH)
|
||||
( cd newlib-$(XEN_TARGET_ARCH) && \
|
||||
- CC_FOR_TARGET="$(CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(NEWLIB_CFLAGS)" AR_FOR_TARGET=$(AR) LD_FOR_TARGET=$(LD) RANLIB_FOR_TARGET=$(RANLIB) ../newlib-$(NEWLIB_VERSION)/configure --prefix=$(CROSS_PREFIX) --verbose --target=$(GNU_TARGET_ARCH)-xen-elf --enable-newlib-io-long-long --disable-multilib && \
|
||||
+ CC_FOR_TARGET="$(CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(NEWLIB_CFLAGS)" AR_FOR_TARGET=$(AR) LD_FOR_TARGET=$(LD) LDFLAGS= RANLIB_FOR_TARGET=$(RANLIB) ../newlib-$(NEWLIB_VERSION)/configure --prefix=$(CROSS_PREFIX) --verbose --target=$(GNU_TARGET_ARCH)-xen-elf --enable-newlib-io-long-long --disable-multilib && \
|
||||
$(CROSS_MAKE) && \
|
||||
$(CROSS_MAKE) install )
|
||||
|
||||
@@ -121,7 +121,6 @@
|
||||
############
|
||||
|
||||
zlib-$(ZLIB_VERSION).tar.gz:
|
||||
- $(WGET) $(ZLIB_URL)/$@
|
||||
|
||||
zlib-$(XEN_TARGET_ARCH): zlib-$(ZLIB_VERSION).tar.gz
|
||||
tar xzf $<
|
||||
@@ -132,7 +132,7 @@
|
||||
cross-zlib: $(ZLIB_STAMPFILE)
|
||||
$(ZLIB_STAMPFILE): zlib-$(XEN_TARGET_ARCH) $(NEWLIB_STAMPFILE)
|
||||
( cd $< && \
|
||||
- CFLAGS="$(TARGET_CPPFLAGS) $(TARGET_CFLAGS)" CC=$(CC) ./configure --prefix=$(CROSS_PREFIX)/$(GNU_TARGET_ARCH)-xen-elf && \
|
||||
+ CFLAGS="$(TARGET_CPPFLAGS) $(TARGET_CFLAGS)" CC="$(CC)" ./configure --prefix=$(CROSS_PREFIX)/$(GNU_TARGET_ARCH)-xen-elf && \
|
||||
$(CROSS_MAKE) libz.a && \
|
||||
$(CROSS_MAKE) install )
|
||||
|
||||
@@ -141,7 +142,6 @@
|
||||
##############
|
||||
|
||||
pciutils-$(LIBPCI_VERSION).tar.bz2:
|
||||
- $(WGET) $(LIBPCI_URL)/$@
|
||||
|
||||
pciutils-$(XEN_TARGET_ARCH): pciutils-$(LIBPCI_VERSION).tar.bz2
|
||||
tar xjf $<
|
||||
@@ -169,7 +170,6 @@
|
||||
######
|
||||
|
||||
lwip-$(LWIP_VERSION).tar.gz:
|
||||
- $(WGET) $(LWIP_URL)/$@
|
||||
|
||||
lwip-$(XEN_TARGET_ARCH): lwip-$(LWIP_VERSION).tar.gz
|
||||
tar xzf $<
|
||||
@@ -325,7 +326,6 @@
|
||||
######
|
||||
|
||||
grub-$(GRUB_VERSION).tar.gz:
|
||||
- $(WGET) $(GRUB_URL)/$@
|
||||
|
||||
grub-upstream: grub-$(GRUB_VERSION).tar.gz
|
||||
tar xzf $<
|
||||
@@ -392,7 +393,7 @@
|
||||
$(INSTALL_DIR) "$(DESTDIR)$(XENFIRMWAREDIR)"
|
||||
$(INSTALL_DATA) mini-os-$(XEN_TARGET_ARCH)-ioemu/mini-os.gz "$(DESTDIR)$(XENFIRMWAREDIR)/ioemu-stubdom.gz"
|
||||
|
||||
-install-grub: pv-grub
|
||||
+install-grub:
|
||||
$(INSTALL_DIR) "$(DESTDIR)$(XENFIRMWAREDIR)"
|
||||
$(INSTALL_DATA) mini-os-$(XEN_TARGET_ARCH)-grub/mini-os.gz "$(DESTDIR)$(XENFIRMWAREDIR)/pv-grub-$(XEN_TARGET_ARCH).gz"
|
||||
|
@ -1,113 +0,0 @@
|
||||
# Copyright 1999-2013 Gentoo Foundation
|
||||
# Distributed under the terms of the GNU General Public License v2
|
||||
# $Header: /var/cvsroot/gentoo-x86/app-emulation/xen-pvgrub/xen-pvgrub-4.2.1.ebuild,v 1.2 2013/01/30 14:12:30 idella4 Exp $
|
||||
|
||||
EAPI="4"
|
||||
|
||||
inherit flag-o-matic eutils multilib toolchain-funcs
|
||||
|
||||
XEN_EXTFILES_URL="http://xenbits.xensource.com/xen-extfiles"
|
||||
LIBPCI_URL=ftp://atrey.karlin.mff.cuni.cz/pub/linux/pci
|
||||
GRUB_URL=mirror://gnu-alpha/grub
|
||||
SRC_URI="
|
||||
http://bits.xensource.com/oss-xen/release/${PV}/xen-${PV}.tar.gz
|
||||
$GRUB_URL/grub-0.97.tar.gz
|
||||
$XEN_EXTFILES_URL/zlib-1.2.3.tar.gz
|
||||
$LIBPCI_URL/pciutils-2.2.9.tar.bz2
|
||||
$XEN_EXTFILES_URL/lwip-1.3.0.tar.gz
|
||||
$XEN_EXTFILES_URL/newlib/newlib-1.16.0.tar.gz"
|
||||
|
||||
S="${WORKDIR}/xen-${PV}"
|
||||
|
||||
DESCRIPTION="allows to boot Xen domU kernels from a menu.lst laying inside guest filesystem"
|
||||
HOMEPAGE="http://xen.org/"
|
||||
LICENSE="GPL-2"
|
||||
SLOT="0"
|
||||
KEYWORDS="~amd64 ~x86"
|
||||
IUSE="custom-cflags"
|
||||
|
||||
DEPEND="sys-devel/gettext
|
||||
sys-devel/gcc"
|
||||
|
||||
RDEPEND=">=app-emulation/xen-4.2.1"
|
||||
|
||||
src_prepare() {
|
||||
|
||||
# if the user *really* wants to use their own custom-cflags, let them
|
||||
if use custom-cflags; then
|
||||
einfo "User wants their own CFLAGS - removing defaults"
|
||||
# try and remove all the default custom-cflags
|
||||
find "${S}" -name Makefile -o -name Rules.mk -o -name Config.mk -exec sed \
|
||||
-e 's/CFLAGS\(.*\)=\(.*\)-O3\(.*\)/CFLAGS\1=\2\3/' \
|
||||
-e 's/CFLAGS\(.*\)=\(.*\)-march=i686\(.*\)/CFLAGS\1=\2\3/' \
|
||||
-e 's/CFLAGS\(.*\)=\(.*\)-fomit-frame-pointer\(.*\)/CFLAGS\1=\2\3/' \
|
||||
-e 's/CFLAGS\(.*\)=\(.*\)-g3*\s\(.*\)/CFLAGS\1=\2 \3/' \
|
||||
-e 's/CFLAGS\(.*\)=\(.*\)-O2\(.*\)/CFLAGS\1=\2\3/' \
|
||||
-i {} \;
|
||||
fi
|
||||
|
||||
#Substitute for internal downloading
|
||||
cp $DISTDIR/zlib-1.2.3.tar.gz \
|
||||
$DISTDIR/pciutils-2.2.9.tar.bz2 \
|
||||
$DISTDIR/lwip-1.3.0.tar.gz \
|
||||
$DISTDIR/newlib-1.16.0.tar.gz \
|
||||
$DISTDIR/grub-0.97.tar.gz \
|
||||
./stubdom/ || die "files not coped to stubdom"
|
||||
# Note: tip to patch grub gentoo style, for review soon. This is around 1/3.
|
||||
# cp "${WORKDIR}"/patch/{00[3-6]_all_grub*,010_all_grub*,01[3-9]_all_grub*,0[6-7]0_all_grub*} \
|
||||
# "${WORKDIR}"/patch/{110_all_grub*,300_all_grub*} \
|
||||
# stubdom/grub.patches/ || die
|
||||
einfo "files copied to stubdom"
|
||||
|
||||
# Patch the unmergeable newlib, fix most of the leftover gcc QA issues
|
||||
cp "${FILESDIR}"/newlib-implicits.patch stubdom || die
|
||||
|
||||
# Patch stubdom/Makefile to patch insource newlib & prevent internal downloading
|
||||
epatch "${FILESDIR}"/${P/-pvgrub/}-externals.patch
|
||||
|
||||
# Drop .config and Fix gcc-4.6
|
||||
epatch "${FILESDIR}"/${PN/-pvgrub/}-4-fix_dotconfig-gcc.patch
|
||||
|
||||
# fix jobserver in Makefile
|
||||
epatch "${FILESDIR}"/${PN/-pvgrub/}-4.2.0-jserver.patch
|
||||
}
|
||||
|
||||
src_compile() {
|
||||
use custom-cflags || unset CFLAGS
|
||||
if test-flag-CC -fno-strict-overflow; then
|
||||
append-flags -fno-strict-overflow
|
||||
fi
|
||||
|
||||
emake CC="$(tc-getCC)" LD="$(tc-getLD)" -C tools/include
|
||||
|
||||
# TODO; fix those -j1
|
||||
if use x86; then
|
||||
emake CC="$(tc-getCC)" LD="$(tc-getLD)" \
|
||||
XEN_TARGET_ARCH="x86_32" -C stubdom pv-grub
|
||||
elif use amd64; then
|
||||
emake CC="$(tc-getCC)" LD="$(tc-getLD)" \
|
||||
XEN_TARGET_ARCH="x86_64" -C stubdom pv-grub
|
||||
if use multilib; then
|
||||
multilib_toolchain_setup x86
|
||||
emake XEN_TARGET_ARCH="x86_32" -C stubdom pv-grub
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
src_install() {
|
||||
if use x86; then
|
||||
emake XEN_TARGET_ARCH="x86_32" DESTDIR="${D}" -C stubdom install-grub
|
||||
fi
|
||||
if use amd64; then
|
||||
emake XEN_TARGET_ARCH="x86_64" DESTDIR="${D}" -C stubdom install-grub
|
||||
if use multilib; then
|
||||
emake XEN_TARGET_ARCH="x86_32" DESTDIR="${D}" -C stubdom install-grub
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
pkg_postinst() {
|
||||
elog "Official Xen Guide and the unoffical wiki page:"
|
||||
elog " http://www.gentoo.org/doc/en/xen-guide.xml"
|
||||
elog " http://en.gentoo-wiki.com/wiki/Xen/"
|
||||
}
|
@ -1,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
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,261 @@
|
||||
From 59f66d58180832af6b99a9e4489031b5c2f627ab Mon Sep 17 00:00:00 2001
|
||||
From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Date: Fri, 14 Jun 2013 16:43:17 +0100
|
||||
Subject: [PATCH 09/23] tools/xcutils/readnotes: adjust print_l1_mfn_valid_note
|
||||
|
||||
Use the new PTRVAL macros and elf_access_unsigned in
|
||||
print_l1_mfn_valid_note.
|
||||
|
||||
No functional change unless the input is wrong, or we are reading a
|
||||
file for a different endianness.
|
||||
|
||||
Separated out from the previous patch because this change does produce
|
||||
a difference in the generated code.
|
||||
|
||||
This is part of the fix to a security issue, XSA-55.
|
||||
|
||||
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
---
|
||||
tools/xcutils/readnotes.c | 11 ++++++-----
|
||||
1 files changed, 6 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/tools/xcutils/readnotes.c b/tools/xcutils/readnotes.c
|
||||
index 2af047d..7ff2530 100644
|
||||
--- a/tools/xcutils/readnotes.c
|
||||
+++ b/tools/xcutils/readnotes.c
|
||||
@@ -77,22 +77,23 @@ static void print_numeric_note(const char *prefix, struct elf_binary *elf,
|
||||
}
|
||||
|
||||
static void print_l1_mfn_valid_note(const char *prefix, struct elf_binary *elf,
|
||||
- const elf_note *note)
|
||||
+ ELF_HANDLE_DECL(elf_note) note)
|
||||
{
|
||||
int descsz = elf_uval(elf, note, descsz);
|
||||
- const uint32_t *desc32 = elf_note_desc(elf, note);
|
||||
- const uint64_t *desc64 = elf_note_desc(elf, note);
|
||||
+ ELF_PTRVAL_CONST_VOID desc = elf_note_desc(elf, note);
|
||||
|
||||
/* XXX should be able to cope with a list of values. */
|
||||
switch ( descsz / 2 )
|
||||
{
|
||||
case 8:
|
||||
printf("%s: mask=%#"PRIx64" value=%#"PRIx64"\n", prefix,
|
||||
- desc64[0], desc64[1]);
|
||||
+ elf_access_unsigned(elf, desc, 0, 8),
|
||||
+ elf_access_unsigned(elf, desc, 8, 8));
|
||||
break;
|
||||
case 4:
|
||||
printf("%s: mask=%#"PRIx32" value=%#"PRIx32"\n", prefix,
|
||||
- desc32[0],desc32[1]);
|
||||
+ (uint32_t)elf_access_unsigned(elf, desc, 0, 4),
|
||||
+ (uint32_t)elf_access_unsigned(elf, desc, 4, 4));
|
||||
break;
|
||||
}
|
||||
|
||||
--
|
||||
1.7.2.5
|
||||
#From db14d5bd9b6508adfcd2b910f454fae12fa4ba00 Mon Sep 17 00:00:00 2001
|
||||
#From: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
#Date: Fri, 14 Jun 2013 16:43:17 +0100
|
||||
#Subject: [PATCH 10/23] libelf: check nul-terminated strings properly
|
||||
#
|
||||
#It is not safe to simply take pointers into the ELF and use them as C
|
||||
#pointers. They might not be properly nul-terminated (and the pointers
|
||||
#might be wild).
|
||||
#
|
||||
#So we are going to introduce a new function elf_strval for safely
|
||||
#getting strings. This will check that the addresses are in range and
|
||||
#that there is a proper nul-terminated string. Of course it might
|
||||
#discover that there isn't. In that case, it will be made to fail.
|
||||
#This means that elf_note_name might fail, too.
|
||||
#
|
||||
#For the benefit of call sites which are just going to pass the value
|
||||
#to a printf-like function, we provide elf_strfmt which returns
|
||||
#"(invalid)" on failure rather than NULL.
|
||||
#
|
||||
#In this patch we introduce dummy definitions of these functions. We
|
||||
#introduce calls to elf_strval and elf_strfmt everywhere, and update
|
||||
#all the call sites with appropriate error checking.
|
||||
#
|
||||
#There is not yet any semantic change, since before this patch all the
|
||||
#places where we introduce elf_strval dereferenced the value anyway, so
|
||||
#it mustn't have been NULL.
|
||||
#
|
||||
#In future patches, when elf_strval is made able return NULL, when it
|
||||
#does so it will mark the elf "broken" so that an appropriate
|
||||
#diagnostic can be printed.
|
||||
#
|
||||
#This is part of the fix to a security issue, XSA-55.
|
||||
#
|
||||
#Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
#Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
#Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
|
||||
#---
|
||||
# tools/xcutils/readnotes.c | 11 ++++++++---
|
||||
# xen/common/libelf/libelf-dominfo.c | 13 ++++++++++---
|
||||
# xen/common/libelf/libelf-tools.c | 10 +++++++---
|
||||
# xen/include/xen/libelf.h | 7 +++++--
|
||||
# 4 files changed, 30 insertions(+), 11 deletions(-)
|
||||
#
|
||||
diff --git a/tools/xcutils/readnotes.c b/tools/xcutils/readnotes.c
|
||||
index 7ff2530..cfae994 100644
|
||||
--- a/tools/xcutils/readnotes.c
|
||||
+++ b/tools/xcutils/readnotes.c
|
||||
@@ -63,7 +63,7 @@ struct setup_header {
|
||||
static void print_string_note(const char *prefix, struct elf_binary *elf,
|
||||
ELF_HANDLE_DECL(elf_note) note)
|
||||
{
|
||||
- printf("%s: %s\n", prefix, (char*)elf_note_desc(elf, note));
|
||||
+ printf("%s: %s\n", prefix, elf_strfmt(elf, elf_note_desc(elf, note)));
|
||||
}
|
||||
|
||||
static void print_numeric_note(const char *prefix, struct elf_binary *elf,
|
||||
@@ -103,10 +103,14 @@ static int print_notes(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) start,
|
||||
{
|
||||
ELF_HANDLE_DECL(elf_note) note;
|
||||
int notes_found = 0;
|
||||
+ const char *this_note_name;
|
||||
|
||||
for ( note = start; ELF_HANDLE_PTRVAL(note) < ELF_HANDLE_PTRVAL(end); note = elf_note_next(elf, note) )
|
||||
{
|
||||
- if (0 != strcmp(elf_note_name(elf, note), "Xen"))
|
||||
+ this_note_name = elf_note_name(elf, note);
|
||||
+ if (NULL == this_note_name)
|
||||
+ continue;
|
||||
+ if (0 != strcmp(this_note_name, "Xen"))
|
||||
continue;
|
||||
|
||||
notes_found++;
|
||||
@@ -294,7 +298,8 @@ int main(int argc, char **argv)
|
||||
|
||||
shdr = elf_shdr_by_name(&elf, "__xen_guest");
|
||||
if (ELF_HANDLE_VALID(shdr))
|
||||
- printf("__xen_guest: %s\n", (char*)elf_section_start(&elf, shdr));
|
||||
+ printf("__xen_guest: %s\n",
|
||||
+ elf_strfmt(&elf, elf_section_start(&elf, shdr)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
diff --git a/xen/common/libelf/libelf-dominfo.c b/xen/common/libelf/libelf-dominfo.c
|
||||
index 7140d59..b217f8f 100644
|
||||
--- a/xen/common/libelf/libelf-dominfo.c
|
||||
+++ b/xen/common/libelf/libelf-dominfo.c
|
||||
@@ -137,7 +137,10 @@ int elf_xen_parse_note(struct elf_binary *elf,
|
||||
|
||||
if ( note_desc[type].str )
|
||||
{
|
||||
- str = elf_note_desc(elf, note);
|
||||
+ str = elf_strval(elf, elf_note_desc(elf, note));
|
||||
+ if (str == NULL)
|
||||
+ /* elf_strval will mark elf broken if it fails so no need to log */
|
||||
+ return 0;
|
||||
elf_msg(elf, "%s: %s = \"%s\"\n", __FUNCTION__,
|
||||
note_desc[type].name, str);
|
||||
parms->elf_notes[type].type = XEN_ENT_STR;
|
||||
@@ -220,6 +223,7 @@ static int elf_xen_parse_notes(struct elf_binary *elf,
|
||||
{
|
||||
int xen_elfnotes = 0;
|
||||
ELF_HANDLE_DECL(elf_note) note;
|
||||
+ const char *note_name;
|
||||
|
||||
parms->elf_note_start = start;
|
||||
parms->elf_note_end = end;
|
||||
@@ -227,7 +231,10 @@ static int elf_xen_parse_notes(struct elf_binary *elf,
|
||||
ELF_HANDLE_PTRVAL(note) < parms->elf_note_end;
|
||||
note = elf_note_next(elf, note) )
|
||||
{
|
||||
- if ( strcmp(elf_note_name(elf, note), "Xen") )
|
||||
+ note_name = elf_note_name(elf, note);
|
||||
+ if ( note_name == NULL )
|
||||
+ continue;
|
||||
+ if ( strcmp(note_name, "Xen") )
|
||||
continue;
|
||||
if ( elf_xen_parse_note(elf, parms, note) )
|
||||
return -1;
|
||||
@@ -541,7 +548,7 @@ int elf_xen_parse(struct elf_binary *elf,
|
||||
parms->elf_note_start = ELF_INVALID_PTRVAL;
|
||||
parms->elf_note_end = ELF_INVALID_PTRVAL;
|
||||
elf_msg(elf, "%s: __xen_guest: \"%s\"\n", __FUNCTION__,
|
||||
- parms->guest_info);
|
||||
+ elf_strfmt(elf, parms->guest_info));
|
||||
elf_xen_parse_guest_info(elf, parms);
|
||||
break;
|
||||
}
|
||||
diff --git a/xen/common/libelf/libelf-tools.c b/xen/common/libelf/libelf-tools.c
|
||||
index f1fd886..3a0cde1 100644
|
||||
--- a/xen/common/libelf/libelf-tools.c
|
||||
+++ b/xen/common/libelf/libelf-tools.c
|
||||
@@ -119,7 +119,7 @@ const char *elf_section_name(struct elf_binary *elf,
|
||||
if ( ELF_PTRVAL_INVALID(elf->sec_strtab) )
|
||||
return "unknown";
|
||||
|
||||
- return elf->sec_strtab + elf_uval(elf, shdr, sh_name);
|
||||
+ return elf_strval(elf, elf->sec_strtab + elf_uval(elf, shdr, sh_name));
|
||||
}
|
||||
|
||||
ELF_PTRVAL_CONST_VOID elf_section_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr)
|
||||
@@ -151,6 +151,7 @@ ELF_HANDLE_DECL(elf_sym) elf_sym_by_name(struct elf_binary *elf, const char *sym
|
||||
ELF_PTRVAL_CONST_VOID end = elf_section_end(elf, elf->sym_tab);
|
||||
ELF_HANDLE_DECL(elf_sym) sym;
|
||||
uint64_t info, name;
|
||||
+ const char *sym_name;
|
||||
|
||||
for ( ; ptr < end; ptr += elf_size(elf, sym) )
|
||||
{
|
||||
@@ -159,7 +160,10 @@ ELF_HANDLE_DECL(elf_sym) elf_sym_by_name(struct elf_binary *elf, const char *sym
|
||||
name = elf_uval(elf, sym, st_name);
|
||||
if ( ELF32_ST_BIND(info) != STB_GLOBAL )
|
||||
continue;
|
||||
- if ( strcmp(elf->sym_strtab + name, symbol) )
|
||||
+ sym_name = elf_strval(elf, elf->sym_strtab + name);
|
||||
+ if ( sym_name == NULL ) /* out of range, oops */
|
||||
+ return ELF_INVALID_HANDLE(elf_sym);
|
||||
+ if ( strcmp(sym_name, symbol) )
|
||||
continue;
|
||||
return sym;
|
||||
}
|
||||
@@ -177,7 +181,7 @@ ELF_HANDLE_DECL(elf_sym) elf_sym_by_index(struct elf_binary *elf, int index)
|
||||
|
||||
const char *elf_note_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note)
|
||||
{
|
||||
- return ELF_HANDLE_PTRVAL(note) + elf_size(elf, note);
|
||||
+ return elf_strval(elf, ELF_HANDLE_PTRVAL(note) + elf_size(elf, note));
|
||||
}
|
||||
|
||||
ELF_PTRVAL_CONST_VOID elf_note_desc(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note)
|
||||
diff --git a/xen/include/xen/libelf.h b/xen/include/xen/libelf.h
|
||||
index cefd3d3..af5b5c5 100644
|
||||
--- a/xen/include/xen/libelf.h
|
||||
+++ b/xen/include/xen/libelf.h
|
||||
@@ -252,6 +252,9 @@ uint64_t elf_access_unsigned(struct elf_binary *elf, ELF_PTRVAL_CONST_VOID ptr,
|
||||
uint64_t elf_round_up(struct elf_binary *elf, uint64_t addr);
|
||||
|
||||
|
||||
+#define elf_strval(elf,x) ((const char*)(x)) /* may return NULL in the future */
|
||||
+#define elf_strfmt(elf,x) ((const char*)(x)) /* will return (invalid) instead */
|
||||
+
|
||||
#define elf_memcpy_safe(elf, dst, src, sz) memcpy((dst),(src),(sz))
|
||||
#define elf_memset_safe(elf, dst, c, sz) memset((dst),(c),(sz))
|
||||
/*
|
||||
@@ -279,7 +282,7 @@ ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_name(struct elf_binary *elf, const char *n
|
||||
ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_index(struct elf_binary *elf, int index);
|
||||
ELF_HANDLE_DECL(elf_phdr) elf_phdr_by_index(struct elf_binary *elf, int index);
|
||||
|
||||
-const char *elf_section_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr);
|
||||
+const char *elf_section_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr); /* might return NULL if inputs are invalid */
|
||||
ELF_PTRVAL_CONST_VOID elf_section_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr);
|
||||
ELF_PTRVAL_CONST_VOID elf_section_end(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr);
|
||||
|
||||
@@ -289,7 +292,7 @@ ELF_PTRVAL_CONST_VOID elf_segment_end(struct elf_binary *elf, ELF_HANDLE_DECL(el
|
||||
ELF_HANDLE_DECL(elf_sym) elf_sym_by_name(struct elf_binary *elf, const char *symbol);
|
||||
ELF_HANDLE_DECL(elf_sym) elf_sym_by_index(struct elf_binary *elf, int index);
|
||||
|
||||
-const char *elf_note_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
|
||||
+const char *elf_note_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note); /* may return NULL */
|
||||
ELF_PTRVAL_CONST_VOID elf_note_desc(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
|
||||
uint64_t elf_note_numeric(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
|
||||
uint64_t elf_note_numeric_array(struct elf_binary *, ELF_HANDLE_DECL(elf_note),
|
||||
--
|
||||
1.7.2.5
|
||||
|
@ -0,0 +1,334 @@
|
||||
libxl: Restrict permissions on PV console device xenstore nodes
|
||||
|
||||
Matthew Daley has observed that the PV console protocol places sensitive host
|
||||
state into a guest writeable xenstore locations, this includes:
|
||||
|
||||
- The pty used to communicate between the console backend daemon and its
|
||||
client, allowing the guest administrator to read and write arbitrary host
|
||||
files.
|
||||
- The output file, allowing the guest administrator to write arbitrary host
|
||||
files or to target arbitrary qemu chardevs which include sockets, udp, ptr,
|
||||
pipes etc (see -chardev in qemu(1) for a more complete list).
|
||||
- The maximum buffer size, allowing the guest administrator to consume more
|
||||
resources than the host administrator has configured.
|
||||
- The backend to use (qemu vs xenconsoled), potentially allowing the guest
|
||||
administrator to confuse host software.
|
||||
|
||||
So we arrange to make the sensitive keys in the xenstore frontend directory
|
||||
read only for the guest. This is safe since the xenstore permissions model,
|
||||
unlike POSIX directory permissions, does not allow the guest to remove and
|
||||
recreate a node if it has write access to the containing directory.
|
||||
|
||||
There are a few associated wrinkles:
|
||||
|
||||
- The primary PV console is "special". It's xenstore node is not under the
|
||||
usual /devices/ subtree and it does not use the customary xenstore state
|
||||
machine protocol. Unfortunately its directory is used for other things,
|
||||
including the vnc-port node, which we do not want the guest to be able to
|
||||
write to. Rather than trying to track down all the possible secondary uses
|
||||
of this directory just make it r/o to the guest. All newly created
|
||||
subdirectories inherit these permissions and so are now safe by default.
|
||||
|
||||
- The other serial consoles do use the customary xenstore state machine and
|
||||
therefore need write access to at least the "protocol" and "state" nodes,
|
||||
however they may also want to use arbitrary "feature-foo" nodes (although
|
||||
I'm not aware of any) and therefore we cannot simply lock down the entire
|
||||
frontend directory. Instead we add support to libxl__device_generic_add for
|
||||
frontend keys which are explicitly read only and use that to lock down the
|
||||
sensitive keys.
|
||||
|
||||
- Minios' console frontend wants to write the "type" node, which it has no
|
||||
business doing since this is a host/toolstack level decision. This fails
|
||||
now that the node has become read only to the PV guest. Since the toolstack
|
||||
already writes this node just remove the attempt to set it.
|
||||
|
||||
This is CVE-XXXX-XXX / XSA-57
|
||||
|
||||
Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
|
||||
Conflicts:
|
||||
tools/libxl/libxl.c (no vtpm, free front_ro on error in
|
||||
libxl__device_console_add)
|
||||
|
||||
diff --git a/extras/mini-os/console/xenbus.c b/extras/mini-os/console/xenbus.c
|
||||
index 77de82a..e65baf7 100644
|
||||
--- a/extras/mini-os/console/xenbus.c
|
||||
+++ b/extras/mini-os/console/xenbus.c
|
||||
@@ -122,12 +122,6 @@ again:
|
||||
goto abort_transaction;
|
||||
}
|
||||
|
||||
- err = xenbus_printf(xbt, nodename, "type", "%s", "ioemu");
|
||||
- if (err) {
|
||||
- message = "writing type";
|
||||
- goto abort_transaction;
|
||||
- }
|
||||
-
|
||||
snprintf(path, sizeof(path), "%s/state", nodename);
|
||||
err = xenbus_switch_state(xbt, path, XenbusStateConnected);
|
||||
if (err) {
|
||||
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
|
||||
index a6e9601..32d788a 100644
|
||||
--- a/tools/libxl/libxl.c
|
||||
+++ b/tools/libxl/libxl.c
|
||||
@@ -1920,8 +1920,9 @@ static void device_disk_add(libxl__egc *egc, uint32_t domid,
|
||||
flexarray_append(front, disk->is_cdrom ? "cdrom" : "disk");
|
||||
|
||||
libxl__device_generic_add(gc, t, device,
|
||||
- libxl__xs_kvs_of_flexarray(gc, back, back->count),
|
||||
- libxl__xs_kvs_of_flexarray(gc, front, front->count));
|
||||
+ libxl__xs_kvs_of_flexarray(gc, back, back->count),
|
||||
+ libxl__xs_kvs_of_flexarray(gc, front, front->count),
|
||||
+ NULL);
|
||||
|
||||
rc = libxl__xs_transaction_commit(gc, &t);
|
||||
if (!rc) break;
|
||||
@@ -2633,8 +2634,9 @@ void libxl__device_nic_add(libxl__egc *egc, uint32_t domid,
|
||||
flexarray_append(front, libxl__sprintf(gc,
|
||||
LIBXL_MAC_FMT, LIBXL_MAC_BYTES(nic->mac)));
|
||||
libxl__device_generic_add(gc, XBT_NULL, device,
|
||||
- libxl__xs_kvs_of_flexarray(gc, back, back->count),
|
||||
- libxl__xs_kvs_of_flexarray(gc, front, front->count));
|
||||
+ libxl__xs_kvs_of_flexarray(gc, back, back->count),
|
||||
+ libxl__xs_kvs_of_flexarray(gc, front, front->count),
|
||||
+ NULL);
|
||||
|
||||
aodev->dev = device;
|
||||
aodev->action = DEVICE_CONNECT;
|
||||
@@ -2830,7 +2832,7 @@ int libxl__device_console_add(libxl__gc *gc, uint32_t domid,
|
||||
libxl__device_console *console,
|
||||
libxl__domain_build_state *state)
|
||||
{
|
||||
- flexarray_t *front;
|
||||
+ flexarray_t *front, *ro_front;
|
||||
flexarray_t *back;
|
||||
libxl__device device;
|
||||
int rc;
|
||||
@@ -2845,6 +2847,11 @@ int libxl__device_console_add(libxl__gc *gc, uint32_t domid,
|
||||
rc = ERROR_NOMEM;
|
||||
goto out;
|
||||
}
|
||||
+ ro_front = flexarray_make(16, 1);
|
||||
+ if (!ro_front) {
|
||||
+ rc = ERROR_NOMEM;
|
||||
+ goto out;
|
||||
+ }
|
||||
back = flexarray_make(16, 1);
|
||||
if (!back) {
|
||||
rc = ERROR_NOMEM;
|
||||
@@ -2871,21 +2878,24 @@ int libxl__device_console_add(libxl__gc *gc, uint32_t domid,
|
||||
|
||||
flexarray_append(front, "backend-id");
|
||||
flexarray_append(front, libxl__sprintf(gc, "%d", console->backend_domid));
|
||||
- flexarray_append(front, "limit");
|
||||
- flexarray_append(front, libxl__sprintf(gc, "%d", LIBXL_XENCONSOLE_LIMIT));
|
||||
- flexarray_append(front, "type");
|
||||
+
|
||||
+ flexarray_append(ro_front, "limit");
|
||||
+ flexarray_append(ro_front, libxl__sprintf(gc, "%d", LIBXL_XENCONSOLE_LIMIT));
|
||||
+ flexarray_append(ro_front, "type");
|
||||
if (console->consback == LIBXL__CONSOLE_BACKEND_XENCONSOLED)
|
||||
- flexarray_append(front, "xenconsoled");
|
||||
+ flexarray_append(ro_front, "xenconsoled");
|
||||
else
|
||||
- flexarray_append(front, "ioemu");
|
||||
- flexarray_append(front, "output");
|
||||
- flexarray_append(front, console->output);
|
||||
+ flexarray_append(ro_front, "ioemu");
|
||||
+ flexarray_append(ro_front, "output");
|
||||
+ flexarray_append(ro_front, console->output);
|
||||
+ flexarray_append(ro_front, "tty");
|
||||
+ flexarray_append(ro_front, "");
|
||||
|
||||
if (state) {
|
||||
- flexarray_append(front, "port");
|
||||
- flexarray_append(front, libxl__sprintf(gc, "%"PRIu32, state->console_port));
|
||||
- flexarray_append(front, "ring-ref");
|
||||
- flexarray_append(front, libxl__sprintf(gc, "%lu", state->console_mfn));
|
||||
+ flexarray_append(ro_front, "port");
|
||||
+ flexarray_append(ro_front, libxl__sprintf(gc, "%"PRIu32, state->console_port));
|
||||
+ flexarray_append(ro_front, "ring-ref");
|
||||
+ flexarray_append(ro_front, libxl__sprintf(gc, "%lu", state->console_mfn));
|
||||
} else {
|
||||
flexarray_append(front, "state");
|
||||
flexarray_append(front, libxl__sprintf(gc, "%d", 1));
|
||||
@@ -2894,11 +2904,13 @@ int libxl__device_console_add(libxl__gc *gc, uint32_t domid,
|
||||
}
|
||||
|
||||
libxl__device_generic_add(gc, XBT_NULL, &device,
|
||||
- libxl__xs_kvs_of_flexarray(gc, back, back->count),
|
||||
- libxl__xs_kvs_of_flexarray(gc, front, front->count));
|
||||
+ libxl__xs_kvs_of_flexarray(gc, back, back->count),
|
||||
+ libxl__xs_kvs_of_flexarray(gc, front, front->count),
|
||||
+ libxl__xs_kvs_of_flexarray(gc, ro_front, ro_front->count));
|
||||
rc = 0;
|
||||
out_free:
|
||||
flexarray_free(back);
|
||||
+ flexarray_free(ro_front);
|
||||
flexarray_free(front);
|
||||
out:
|
||||
return rc;
|
||||
@@ -2982,8 +2994,9 @@ int libxl__device_vkb_add(libxl__gc *gc, uint32_t domid,
|
||||
flexarray_append(front, libxl__sprintf(gc, "%d", 1));
|
||||
|
||||
libxl__device_generic_add(gc, XBT_NULL, &device,
|
||||
- libxl__xs_kvs_of_flexarray(gc, back, back->count),
|
||||
- libxl__xs_kvs_of_flexarray(gc, front, front->count));
|
||||
+ libxl__xs_kvs_of_flexarray(gc, back, back->count),
|
||||
+ libxl__xs_kvs_of_flexarray(gc, front, front->count),
|
||||
+ NULL);
|
||||
rc = 0;
|
||||
out_free:
|
||||
flexarray_free(back);
|
||||
@@ -3096,8 +3109,9 @@ int libxl__device_vfb_add(libxl__gc *gc, uint32_t domid, libxl_device_vfb *vfb)
|
||||
flexarray_append_pair(front, "state", libxl__sprintf(gc, "%d", 1));
|
||||
|
||||
libxl__device_generic_add(gc, XBT_NULL, &device,
|
||||
- libxl__xs_kvs_of_flexarray(gc, back, back->count),
|
||||
- libxl__xs_kvs_of_flexarray(gc, front, front->count));
|
||||
+ libxl__xs_kvs_of_flexarray(gc, back, back->count),
|
||||
+ libxl__xs_kvs_of_flexarray(gc, front, front->count),
|
||||
+ NULL);
|
||||
rc = 0;
|
||||
out_free:
|
||||
flexarray_free(front);
|
||||
diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
|
||||
index c3283f1..1c04a21 100644
|
||||
--- a/tools/libxl/libxl_device.c
|
||||
+++ b/tools/libxl/libxl_device.c
|
||||
@@ -84,11 +84,12 @@ out:
|
||||
}
|
||||
|
||||
int libxl__device_generic_add(libxl__gc *gc, xs_transaction_t t,
|
||||
- libxl__device *device, char **bents, char **fents)
|
||||
+ libxl__device *device, char **bents, char **fents, char **ro_fents)
|
||||
{
|
||||
libxl_ctx *ctx = libxl__gc_owner(gc);
|
||||
char *frontend_path, *backend_path;
|
||||
struct xs_permissions frontend_perms[2];
|
||||
+ struct xs_permissions ro_frontend_perms[2];
|
||||
struct xs_permissions backend_perms[2];
|
||||
int create_transaction = t == XBT_NULL;
|
||||
|
||||
@@ -100,22 +101,37 @@ int libxl__device_generic_add(libxl__gc *gc, xs_transaction_t t,
|
||||
frontend_perms[1].id = device->backend_domid;
|
||||
frontend_perms[1].perms = XS_PERM_READ;
|
||||
|
||||
- backend_perms[0].id = device->backend_domid;
|
||||
- backend_perms[0].perms = XS_PERM_NONE;
|
||||
- backend_perms[1].id = device->domid;
|
||||
- backend_perms[1].perms = XS_PERM_READ;
|
||||
+ ro_frontend_perms[0].id = backend_perms[0].id = device->backend_domid;
|
||||
+ ro_frontend_perms[0].perms = backend_perms[0].perms = XS_PERM_NONE;
|
||||
+ ro_frontend_perms[1].id = backend_perms[1].id = device->domid;
|
||||
+ ro_frontend_perms[1].perms = backend_perms[1].perms = XS_PERM_READ;
|
||||
|
||||
retry_transaction:
|
||||
if (create_transaction)
|
||||
t = xs_transaction_start(ctx->xsh);
|
||||
/* FIXME: read frontend_path and check state before removing stuff */
|
||||
|
||||
- if (fents) {
|
||||
+ if (fents || ro_fents) {
|
||||
xs_rm(ctx->xsh, t, frontend_path);
|
||||
xs_mkdir(ctx->xsh, t, frontend_path);
|
||||
- xs_set_permissions(ctx->xsh, t, frontend_path, frontend_perms, ARRAY_SIZE(frontend_perms));
|
||||
+ /* Console 0 is a special case. It doesn't use the regular PV
|
||||
+ * state machine but also the frontend directory has
|
||||
+ * historically contained other information, such as the
|
||||
+ * vnc-port, which we don't want the guest fiddling with.
|
||||
+ */
|
||||
+ if (device->kind == LIBXL__DEVICE_KIND_CONSOLE && device->devid == 0)
|
||||
+ xs_set_permissions(ctx->xsh, t, frontend_path,
|
||||
+ ro_frontend_perms, ARRAY_SIZE(ro_frontend_perms));
|
||||
+ else
|
||||
+ xs_set_permissions(ctx->xsh, t, frontend_path,
|
||||
+ frontend_perms, ARRAY_SIZE(frontend_perms));
|
||||
xs_write(ctx->xsh, t, libxl__sprintf(gc, "%s/backend", frontend_path), backend_path, strlen(backend_path));
|
||||
- libxl__xs_writev(gc, t, frontend_path, fents);
|
||||
+ if (fents)
|
||||
+ libxl__xs_writev_perms(gc, t, frontend_path, fents,
|
||||
+ frontend_perms, ARRAY_SIZE(frontend_perms));
|
||||
+ if (ro_fents)
|
||||
+ libxl__xs_writev_perms(gc, t, frontend_path, ro_fents,
|
||||
+ ro_frontend_perms, ARRAY_SIZE(ro_frontend_perms));
|
||||
}
|
||||
|
||||
if (bents) {
|
||||
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
|
||||
index 13fa509..ae96a74 100644
|
||||
--- a/tools/libxl/libxl_internal.h
|
||||
+++ b/tools/libxl/libxl_internal.h
|
||||
@@ -516,6 +516,11 @@ _hidden char **libxl__xs_kvs_of_flexarray(libxl__gc *gc, flexarray_t *array, int
|
||||
/* treats kvs as pairs of keys and values and writes each to dir. */
|
||||
_hidden int libxl__xs_writev(libxl__gc *gc, xs_transaction_t t,
|
||||
const char *dir, char **kvs);
|
||||
+/* as writev but also sets the permissions on each path */
|
||||
+_hidden int libxl__xs_writev_perms(libxl__gc *gc, xs_transaction_t t,
|
||||
+ const char *dir, char *kvs[],
|
||||
+ struct xs_permissions *perms,
|
||||
+ unsigned int num_perms);
|
||||
/* _atonce creates a transaction and writes all keys at once */
|
||||
_hidden int libxl__xs_writev_atonce(libxl__gc *gc,
|
||||
const char *dir, char **kvs);
|
||||
@@ -930,7 +935,7 @@ _hidden int libxl__device_console_add(libxl__gc *gc, uint32_t domid,
|
||||
libxl__domain_build_state *state);
|
||||
|
||||
_hidden int libxl__device_generic_add(libxl__gc *gc, xs_transaction_t t,
|
||||
- libxl__device *device, char **bents, char **fents);
|
||||
+ libxl__device *device, char **bents, char **fents, char **ro_fents);
|
||||
_hidden char *libxl__device_backend_path(libxl__gc *gc, libxl__device *device);
|
||||
_hidden char *libxl__device_frontend_path(libxl__gc *gc, libxl__device *device);
|
||||
_hidden int libxl__parse_backend_path(libxl__gc *gc, const char *path,
|
||||
diff --git a/tools/libxl/libxl_pci.c b/tools/libxl/libxl_pci.c
|
||||
index 48986f3..d373b4d 100644
|
||||
--- a/tools/libxl/libxl_pci.c
|
||||
+++ b/tools/libxl/libxl_pci.c
|
||||
@@ -106,7 +106,8 @@ int libxl__create_pci_backend(libxl__gc *gc, uint32_t domid,
|
||||
|
||||
libxl__device_generic_add(gc, XBT_NULL, &device,
|
||||
libxl__xs_kvs_of_flexarray(gc, back, back->count),
|
||||
- libxl__xs_kvs_of_flexarray(gc, front, front->count));
|
||||
+ libxl__xs_kvs_of_flexarray(gc, front, front->count),
|
||||
+ NULL);
|
||||
|
||||
out:
|
||||
if (back)
|
||||
diff --git a/tools/libxl/libxl_xshelp.c b/tools/libxl/libxl_xshelp.c
|
||||
index 52af484..d7eaa66 100644
|
||||
--- a/tools/libxl/libxl_xshelp.c
|
||||
+++ b/tools/libxl/libxl_xshelp.c
|
||||
@@ -41,8 +41,10 @@ char **libxl__xs_kvs_of_flexarray(libxl__gc *gc, flexarray_t *array, int length)
|
||||
return kvs;
|
||||
}
|
||||
|
||||
-int libxl__xs_writev(libxl__gc *gc, xs_transaction_t t,
|
||||
- const char *dir, char *kvs[])
|
||||
+int libxl__xs_writev_perms(libxl__gc *gc, xs_transaction_t t,
|
||||
+ const char *dir, char *kvs[],
|
||||
+ struct xs_permissions *perms,
|
||||
+ unsigned int num_perms)
|
||||
{
|
||||
libxl_ctx *ctx = libxl__gc_owner(gc);
|
||||
char *path;
|
||||
@@ -56,11 +58,19 @@ int libxl__xs_writev(libxl__gc *gc, xs_transaction_t t,
|
||||
if (path && kvs[i + 1]) {
|
||||
int length = strlen(kvs[i + 1]);
|
||||
xs_write(ctx->xsh, t, path, kvs[i + 1], length);
|
||||
+ if (perms)
|
||||
+ xs_set_permissions(ctx->xsh, t, path, perms, num_perms);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
+int libxl__xs_writev(libxl__gc *gc, xs_transaction_t t,
|
||||
+ const char *dir, char *kvs[])
|
||||
+{
|
||||
+ return libxl__xs_writev_perms(gc, t, dir, kvs, NULL, 0);
|
||||
+}
|
||||
+
|
||||
int libxl__xs_writev_atonce(libxl__gc *gc,
|
||||
const char *dir, char *kvs[])
|
||||
{
|
||||
|
@ -1,26 +0,0 @@
|
||||
Index: xen-3.3.0/tools/ioemu-qemu-xen/Makefile
|
||||
===================================================================
|
||||
--- xen-3.3.0.orig/tools/ioemu-qemu-xen/Makefile
|
||||
+++ xen-3.3.0/tools/ioemu-qemu-xen/Makefile
|
||||
@@ -205,7 +205,7 @@ endif
|
||||
install: all $(if $(BUILD_DOCS),install-doc)
|
||||
mkdir -p "$(DESTDIR)$(bindir)"
|
||||
ifneq ($(TOOLS),)
|
||||
- $(INSTALL) -m 755 -s $(TOOLS) "$(DESTDIR)$(bindir)"
|
||||
+ $(INSTALL) -m 755 $(TOOLS) "$(DESTDIR)$(bindir)"
|
||||
endif
|
||||
mkdir -p "$(DESTDIR)$(datadir)"
|
||||
set -e; for x in bios.bin vgabios.bin vgabios-cirrus.bin ppc_rom.bin \
|
||||
Index: xen-3.3.0/tools/ioemu-qemu-xen/Makefile.target
|
||||
===================================================================
|
||||
--- xen-3.3.0.orig/tools/ioemu-qemu-xen/Makefile.target
|
||||
+++ xen-3.3.0/tools/ioemu-qemu-xen/Makefile.target
|
||||
@@ -707,7 +707,7 @@ clean:
|
||||
|
||||
install: all install-hook
|
||||
ifneq ($(PROGS),)
|
||||
- $(INSTALL) -m 755 -s $(PROGS) "$(DESTDIR)$(bindir)"
|
||||
+ $(INSTALL) -m 755 $(PROGS) "$(DESTDIR)$(bindir)"
|
||||
endif
|
||||
|
||||
# Include automatically generated dependency files
|
@ -1,15 +0,0 @@
|
||||
2011-10-22 Ralf Glauberman <ralfglauberman@gmx.de>
|
||||
|
||||
#360805 Don't compile ipxe with pie on hardened.
|
||||
* /tools/firmware/etherboot/patches/ipxe-nopie.patche New patch
|
||||
Reconstituted patch; Tue Jan 29 14:35:13 WST 2013
|
||||
|
||||
diff -ur xen-4.2.0.orig/tools/firmware/etherboot/patches/series xen-4.2.0/tools/firmware/etherboot/patches/series
|
||||
--- tools/firmware/etherboot/patches/series 2013-01-29 14:34:10.773520921 +0800
|
||||
+++ tools/firmware/etherboot/patches/series 2013-01-29 14:33:31.781519209 +0800
|
||||
@@ -2,3 +2,4 @@
|
||||
build_fix_1.patch
|
||||
build_fix_2.patch
|
||||
build_fix_3.patch
|
||||
+ipxe-nopie.patch
|
||||
|
@ -1,10 +0,0 @@
|
||||
diff -ur xen-4.1.1.orig//tools/check/check_curl xen-4.1.1/tools/check/check_curl
|
||||
--- xen-4.1.1.orig//tools/check/check_curl 2011-06-15 00:03:44.000000000 +0800
|
||||
+++ xen-4.1.1/tools/check/check_curl 2011-10-14 00:42:08.189717078 +0800
|
||||
@@ -9,5 +9,6 @@
|
||||
fi
|
||||
|
||||
has_or_fail curl-config
|
||||
curl_libs=`curl-config --libs` || fail "curl-config --libs failed"
|
||||
+curl_libs=`echo $curl_libs | sed -re 's/-(W|march|mtune|pipe)[^[:space:]]*[[:space:]]//g'` || fail "curl-config --libs failed"
|
||||
test_link $curl_libs || fail "dependency libraries for curl are missing"
|
@ -1,37 +0,0 @@
|
||||
Index: xen-tools-4.1.1/tools/libxl/libxl_dm.c
|
||||
===================================================================
|
||||
--- xen-4.1.1.orig/tools/libxl/libxl_dm.c Tue Mar 15 10:14:27 2011 +0000
|
||||
+++ xen-4.1.1/tools/libxl/libxl_dm.c Tue Mar 15 18:19:47 2011 +0000
|
||||
@@ -828,8 +828,29 @@
|
||||
goto out;
|
||||
}
|
||||
|
||||
- if (nr_disks > 0 && !libxl__blktap_enabled(&gc))
|
||||
- ret = 1;
|
||||
+ if (nr_disks > 0) {
|
||||
+ int blktap_enabled = -1;
|
||||
+ for (i = 0; i < nr_disks; i++) {
|
||||
+ switch (disks[i].backend) {
|
||||
+ case DISK_BACKEND_TAP:
|
||||
+ if (blktap_enabled == -1)
|
||||
+ blktap_enabled = libxl__blktap_enabled(&gc);
|
||||
+ if (!blktap_enabled) {
|
||||
+ ret = 1;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ break;
|
||||
+
|
||||
+ case DISK_BACKEND_QDISK:
|
||||
+ ret = 1;
|
||||
+ goto out;
|
||||
+
|
||||
+ case DISK_BACKEND_PHY:
|
||||
+ case DISK_BACKEND_UNKNOWN:
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
|
||||
out:
|
||||
libxl__free_all(&gc);
|
||||
|
@ -1,12 +0,0 @@
|
||||
--- tools/python/xen/xm/create.py
|
||||
+++ tools/python/xen/xm/create.py
|
||||
@@ -1538,6 +1538,9 @@
|
||||
SXPPrettyPrint.prettyprint(config)
|
||||
|
||||
if opts.vals.xmldryrun and serverType == SERVER_XEN_API:
|
||||
+ import xml
|
||||
+ if hasattr(xml, "use_pyxml"):
|
||||
+ xml.use_pyxml()
|
||||
from xml.dom.ext import PrettyPrint as XMLPrettyPrint
|
||||
XMLPrettyPrint(doc)
|
||||
|
@ -1,345 +0,0 @@
|
||||
# Copyright 1999-2013 Gentoo Foundation
|
||||
# Distributed under the terms of the GNU General Public License v2
|
||||
# $Header: /var/cvsroot/gentoo-x86/app-emulation/xen-tools/xen-tools-4.2.0-r3.ebuild,v 1.10 2013/03/05 18:05:35 idella4 Exp $
|
||||
|
||||
EAPI=5
|
||||
|
||||
PYTHON_COMPAT=( python{2_6,2_7} )
|
||||
PYTHON_REQ_USE='xml,threads'
|
||||
|
||||
IPXE_TARBALL_URL="http://dev.gentoo.org/~idella4/tarballs/ipxe.tar.gz"
|
||||
XEN_SEABIOS_URL="http://dev.gentoo.org/~idella4/tarballs/seabios-0-20121121.tar.bz2"
|
||||
|
||||
if [[ $PV == *9999 ]]; then
|
||||
KEYWORDS=""
|
||||
REPO="xen-unstable.hg"
|
||||
EHG_REPO_URI="http://xenbits.xensource.com/${REPO}"
|
||||
S="${WORKDIR}/${REPO}"
|
||||
live_eclass="mercurial"
|
||||
else
|
||||
KEYWORDS="amd64 x86"
|
||||
SRC_URI="http://bits.xensource.com/oss-xen/release/${PV}/xen-${PV}.tar.gz
|
||||
$IPXE_TARBALL_URL
|
||||
$XEN_SEABIOS_URL"
|
||||
S="${WORKDIR}/xen-${PV}"
|
||||
fi
|
||||
|
||||
inherit flag-o-matic eutils multilib python-single-r1 toolchain-funcs udev ${live_eclass}
|
||||
|
||||
DESCRIPTION="Xend daemon and tools"
|
||||
HOMEPAGE="http://xen.org/"
|
||||
DOCS=( README docs/README.xen-bugtool )
|
||||
|
||||
LICENSE="GPL-2"
|
||||
SLOT="0"
|
||||
# TODO soon; ocaml up for a potential name change
|
||||
IUSE="api custom-cflags debug doc flask hvm ocaml qemu pygrub screen static-libs xend"
|
||||
|
||||
REQUIRED_USE="hvm? ( qemu )"
|
||||
|
||||
CDEPEND="dev-libs/yajl
|
||||
dev-python/lxml[${PYTHON_USEDEP}]
|
||||
dev-python/pypam[${PYTHON_USEDEP}]
|
||||
sys-libs/zlib
|
||||
sys-power/iasl
|
||||
ocaml? ( dev-ml/findlib )
|
||||
hvm? ( media-libs/libsdl )
|
||||
${PYTHON_DEPS}
|
||||
api? ( dev-libs/libxml2
|
||||
net-misc/curl )
|
||||
${PYTHON_DEPS}
|
||||
pygrub? ( ${PYTHON_DEPS//${PYTHON_REQ_USE}/ncurses} )"
|
||||
DEPEND="${CDEPEND}
|
||||
sys-devel/bin86
|
||||
sys-devel/dev86
|
||||
dev-lang/perl
|
||||
app-misc/pax-utils
|
||||
doc? (
|
||||
app-doc/doxygen
|
||||
dev-tex/latex2html[png,gif]
|
||||
media-gfx/transfig
|
||||
media-gfx/graphviz
|
||||
dev-tex/xcolor
|
||||
dev-texlive/texlive-latexextra
|
||||
virtual/latex-base
|
||||
dev-tex/latexmk
|
||||
dev-texlive/texlive-latex
|
||||
dev-texlive/texlive-pictures
|
||||
dev-texlive/texlive-latexrecommended
|
||||
)
|
||||
hvm? ( x11-proto/xproto
|
||||
)"
|
||||
RDEPEND="${CDEPEND}
|
||||
sys-apps/iproute2
|
||||
net-misc/bridge-utils
|
||||
ocaml? ( >=dev-lang/ocaml-3.12.0 )
|
||||
screen? (
|
||||
app-misc/screen
|
||||
app-admin/logrotate
|
||||
)
|
||||
virtual/udev"
|
||||
|
||||
# hvmloader is used to bootstrap a fully virtualized kernel
|
||||
# Approved by QA team in bug #144032
|
||||
QA_WX_LOAD="usr/lib/xen/boot/hvmloader"
|
||||
|
||||
RESTRICT="test"
|
||||
|
||||
pkg_setup() {
|
||||
python-single-r1_pkg_setup
|
||||
export "CONFIG_LOMOUNT=y"
|
||||
|
||||
if has_version dev-libs/libgcrypt; then
|
||||
export "CONFIG_GCRYPT=y"
|
||||
fi
|
||||
|
||||
if use qemu; then
|
||||
export "CONFIG_IOEMU=y"
|
||||
else
|
||||
export "CONFIG_IOEMU=n"
|
||||
fi
|
||||
|
||||
if ! use x86 && ! has x86 $(get_all_abis) && use hvm; then
|
||||
eerror "HVM (VT-x and AMD-v) cannot be built on this system. An x86 or"
|
||||
eerror "an amd64 multilib profile is required. Remove the hvm use flag"
|
||||
eerror "to build xen-tools on your current profile."
|
||||
die "USE=hvm is unsupported on this system."
|
||||
fi
|
||||
|
||||
if [[ -z ${XEN_TARGET_ARCH} ]] ; then
|
||||
if use x86 && use amd64; then
|
||||
die "Confusion! Both x86 and amd64 are set in your use flags!"
|
||||
elif use x86; then
|
||||
export XEN_TARGET_ARCH="x86_32"
|
||||
elif use amd64 ; then
|
||||
export XEN_TARGET_ARCH="x86_64"
|
||||
else
|
||||
die "Unsupported architecture!"
|
||||
fi
|
||||
fi
|
||||
|
||||
use api && export "LIBXENAPI_BINDINGS=y"
|
||||
use flask && export "FLASK_ENABLE=y"
|
||||
}
|
||||
|
||||
src_prepare() {
|
||||
# Drop .config, fixes to gcc-4.6
|
||||
epatch "${FILESDIR}"/${PN/-tools/}-4-fix_dotconfig-gcc.patch
|
||||
|
||||
# Xend
|
||||
if ! use xend; then
|
||||
sed -e 's:xm xen-bugtool xen-python-path xend:xen-bugtool xen-python-path:' \
|
||||
-i tools/misc/Makefile || die "Disabling xend failed"
|
||||
sed -e 's:^XEND_INITD:#XEND_INITD:' \
|
||||
-i tools/examples/Makefile || die "Disabling xend failed"
|
||||
fi
|
||||
|
||||
# if the user *really* wants to use their own custom-cflags, let them
|
||||
if use custom-cflags; then
|
||||
einfo "User wants their own CFLAGS - removing defaults"
|
||||
|
||||
# try and remove all the default cflags
|
||||
find "${S}" \( -name Makefile -o -name Rules.mk -o -name Config.mk \) \
|
||||
-exec sed \
|
||||
-e 's/CFLAGS\(.*\)=\(.*\)-O3\(.*\)/CFLAGS\1=\2\3/' \
|
||||
-e 's/CFLAGS\(.*\)=\(.*\)-march=i686\(.*\)/CFLAGS\1=\2\3/' \
|
||||
-e 's/CFLAGS\(.*\)=\(.*\)-fomit-frame-pointer\(.*\)/CFLAGS\1=\2\3/' \
|
||||
-e 's/CFLAGS\(.*\)=\(.*\)-g3*\s\(.*\)/CFLAGS\1=\2 \3/' \
|
||||
-e 's/CFLAGS\(.*\)=\(.*\)-O2\(.*\)/CFLAGS\1=\2\3/' \
|
||||
-i {} + || die "failed to re-set custom-cflags"
|
||||
fi
|
||||
|
||||
if ! use pygrub; then
|
||||
sed -e '/^SUBDIRS-$(PYTHON_TOOLS) += pygrub$/d' -i tools/Makefile || die
|
||||
fi
|
||||
|
||||
# Disable hvm support on systems that don't support x86_32 binaries.
|
||||
if ! use hvm; then
|
||||
sed -e '/^CONFIG_IOEMU := y$/d' -i config/*.mk || die
|
||||
sed -e '/SUBDIRS-$(CONFIG_X86) += firmware/d' -i tools/Makefile || die
|
||||
fi
|
||||
|
||||
# Don't bother with qemu, only needed for fully virtualised guests
|
||||
if ! use qemu; then
|
||||
sed -e "/^CONFIG_IOEMU := y$/d" -i config/*.mk || die
|
||||
sed -e "s:install-tools\: tools/ioemu-dir:install-tools\: :g" -i Makefile || die
|
||||
fi
|
||||
|
||||
# Fix texi2html build error with new texi2html
|
||||
epatch "${FILESDIR}"/${PN}-4-docfix.patch
|
||||
|
||||
# Fix network broadcast on bridged networks
|
||||
epatch "${FILESDIR}/${PN}-3.4.0-network-bridge-broadcast.patch"
|
||||
|
||||
# Prevent the downloading of ipxe, seabios
|
||||
epatch "${FILESDIR}"/${P/-tools/}-anti-download.patch
|
||||
cp "${DISTDIR}"/ipxe.tar.gz tools/firmware/etherboot/ || die
|
||||
mv ../seabios-dir-remote tools/firmware/ || die
|
||||
pushd tools/firmware/ > /dev/null
|
||||
ln -s seabios-dir-remote seabios-dir || die
|
||||
popd > /dev/null
|
||||
|
||||
# Fix bridge by idella4, bug #362575
|
||||
epatch "${FILESDIR}/${PN}-4.1.1-bridge.patch"
|
||||
|
||||
# Don't build ipxe with pie on hardened, Bug #360805
|
||||
if gcc-specs-pie; then
|
||||
epatch "${FILESDIR}"/ipxe-nopie.patch
|
||||
fi
|
||||
|
||||
# Prevent double stripping of files at install
|
||||
epatch "${FILESDIR}"/${P/-tools/}-nostrip.patch
|
||||
|
||||
# fix jobserver in Makefile
|
||||
epatch "${FILESDIR}"/${P/-tools/}-jserver.patch
|
||||
|
||||
#Sec patches
|
||||
epatch "${FILESDIR}"/xen-4-CVE-2012-4544-XSA-25.patch \
|
||||
"${FILESDIR}"/xen-4-CVE-2012-6075-XSA-41.patch
|
||||
}
|
||||
|
||||
src_compile() {
|
||||
export VARTEXFONTS="${T}/fonts"
|
||||
local myopt
|
||||
use debug && myopt="${myopt} debug=y"
|
||||
|
||||
use custom-cflags || unset CFLAGS
|
||||
if test-flag-CC -fno-strict-overflow; then
|
||||
append-flags -fno-strict-overflow
|
||||
fi
|
||||
|
||||
unset LDFLAGS
|
||||
unset CFLAGS
|
||||
emake CC="$(tc-getCC)" LD="$(tc-getLD)" -C tools ${myopt}
|
||||
|
||||
use doc && emake -C docs txt html
|
||||
emake -C docs man-pages
|
||||
}
|
||||
|
||||
src_install() {
|
||||
# Override auto-detection in the build system, bug #382573
|
||||
export INITD_DIR=/tmp/init.d
|
||||
export CONFIG_LEAF_DIR=../tmp/default
|
||||
|
||||
# Let the build system compile installed Python modules.
|
||||
local PYTHONDONTWRITEBYTECODE
|
||||
export PYTHONDONTWRITEBYTECODE
|
||||
|
||||
emake DESTDIR="${D}" DOCDIR="/usr/share/doc/${PF}" \
|
||||
install-tools
|
||||
|
||||
# Fix the remaining Python shebangs.
|
||||
python_fix_shebang "${D}"
|
||||
|
||||
# Remove RedHat-specific stuff
|
||||
rm -rf "${D}"tmp || die
|
||||
|
||||
# uncomment lines in xl.conf
|
||||
sed -e 's:^#autoballoon=1:autoballoon=1:' \
|
||||
-e 's:^#lockfile="/var/lock/xl":lockfile="/var/lock/xl":' \
|
||||
-e 's:^#vifscript="vif-bridge":vifscript="vif-bridge":' \
|
||||
-i tools/examples/xl.conf || die
|
||||
|
||||
if use doc; then
|
||||
emake DESTDIR="${D}" DOCDIR="/usr/share/doc/${PF}" install-docs
|
||||
|
||||
dohtml -r docs/html/
|
||||
docinto pdf
|
||||
dodoc ${DOCS[@]}
|
||||
[ -d "${D}"/usr/share/doc/xen ] && mv "${ED}"/usr/share/doc/xen/* "${ED}"/usr/share/doc/${PF}/html
|
||||
fi
|
||||
|
||||
rm -rf "${D}"/usr/share/doc/xen/
|
||||
doman docs/man?/*
|
||||
|
||||
if use xend; then
|
||||
newinitd "${FILESDIR}"/xend.initd-r2 xend || die "Couldn't install xen.initd"
|
||||
fi
|
||||
newconfd "${FILESDIR}"/xendomains.confd xendomains
|
||||
newconfd "${FILESDIR}"/xenstored.confd xenstored
|
||||
newconfd "${FILESDIR}"/xenconsoled.confd xenconsoled
|
||||
newinitd "${FILESDIR}"/xendomains.initd-r2 xendomains
|
||||
newinitd "${FILESDIR}"/xenstored.initd xenstored
|
||||
newinitd "${FILESDIR}"/xenconsoled.initd xenconsoled
|
||||
|
||||
if use screen; then
|
||||
cat "${FILESDIR}"/xendomains-screen.confd >> "${D}"/etc/conf.d/xendomains || die
|
||||
cp "${FILESDIR}"/xen-consoles.logrotate "${D}"/etc/xen/ || die
|
||||
keepdir /var/log/xen-consoles
|
||||
fi
|
||||
|
||||
# Set dirs for qemu files,; Bug #458818
|
||||
if use qemu; then
|
||||
if use x86; then
|
||||
dodir /usr/lib/xen/bin
|
||||
elif use amd64; then
|
||||
mv "${D}"usr/lib/xen/bin/qemu* "${D}"usr/$(get_libdir)/xen/bin/ || die
|
||||
fi
|
||||
fi
|
||||
|
||||
# For -static-libs wrt Bug 384355
|
||||
if ! use static-libs; then
|
||||
rm -f "${D}"usr/$(get_libdir)/*.a "${ED}"usr/$(get_libdir)/ocaml/*/*.a
|
||||
fi
|
||||
|
||||
# xend expects these to exist
|
||||
keepdir /var/run/xenstored /var/lib/xenstored /var/xen/dump /var/lib/xen /var/log/xen
|
||||
|
||||
# for xendomains
|
||||
keepdir /etc/xen/auto
|
||||
|
||||
# Temp QA workaround
|
||||
dodir "$(udev_get_udevdir)"
|
||||
mv "${D}"/etc/udev/* "${ED}/$(udev_get_udevdir)"
|
||||
rm -rf "${D}"/etc/udev
|
||||
|
||||
# Remove files failing QA AFTER emake installs them, avoiding seeking absent files
|
||||
find "${D}" \( -name openbios-sparc32 -o -name openbios-sparc64 \
|
||||
-o -name openbios-ppc -o -name palcode-clipper \) -delete || die
|
||||
}
|
||||
|
||||
pkg_postinst() {
|
||||
elog "Official Xen Guide and the unoffical wiki page:"
|
||||
elog " http://www.gentoo.org/doc/en/xen-guide.xml"
|
||||
elog " http://gentoo-wiki.com/HOWTO_Xen_and_Gentoo"
|
||||
|
||||
if [[ "$(scanelf -s __guard -q "${PYTHON}")" ]] ; then
|
||||
echo
|
||||
ewarn "xend may not work when python is built with stack smashing protection (ssp)."
|
||||
ewarn "If 'xm create' fails with '<ProtocolError for /RPC2: -1 >', see bug #141866"
|
||||
ewarn "This problem may be resolved as of Xen 3.0.4, if not post in the bug."
|
||||
fi
|
||||
|
||||
# TODO: we need to have the current Python slot here.
|
||||
if ! has_version "dev-lang/python[ncurses]"; then
|
||||
echo
|
||||
ewarn "NB: Your dev-lang/python is built without USE=ncurses."
|
||||
ewarn "Please rebuild python with USE=ncurses to make use of xenmon.py."
|
||||
fi
|
||||
|
||||
if has_version "sys-apps/iproute2[minimal]"; then
|
||||
echo
|
||||
ewarn "Your sys-apps/iproute2 is built with USE=minimal. Networking"
|
||||
ewarn "will not work until you rebuild iproute2 without USE=minimal."
|
||||
fi
|
||||
|
||||
if ! use hvm; then
|
||||
echo
|
||||
elog "HVM (VT-x and AMD-V) support has been disabled. If you need hvm"
|
||||
elog "support enable the hvm use flag."
|
||||
elog "An x86 or amd64 multilib system is required to build HVM support."
|
||||
echo
|
||||
elog "The qemu use flag has been removed and replaced with hvm."
|
||||
fi
|
||||
|
||||
if use xend; then
|
||||
echo
|
||||
elog "xend capability has been enabled and installed"
|
||||
fi
|
||||
|
||||
if grep -qsF XENSV= "${ROOT}/etc/conf.d/xend"; then
|
||||
echo
|
||||
elog "xensv is broken upstream (Gentoo bug #142011)."
|
||||
elog "Please remove '${ROOT%/}/etc/conf.d/xend', as it is no longer needed."
|
||||
fi
|
||||
}
|
@ -1,347 +0,0 @@
|
||||
# Copyright 1999-2013 Gentoo Foundation
|
||||
# Distributed under the terms of the GNU General Public License v2
|
||||
# $Header: /var/cvsroot/gentoo-x86/app-emulation/xen-tools/xen-tools-4.2.1-r2.ebuild,v 1.6 2013/03/05 18:05:35 idella4 Exp $
|
||||
|
||||
EAPI=5
|
||||
|
||||
PYTHON_COMPAT=( python{2_6,2_7} )
|
||||
PYTHON_REQ_USE='xml,threads'
|
||||
|
||||
IPXE_TARBALL_URL="http://dev.gentoo.org/~idella4/tarballs/ipxe.tar.gz"
|
||||
XEN_SEABIOS_URL="http://dev.gentoo.org/~idella4/tarballs/seabios-0-20121121.tar.bz2"
|
||||
|
||||
if [[ $PV == *9999 ]]; then
|
||||
KEYWORDS=""
|
||||
REPO="xen-unstable.hg"
|
||||
EHG_REPO_URI="http://xenbits.xensource.com/${REPO}"
|
||||
S="${WORKDIR}/${REPO}"
|
||||
live_eclass="mercurial"
|
||||
else
|
||||
KEYWORDS="~amd64 ~x86"
|
||||
SRC_URI="http://bits.xensource.com/oss-xen/release/${PV}/xen-${PV}.tar.gz
|
||||
$IPXE_TARBALL_URL
|
||||
$XEN_SEABIOS_URL"
|
||||
S="${WORKDIR}/xen-${PV}"
|
||||
fi
|
||||
|
||||
inherit flag-o-matic eutils multilib python-single-r1 toolchain-funcs udev ${live_eclass}
|
||||
|
||||
DESCRIPTION="Xend daemon and tools"
|
||||
HOMEPAGE="http://xen.org/"
|
||||
DOCS=( README docs/README.xen-bugtool )
|
||||
|
||||
LICENSE="GPL-2"
|
||||
SLOT="0"
|
||||
IUSE="api custom-cflags debug doc flask hvm qemu ocaml pygrub screen static-libs xend"
|
||||
|
||||
REQUIRED_USE="hvm? ( qemu )"
|
||||
|
||||
CDEPEND="<dev-libs/yajl-2
|
||||
dev-python/lxml[${PYTHON_USEDEP}]
|
||||
dev-python/pypam[${PYTHON_USEDEP}]
|
||||
sys-libs/zlib
|
||||
sys-power/iasl
|
||||
ocaml? ( dev-ml/findlib )
|
||||
hvm? ( media-libs/libsdl )
|
||||
${PYTHON_DEPS}
|
||||
api? ( dev-libs/libxml2
|
||||
net-misc/curl )
|
||||
${PYTHON_DEPS}
|
||||
pygrub? ( ${PYTHON_DEPS//${PYTHON_REQ_USE}/ncurses} )"
|
||||
DEPEND="${CDEPEND}
|
||||
sys-devel/bin86
|
||||
sys-devel/dev86
|
||||
dev-lang/perl
|
||||
app-misc/pax-utils
|
||||
doc? (
|
||||
app-doc/doxygen
|
||||
dev-tex/latex2html[png,gif]
|
||||
media-gfx/transfig
|
||||
media-gfx/graphviz
|
||||
dev-tex/xcolor
|
||||
dev-texlive/texlive-latexextra
|
||||
virtual/latex-base
|
||||
dev-tex/latexmk
|
||||
dev-texlive/texlive-latex
|
||||
dev-texlive/texlive-pictures
|
||||
dev-texlive/texlive-latexrecommended
|
||||
)
|
||||
hvm? ( x11-proto/xproto
|
||||
)"
|
||||
RDEPEND="${CDEPEND}
|
||||
sys-apps/iproute2
|
||||
net-misc/bridge-utils
|
||||
ocaml? ( >=dev-lang/ocaml-3.12.0 )
|
||||
screen? (
|
||||
app-misc/screen
|
||||
app-admin/logrotate
|
||||
)
|
||||
virtual/udev"
|
||||
|
||||
# hvmloader is used to bootstrap a fully virtualized kernel
|
||||
# Approved by QA team in bug #144032
|
||||
QA_WX_LOAD="usr/lib/xen/boot/hvmloader"
|
||||
|
||||
RESTRICT="test"
|
||||
|
||||
pkg_setup() {
|
||||
python-single-r1_pkg_setup
|
||||
export "CONFIG_LOMOUNT=y"
|
||||
|
||||
if has_version dev-libs/libgcrypt; then
|
||||
export "CONFIG_GCRYPT=y"
|
||||
fi
|
||||
|
||||
if use qemu; then
|
||||
export "CONFIG_IOEMU=y"
|
||||
else
|
||||
export "CONFIG_IOEMU=n"
|
||||
fi
|
||||
|
||||
if ! use x86 && ! has x86 $(get_all_abis) && use hvm; then
|
||||
eerror "HVM (VT-x and AMD-v) cannot be built on this system. An x86 or"
|
||||
eerror "an amd64 multilib profile is required. Remove the hvm use flag"
|
||||
eerror "to build xen-tools on your current profile."
|
||||
die "USE=hvm is unsupported on this system."
|
||||
fi
|
||||
|
||||
if [[ -z ${XEN_TARGET_ARCH} ]] ; then
|
||||
if use x86 && use amd64; then
|
||||
die "Confusion! Both x86 and amd64 are set in your use flags!"
|
||||
elif use x86; then
|
||||
export XEN_TARGET_ARCH="x86_32"
|
||||
elif use amd64 ; then
|
||||
export XEN_TARGET_ARCH="x86_64"
|
||||
else
|
||||
die "Unsupported architecture!"
|
||||
fi
|
||||
fi
|
||||
|
||||
use api && export "LIBXENAPI_BINDINGS=y"
|
||||
use flask && export "FLASK_ENABLE=y"
|
||||
}
|
||||
|
||||
src_prepare() {
|
||||
# Drop .config, fixes to gcc-4.6
|
||||
epatch "${FILESDIR}"/${PN/-tools/}-4-fix_dotconfig-gcc.patch
|
||||
|
||||
# Xend
|
||||
if ! use xend; then
|
||||
sed -e 's:xm xen-bugtool xen-python-path xend:xen-bugtool xen-python-path:' \
|
||||
-i tools/misc/Makefile || die "Disabling xend failed"
|
||||
sed -e 's:^XEND_INITD:#XEND_INITD:' \
|
||||
-i tools/examples/Makefile || die "Disabling xend failed"
|
||||
fi
|
||||
|
||||
# if the user *really* wants to use their own custom-cflags, let them
|
||||
if use custom-cflags; then
|
||||
einfo "User wants their own CFLAGS - removing defaults"
|
||||
|
||||
# try and remove all the default cflags
|
||||
find "${S}" \( -name Makefile -o -name Rules.mk -o -name Config.mk \) \
|
||||
-exec sed \
|
||||
-e 's/CFLAGS\(.*\)=\(.*\)-O3\(.*\)/CFLAGS\1=\2\3/' \
|
||||
-e 's/CFLAGS\(.*\)=\(.*\)-march=i686\(.*\)/CFLAGS\1=\2\3/' \
|
||||
-e 's/CFLAGS\(.*\)=\(.*\)-fomit-frame-pointer\(.*\)/CFLAGS\1=\2\3/' \
|
||||
-e 's/CFLAGS\(.*\)=\(.*\)-g3*\s\(.*\)/CFLAGS\1=\2 \3/' \
|
||||
-e 's/CFLAGS\(.*\)=\(.*\)-O2\(.*\)/CFLAGS\1=\2\3/' \
|
||||
-i {} + || die "failed to re-set custom-cflags"
|
||||
fi
|
||||
|
||||
if ! use pygrub; then
|
||||
sed -e '/^SUBDIRS-$(PYTHON_TOOLS) += pygrub$/d' -i tools/Makefile || die
|
||||
fi
|
||||
|
||||
# Disable hvm support on systems that don't support x86_32 binaries.
|
||||
if ! use hvm; then
|
||||
sed -e '/^CONFIG_IOEMU := y$/d' -i config/*.mk || die
|
||||
sed -e '/SUBDIRS-$(CONFIG_X86) += firmware/d' -i tools/Makefile || die
|
||||
fi
|
||||
|
||||
# Don't bother with qemu, only needed for fully virtualised guests
|
||||
if ! use qemu; then
|
||||
sed -e "/^CONFIG_IOEMU := y$/d" -i config/*.mk || die
|
||||
sed -e "s:install-tools\: tools/ioemu-dir:install-tools\: :g" -i Makefile || die
|
||||
fi
|
||||
|
||||
# Fix texi2html build error with new texi2html
|
||||
epatch "${FILESDIR}"/${PN}-4-docfix.patch
|
||||
|
||||
# Fix network broadcast on bridged networks
|
||||
epatch "${FILESDIR}/${PN}-3.4.0-network-bridge-broadcast.patch"
|
||||
|
||||
# Prevent the downloading of ipxe, seabios
|
||||
epatch "${FILESDIR}"/${PN/-tools/}-4.2.0-anti-download.patch
|
||||
cp "${DISTDIR}"/ipxe.tar.gz tools/firmware/etherboot/ || die
|
||||
mv ../seabios-dir-remote tools/firmware/ || die
|
||||
pushd tools/firmware/ > /dev/null
|
||||
ln -s seabios-dir-remote seabios-dir || die
|
||||
popd > /dev/null
|
||||
|
||||
# Fix bridge by idella4, bug #362575
|
||||
epatch "${FILESDIR}/${PN}-4.1.1-bridge.patch"
|
||||
|
||||
# Don't build ipxe with pie on hardened, Bug #360805
|
||||
if gcc-specs-pie; then
|
||||
epatch "${FILESDIR}"/ipxe-nopie.patch
|
||||
fi
|
||||
|
||||
# Prevent double stripping of files at install
|
||||
epatch "${FILESDIR}"/${PN/-tools/}-4.2.0-nostrip.patch
|
||||
|
||||
# fix jobserver in Makefile
|
||||
epatch "${FILESDIR}"/${PN/-tools/}-4.2.0-jserver.patch
|
||||
|
||||
#Sec patch, currently valid
|
||||
epatch "${FILESDIR}"/xen-4-CVE-2012-6075-XSA-41.patch
|
||||
|
||||
if use hvm; then
|
||||
cp -r "${FILESDIR}"/stubs-32.h xen/tools/include || die "copy of header file failed"
|
||||
einfo "stubs-32.h added"
|
||||
fi
|
||||
}
|
||||
|
||||
src_compile() {
|
||||
export VARTEXFONTS="${T}/fonts"
|
||||
local myopt
|
||||
use debug && myopt="${myopt} debug=y"
|
||||
|
||||
use custom-cflags || unset CFLAGS
|
||||
if test-flag-CC -fno-strict-overflow; then
|
||||
append-flags -fno-strict-overflow
|
||||
fi
|
||||
|
||||
unset LDFLAGS
|
||||
unset CFLAGS
|
||||
emake CC="$(tc-getCC)" LD="$(tc-getLD)" -C tools ${myopt}
|
||||
|
||||
use doc && emake -C docs txt html
|
||||
emake -C docs man-pages
|
||||
}
|
||||
|
||||
src_install() {
|
||||
# Override auto-detection in the build system, bug #382573
|
||||
export INITD_DIR=/tmp/init.d
|
||||
export CONFIG_LEAF_DIR=../tmp/default
|
||||
|
||||
# Let the build system compile installed Python modules.
|
||||
local PYTHONDONTWRITEBYTECODE
|
||||
export PYTHONDONTWRITEBYTECODE
|
||||
|
||||
emake DESTDIR="${D}" DOCDIR="/usr/share/doc/${PF}" install-tools
|
||||
|
||||
# Fix the remaining Python shebangs.
|
||||
python_fix_shebang "${D}"
|
||||
|
||||
# Remove RedHat-specific stuff
|
||||
rm -rf "${D}"tmp || die
|
||||
|
||||
# uncomment lines in xl.conf
|
||||
sed -e 's:^#autoballoon=1:autoballoon=1:' \
|
||||
-e 's:^#lockfile="/var/lock/xl":lockfile="/var/lock/xl":' \
|
||||
-e 's:^#vifscript="vif-bridge":vifscript="vif-bridge":' \
|
||||
-i tools/examples/xl.conf || die
|
||||
|
||||
if use doc; then
|
||||
emake DESTDIR="${D}" DOCDIR="/usr/share/doc/${PF}" install-docs
|
||||
|
||||
dohtml -r docs/
|
||||
docinto pdf
|
||||
dodoc ${DOCS[@]}
|
||||
[ -d "${D}"/usr/share/doc/xen ] && mv "${D}"/usr/share/doc/xen/* "${D}"/usr/share/doc/${PF}/html
|
||||
fi
|
||||
|
||||
rm -rf "${D}"/usr/share/doc/xen/
|
||||
doman docs/man?/*
|
||||
|
||||
if use xend; then
|
||||
newinitd "${FILESDIR}"/xend.initd-r2 xend || die "Couldn't install xen.initd"
|
||||
fi
|
||||
newconfd "${FILESDIR}"/xendomains.confd xendomains
|
||||
newconfd "${FILESDIR}"/xenstored.confd xenstored
|
||||
newconfd "${FILESDIR}"/xenconsoled.confd xenconsoled
|
||||
newinitd "${FILESDIR}"/xendomains.initd-r2 xendomains
|
||||
newinitd "${FILESDIR}"/xenstored.initd xenstored
|
||||
newinitd "${FILESDIR}"/xenconsoled.initd xenconsoled
|
||||
|
||||
if use screen; then
|
||||
cat "${FILESDIR}"/xendomains-screen.confd >> "${D}"/etc/conf.d/xendomains || die
|
||||
cp "${FILESDIR}"/xen-consoles.logrotate "${D}"/etc/xen/ || die
|
||||
keepdir /var/log/xen-consoles
|
||||
fi
|
||||
|
||||
# Set dirs for qemu files,; Bug #458818
|
||||
if use qemu; then
|
||||
if use x86; then
|
||||
dodir /usr/lib/xen/bin
|
||||
elif use amd64; then
|
||||
mv "${D}"usr/lib/xen/bin/qemu* "${D}"usr/$(get_libdir)/xen/bin/ || die
|
||||
fi
|
||||
fi
|
||||
|
||||
# For -static-libs wrt Bug 384355
|
||||
if ! use static-libs; then
|
||||
rm -f "${D}"usr/$(get_libdir)/*.a "${D}"usr/$(get_libdir)/ocaml/*/*.a
|
||||
fi
|
||||
|
||||
# xend expects these to exist
|
||||
keepdir /var/run/xenstored /var/lib/xenstored /var/xen/dump /var/lib/xen /var/log/xen
|
||||
|
||||
# for xendomains
|
||||
keepdir /etc/xen/auto
|
||||
|
||||
# Temp QA workaround
|
||||
dodir "$(udev_get_udevdir)"
|
||||
mv "${D}"/etc/udev/* "${D}/$(udev_get_udevdir)"
|
||||
rm -rf "${D}"/etc/udev
|
||||
|
||||
# Remove files failing QA AFTER emake installs them, avoiding seeking absent files
|
||||
find "${D}" \( -name openbios-sparc32 -o -name openbios-sparc64 \
|
||||
-o -name openbios-ppc -o -name palcode-clipper \) -delete || die
|
||||
}
|
||||
|
||||
pkg_postinst() {
|
||||
elog "Official Xen Guide and the unoffical wiki page:"
|
||||
elog " http://www.gentoo.org/doc/en/xen-guide.xml"
|
||||
elog " http://gentoo-wiki.com/HOWTO_Xen_and_Gentoo"
|
||||
|
||||
if [[ "$(scanelf -s __guard -q "${PYTHON}")" ]] ; then
|
||||
echo
|
||||
ewarn "xend may not work when python is built with stack smashing protection (ssp)."
|
||||
ewarn "If 'xm create' fails with '<ProtocolError for /RPC2: -1 >', see bug #141866"
|
||||
ewarn "This problem may be resolved as of Xen 3.0.4, if not post in the bug."
|
||||
fi
|
||||
|
||||
# TODO: we need to have the current Python slot here.
|
||||
if ! has_version "dev-lang/python[ncurses]"; then
|
||||
echo
|
||||
ewarn "NB: Your dev-lang/python is built without USE=ncurses."
|
||||
ewarn "Please rebuild python with USE=ncurses to make use of xenmon.py."
|
||||
fi
|
||||
|
||||
if has_version "sys-apps/iproute2[minimal]"; then
|
||||
echo
|
||||
ewarn "Your sys-apps/iproute2 is built with USE=minimal. Networking"
|
||||
ewarn "will not work until you rebuild iproute2 without USE=minimal."
|
||||
fi
|
||||
|
||||
if ! use hvm; then
|
||||
echo
|
||||
elog "HVM (VT-x and AMD-V) support has been disabled. If you need hvm"
|
||||
elog "support enable the hvm use flag."
|
||||
elog "An x86 or amd64 multilib system is required to build HVM support."
|
||||
echo
|
||||
elog "The qemu use flag has been removed and replaced with hvm."
|
||||
fi
|
||||
|
||||
if use xend; then
|
||||
echo
|
||||
elog "xend capability has been enabled and installed"
|
||||
fi
|
||||
|
||||
if grep -qsF XENSV= "${ROOT}/etc/conf.d/xend"; then
|
||||
echo
|
||||
elog "xensv is broken upstream (Gentoo bug #142011)."
|
||||
elog "Please remove '${ROOT%/}/etc/conf.d/xend', as it is no longer needed."
|
||||
fi
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
|
||||
# HG changeset patch
|
||||
# User Ian Jackson <Ian.Jackson@eu.citrix.com>
|
||||
# Date 1352892795 0
|
||||
# Node ID 788af5959f692ca16942937055afb09b760f2166
|
||||
# Parent bdb5cde7f79d77f8578bcd8e24d74d09a2c7caa6
|
||||
VCPU/timers: Prevent overflow in calculations, leading to DoS vulnerability
|
||||
|
||||
The timer action for a vcpu periodic timer is to calculate the next
|
||||
expiry time, and to reinsert itself into the timer queue. If the
|
||||
deadline ends up in the past, Xen never leaves __do_softirq(). The
|
||||
affected PCPU will stay in an infinite loop until Xen is killed by the
|
||||
watchdog (if enabled).
|
||||
|
||||
This is a security problem, XSA-20 / CVE-2012-4535.
|
||||
|
||||
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
|
||||
Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
Committed-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
|
||||
xen-unstable changeset: 26148:bf58b94b3cef
|
||||
Backport-requested-by: security@xen.org
|
||||
Committed-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
|
||||
diff -r bdb5cde7f79d -r 788af5959f69 xen/common/domain.c
|
||||
--- xen/common/domain.c Wed Nov 14 10:40:41 2012 +0100
|
||||
+++ xen/common/domain.c Wed Nov 14 11:33:15 2012 +0000
|
||||
@@ -882,6 +882,9 @@ long do_vcpu_op(int cmd, int vcpuid, XEN
|
||||
if ( set.period_ns < MILLISECS(1) )
|
||||
return -EINVAL;
|
||||
|
||||
+ if ( set.period_ns > STIME_DELTA_MAX )
|
||||
+ return -EINVAL;
|
||||
+
|
||||
v->periodic_period = set.period_ns;
|
||||
vcpu_force_reschedule(v);
|
||||
|
||||
diff -r bdb5cde7f79d -r 788af5959f69 xen/include/xen/time.h
|
||||
--- xen/include/xen/time.h Wed Nov 14 10:40:41 2012 +0100
|
||||
+++ xen/include/xen/time.h Wed Nov 14 11:33:15 2012 +0000
|
||||
@@ -55,6 +55,8 @@ struct tm gmtime(unsigned long t);
|
||||
#define MILLISECS(_ms) ((s_time_t)((_ms) * 1000000ULL))
|
||||
#define MICROSECS(_us) ((s_time_t)((_us) * 1000ULL))
|
||||
#define STIME_MAX ((s_time_t)((uint64_t)~0ull>>1))
|
||||
+/* Chosen so (NOW() + delta) wont overflow without an uptime of 200 years */
|
||||
+#define STIME_DELTA_MAX ((s_time_t)((uint64_t)~0ull>>2))
|
||||
|
||||
extern void update_vcpu_system_time(struct vcpu *v);
|
||||
extern void update_domain_wallclock_time(struct domain *d);
|
||||
|
@ -1,50 +0,0 @@
|
||||
# HG changeset patch
|
||||
# User Ian Jackson <Ian.Jackson@eu.citrix.com>
|
||||
# Date 1352893017 0
|
||||
# Node ID 4cffe28427e0c7dbeaa7c109ed393dde0fe026ba
|
||||
# Parent 788af5959f692ca16942937055afb09b760f2166
|
||||
x86/physmap: Prevent incorrect updates of m2p mappings
|
||||
|
||||
In certain conditions, such as low memory, set_p2m_entry() can fail.
|
||||
Currently, the p2m and m2p tables will get out of sync because we still
|
||||
update the m2p table after the p2m update has failed.
|
||||
|
||||
If that happens, subsequent guest-invoked memory operations can cause
|
||||
BUG()s and ASSERT()s to kill Xen.
|
||||
|
||||
This is fixed by only updating the m2p table iff the p2m was
|
||||
successfully updated.
|
||||
|
||||
This is a security problem, XSA-22 / CVE-2012-4537.
|
||||
|
||||
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
|
||||
Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Committed-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
|
||||
xen-unstable changeset: 26149:6b6a4007a609
|
||||
Backport-requested-by: security@xen.org
|
||||
Committed-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
|
||||
diff -r 788af5959f69 -r 4cffe28427e0 xen/arch/x86/mm/p2m.c
|
||||
--- xen/arch/x86/mm/p2m.c Wed Nov 14 11:33:15 2012 +0000
|
||||
+++ xen/arch/x86/mm/p2m.c Wed Nov 14 11:36:57 2012 +0000
|
||||
@@ -654,7 +654,10 @@ guest_physmap_add_entry(struct domain *d
|
||||
if ( mfn_valid(_mfn(mfn)) )
|
||||
{
|
||||
if ( !set_p2m_entry(p2m, gfn, _mfn(mfn), page_order, t, p2m->default_access) )
|
||||
+ {
|
||||
rc = -EINVAL;
|
||||
+ goto out; /* Failed to update p2m, bail without updating m2p. */
|
||||
+ }
|
||||
if ( !p2m_is_grant(t) )
|
||||
{
|
||||
for ( i = 0; i < (1UL << page_order); i++ )
|
||||
@@ -677,6 +680,7 @@ guest_physmap_add_entry(struct domain *d
|
||||
}
|
||||
}
|
||||
|
||||
+out:
|
||||
p2m_unlock(p2m);
|
||||
|
||||
return rc;
|
@ -1,43 +0,0 @@
|
||||
|
||||
# HG changeset patch
|
||||
# User Ian Jackson <Ian.Jackson@eu.citrix.com>
|
||||
# Date 1352893365 0
|
||||
# Node ID 159080b58dda9d19a5d3be42359e667bdb3e61ca
|
||||
# Parent 4cffe28427e0c7dbeaa7c109ed393dde0fe026ba
|
||||
xen/mm/shadow: check toplevel pagetables are present before unhooking them.
|
||||
|
||||
If the guest has not fully populated its top-level PAE entries when it calls
|
||||
HVMOP_pagetable_dying, the shadow code could try to unhook entries from
|
||||
MFN 0. Add a check to avoid that case.
|
||||
|
||||
This issue was introduced by c/s 21239:b9d2db109cf5.
|
||||
|
||||
This is a security problem, XSA-23 / CVE-2012-4538.
|
||||
|
||||
Signed-off-by: Tim Deegan <tim@xen.org>
|
||||
Tested-by: Andrew Cooper <andrew.cooper3@citrix.com>
|
||||
Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
Committed-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
|
||||
xen-unstable changeset: 26150:c7a01b6450e4
|
||||
Backport-requested-by: security@xen.org
|
||||
Committed-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
|
||||
diff -r 4cffe28427e0 -r 159080b58dda xen/arch/x86/mm/shadow/multi.c
|
||||
--- xen/arch/x86/mm/shadow/multi.c Wed Nov 14 11:36:57 2012 +0000
|
||||
+++ xen/arch/x86/mm/shadow/multi.c Wed Nov 14 11:42:45 2012 +0000
|
||||
@@ -4734,8 +4734,12 @@ static void sh_pagetable_dying(struct vc
|
||||
unsigned long gfn;
|
||||
mfn_t smfn, gmfn;
|
||||
|
||||
- if ( fast_path )
|
||||
- smfn = _mfn(pagetable_get_pfn(v->arch.shadow_table[i]));
|
||||
+ if ( fast_path ) {
|
||||
+ if ( pagetable_is_null(v->arch.shadow_table[i]) )
|
||||
+ smfn = _mfn(INVALID_MFN);
|
||||
+ else
|
||||
+ smfn = _mfn(pagetable_get_pfn(v->arch.shadow_table[i]));
|
||||
+ }
|
||||
else
|
||||
{
|
||||
/* retrieving the l2s */
|
@ -1,36 +0,0 @@
|
||||
# HG changeset patch
|
||||
# User Ian Jackson <Ian.Jackson@eu.citrix.com>
|
||||
# Date 1352893567 0
|
||||
# Node ID 8ca6372315f826881f9de141ac1227ef962100cf
|
||||
# Parent 159080b58dda9d19a5d3be42359e667bdb3e61ca
|
||||
compat/gnttab: Prevent infinite loop in compat code
|
||||
|
||||
c/s 20281:95ea2052b41b, which introduces Grant Table version 2
|
||||
hypercalls introduces a vulnerability whereby the compat hypercall
|
||||
handler can fall into an infinite loop.
|
||||
|
||||
If the watchdog is enabled, Xen will die after the timeout.
|
||||
|
||||
This is a security problem, XSA-24 / CVE-2012-4539.
|
||||
|
||||
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
|
||||
Acked-by: Jan Beulich <jbeulich@suse.com>
|
||||
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Committed-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
|
||||
xen-unstable changeset: 26151:b64a7d868f06
|
||||
Backport-requested-by: security@xen.org
|
||||
Committed-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
|
||||
diff -r 159080b58dda -r 8ca6372315f8 xen/common/compat/grant_table.c
|
||||
--- xen/common/compat/grant_table.c Wed Nov 14 11:42:45 2012 +0000
|
||||
+++ xen/common/compat/grant_table.c Wed Nov 14 11:46:07 2012 +0000
|
||||
@@ -318,6 +318,8 @@ int compat_grant_table_op(unsigned int c
|
||||
#undef XLAT_gnttab_get_status_frames_HNDL_frame_list
|
||||
if ( unlikely(__copy_to_guest(cmp_uop, &cmp.get_status, 1)) )
|
||||
rc = -EFAULT;
|
||||
+ else
|
||||
+ i = 1;
|
||||
}
|
||||
break;
|
||||
}
|
@ -1,113 +0,0 @@
|
||||
# HG changeset patch
|
||||
# User Jan Beulich <jbeulich@suse.com>
|
||||
# Date 1354644138 0
|
||||
# Node ID dea7d4e5bfc1627133c0c19706fea1fbc9e5a378
|
||||
# Parent 9e13427c023020756768c73217dab05295709fb3
|
||||
gnttab: fix releasing of memory upon switches between versions
|
||||
|
||||
gnttab_unpopulate_status_frames() incompletely freed the pages
|
||||
previously used as status frame in that they did not get removed from
|
||||
the domain's xenpage_list, thus causing subsequent list corruption
|
||||
when those pages did get allocated again for the same or another purpose.
|
||||
|
||||
Similarly, grant_table_create() and gnttab_grow_table() both improperly
|
||||
clean up in the event of an error - pages already shared with the guest
|
||||
can't be freed by just passing them to free_xenheap_page(). Fix this by
|
||||
sharing the pages only after all allocations succeeded.
|
||||
|
||||
This is CVE-2012-5510 / XSA-26.
|
||||
|
||||
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
||||
Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
Committed-by: Ian Jackson <ian.jackson.citrix.com>
|
||||
|
||||
diff -r 9e13427c0230 -r dea7d4e5bfc1 xen/common/grant_table.c
|
||||
--- xen/common/grant_table.c Thu Nov 29 16:59:43 2012 +0000
|
||||
+++ xen/common/grant_table.c Tue Dec 04 18:02:18 2012 +0000
|
||||
@@ -1173,12 +1173,13 @@ fault:
|
||||
}
|
||||
|
||||
static int
|
||||
-gnttab_populate_status_frames(struct domain *d, struct grant_table *gt)
|
||||
+gnttab_populate_status_frames(struct domain *d, struct grant_table *gt,
|
||||
+ unsigned int req_nr_frames)
|
||||
{
|
||||
unsigned i;
|
||||
unsigned req_status_frames;
|
||||
|
||||
- req_status_frames = grant_to_status_frames(gt->nr_grant_frames);
|
||||
+ req_status_frames = grant_to_status_frames(req_nr_frames);
|
||||
for ( i = nr_status_frames(gt); i < req_status_frames; i++ )
|
||||
{
|
||||
if ( (gt->status[i] = alloc_xenheap_page()) == NULL )
|
||||
@@ -1209,7 +1210,12 @@ gnttab_unpopulate_status_frames(struct d
|
||||
|
||||
for ( i = 0; i < nr_status_frames(gt); i++ )
|
||||
{
|
||||
- page_set_owner(virt_to_page(gt->status[i]), dom_xen);
|
||||
+ struct page_info *pg = virt_to_page(gt->status[i]);
|
||||
+
|
||||
+ BUG_ON(page_get_owner(pg) != d);
|
||||
+ if ( test_and_clear_bit(_PGC_allocated, &pg->count_info) )
|
||||
+ put_page(pg);
|
||||
+ BUG_ON(pg->count_info & ~PGC_xen_heap);
|
||||
free_xenheap_page(gt->status[i]);
|
||||
gt->status[i] = NULL;
|
||||
}
|
||||
@@ -1247,19 +1253,18 @@ gnttab_grow_table(struct domain *d, unsi
|
||||
clear_page(gt->shared_raw[i]);
|
||||
}
|
||||
|
||||
+ /* Status pages - version 2 */
|
||||
+ if (gt->gt_version > 1)
|
||||
+ {
|
||||
+ if ( gnttab_populate_status_frames(d, gt, req_nr_frames) )
|
||||
+ goto shared_alloc_failed;
|
||||
+ }
|
||||
+
|
||||
/* Share the new shared frames with the recipient domain */
|
||||
for ( i = nr_grant_frames(gt); i < req_nr_frames; i++ )
|
||||
gnttab_create_shared_page(d, gt, i);
|
||||
-
|
||||
gt->nr_grant_frames = req_nr_frames;
|
||||
|
||||
- /* Status pages - version 2 */
|
||||
- if (gt->gt_version > 1)
|
||||
- {
|
||||
- if ( gnttab_populate_status_frames(d, gt) )
|
||||
- goto shared_alloc_failed;
|
||||
- }
|
||||
-
|
||||
return 1;
|
||||
|
||||
shared_alloc_failed:
|
||||
@@ -2157,7 +2162,7 @@ gnttab_set_version(XEN_GUEST_HANDLE(gntt
|
||||
|
||||
if ( op.version == 2 && gt->gt_version < 2 )
|
||||
{
|
||||
- res = gnttab_populate_status_frames(d, gt);
|
||||
+ res = gnttab_populate_status_frames(d, gt, nr_grant_frames(gt));
|
||||
if ( res < 0)
|
||||
goto out_unlock;
|
||||
}
|
||||
@@ -2600,14 +2605,15 @@ grant_table_create(
|
||||
clear_page(t->shared_raw[i]);
|
||||
}
|
||||
|
||||
- for ( i = 0; i < INITIAL_NR_GRANT_FRAMES; i++ )
|
||||
- gnttab_create_shared_page(d, t, i);
|
||||
-
|
||||
/* Status pages for grant table - for version 2 */
|
||||
t->status = xzalloc_array(grant_status_t *,
|
||||
grant_to_status_frames(max_nr_grant_frames));
|
||||
if ( t->status == NULL )
|
||||
goto no_mem_4;
|
||||
+
|
||||
+ for ( i = 0; i < INITIAL_NR_GRANT_FRAMES; i++ )
|
||||
+ gnttab_create_shared_page(d, t, i);
|
||||
+
|
||||
t->nr_status_frames = 0;
|
||||
|
||||
/* Okay, install the structure. */
|
||||
|
||||
|
@ -1,56 +0,0 @@
|
||||
|
||||
# HG changeset patch
|
||||
# User Jan Beulich <jbeulich@suse.com>
|
||||
# Date 1354644164 0
|
||||
# Node ID 83ab3cd0f8e44ad588932aba93d3b5f92a888a08
|
||||
# Parent 5771c761ff1bb249dc683d7ec019d76a2a03a048
|
||||
xen: add missing guest address range checks to XENMEM_exchange handlers
|
||||
|
||||
Ever since its existence (3.0.3 iirc) the handler for this has been
|
||||
using non address range checking guest memory accessors (i.e.
|
||||
the ones prefixed with two underscores) without first range
|
||||
checking the accessed space (via guest_handle_okay()), allowing
|
||||
a guest to access and overwrite hypervisor memory.
|
||||
|
||||
This is XSA-29 / CVE-2012-5513.
|
||||
|
||||
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
||||
Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Committed-by: Ian Jackson <ian.jackson.citrix.com>
|
||||
|
||||
diff -r 5771c761ff1b -r 83ab3cd0f8e4 xen/common/compat/memory.c
|
||||
--- a/xen/common/compat/memory.c Tue Dec 04 18:02:38 2012 +0000
|
||||
+++ b/xen/common/compat/memory.c Tue Dec 04 18:02:44 2012 +0000
|
||||
@@ -115,6 +115,12 @@ int compat_memory_op(unsigned int cmd, X
|
||||
(cmp.xchg.out.nr_extents << cmp.xchg.out.extent_order)) )
|
||||
return -EINVAL;
|
||||
|
||||
+ if ( !compat_handle_okay(cmp.xchg.in.extent_start,
|
||||
+ cmp.xchg.in.nr_extents) ||
|
||||
+ !compat_handle_okay(cmp.xchg.out.extent_start,
|
||||
+ cmp.xchg.out.nr_extents) )
|
||||
+ return -EFAULT;
|
||||
+
|
||||
start_extent = cmp.xchg.nr_exchanged;
|
||||
end_extent = (COMPAT_ARG_XLAT_SIZE - sizeof(*nat.xchg)) /
|
||||
(((1U << ABS(order_delta)) + 1) *
|
||||
diff -r 5771c761ff1b -r 83ab3cd0f8e4 xen/common/memory.c
|
||||
--- a/xen/common/memory.c Tue Dec 04 18:02:38 2012 +0000
|
||||
+++ b/xen/common/memory.c Tue Dec 04 18:02:44 2012 +0000
|
||||
@@ -308,6 +308,13 @@ static long memory_exchange(XEN_GUEST_HA
|
||||
goto fail_early;
|
||||
}
|
||||
|
||||
+ if ( !guest_handle_okay(exch.in.extent_start, exch.in.nr_extents) ||
|
||||
+ !guest_handle_okay(exch.out.extent_start, exch.out.nr_extents) )
|
||||
+ {
|
||||
+ rc = -EFAULT;
|
||||
+ goto fail_early;
|
||||
+ }
|
||||
+
|
||||
/* Only privileged guests can allocate multi-page contiguous extents. */
|
||||
if ( !multipage_allocation_permitted(current->domain,
|
||||
exch.in.extent_order) ||
|
||||
|
||||
|
@ -1,56 +0,0 @@
|
||||
xen: fix error handling of guest_physmap_mark_populate_on_demand()
|
||||
|
||||
The only user of the "out" label bypasses a necessary unlock, thus
|
||||
enabling the caller to lock up Xen.
|
||||
|
||||
Also, the function was never meant to be called by a guest for itself,
|
||||
so rather than inspecting the code paths in depth for potential other
|
||||
problems this might cause, and adjusting e.g. the non-guest printk()
|
||||
in the above error path, just disallow the guest access to it.
|
||||
|
||||
Finally, the printk() (considering its potential of spamming the log,
|
||||
the more that it's not using XENLOG_GUEST), is being converted to
|
||||
P2M_DEBUG(), as debugging is what it apparently was added for in the
|
||||
first place.
|
||||
|
||||
This is XSA-30 / CVE-2012-5514.
|
||||
|
||||
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
||||
Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
Acked-by: George Dunlap <george.dunlap@eu.citrix.com>
|
||||
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Committed-by: Ian Jackson <ian.jackson.citrix.com>
|
||||
|
||||
diff -r 83ab3cd0f8e4 -r 09a48c5da636 xen/arch/x86/mm/p2m-pod.c
|
||||
--- xen/arch/x86/mm/p2m-pod.c Tue Dec 04 18:02:44 2012 +0000
|
||||
+++ xen/arch/x86/mm/p2m-pod.c Tue Dec 04 18:02:48 2012 +0000
|
||||
@@ -1117,6 +1117,9 @@ guest_physmap_mark_populate_on_demand(st
|
||||
mfn_t omfn;
|
||||
int rc = 0;
|
||||
|
||||
+ if ( !IS_PRIV_FOR(current->domain, d) )
|
||||
+ return -EPERM;
|
||||
+
|
||||
if ( !paging_mode_translate(d) )
|
||||
return -EINVAL;
|
||||
|
||||
@@ -1135,8 +1138,7 @@ guest_physmap_mark_populate_on_demand(st
|
||||
omfn = p2m->get_entry(p2m, gfn + i, &ot, &a, 0, NULL);
|
||||
if ( p2m_is_ram(ot) )
|
||||
{
|
||||
- printk("%s: gfn_to_mfn returned type %d!\n",
|
||||
- __func__, ot);
|
||||
+ P2M_DEBUG("gfn_to_mfn returned type %d!\n", ot);
|
||||
rc = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
@@ -1160,9 +1162,9 @@ guest_physmap_mark_populate_on_demand(st
|
||||
pod_unlock(p2m);
|
||||
}
|
||||
|
||||
+out:
|
||||
gfn_unlock(p2m, gfn, order);
|
||||
|
||||
-out:
|
||||
return rc;
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
|
||||
# HG changeset patch
|
||||
# User Jan Beulich <jbeulich@suse.com>
|
||||
# Date 1354644172 0
|
||||
# Node ID 2c3f00c5189b9269f9840be93d03f058c8994f6e
|
||||
# Parent 09a48c5da6368ac61bdba5ee09253c2b20d7b577
|
||||
memop: limit guest specified extent order
|
||||
|
||||
Allowing unbounded order values here causes almost unbounded loops
|
||||
and/or partially incomplete requests, particularly in PoD code.
|
||||
|
||||
The added range checks in populate_physmap(), decrease_reservation(),
|
||||
and the "in" one in memory_exchange() architecturally all could use
|
||||
PADDR_BITS - PAGE_SHIFT, and are being artificially constrained to
|
||||
MAX_ORDER.
|
||||
|
||||
This is XSA-31 / CVE-2012-5515.
|
||||
|
||||
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
||||
Acked-by: Tim Deegan <tim@xen.org>
|
||||
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
Committed-by: Ian Jackson <ian.jackson.citrix.com>
|
||||
|
||||
diff -r 09a48c5da636 -r 2c3f00c5189b xen/common/memory.c
|
||||
--- xen/common/memory.c Tue Dec 04 18:02:48 2012 +0000
|
||||
+++ xen/common/memory.c Tue Dec 04 18:02:52 2012 +0000
|
||||
@@ -115,7 +115,8 @@ static void populate_physmap(struct memo
|
||||
|
||||
if ( a->memflags & MEMF_populate_on_demand )
|
||||
{
|
||||
- if ( guest_physmap_mark_populate_on_demand(d, gpfn,
|
||||
+ if ( a->extent_order > MAX_ORDER ||
|
||||
+ guest_physmap_mark_populate_on_demand(d, gpfn,
|
||||
a->extent_order) < 0 )
|
||||
goto out;
|
||||
}
|
||||
@@ -235,7 +236,8 @@ static void decrease_reservation(struct
|
||||
xen_pfn_t gmfn;
|
||||
|
||||
if ( !guest_handle_subrange_okay(a->extent_list, a->nr_done,
|
||||
- a->nr_extents-1) )
|
||||
+ a->nr_extents-1) ||
|
||||
+ a->extent_order > MAX_ORDER )
|
||||
return;
|
||||
|
||||
for ( i = a->nr_done; i < a->nr_extents; i++ )
|
||||
@@ -297,6 +299,9 @@ static long memory_exchange(XEN_GUEST_HA
|
||||
if ( (exch.nr_exchanged > exch.in.nr_extents) ||
|
||||
/* Input and output domain identifiers match? */
|
||||
(exch.in.domid != exch.out.domid) ||
|
||||
+ /* Extent orders are sensible? */
|
||||
+ (exch.in.extent_order > MAX_ORDER) ||
|
||||
+ (exch.out.extent_order > MAX_ORDER) ||
|
||||
/* Sizes of input and output lists do not overflow a long? */
|
||||
((~0UL >> exch.in.extent_order) < exch.in.nr_extents) ||
|
||||
((~0UL >> exch.out.extent_order) < exch.out.nr_extents) ||
|
||||
|
||||
|
@ -1,23 +0,0 @@
|
||||
x86: get_page_from_gfn() must return NULL for invalid GFNs
|
||||
|
||||
... also in the non-translated case.
|
||||
|
||||
This is XSA-32 / CVE-2012-xxxx.
|
||||
|
||||
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
||||
Acked-by: Tim Deegan <tim@xen.org>
|
||||
|
||||
diff --git a/xen/include/asm-x86/p2m.h b/xen/include/asm-x86/p2m.h
|
||||
index 28be4e8..907a817 100644
|
||||
--- xen/include/asm-x86/p2m.h
|
||||
+++ xen/include/asm-x86/p2m.h
|
||||
@@ -384,7 +384,7 @@ static inline struct page_info *get_page_from_gfn(
|
||||
if (t)
|
||||
*t = p2m_ram_rw;
|
||||
page = __mfn_to_page(gfn);
|
||||
- return get_page(page, d) ? page : NULL;
|
||||
+ return mfn_valid(gfn) && get_page(page, d) ? page : NULL;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,211 +0,0 @@
|
||||
commit 66141b2e068fa39f28bdda6be05882e323663687
|
||||
Author: Michael Young
|
||||
Date: Tue Jan 22 22:22:10 2013 +0000
|
||||
|
||||
Security fix from nested virtualization CVE-2013-0151,
|
||||
restore status option to xend which is used by libvirt
|
||||
#diff --git a/xsa34-4.2.patch b/xsa34-4.2.patch
|
||||
#new file mode 100644
|
||||
#index 0000000..f5328ef
|
||||
#--- /dev/null
|
||||
#+++ xsa34-4.2.patch
|
||||
#@@ -0,0 +1,30 @@
|
||||
#+x86_32: don't allow use of nested HVM
|
||||
#+
|
||||
#+There are (indirect) uses of map_domain_page() in the nested HVM code
|
||||
#+that are unsafe when not just using the 1:1 mapping.
|
||||
#+
|
||||
#+This is XSA-34 / CVE-2013-0151.
|
||||
#+
|
||||
#+Signed-off-by: Jan Beulich
|
||||
#+
|
||||
#diff --git a/xsa35-4.2-with-xsa34.patch b/xsa35-4.2-with-xsa34.patch
|
||||
#new file mode 100644
|
||||
#index 0000000..28c6171
|
||||
#--- /dev/null
|
||||
#+++ xsa35-4.2-with-xsa34.patch
|
||||
#@@ -0,0 +1,24 @@
|
||||
#+xen: Do not allow guests to enable nested HVM on themselves
|
||||
#+
|
||||
#+There is no reason for this and doing so exposes a memory leak to
|
||||
#+guests. Only toolstacks need write access to this HVM param.
|
||||
#+
|
||||
#+This is XSA-35 / CVE-2013-0152.
|
||||
#+
|
||||
#+Signed-off-by: Ian Campbell
|
||||
#+Acked-by: Jan Beulich
|
||||
#+
|
||||
--- xen/arch/x86/hvm/hvm.c
|
||||
+++ xen/arch/x86/hvm/hvm.c
|
||||
@@ -3858,6 +3858,11 @@
|
||||
rc = -EINVAL;
|
||||
break;
|
||||
case HVM_PARAM_NESTEDHVM:
|
||||
+ if ( !IS_PRIV(current->domain) )
|
||||
+ {
|
||||
+ rc = -EPERM;
|
||||
+ break;
|
||||
+ }
|
||||
if ( a.value > 1 )
|
||||
rc = -EINVAL;
|
||||
if ( !is_hvm_domain(d) )
|
||||
@@ -3926,6 +3926,10 @@ long do_hvm_op(unsigned long op, XEN_GUE
|
||||
rc = -EINVAL;
|
||||
break;
|
||||
case HVM_PARAM_NESTEDHVM:
|
||||
+#ifdef __i386__
|
||||
+ if ( a.value )
|
||||
+ rc = -EINVAL;
|
||||
+#else
|
||||
if ( a.value > 1 )
|
||||
rc = -EINVAL;
|
||||
if ( !is_hvm_domain(d) )
|
||||
@@ -3940,6 +3944,7 @@ long do_hvm_op(unsigned long op, XEN_GUE
|
||||
for_each_vcpu(d, v)
|
||||
if ( rc == 0 )
|
||||
rc = nestedhvm_vcpu_initialise(v);
|
||||
+#endif
|
||||
break;
|
||||
case HVM_PARAM_BUFIOREQ_EVTCHN:
|
||||
rc = -EINVAL;
|
||||
# HG changeset patch
|
||||
# User Tim Deegan <tim@xen.org>
|
||||
# Date 1354644158 0
|
||||
# Node ID 5771c761ff1bb249dc683d7ec019d76a2a03a048
|
||||
# Parent dea7d4e5bfc1627133c0c19706fea1fbc9e5a378
|
||||
#hvm: Limit the size of large HVM op batches
|
||||
#
|
||||
#Doing large p2m updates for HVMOP_track_dirty_vram without preemption
|
||||
#ties up the physical processor. Integrating preemption into the p2m
|
||||
#updates is hard so simply limit to 1GB which is sufficient for a 15000
|
||||
#* 15000 * 32bpp framebuffer.
|
||||
#
|
||||
#For HVMOP_modified_memory and HVMOP_set_mem_type preemptible add the
|
||||
#necessary machinery to handle preemption.
|
||||
#
|
||||
#This is CVE-2012-5511 / XSA-27.
|
||||
#
|
||||
#Signed-off-by: Tim Deegan <tim@xen.org>
|
||||
#Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
|
||||
#Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
#Committed-by: Ian Jackson <ian.jackson.citrix.com>
|
||||
#
|
||||
#v2: Provide definition of GB to fix x86-32 compile.
|
||||
#
|
||||
#Signed-off-by: Jan Beulich <JBeulich@suse.com>
|
||||
#Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
||||
diff -r dea7d4e5bfc1 -r 5771c761ff1b xen/arch/x86/hvm/hvm.c
|
||||
--- xen/arch/x86/hvm/hvm.c Tue Dec 04 18:02:18 2012 +0000
|
||||
+++ xen/arch/x86/hvm/hvm.c Tue Dec 04 18:02:38 2012 +0000
|
||||
@@ -3969,6 +3969,9 @@ long do_hvm_op(unsigned long op, XEN_GUE
|
||||
if ( !is_hvm_domain(d) )
|
||||
goto param_fail2;
|
||||
|
||||
+ if ( a.nr > GB(1) >> PAGE_SHIFT )
|
||||
+ goto param_fail2;
|
||||
+
|
||||
rc = xsm_hvm_param(d, op);
|
||||
if ( rc )
|
||||
goto param_fail2;
|
||||
@@ -3995,7 +3998,6 @@ long do_hvm_op(unsigned long op, XEN_GUE
|
||||
{
|
||||
struct xen_hvm_modified_memory a;
|
||||
struct domain *d;
|
||||
- unsigned long pfn;
|
||||
|
||||
if ( copy_from_guest(&a, arg, 1) )
|
||||
return -EFAULT;
|
||||
@@ -4022,9 +4024,11 @@ long do_hvm_op(unsigned long op, XEN_GUE
|
||||
if ( !paging_mode_log_dirty(d) )
|
||||
goto param_fail3;
|
||||
|
||||
- for ( pfn = a.first_pfn; pfn < a.first_pfn + a.nr; pfn++ )
|
||||
+ while ( a.nr > 0 )
|
||||
{
|
||||
+ unsigned long pfn = a.first_pfn;
|
||||
struct page_info *page;
|
||||
+
|
||||
page = get_page_from_gfn(d, pfn, NULL, P2M_UNSHARE);
|
||||
if ( page )
|
||||
{
|
||||
@@ -4034,6 +4038,19 @@ long do_hvm_op(unsigned long op, XEN_GUE
|
||||
sh_remove_shadows(d->vcpu[0], _mfn(page_to_mfn(page)), 1, 0);
|
||||
put_page(page);
|
||||
}
|
||||
+
|
||||
+ a.first_pfn++;
|
||||
+ a.nr--;
|
||||
+
|
||||
+ /* Check for continuation if it's not the last interation */
|
||||
+ if ( a.nr > 0 && hypercall_preempt_check() )
|
||||
+ {
|
||||
+ if ( copy_to_guest(arg, &a, 1) )
|
||||
+ rc = -EFAULT;
|
||||
+ else
|
||||
+ rc = -EAGAIN;
|
||||
+ break;
|
||||
+ }
|
||||
}
|
||||
|
||||
param_fail3:
|
||||
@@ -4089,7 +4106,6 @@ long do_hvm_op(unsigned long op, XEN_GUE
|
||||
{
|
||||
struct xen_hvm_set_mem_type a;
|
||||
struct domain *d;
|
||||
- unsigned long pfn;
|
||||
|
||||
/* Interface types to internal p2m types */
|
||||
p2m_type_t memtype[] = {
|
||||
@@ -4122,8 +4138,9 @@ long do_hvm_op(unsigned long op, XEN_GUE
|
||||
if ( a.hvmmem_type >= ARRAY_SIZE(memtype) )
|
||||
goto param_fail4;
|
||||
|
||||
- for ( pfn = a.first_pfn; pfn < a.first_pfn + a.nr; pfn++ )
|
||||
+ while ( a.nr )
|
||||
{
|
||||
+ unsigned long pfn = a.first_pfn;
|
||||
p2m_type_t t;
|
||||
p2m_type_t nt;
|
||||
mfn_t mfn;
|
||||
@@ -4163,6 +4180,19 @@ long do_hvm_op(unsigned long op, XEN_GUE
|
||||
}
|
||||
}
|
||||
put_gfn(d, pfn);
|
||||
+
|
||||
+ a.first_pfn++;
|
||||
+ a.nr--;
|
||||
+
|
||||
+ /* Check for continuation if it's not the last interation */
|
||||
+ if ( a.nr > 0 && hypercall_preempt_check() )
|
||||
+ {
|
||||
+ if ( copy_to_guest(arg, &a, 1) )
|
||||
+ rc = -EFAULT;
|
||||
+ else
|
||||
+ rc = -EAGAIN;
|
||||
+ goto param_fail4;
|
||||
+ }
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
diff -r dea7d4e5bfc1 -r 5771c761ff1b xen/include/asm-x86/config.h
|
||||
--- xen/include/asm-x86/config.h Tue Dec 04 18:02:18 2012 +0000
|
||||
+++ xen/include/asm-x86/config.h Tue Dec 04 18:02:38 2012 +0000
|
||||
@@ -119,6 +119,9 @@ extern char wakeup_start[];
|
||||
extern unsigned int video_mode, video_flags;
|
||||
extern unsigned short boot_edid_caps;
|
||||
extern unsigned char boot_edid_info[128];
|
||||
+
|
||||
+#define GB(_gb) (_gb ## UL << 30)
|
||||
+
|
||||
#endif
|
||||
|
||||
#define asmlinkage
|
||||
@@ -134,7 +137,6 @@ extern unsigned char boot_edid_info[128]
|
||||
#define PML4_ADDR(_slot) \
|
||||
((((_slot ## UL) >> 8) * 0xffff000000000000UL) | \
|
||||
(_slot ## UL << PML4_ENTRY_BITS))
|
||||
-#define GB(_gb) (_gb ## UL << 30)
|
||||
#else
|
||||
#define PML4_ENTRY_BYTES (1 << PML4_ENTRY_BITS)
|
||||
#define PML4_ADDR(_slot) \
|
||||
|
@ -1,31 +0,0 @@
|
||||
defer event channel bucket pointer store until after XSM checks
|
||||
|
||||
Otherwise a dangling pointer can be left, which would cause subsequent
|
||||
memory corruption as soon as the space got re-allocated for some other
|
||||
purpose.
|
||||
|
||||
This is CVE-2013-1920 / XSA-47.
|
||||
|
||||
Reported-by: Wei Liu <wei.liu2@citrix.com>
|
||||
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
||||
Reviewed-by: Tim Deegan <tim@xen.org>
|
||||
|
||||
--- a/xen/common/event_channel.c
|
||||
+++ b/xen/common/event_channel.c
|
||||
@@ -140,7 +140,6 @@ static int get_free_port(struct domain *
|
||||
chn = xzalloc_array(struct evtchn, EVTCHNS_PER_BUCKET);
|
||||
if ( unlikely(chn == NULL) )
|
||||
return -ENOMEM;
|
||||
- bucket_from_port(d, port) = chn;
|
||||
|
||||
for ( i = 0; i < EVTCHNS_PER_BUCKET; i++ )
|
||||
{
|
||||
@@ -153,6 +152,8 @@ static int get_free_port(struct domain *
|
||||
}
|
||||
}
|
||||
|
||||
+ bucket_from_port(d, port) = chn;
|
||||
+
|
||||
return port;
|
||||
}
|
||||
|
@ -1,74 +0,0 @@
|
||||
|
||||
# HG changeset patch
|
||||
# User Tim Deegan <Tim.Deegan@citrix.com>
|
||||
# Date 1313145221 -3600
|
||||
# Node ID 84e3706df07a1963e23cd3875d8603917657d462
|
||||
# Parent cb22fa57ff252893b6adb1481e09b1287eacd990
|
||||
Passthrough: disable bus-mastering on any card that causes an IOMMU fault.
|
||||
|
||||
This stops the card from raising back-to-back faults and live-locking
|
||||
the CPU that handles them.
|
||||
|
||||
Signed-off-by: Tim Deegan <tim@xen.org>
|
||||
Acked-by: Wei Wang2 <wei.wang2@amd.com>
|
||||
Acked-by: Allen M Kay <allen.m.kay@intel.com>
|
||||
|
||||
diff -r cb22fa57ff25 -r 84e3706df07a xen/drivers/passthrough/amd/iommu_init.c
|
||||
--- a/xen/drivers/passthrough/amd/iommu_init.c Mon Jul 25 16:48:39 2011 +0100
|
||||
+++ b/xen/drivers/passthrough/amd/iommu_init.c Fri Aug 12 11:33:41 2011 +0100
|
||||
@@ -462,7 +462,7 @@
|
||||
|
||||
static void parse_event_log_entry(u32 entry[])
|
||||
{
|
||||
- u16 domain_id, device_id;
|
||||
+ u16 domain_id, device_id, bdf, cword;
|
||||
u32 code;
|
||||
u64 *addr;
|
||||
char * event_str[] = {"ILLEGAL_DEV_TABLE_ENTRY",
|
||||
@@ -497,6 +497,18 @@
|
||||
"%s: domain = %d, device id = 0x%04x, "
|
||||
"fault address = 0x%"PRIx64"\n",
|
||||
event_str[code-1], domain_id, device_id, *addr);
|
||||
+
|
||||
+ /* Tell the device to stop DMAing; we can't rely on the guest to
|
||||
+ * control it for us. */
|
||||
+ for ( bdf = 0; bdf < ivrs_bdf_entries; bdf++ )
|
||||
+ if ( get_dma_requestor_id(bdf) == device_id )
|
||||
+ {
|
||||
+ cword = pci_conf_read16(PCI_BUS(bdf), PCI_SLOT(bdf),
|
||||
+ PCI_FUNC(bdf), PCI_COMMAND);
|
||||
+ pci_conf_write16(PCI_BUS(bdf), PCI_SLOT(bdf),
|
||||
+ PCI_FUNC(bdf), PCI_COMMAND,
|
||||
+ cword & ~PCI_COMMAND_MASTER);
|
||||
+ }
|
||||
}
|
||||
else
|
||||
{
|
||||
diff -r cb22fa57ff25 -r 84e3706df07a xen/drivers/passthrough/vtd/iommu.c
|
||||
--- a/xen/drivers/passthrough/vtd/iommu.c Mon Jul 25 16:48:39 2011 +0100
|
||||
+++ b/xen/drivers/passthrough/vtd/iommu.c Fri Aug 12 11:33:41 2011 +0100
|
||||
@@ -893,7 +893,7 @@
|
||||
while (1)
|
||||
{
|
||||
u8 fault_reason;
|
||||
- u16 source_id;
|
||||
+ u16 source_id, cword;
|
||||
u32 data;
|
||||
u64 guest_addr;
|
||||
int type;
|
||||
@@ -926,6 +926,14 @@
|
||||
iommu_page_fault_do_one(iommu, type, fault_reason,
|
||||
source_id, guest_addr);
|
||||
|
||||
+ /* Tell the device to stop DMAing; we can't rely on the guest to
|
||||
+ * control it for us. */
|
||||
+ cword = pci_conf_read16(PCI_BUS(source_id), PCI_SLOT(source_id),
|
||||
+ PCI_FUNC(source_id), PCI_COMMAND);
|
||||
+ pci_conf_write16(PCI_BUS(source_id), PCI_SLOT(source_id),
|
||||
+ PCI_FUNC(source_id), PCI_COMMAND,
|
||||
+ cword & ~PCI_COMMAND_MASTER);
|
||||
+
|
||||
fault_index++;
|
||||
if ( fault_index > cap_num_fault_regs(iommu->cap) )
|
||||
fault_index = 0;
|
||||
|
@ -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,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,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 +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"
|
@ -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}"
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue