diff options
author | Alan Modra <amodra@gmail.com> | 2020-06-01 14:21:50 +0930 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2020-06-01 23:33:28 +0930 |
commit | 2fdb65f247379befd548a33ea185172968b9ebb9 (patch) | |
tree | adc90cec8f4d5c1b596aa7551852f73003f88ec8 | |
parent | 3c3d03769e4d6fea4c8ee97bf36a2ca7d572461c (diff) | |
download | gdb-2fdb65f247379befd548a33ea185172968b9ebb9.zip gdb-2fdb65f247379befd548a33ea185172968b9ebb9.tar.gz gdb-2fdb65f247379befd548a33ea185172968b9ebb9.tar.bz2 |
alpha-vms: ETIR checks
Better validity checks, and remove a fuzzer vulnerability of sorts that
targeted the store-immediate-repeat command with a zero length but
very large repeat counts to chew cpu.
* vms-alpha.c (_bfd_vms_slurp_etir): Check bound for the current
command against cmd_length, not the end of record. For
ETIR__C_STO_IMMR check size against cmd_length, mask repeat count
to 32-bits and break out on zero size. Add ETIR__C_STC_LP_PSB
cmd_length test.
-rw-r--r-- | bfd/ChangeLog | 8 | ||||
-rw-r--r-- | bfd/vms-alpha.c | 34 |
2 files changed, 29 insertions, 13 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 05452c5..d4d4c45 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,11 @@ +2020-06-01 Alan Modra <amodra@gmail.com> + + * vms-alpha.c (_bfd_vms_slurp_etir): Check bound for the current + command against cmd_length, not the end of record. For + ETIR__C_STO_IMMR check size against cmd_length, mask repeat count + to 32-bits and break out on zero size. Add ETIR__C_STC_LP_PSB + cmd_length test. + 2020-05-28 David Faust <david.faust@oracle.com> * elf64-bpf.c (bpf_elf_relocate_section): Fix handling of diff --git a/bfd/vms-alpha.c b/bfd/vms-alpha.c index 8e923d2..e31a9e4 100644 --- a/bfd/vms-alpha.c +++ b/bfd/vms-alpha.c @@ -1925,11 +1925,12 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info) return FALSE; } ptr += 4; + cmd_length -= 4; #if VMS_DEBUG _bfd_vms_debug (4, "etir: %s(%d)\n", _bfd_vms_etir_name (cmd), cmd); - _bfd_hexdump (8, ptr, cmd_length - 4, 0); + _bfd_hexdump (8, ptr, cmd_length, 0); #endif switch (cmd) @@ -1939,7 +1940,7 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info) stack 32 bit value of symbol (high bits set to 0). */ case ETIR__C_STA_GBL: - _bfd_vms_get_value (abfd, ptr, maxptr, info, &op1, &h); + _bfd_vms_get_value (abfd, ptr, ptr + cmd_length, info, &op1, &h); if (!_bfd_vms_push (abfd, op1, alpha_vms_sym_to_ctxt (h))) return FALSE; break; @@ -1949,7 +1950,7 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info) stack 32 bit value, sign extend to 64 bit. */ case ETIR__C_STA_LW: - if (ptr + 4 > maxptr) + if (cmd_length < 4) goto corrupt_etir; if (!_bfd_vms_push (abfd, bfd_getl32 (ptr), RELC_NONE)) return FALSE; @@ -1960,7 +1961,7 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info) stack 64 bit value of symbol. */ case ETIR__C_STA_QW: - if (ptr + 8 > maxptr) + if (cmd_length < 8) goto corrupt_etir; if (!_bfd_vms_push (abfd, bfd_getl64 (ptr), RELC_NONE)) return FALSE; @@ -1976,7 +1977,7 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info) { int psect; - if (ptr + 12 > maxptr) + if (cmd_length < 12) goto corrupt_etir; psect = bfd_getl32 (ptr); if ((unsigned int) psect >= PRIV (section_count)) @@ -2079,13 +2080,18 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info) { int size; - if (ptr + 4 > maxptr) + if (cmd_length < 4) goto corrupt_etir; size = bfd_getl32 (ptr); + if (size > cmd_length - 4) + goto corrupt_etir; if (!_bfd_vms_pop (abfd, &op1, &rel1)) return FALSE; if (rel1 != RELC_NONE) goto bad_context; + if (size == 0) + break; + op1 &= 0xffffffff; while (op1-- > 0) if (!image_write (abfd, ptr + 4, size)) return FALSE; @@ -2095,7 +2101,7 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info) /* Store global: write symbol value arg: cs global symbol name. */ case ETIR__C_STO_GBL: - _bfd_vms_get_value (abfd, ptr, maxptr, info, &op1, &h); + _bfd_vms_get_value (abfd, ptr, ptr + cmd_length, info, &op1, &h); if (h && h->sym) { if (h->sym->typ == EGSD__C_SYMG) @@ -2120,7 +2126,7 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info) /* Store code address: write address of entry point arg: cs global symbol name (procedure). */ case ETIR__C_STO_CA: - _bfd_vms_get_value (abfd, ptr, maxptr, info, &op1, &h); + _bfd_vms_get_value (abfd, ptr, ptr + cmd_length, info, &op1, &h); if (h && h->sym) { if (h->sym->flags & EGSY__V_NORM) @@ -2172,7 +2178,7 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info) { unsigned int size; - if (ptr + 4 > maxptr) + if (cmd_length < 4) goto corrupt_etir; size = bfd_getl32 (ptr); if (!image_write (abfd, ptr + 4, size)) @@ -2187,7 +2193,7 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info) store global longword: store 32bit value of symbol arg: cs symbol name. */ case ETIR__C_STO_GBL_LW: - _bfd_vms_get_value (abfd, ptr, maxptr, info, &op1, &h); + _bfd_vms_get_value (abfd, ptr, ptr + cmd_length, info, &op1, &h); #if 0 abort (); #endif @@ -2241,7 +2247,9 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info) da signature. */ case ETIR__C_STC_LP_PSB: - _bfd_vms_get_value (abfd, ptr + 4, maxptr, info, &op1, &h); + if (cmd_length < 4) + goto corrupt_etir; + _bfd_vms_get_value (abfd, ptr + 4, ptr + cmd_length, info, &op1, &h); if (h && h->sym) { if (h->sym->typ == EGSD__C_SYMG) @@ -2340,7 +2348,7 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info) /* Augment relocation base: increment image location counter by offset arg: lw offset value. */ case ETIR__C_CTL_AUGRB: - if (ptr + 4 > maxptr) + if (cmd_length < 4) goto corrupt_etir; op1 = bfd_getl32 (ptr); image_inc_ptr (abfd, op1); @@ -2554,7 +2562,7 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info) break; } - ptr += cmd_length - 4; + ptr += cmd_length; } return TRUE; |