From: Alan Modra Date: Mon, 1 Jun 2020 04:51:50 +0000 (+0930) Subject: alpha-vms: ETIR checks X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=2fdb65f247379befd548a33ea185172968b9ebb9;p=binutils-gdb.git 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. --- diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 05452c5d467..d4d4c4565b0 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,11 @@ +2020-06-01 Alan Modra + + * 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 * elf64-bpf.c (bpf_elf_relocate_section): Fix handling of diff --git a/bfd/vms-alpha.c b/bfd/vms-alpha.c index 8e923d2c792..e31a9e4ca10 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;