diff options
author | Nick Alcock <nick.alcock@oracle.com> | 2022-03-18 00:49:11 +0000 |
---|---|---|
committer | Nick Alcock <nick.alcock@oracle.com> | 2022-03-23 13:48:32 +0000 |
commit | 84f5c557a4883d336b238e4bf5264bb920e008d9 (patch) | |
tree | 839cf758597853b2d1bd9cd1f535ef11f6226660 /libctf | |
parent | 203bfa2f6bd275df4089131bac0a17c278c37a1a (diff) | |
download | binutils-84f5c557a4883d336b238e4bf5264bb920e008d9.zip binutils-84f5c557a4883d336b238e4bf5264bb920e008d9.tar.gz binutils-84f5c557a4883d336b238e4bf5264bb920e008d9.tar.bz2 |
libctf, ld: diagnose corrupted CTF header cth_strlen
The last section in a CTF dict is the string table, at an offset
represented by the cth_stroff header field. Its length is recorded in
the next field, cth_strlen, and the two added together are taken as the
size of the CTF dict. Upon opening a dict, we check that none of the
header offsets exceed this size, and we check when uncompressing a
compressed dict that the result of the uncompression is the same length:
but CTF dicts need not be compressed, and short ones are not.
Uncompressed dicts just use the ctf_size without checking it. This
field is thankfully almost unused: it is mostly used when reserializing
a dict, which can't be done to dicts read off disk since they're
read-only.
However, when opening an uncompressed foreign-endian dict we have to
copy it out of the mmaped region it is stored in so we can endian-
swap it, and we use ctf_size when doing that. When the cth_strlen is
corrupt, this can overrun.
Fix this by checking the ctf_size in all uncompressed cases, just as we
already do in the compressed case. Add a new test.
This came to light because various corrupted-CTF raw-asm tests had an
incorrect cth_strlen: fix all of them so they produce the expected
error again.
libctf/
PR libctf/28933
* ctf-open.c (ctf_bufopen_internal): Always check uncompressed
CTF dict sizes against the section size in case the cth_strlen is
corrupt.
ld/
PR libctf/28933
* testsuite/ld-ctf/diag-strlen-invalid.*: New test,
derived from diag-cttname-invalid.s.
* testsuite/ld-ctf/diag-cttname-invalid.s: Fix incorrect cth_strlen.
* testsuite/ld-ctf/diag-cttname-null.s: Likewise.
* testsuite/ld-ctf/diag-cuname.s: Likewise.
* testsuite/ld-ctf/diag-parlabel.s: Likewise.
* testsuite/ld-ctf/diag-parname.s: Likewise.
Diffstat (limited to 'libctf')
-rw-r--r-- | libctf/ctf-open.c | 45 |
1 files changed, 29 insertions, 16 deletions
diff --git a/libctf/ctf-open.c b/libctf/ctf-open.c index c7ca37e..3f8d336 100644 --- a/libctf/ctf-open.c +++ b/libctf/ctf-open.c @@ -1517,26 +1517,39 @@ ctf_bufopen_internal (const ctf_sect_t *ctfsect, const ctf_sect_t *symsect, goto bad; } } - else if (foreign_endian) + else { - if ((fp->ctf_base = malloc (fp->ctf_size)) == NULL) + if (_libctf_unlikely_ (ctfsect->cts_size < hdrsz + fp->ctf_size)) { - err = ECTF_ZALLOC; + ctf_err_warn (NULL, 0, ECTF_CORRUPT, + _("%lu byte long CTF dictionary overruns %lu byte long CTF section"), + (unsigned long) ctfsect->cts_size, + (unsigned long) (hdrsz + fp->ctf_size)); + err = ECTF_CORRUPT; goto bad; } - fp->ctf_dynbase = fp->ctf_base; - memcpy (fp->ctf_base, ((unsigned char *) ctfsect->cts_data) + hdrsz, - fp->ctf_size); - fp->ctf_buf = fp->ctf_base; - } - else - { - /* We are just using the section passed in -- but its header may be an old - version. Point ctf_buf past the old header, and never touch it - again. */ - fp->ctf_base = (unsigned char *) ctfsect->cts_data; - fp->ctf_dynbase = NULL; - fp->ctf_buf = fp->ctf_base + hdrsz; + + if (foreign_endian) + { + if ((fp->ctf_base = malloc (fp->ctf_size)) == NULL) + { + err = ECTF_ZALLOC; + goto bad; + } + fp->ctf_dynbase = fp->ctf_base; + memcpy (fp->ctf_base, ((unsigned char *) ctfsect->cts_data) + hdrsz, + fp->ctf_size); + fp->ctf_buf = fp->ctf_base; + } + else + { + /* We are just using the section passed in -- but its header may + be an old version. Point ctf_buf past the old header, and + never touch it again. */ + fp->ctf_base = (unsigned char *) ctfsect->cts_data; + fp->ctf_dynbase = NULL; + fp->ctf_buf = fp->ctf_base + hdrsz; + } } /* Once we have uncompressed and validated the CTF data buffer, we can |