Commit Graph

204 Commits

Author SHA1 Message Date
Mark Wielaard b9fd0eee50 libelf: Split checks for ehdr and shdr, drop phdr check in file_read_elf.
There are various places in the code that check whether mmapped structures
are correctly aligned (or ALLOW_UNALIGNED is set). Some of these checks
are asserts. Like the one in elf(32|64)_getshdr. We should not get into
that part of the code if the shdr scn structure was cached in elf_begin
because it was mmapped in and properly aligned.

These asserts could trigger because in elf_begin.c file_read_elf ()
all alignment checks were combined. So even though only one of the ehdr,
shdr or phdr structures were not properly aligned all structures would be
copied. Also the phdr structure was not even read in elf_begin, so the
alignment check was unnecessary.

This patch splits the alignment checks and reading of ehdr and shdr
structures into separate code paths. It also drops the phdr alignment
checks in elf_begin. Those phdr checks are done in elf(32|64)_getphdr
already.

Signed-off-by: Mark Wielaard <mjw@redhat.com>
2015-06-08 11:12:38 +02:00
Mark Wielaard 96f6c995ff libelf: Fix possible unbounded stack usage in load_shdr_wrlock.
When a copy needs to be made of the shdrs, allocate with malloc and free
after conversion instead of calling alloca.

Signed-off-by: Mark Wielaard <mjw@redhat.com>
2015-06-05 14:48:55 +02:00
Mark Wielaard 2ec5182478 libelf: Fix possible unbounded stack usage in getphdr_wrlock.
When a copy needs to be made of the phdrs, allocate with malloc and free
after conversion instead of calling alloca.

Signed-off-by: Mark Wielaard <mjw@redhat.com>
2015-06-05 14:48:55 +02:00
Mark Wielaard f78e864047 libelf: Fix unbounded stack usage in elf_getarsym for !ALLOW_UNALIGNED case.
The number of entries in the index can be large, don't use alloca to
read in temporary data, use malloc (which is freed after out).

Signed-off-by: Mark Wielaard <mjw@redhat.com>
2015-06-05 14:48:55 +02:00
Mark Wielaard fc9b79400a libelf: Don't call memmove with possible NULL buffer.
When size is zero the buffer src and dest buffers might be NULL.

Signed-off-by: Mark Wielaard <mjw@redhat.com>
2015-06-05 14:44:59 +02:00
Mark Wielaard b4ad3c4b81 libelf: Don't call mempcpy with possible NULL d_buf.
When d_size is zero d_buf might be NULL. last_position doesn't need to be
updated in that case.

Signed-off-by: Mark Wielaard <mjw@redhat.com>
2015-06-05 14:44:59 +02:00
Mark Wielaard e6261005ea libelf: Fix possible unbounded stack usage in updatefile.
Allocate shdr_data and scns with malloc, not alloca. Free after writing
section headers.

Signed-off-by: Mark Wielaard <mjw@redhat.com>
2015-05-27 23:04:31 +02:00
Mark Wielaard 2e5df0c350 libelf: Fix possible unbounded stack usage in updatemmap.
Allocate temporary shdr storage with malloc, not alloca. Free after
writing section headers.

Signed-off-by: Mark Wielaard <mjw@redhat.com>
2015-05-27 23:04:31 +02:00
Mark Wielaard bfb9a752c3 libelf: Fix possible unbounded stack usage in elf_getarsym.
The number of entries in the index can be large, don't use alloca to
read in temporary data, use malloc (and free after out).

Signed-off-by: Mark Wielaard <mjw@redhat.com>
2015-05-27 23:04:31 +02:00
Mark Wielaard 77482c4bf6 libelf: Use posix_fallocate instead of ftruncate to extend ELF file.
This fixes an obscure SIGBUS error when using ELF_C_WRITE_MMAP on an ELF
file that needs extending when the underlying file system is (nearly) full.

Use posix_fallocate to make sure the file content is really there. Using
ftruncate might mean the file is extended, but space isn't allocated yet.
This might cause a SIGBUS once we write into the mmapped space and the disk
is full.

Using fallocate might fail on some file systems. posix_fallocate is
required to extend the file and allocate enough space even if the
underlying filesystem would normally return EOPNOTSUPP or the kernel
doesn't implement the fallocate syscall. Also posix_fallocate has been in
glibc since 2.1.94, while support for fallocate was only added in 2.10
and kernel 2.6.23.

Signed-off-by: Mark Wielaard <mjw@redhat.com>
2015-05-27 17:10:48 +02:00
Mark Wielaard c2297eab17 libelf: If e_phnum is zero then set e_phoff also to zero.
If phnum is zero make sure e_phoff is also zero and not some random value.
That would cause trouble in update_file. This could happen when ELF_F_LAYOUT
is set and the user copied over a ehdr from a bogus ELF file where the phdrs
are unreadable. In that case trying to write out the new ELF image would
crash trying to follow the bogus e_phdr value.

Signed-off-by: Mark Wielaard <mjw@redhat.com>
2015-05-18 15:48:04 +02:00
Mark Wielaard c0748eff84 libelf: More checking of valid sh_addralign values.
There were two issues with bogus sh_addralign values. First we would only
check the individual Elf_Data d_align values were powerof2. But not the
actual shdr addralign value. This would cause an issue if the shdr addralign
was bigger than all of the individual d_align values. Then we could write
out a bogus (! powerof2) shdr addralign value for the sections. Secondly
when reading in the Elf_Data we would set the d_align value to the value
of the shdr addralign value. But we would not check it was valid at all.
In practice there are ELF files with incorrect sh_addralign values (they
are a powerof2, but aren't aligned to the ELF image offset). We would try
to fix that up in elf_update by adding extra padding. But this could bloat
the ELF image a lot for large alignment values. So for too large alignments
that are bigger than the offset in the ELF file clamp them to the offset
value. This could lead us to reject to write out the data again when the
offset was not a powerof2. But this will only happen for aligment values
bigger than 64. Which are uncommon in practice.

Signed-off-by: Mark Wielaard <mjw@redhat.com>
2015-05-18 15:48:04 +02:00
Mark Wielaard 458027d294 libelf: Make sure shdrs are valid before storing extended phnum in newphdr.
Creating phdr with more than PN_XNUM phnum requires a valid section zero
shdr to store the extended value. Make sure the shdrs are valid. Also fix
the error when count was too big to store by setting ELF_E_INVALID_INDEX
before failing.

Signed-off-by: Mark Wielaard <mjw@redhat.com>
2015-05-18 15:48:04 +02:00
Mark Wielaard a2b964c7db Always call gelf_fsize with EV_CURRENT as argument.
Don't trust the elf version given by the file. It could be completely
bogus. In which case gelf_fsize just returns zero. Which could cause
divide by zero errors.

https://bugzilla.redhat.com/show_bug.cgi?id=1170810#c34

Signed-off-by: Mark Wielaard <mjw@redhat.com>
2015-05-13 16:31:52 +02:00
Mark Wielaard 59c1f12303 libelf: Make sure version xlate dest buffer is fully defined.
https://bugzilla.redhat.com/show_bug.cgi?id=1170810#c16
contains an example of usage of undefined memory when version section
data needs to be translated, but the version xlate functions detect they
cannot fully transform the section data. To make sure the dest buffer
data is completely defined this patch makes sure all data is moved
from src to dest first. This is somewhat inefficient since normally
all data will be fully converted. But the translation functions have
no way to indicate only partial data was converted.

Reported-by: Alexander Cherepanov <cherepan@mccme.ru>
Signed-off-by: Mark Wielaard <mjw@redhat.com>
2015-05-06 13:43:22 +02:00
Mark Wielaard bcefec514e Update elf.h from glibc.
Signed-off-by: Mark Wielaard <mjw@redhat.com>
2015-04-28 14:41:12 +02:00
Mark Wielaard 5370bb0a64 libelf: Don't extend ELF file size with SHT_NOBITS sh_offset.
Don't explicitly extend the file size for SHT_NOBITS sections. Since
that could cause a size beyond any actual file content it will cause
issues when the underlying ELF file has been mmapped or will extend
the file size to increase (writing fill bytes) when not mmapped. The
sh_offset value is essentially meaningless for SHT_NOBITS. gabi says
that a NOBITS section sh_offset member locates the "conceptual
placement" in the file. But it doesn't say this cannot be beyond the
enf of the file. When ELF_F_LAYOUT is set we should trust sh_offset
as given is what is wanted for an SHT_NOBITS section without extending
the file size.

https://bugzilla.redhat.com/show_bug.cgi?id=1020842

Buggy binutils ld could generate files where SHT_NOBITS sections have
sh_offset outside the file.
https://sourceware.org/bugzilla/show_bug.cgi?id=12921

Signed-off-by: Mark Wielaard <mjw@redhat.com>
2015-03-27 23:04:34 +01:00
Mark Wielaard 6c9f1ec5c5 libelf: Make __libelf_set_data_list_rdlock an internal_function.
__libelf_set_data_list_rdlock from elf_getdata.c is marked as an
internal_function in the implementation, but not in libelfP.h when it
is declared.  Add internal_function to the declaration. This broke
the i686 build.

Reported-by: Alexander Cherepanov <ch3root@openwall.com>
Signed-off-by: Mark Wielaard <mjw@redhat.com>
2015-02-19 22:21:46 +01:00
Jan Kratochvil 6f5934c1af libelf: Consider sh_addralign 0 as 1
Currently the Koji build for arm32 fails with:
	extracting debug info from /builddir/build/BUILDROOT/etcd-2.0.0-0.3.rc1.fc22.arm/usr/bin/etcd
	Failed to write file: invalid section alignment

This is because the binary etcd
	http://people.redhat.com/jkratoch/etcdctl.xz
contains:
	Section Headers:
	  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
	  [11] .rel.plt          REL             00459ee0 449ee0 000088 08   A 13   0  0
	                                                                               ^
which corresponds to golang's code:
	go/src/cmd/ld/elf.c
		case EM_X86_64:
			sh = elfshname(".rela.plt");
			sh->addralign = RegSize;
		default:
			sh = elfshname(".rel.plt");
			<nothing>

ELF spec says:
	Values 0 and 1 mean the section has no alignment constraints.
and libelf/elf32_updatenull.c really parses it that way at line 204
	ElfW2(LIBELFBITS,Word) sh_align = shdr->sh_addralign ?: 1;
but unfortunately the later line being patched no longer does.

libelf/
2015-02-07  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* elf32_updatenull.c (__elfw2(LIBELFBITS,updatenull_wrlock)): Consider
	sh_addralign 0 as 1.

Signed-off-by: Jan Kratochvil <jan.kratochvil@redhat.com>
2015-02-07 15:08:20 +01:00
Mark Wielaard 9d481b29e7 libelf: Make sure string returned by elf_strptr is NUL terminated.
The result of elf_strptr is often used directly to print or strcmp
the string. If the section data was truncated or corrupted that could
lead to invalid memory reads possibly crashing the application.
https://bugzilla.redhat.com/show_bug.cgi?id=1170810#c24

Reported-by: Alexander Cherepanov <cherepan@mccme.ru>
Signed-off-by: Mark Wielaard <mjw@redhat.com>
2015-02-06 22:36:43 +01:00
Mark Wielaard 710ca87893 libelf: elf_strptr should use datalist when data has been added to section.
elf_strptr always used the rawdata when available. But when data has been
added to the section it should find the correct buffer in the datalist.

Adds a large testcase that checks various ways of adding and extracting
strings from a section.

Signed-off-by: Mark Wielaard <mjw@redhat.com>
2015-02-06 22:29:34 +01:00
Mark Wielaard b543cdd95a libelf: Fix elf_newdata when raw ELF file/image data is available.
When ELF data for a section has been read by elf_rawdata, data_read
and rawdata_base are set, but data_list_rear will not be set until the
data will be converted (by elf_getdata). elf_newdata would overwrite
the existing data in that case. Both elf_getdata and elf_update rely
on the fact that when data_list_rear is set they don't have to look
at the raw data anymore. So make sure we update the data list properly
before adding any new data and raw data is available in elf_newdata.

Add newdata test that calls elf_newdata before and after elf_rawdata
and elf_getdata and checks the new size and contents of the section.

Signed-off-by: Mark Wielaard <mjw@redhat.com>
2015-02-06 22:24:08 +01:00
Mark Wielaard 058ae7b4d5 libelf: elf_strptr should fetch the shdr for the section if not yet known.
elf_strptr might be called before the shdrs are read in. In that case it
needs to explicitly call __elf[32|64]_getshdr_rdlock to check the section
type and size. The new strptr testcase triggers this corner case and crashes
before the fix.

Signed-off-by: Mark Wielaard <mjw@redhat.com>
2015-02-06 22:18:52 +01:00
Mark Wielaard cc62e378c2 libelf: gelf_getphdr should check phdr index is valid.
elf_getphdrnum does checks the phdrnum makes sense. But gelf_getphdr
checked the given index against the "raw" e_phnum or internal
__elf_getphdrnum_rdlock result without checking. Extract the checking
code into a new internal  __elf_getphdrnum_chk_rdlock function and
use that.

Found by afl-fuzz.

Signed-off-by: Mark Wielaard <mjw@redhat.com>
2015-01-15 14:04:28 +01:00
Mark Wielaard 68588d628a libelf: ar_size cannot be negative. Fix max ar size.
Elf_Arhdr ar_size is loff_t, which is signed. Make sure it isn't negative.
When the parent start_offset is non-zero maxsize should include it to
compensate for ar offset.

Found with afl-fuzz.

Signed-off-by: Mark Wielaard <mjw@redhat.com>
2015-01-12 22:02:46 +01:00
Alexander Cherepanov 147018e729 libelf: Fix dir traversal vuln in ar extraction.
read_long_names terminates names at the first '/' found but then skips
one character without checking (it's supposed to be '\n'). Hence the
next name could start with any character including '/'. This leads to
a directory traversal vulnerability at the time the contents of the
archive is extracted.

The danger is mitigated by the fact that only one '/' is possible in a
resulting filename and only in the leading position. Hence only files
in the root directory can be written via this vuln and only when ar is
executed as root.

The fix for the vuln is to not skip any characters while looking
for '/'.

Signed-off-by: Alexander Cherepanov <cherepan@mccme.ru>
2014-12-29 00:57:17 +01:00
Ulrich Drepper 898ed26144 avoid scary command output
The commands to check for invalid text relocations in the generated DSOs
shouldn't be displayed.  They contain an echo which prints the text.
This patch suppresses the commands from being printed.
2014-12-18 23:47:22 +01:00
Mark Wielaard 55f847d63a libelf: Make sure ar archive long_names len fits in mapped ELF file.
Signed-off-by: Mark Wielaard <mjw@redhat.com>
2014-12-17 16:49:03 +01:00
Mark Wielaard 4bb122a876 libelf: Check index_size doesn't overflow in elf_getarsym.
Signed-off-by: Mark Wielaard <mjw@redhat.com>
2014-12-17 16:49:02 +01:00
Mark Wielaard 9520242b2a libelf: Clear any garbage left in the ar name table.
Signed-off-by: Mark Wielaard <mjw@redhat.com>
2014-12-17 16:43:27 +01:00
Mark Wielaard 65a556fc86 libelf: Correct ELF64 section offset check in file_read_elf.
The ELF64 case didn't check for overflow and accidentially used the 32bit
Shdr size.

Signed-off-by: Mark Wielaard <mjw@redhat.com>
2014-12-15 10:04:23 +01:00
Mark Wielaard 7d63628b8a libelf: Add some ar header sanity checking.
Don't allow entries or size to overflow the parent file size.

Signed-off-by: Mark Wielaard <mjw@redhat.com>
2014-12-15 10:03:03 +01:00
Mark Wielaard 16f08ebdb8 libelf: Make sure n * w doesn't overflow in elf_getarsym.
Signed-off-by: Mark Wielaard <mjw@redhat.com>
2014-12-12 13:04:19 +01:00
Mark Wielaard 805ec833c1 Add configure --disable-textrelcheck option to enable CC=afl-fuzz on 32bit.
Using american fuzzy lop has found a lot of issues. It would be nice to
make using it a bit easier. Our build files make sure that no shared
library uses text relocations, but afl-gcc will insert some on i686.
http://www.akkadia.org/drepper/textrelocs.html

Now CC=afl-gcc ./configure --disable-textrelcheck will allow them so
that afl can instrument the libraries.

Don't try to use or install them except with afl-fuzz. When selinux is
enabled it might prevent loading the libraries with DT_TEXTREL set.

Signed-off-by: Mark Wielaard <mjw@redhat.com>
2014-12-04 14:38:18 +01:00
Mark Wielaard f62658f71f libelf: Change signed overflow check to unsigned in elf_getdata_rawchunk.
Arithmetic of signed values that overflow causes undefined behaviour
Change to explicit unsigned arithmetic overflow check.

Signed-off-by: Mark Wielaard <mjw@redhat.com>
2014-11-26 20:24:13 +01:00
Mark Wielaard 51abc748db libelf: Copy over any leftover data from src to dest in elf_cvt_note.
If any data is left then the data is likely part of the truncated note
name/desc. This probably means the note is corrupted, but it is better
to have the actual data in dest instead of random uninitialized memory.

Signed-off-by: Mark Wielaard <mjw@redhat.com>
2014-11-26 20:21:44 +01:00
Mark Wielaard 2deeb7c510 libelf: elf_getphdrnum sanity check the returned phnum result.
The internal __elf_getphdrnum_rdlock might return an inconsistent phnum.
Return a sanitized value, or return an error to users that rely on phnum
to be consistent. That way iterating over all phdrs using elf_getphdr
will return consistent results.

Signed-off-by: Mark Wielaard <mjw@redhat.com>
2014-11-26 20:12:52 +01:00
Mark Wielaard 9b5fa6b594 libelf: Check for overflow in version_xlate elf_cvt_Verdef and elf_cvt_Verneed.
Signed-off-by: Mark Wielaard <mjw@redhat.com>
2014-11-18 09:56:01 +01:00
Mark Wielaard 5c1a45c2d3 Check elf_strptr didn't fail getting section name.
Since elf_strptr can fail and return NULL we should always check the result
before usage. Debug sections are only handled by section name, so make sure
the name actually exists.

Signed-off-by: Mark Wielaard <mjw@redhat.com>
2014-11-17 23:19:03 +01:00
Mark Wielaard babcdeff28 libelf: elf_getshdrstrndx cannot use SHN_XINDEX without section headers.
Signed-off-by: Mark Wielaard <mjw@redhat.com>
2014-11-17 00:42:53 +01:00
Mark Wielaard 436275edd0 libelf: Fix handling of (extended) phnum.
If there is no e_phoff e_phnum cannot be trusted. Extended phnum can only
be gotten if we have an actual section table and a shdr for section zero,
Extended phnum can be too large to fit in the file (or a size_t).

Signed-off-by: Mark Wielaard <mjw@redhat.com>
2014-11-17 00:33:36 +01:00
Mark Wielaard 8ea90b7a5c gelf_getnote: Check padding overflow.
Since ELF notes need to be properly aligned they can include padding.
Make sure the padding itself and the padding calculation doesn't overflow.

Signed-off-by: Mark Wielaard <mjw@redhat.com>
2014-11-16 11:30:51 +01:00
Mark Wielaard 502430c7b2 libelf: getdata check 64bit values correctly on 32bit arch.
On 32bit arches size_t is too small to do size and overflow checks
of 64bit ELF files. Use the actual Elf64 types to make sure checks
on 64bit ELF files are done correctly on 32bit arches.

Signed-off-by: Mark Wielaard <mjw@redhat.com>
2014-11-16 11:19:34 +01:00
Mark Wielaard df2fe50346 libelf: gelf_getnote check for offset overflow.
Signed-off-by: Mark Wielaard <mjw@redhat.com>
2014-11-14 17:05:08 +01:00
Mark Wielaard c50ddfca10 libelf: Fix unsigned overflow check in elf_getdata. 2014-11-13 15:43:02 +01:00
Mark Wielaard babd5b6d9e libelf: Use mempcpy not __mempcpy.
We were using mempcpy everywhere else, only __libelf_next_arhdr_wrlock used
__mempcpy.

Signed-off-by: Mark Wielaard <mjw@redhat.com>
2014-11-13 15:37:40 +01:00
Mark Wielaard b635b8dcb0 libelf: Correct shdr size check for (raw) getdata.
Reported-by: Hanno Böck <hanno@hboeck.de>
Signed-off-by: Mark Wielaard <mjw@redhat.com>
2014-11-08 14:47:16 +01:00
Petr Machata 237188e4d7 elf_begin sets elf_errno for cases that the file is completely unreadable
- The problem this is trying to solve can be seen for example thus:
	$ eu-readelf -a /
	eu-readelf: failed reading '/': (null)

  With the fix we see a proper error number and get a reasonable error
  message:

	$ eu-readelf -a /
	eu-readelf: failed reading '/': invalid file descriptor

Signed-off-by: Petr Machata <pmachata@redhat.com>
2014-09-11 19:45:11 +02:00
Mark Wielaard 16e2d351bf Update elf.h from glibc.
Includes new bits needed for ppc64le ELFv2 abi.
https://bugzilla.redhat.com/show_bug.cgi?id=1110249

Signed-off-by: Mark Wielaard <mjw@redhat.com>
2014-07-04 13:39:30 +02:00
Mark Wielaard 3232479483 Remove mudflap build option.
The --enable-mudflap configure build has been broken for 2 years without
anybody apparently noticing. GCC 4.9 removed mudflap support. Before
release we now run make distcheck with valgrind support. Removal of the
mudflap configure option simplifies the build a little.

Signed-off-by: Mark Wielaard <mjw@redhat.com>
2014-04-18 11:46:51 +02:00