From: Jason Andryuk <jandryuk@gmail.com>
To: jandryuk@gmail.com, xen-devel@lists.xenproject.org
Cc: andrew.cooper3@citrix.com, george.dunlap@citrix.com,
iwj@xenproject.org, jbeulich@suse.com, julien@xen.org,
roger.pau@citrix.com, sstabellini@kernel.org, wl@xen.org
Subject: [RFC PATCH 2/3] libelf: Use flags to check pv or pvh in elf_xen_parse
Date: Fri, 14 May 2021 11:17:30 -0400 [thread overview]
Message-ID: <20210514151731.19272-2-jandryuk@gmail.com> (raw)
In-Reply-To: <20210514151731.19272-1-jandryuk@gmail.com>
Certain checks are only applicable to PV vs. PVH, so split them and run
only the appropriate checks for each.
This fixes loading a PVH kernel that has a PHYS32_ENTRY but not an ENTRY
ELF note. Such a kernel would fail the virt_entry check which is not
applicable for PVH.
This re-instatates loader and xen version checks for the PV case that
were omited for kernels passing the PHYS32_ENTRY check.
Signed-off-by: Jason Andryuk <jandryuk@gmail.com>
---
tools/fuzz/libelf/libelf-fuzzer.c | 2 +-
tools/libs/guest/xg_dom_elfloader.c | 11 +++-
tools/libs/guest/xg_dom_hvmloader.c | 2 +-
xen/arch/x86/hvm/dom0_build.c | 2 +-
xen/arch/x86/pv/dom0_build.c | 2 +-
xen/common/libelf/libelf-dominfo.c | 91 +++++++++++++++++++++++------
xen/include/xen/libelf.h | 7 ++-
7 files changed, 93 insertions(+), 24 deletions(-)
diff --git a/tools/fuzz/libelf/libelf-fuzzer.c b/tools/fuzz/libelf/libelf-fuzzer.c
index 1ba8571711..f488510618 100644
--- a/tools/fuzz/libelf/libelf-fuzzer.c
+++ b/tools/fuzz/libelf/libelf-fuzzer.c
@@ -17,7 +17,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
return -1;
elf_parse_binary(elf);
- elf_xen_parse(elf, &parms);
+ elf_xen_parse(elf, &parms, ELF_XEN_CHECK_PV | ELF_XEN_CHECK_PVH);
return 0;
}
diff --git a/tools/libs/guest/xg_dom_elfloader.c b/tools/libs/guest/xg_dom_elfloader.c
index 06e713fe11..c3280b1603 100644
--- a/tools/libs/guest/xg_dom_elfloader.c
+++ b/tools/libs/guest/xg_dom_elfloader.c
@@ -120,6 +120,7 @@ static elf_negerrnoval check_elf_kernel(struct xc_dom_image *dom, bool verbose)
static elf_negerrnoval xc_dom_probe_elf_kernel(struct xc_dom_image *dom)
{
struct elf_binary elf;
+ unsigned int flags;
int rc;
rc = check_elf_kernel(dom, 0);
@@ -135,7 +136,9 @@ static elf_negerrnoval xc_dom_probe_elf_kernel(struct xc_dom_image *dom)
* or else we might be trying to load a plain ELF.
*/
elf_parse_binary(&elf);
- rc = elf_xen_parse(&elf, dom->parms);
+ flags = dom->container_type == XC_DOM_PV_CONTAINER ? ELF_XEN_CHECK_PV :
+ ELF_XEN_CHECK_PVH;
+ rc = elf_xen_parse(&elf, dom->parms, flags);
if ( rc != 0 )
return rc;
@@ -146,6 +149,7 @@ static elf_negerrnoval xc_dom_parse_elf_kernel(struct xc_dom_image *dom)
{
struct elf_binary *elf;
elf_negerrnoval rc;
+ unsigned int flags;
rc = check_elf_kernel(dom, 1);
if ( rc != 0 )
@@ -166,7 +170,10 @@ static elf_negerrnoval xc_dom_parse_elf_kernel(struct xc_dom_image *dom)
/* parse binary and get xen meta info */
elf_parse_binary(elf);
- if ( elf_xen_parse(elf, dom->parms) != 0 )
+ flags = dom->container_type == XC_DOM_PV_CONTAINER ? ELF_XEN_CHECK_PV :
+ ELF_XEN_CHECK_PVH;
+ rc = elf_xen_parse(elf, dom->parms, flags);
+ if ( rc != 0 )
{
rc = -EINVAL;
goto out;
diff --git a/tools/libs/guest/xg_dom_hvmloader.c b/tools/libs/guest/xg_dom_hvmloader.c
index ec6ebad7fd..bf28690415 100644
--- a/tools/libs/guest/xg_dom_hvmloader.c
+++ b/tools/libs/guest/xg_dom_hvmloader.c
@@ -73,7 +73,7 @@ static elf_negerrnoval xc_dom_probe_hvm_kernel(struct xc_dom_image *dom)
* else we might be trying to load a PV kernel.
*/
elf_parse_binary(&elf);
- rc = elf_xen_parse(&elf, dom->parms);
+ rc = elf_xen_parse(&elf, dom->parms, ELF_XEN_CHECK_PV | ELF_XEN_CHECK_PVH);
if ( rc == 0 )
return -EINVAL;
diff --git a/xen/arch/x86/hvm/dom0_build.c b/xen/arch/x86/hvm/dom0_build.c
index 5b9192ecc6..552448ce5d 100644
--- a/xen/arch/x86/hvm/dom0_build.c
+++ b/xen/arch/x86/hvm/dom0_build.c
@@ -561,7 +561,7 @@ static int __init pvh_load_kernel(struct domain *d, const module_t *image,
elf_set_verbose(&elf);
#endif
elf_parse_binary(&elf);
- if ( (rc = elf_xen_parse(&elf, &parms)) != 0 )
+ if ( (rc = elf_xen_parse(&elf, &parms, ELF_XEN_CHECK_PVH)) != 0 )
{
printk("Unable to parse kernel for ELFNOTES\n");
return rc;
diff --git a/xen/arch/x86/pv/dom0_build.c b/xen/arch/x86/pv/dom0_build.c
index e0801a9e6d..8bc77b0366 100644
--- a/xen/arch/x86/pv/dom0_build.c
+++ b/xen/arch/x86/pv/dom0_build.c
@@ -353,7 +353,7 @@ int __init dom0_construct_pv(struct domain *d,
elf_set_verbose(&elf);
elf_parse_binary(&elf);
- if ( (rc = elf_xen_parse(&elf, &parms)) != 0 )
+ if ( (rc = elf_xen_parse(&elf, &parms, ELF_XEN_CHECK_PV)) != 0 )
goto out;
/* compatibility check */
diff --git a/xen/common/libelf/libelf-dominfo.c b/xen/common/libelf/libelf-dominfo.c
index b1f36866eb..13eb39ec52 100644
--- a/xen/common/libelf/libelf-dominfo.c
+++ b/xen/common/libelf/libelf-dominfo.c
@@ -359,7 +359,21 @@ elf_errorstatus elf_xen_parse_guest_info(struct elf_binary *elf,
/* ------------------------------------------------------------------------ */
/* sanity checks */
-static elf_errorstatus elf_xen_note_check(struct elf_binary *elf,
+static elf_errorstatus elf_xen_note_check_pvh(struct elf_binary *elf,
+ struct elf_dom_parms *parms)
+{
+ /* PVH only requires one ELF note to be set */
+ if (parms->phys_entry != UNSET_ADDR32 )
+ {
+ elf_msg(elf, "ELF: Found PVH image\n");
+ return 0;
+ } else {
+ elf_err(elf, "ELF: Missing PVH PHYS32_ENTRY\n");
+ return -1;
+ }
+}
+
+static elf_errorstatus elf_xen_note_check_pv(struct elf_binary *elf,
struct elf_dom_parms *parms)
{
if ( (ELF_PTRVAL_INVALID(parms->elf_note_start)) &&
@@ -381,13 +395,6 @@ static elf_errorstatus elf_xen_note_check(struct elf_binary *elf,
return 0;
}
- /* PVH only requires one ELF note to be set */
- if ( parms->phys_entry != UNSET_ADDR32 )
- {
- elf_msg(elf, "ELF: Found PVH image\n");
- return 0;
- }
-
/* Check the contents of the Xen notes or guest string. */
if ( ((strlen(parms->loader) == 0) ||
strncmp(parms->loader, "generic", 7)) &&
@@ -413,7 +420,36 @@ static elf_errorstatus elf_xen_note_check(struct elf_binary *elf,
return 0;
}
-static elf_errorstatus elf_xen_addr_calc_check(struct elf_binary *elf,
+static elf_errorstatus elf_xen_addr_calc_check_pvh(struct elf_binary *elf,
+ struct elf_dom_parms *parms)
+{
+ parms->phys_kstart = elf->pstart;
+ parms->phys_kend = elf->pend;
+
+ if ( parms->bsd_symtab )
+ {
+ elf_parse_bsdsyms(elf, elf->pend);
+ if ( elf->bsd_symtab_pend )
+ parms->phys_kend = elf->bsd_symtab_pend;
+ }
+
+ elf_msg(elf, "ELF: addresses:\n");
+ elf_msg(elf, " phys_kstart = 0x%" PRIx64 "\n", parms->phys_kstart);
+ elf_msg(elf, " phys_kend = 0x%" PRIx64 "\n", parms->phys_kend);
+ elf_msg(elf, " phys_entry = 0x%" PRIx32 "\n", parms->phys_entry);
+
+ if ( parms->phys_kstart > parms->phys_kend ||
+ parms->phys_entry < parms->phys_kstart ||
+ parms->phys_entry > parms->phys_kend )
+ {
+ elf_err(elf, "ERROR: ELF start or entries are out of bounds\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static elf_errorstatus elf_xen_addr_calc_check_pv(struct elf_binary *elf,
struct elf_dom_parms *parms)
{
uint64_t virt_offset;
@@ -453,8 +489,6 @@ static elf_errorstatus elf_xen_addr_calc_check(struct elf_binary *elf,
}
virt_offset = parms->virt_base - parms->elf_paddr_offset;
- parms->phys_kstart = elf->pstart;
- parms->phys_kend = elf->pend;
parms->virt_kstart = elf->pstart + virt_offset;
parms->virt_kend = elf->pend + virt_offset;
@@ -466,7 +500,6 @@ static elf_errorstatus elf_xen_addr_calc_check(struct elf_binary *elf,
elf_parse_bsdsyms(elf, elf->pend);
if ( elf->bsd_symtab_pend )
parms->virt_kend = elf->bsd_symtab_pend + virt_offset;
- parms->phys_kend = elf->bsd_symtab_pend;
}
elf_msg(elf, "ELF: addresses:\n");
@@ -500,9 +533,8 @@ static elf_errorstatus elf_xen_addr_calc_check(struct elf_binary *elf,
/* ------------------------------------------------------------------------ */
/* glue it all together ... */
-
-elf_errorstatus elf_xen_parse(struct elf_binary *elf,
- struct elf_dom_parms *parms)
+static elf_errorstatus elf_xen_parse_common(struct elf_binary *elf,
+ struct elf_dom_parms *parms)
{
ELF_HANDLE_DECL(elf_shdr) shdr;
ELF_HANDLE_DECL(elf_phdr) phdr;
@@ -597,10 +629,35 @@ elf_errorstatus elf_xen_parse(struct elf_binary *elf,
}
}
- if ( elf_xen_note_check(elf, parms) != 0 )
+ return 0;
+}
+
+elf_errorstatus elf_xen_parse(struct elf_binary *elf,
+ struct elf_dom_parms *parms,
+ unsigned int flags)
+{
+ if ( !flags ) {
+ elf_err(elf, "Must specify ELF_XEN_CHECK_{PV,PVH} flags to check");
return -1;
- if ( elf_xen_addr_calc_check(elf, parms) != 0 )
+ }
+
+ if ( elf_xen_parse_common(elf, parms) != 0 )
return -1;
+
+ if ( flags & ELF_XEN_CHECK_PV ) {
+ if ( elf_xen_note_check_pv(elf, parms) != 0 )
+ return -1;
+ if ( elf_xen_addr_calc_check_pv(elf, parms) != 0 )
+ return -1;
+ }
+
+ if ( flags & ELF_XEN_CHECK_PVH ) {
+ if ( elf_xen_note_check_pvh(elf, parms) != 0 )
+ return -1;
+ if ( elf_xen_addr_calc_check_pvh(elf, parms) != 0 )
+ return -1;
+ }
+
return 0;
}
diff --git a/xen/include/xen/libelf.h b/xen/include/xen/libelf.h
index 8d80d0812a..858f42cf07 100644
--- a/xen/include/xen/libelf.h
+++ b/xen/include/xen/libelf.h
@@ -455,8 +455,13 @@ int elf_xen_parse_note(struct elf_binary *elf,
ELF_HANDLE_DECL(elf_note) note);
int elf_xen_parse_guest_info(struct elf_binary *elf,
struct elf_dom_parms *parms);
+
+#define ELF_XEN_CHECK_PV (1 << 0)
+#define ELF_XEN_CHECK_PVH (1 << 1)
+
int elf_xen_parse(struct elf_binary *elf,
- struct elf_dom_parms *parms);
+ struct elf_dom_parms *parms,
+ unsigned int flags);
static inline void *elf_memcpy_unchecked(void *dest, const void *src, size_t n)
{ return memcpy(dest, src, n); }
--
2.31.1
next prev parent reply other threads:[~2021-05-14 15:18 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-05-14 13:50 [PATCH] libelf: improve PVH elfnote parsing Roger Pau Monne
2021-05-14 15:11 ` Jason Andryuk
2021-05-14 15:17 ` [RFC PATCH 1/3] libelf: Introduce phys_kstart/end Jason Andryuk
2021-05-14 15:17 ` Jason Andryuk [this message]
2021-05-14 15:17 ` [RFC PATCH 3/3] libelf: PVH: only allow elf_paddr_offset of 0 Jason Andryuk
2021-05-18 11:28 ` [PATCH] libelf: improve PVH elfnote parsing Roger Pau Monné
2021-05-17 11:09 ` Jan Beulich
2021-05-18 11:22 ` Roger Pau Monné
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210514151731.19272-2-jandryuk@gmail.com \
--to=jandryuk@gmail.com \
--cc=andrew.cooper3@citrix.com \
--cc=george.dunlap@citrix.com \
--cc=iwj@xenproject.org \
--cc=jbeulich@suse.com \
--cc=julien@xen.org \
--cc=roger.pau@citrix.com \
--cc=sstabellini@kernel.org \
--cc=wl@xen.org \
--cc=xen-devel@lists.xenproject.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).