This is an archive of the discontinued LLVM Phabricator instance.

[LLDB] Fix buffer overflow problem in DWARFExpression::Evaluate (2nd attempt)
ClosedPublic

Authored by cmtice on Jul 10 2023, 4:52 PM.

Details

Summary

In two calls to ReadMemory in DWARFExpression.cpp, the buffer size passed to ReadMemory is not checked and can be bigger than the actual size of the buffer. This caused a buffer overflow bug, which we found through Address Sanitizer. This patch fixes the problem by checking the address size when it is first read out of the DWARF, and setting an error and returning immediately if the size is invalid.

This is the second attempt to fix this issue; I reverted the first one, as it was not quite correct.

Diff Detail

Event Timeline

cmtice created this revision.Jul 10 2023, 4:52 PM
Herald added a project: Restricted Project. · View Herald TranscriptJul 10 2023, 4:52 PM
cmtice requested review of this revision.Jul 10 2023, 4:52 PM
cmtice edited the summary of this revision. (Show Details)Jul 10 2023, 4:58 PM
jasonmolenda accepted this revision.Jul 10 2023, 5:02 PM

This looks good to me, thanks for digging in Caroline! Is there a naughty compiler emitting this, or are we mis-parsing somehow?

This revision is now accepted and ready to land.Jul 10 2023, 5:02 PM
cmtice edited the summary of this revision. (Show Details)Jul 10 2023, 5:04 PM

Thanks Jason. I think the compiler is generating some bad DWARF. David Blaikie was investigating that on our end, but he's on vacation this week.

Herald added a project: Restricted Project. · View Herald TranscriptJul 10 2023, 7:48 PM

This looks good to me, thanks for digging in Caroline! Is there a naughty compiler emitting this, or are we mis-parsing somehow?

Thanks Jason. I think the compiler is generating some bad DWARF. David Blaikie was investigating that on our end, but he's on vacation this week.

Yep - something in libc++ built with clang:

              DW_AT_name        ("third_party/llvm/llvm-project/libcxx/src/ios.instantiations.cpp")
                     [0x000000002b32cf96, 0x000000002b32d0e9): DW_OP_breg6 RBP-52, DW_OP_deref_size 0x10, DW_OP_stack_value)
                     [0x000000002b32d116, 0x000000002b32d265): DW_OP_breg6 RBP-56, DW_OP_deref_size 0x10, DW_OP_stack_value)
                        DW_AT_location  (DW_OP_fbreg -56, DW_OP_deref_size 0x10, DW_OP_stack_value)
                     [0x000000002b331396, 0x000000002b3314e6): DW_OP_breg6 RBP-52, DW_OP_deref_size 0x10, DW_OP_stack_value)
                     [0x000000002b331516, 0x000000002b331662): DW_OP_breg6 RBP-56, DW_OP_deref_size 0x10, DW_OP_stack_value)
                        DW_AT_location  (DW_OP_fbreg -56, DW_OP_deref_size 0x10, DW_OP_stack_value)
--
              DW_AT_name        ("third_party/llvm/llvm-project/libcxx/src/locale.cpp")
                     [0x000000002b34146b, 0x000000002b341623): DW_OP_breg6 RBP-48, DW_OP_deref_size 0x10, DW_OP_stack_value
                     [0x000000002b3416d7, 0x000000002b3417e7): DW_OP_breg6 RBP-48, DW_OP_deref_size 0x10, DW_OP_stack_value
                     [0x000000002b342b2b, 0x000000002b342cdd): DW_OP_breg6 RBP-48, DW_OP_deref_size 0x10, DW_OP_stack_value
                     [0x000000002b342d96, 0x000000002b342ea6): DW_OP_breg6 RBP-48, DW_OP_deref_size 0x10, DW_OP_stack_value

I haven't isolated this - got to extract/figure out how our libc++ is built, etc.

lldb/source/Expression/DWARFExpression.cpp
1082–1089

Just as an aside - isn't this code doing an illegal load widening? If the pointer pointed to the end of a page or something, and asked for only one byte - reading extra bytes would be bad (similarly would cause a segfault/UB/etc), right?

(& I'm not sure I understand the comment about endianness - the operation reads that many bytes from the given address)

dblaikie added inline comments.Jul 19 2023, 3:25 PM
lldb/source/Expression/DWARFExpression.cpp
1082–1089

oh, guess I also mentioned this here: https://reviews.llvm.org/D153840#inline-1494202

Simple clang example that produces this invalid DWARF:

void b(double);
void c();
void e(double e) {
  c();
  b(e);
}
$ clang-tot x.ii -g -c -o - -O3 | llvm-dwarfdump-tot - | grep DW_OP_deref_size
                     [0x0000000000000006, 0x0000000000000016): DW_OP_breg7 RSP+0, DW_OP_deref_size 0x10, DW_OP_stack_value)

This seems to be created here: https://github.com/llvm/llvm-project/blob/dd84f5f91c6b234a2f188b6acf8557cae81b8a53/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp#L1281 - so I'll file a bug for @jmorse to take a look at, perhaps.