aboutsummaryrefslogtreecommitdiffstats
path: root/xen/common
diff options
context:
space:
mode:
authorIan Jackson <ian.jackson@eu.citrix.com>2013-06-14 16:39:36 +0100
committerIan Jackson <Ian.Jackson@eu.citrix.com>2013-06-14 16:39:36 +0100
commita004800f8fc607b96527815c8e3beabcb455d8e0 (patch)
treebedfb7dc80066010059b5ffd17b8affdb138b8cd /xen/common
parent7a549a6aa04dba807f8dd4c1577ab6a7592c4c76 (diff)
downloadxen-a004800f8fc607b96527815c8e3beabcb455d8e0.tar.gz
xen-a004800f8fc607b96527815c8e3beabcb455d8e0.tar.bz2
xen-a004800f8fc607b96527815c8e3beabcb455d8e0.zip
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> Reviewed-by: George Dunlap <george.dunlap@eu.citrix.com> Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com> v8: Use "?!?!" to express consternation instead of a ruder phrase. v5: Introduce ELF_NOTE_INVALID, instead of using a literal ~0U. v4: Fix regression in elf_round_up; use uint64_t here. v3: Changes to booleans split off into separate patch. v2: BUGFIX: Eliminate conversion to int of return from elf_xen_parse_notes. BUGFIX: Fix the one printf format thing which needs changing. Remove irrelevant change to constify note_desc.name in libelf-dominfo.c. In xc_dom_load_elf_symtab change one sizeof(int) to sizeof(unsigned). Do not change type of 2nd argument to memset. Provide seddery for easier review. Style fix.
Diffstat (limited to 'xen/common')
-rw-r--r--xen/common/libelf/Makefile2
-rw-r--r--xen/common/libelf/libelf-dominfo.c52
-rw-r--r--xen/common/libelf/libelf-loader.c20
-rw-r--r--xen/common/libelf/libelf-tools.c24
4 files changed, 51 insertions, 47 deletions
diff --git a/xen/common/libelf/Makefile b/xen/common/libelf/Makefile
index 18dc8e206f..5bf8f764f1 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 c4ced67bbd..0b0700260c 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 798f88bd54..937c99b463 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 0b7b2b634c..6543f33615 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);
}