[llvm-bugs] [Bug 46743] New: libunwind's FrameHeaderCache looks broken on Android 10 and earlier

via llvm-bugs llvm-bugs at lists.llvm.org
Thu Jul 16 01:31:36 PDT 2020


https://bugs.llvm.org/show_bug.cgi?id=46743

            Bug ID: 46743
           Summary: libunwind's FrameHeaderCache looks broken on Android
                    10 and earlier
           Product: Runtime Libraries
           Version: trunk
          Hardware: PC
                OS: Linux
            Status: NEW
          Severity: enhancement
          Priority: P
         Component: libunwind
          Assignee: unassignedbugs at nondot.org
          Reporter: rprichard at google.com
                CC: llvm-bugs at lists.llvm.org

libunwind now uses the dlpi_adds and dlpi_subs fields in dl_phdr_info (the
callback struct for dl_iterate_phdr) to detect an unloaded module and
invalidate its cache:

https://reviews.llvm.org/D75954

While these fields were common in glibc/BSD/etc for many years, they're still
very new in Android. (They're not in Android 10, but will be in the next
version.)

https://android-review.googlesource.com/c/platform/bionic/+/1104597/

libunwind isn't checking the callback size parameter, so AFAICT, on current
versions of Android, it will read bogus stack memory. If a module is unloaded
(dlclose), then libunwind might fail to invalidate a cache entry.

This issue won't affect ARM32 (because it uses dl_unwind_find_exidx), which is
the only target that Android proper (the platform and NDK) officially use
libunwind for. Android plans to switch to libunwind for the other
architectures, though, and someone in the larger Android community might be
using libunwind on other architectures.

libgcc also uses these fields, but it verifies that `size` is large enough
before assuming the extended dl_phdr_info fields exists. Maybe libunwind could
use a check like:

    (size >= offsetof(dl_phdr_info, dlpi_subs) + sizeof(...->dlpi_subs))

Aside: IIUC, on a cache miss, we're still scanning each entry of the frame
cache, for each module passed to the callback. That seems slow? I would think
we would want to check the cache on only the first callback invocation, and
we'd want to check the cache even when this condition holds:

    pinfo->dlpi_phnum == 0 || cbdata->targetAddr < pinfo->dlpi_addr

Also: A frame cache is still possible (and probably very helpful) on versions
of Android before R, but it requires special logic. On a cache hit, it's
necessary to scan the modules to verify the hit. This scan can be very quick
compared to the current behavior. I'd like to prototype this, but as it's only
useful for Android, I'm not sure how interested upstream would be.

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20200716/0dd94079/attachment.html>


More information about the llvm-bugs mailing list