diff options
author | Ian Jackson <ian.jackson@eu.citrix.com> | 2013-06-14 16:39:36 +0100 |
---|---|---|
committer | Ian Jackson <Ian.Jackson@eu.citrix.com> | 2013-06-14 16:39:36 +0100 |
commit | a004800f8fc607b96527815c8e3beabcb455d8e0 (patch) | |
tree | bedfb7dc80066010059b5ffd17b8affdb138b8cd /xen/common | |
parent | 7a549a6aa04dba807f8dd4c1577ab6a7592c4c76 (diff) | |
download | xen-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/Makefile | 2 | ||||
-rw-r--r-- | xen/common/libelf/libelf-dominfo.c | 52 | ||||
-rw-r--r-- | xen/common/libelf/libelf-loader.c | 20 | ||||
-rw-r--r-- | xen/common/libelf/libelf-tools.c | 24 |
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); } |