Closed Bug 1527564 Opened 8 months ago Closed 8 months ago

StreamSamplesAndMarkers during child process profiler shutdown does UAF trying to access process name


(Core :: Gecko Profiler, defect, P2)




Tracking Status
firefox67 --- fixed


(Reporter: gerald, Assigned: gerald)




(1 file)

Found by ASAN:

ERROR: AddressSanitizer: heap-use-after-free
READ of size 8 at 0x61b000022088 thread T0 (WebExtensions)
    #0 BeginReading obj-mc-dbg/dist/include/nsTStringRepr.h:127:53
    #1 operator Span obj-mc-dbg/dist/include/nsTSubstring.h:931
    #2 NS_ConvertUTF16toUTF8 obj-mc-dbg/dist/include/nsString.h:98
    #3 mozilla::dom::ContentChild::GetProcessName(nsTSubstring<char>&) const dom/ipc/ContentChild.cpp:1148
    #4 StreamSamplesAndMarkers(char const*, int, ProfileBuffer const&, SpliceableJSONWriter&, mozilla::TimeStamp const&, mozilla::TimeStamp const&, mozilla::TimeStamp const&, double, UniqueStacks&) tools/profiler/core/ProfiledThreadData.cpp:222:9
    #5 ProfiledThreadData::StreamJSON(ProfileBuffer const&, JSContext*, SpliceableJSONWriter&, mozilla::TimeStamp const&, double, bool) tools/profiler/core/ProfiledThreadData.cpp:66:5
    #6 locked_profiler_stream_json_for_this_process(mozilla::BaseAutoLock<PSMutex&> const&, SpliceableJSONWriter&, double, bool) tools/profiler/core/platform.cpp:2021:27
    #7 locked_profiler_save_profile_to_file(mozilla::BaseAutoLock<PSMutex&> const&, char const*, bool) tools/profiler/core/platform.cpp:3038:7
    #8 profiler_shutdown() tools/profiler/core/platform.cpp:2877:9
    #9 ~AutoProfilerInit obj-mc-dbg/dist/include/GeckoProfiler.h:738:25
    #10 XRE_InitChildProcess(int, char**, XREChildData const*) toolkit/xre/nsEmbedFunctions.cpp:761

0x61b000022088 is located 1288 bytes inside of 1456-byte region [0x61b000021b80,0x61b000022130)
freed by thread T0 (Web Content) here:
    #0 __interceptor_free /builds/worker/workspace/moz-toolchain/src/llvm/projects/compiler-rt/lib/asan/
    #1 ~nsAutoPtr obj-mc-dbg/dist/include/nsAutoPtr.h:65:18
    #2 XRE_InitChildProcess(int, char**, XREChildData const*) toolkit/xre/nsEmbedFunctions.cpp:757

previously allocated by thread T0 (Web Content) here:
    #0 __interceptor_malloc /builds/worker/workspace/moz-toolchain/src/llvm/projects/compiler-rt/lib/asan/
    #1 moz_xmalloc memory/mozalloc/mozalloc.cpp:68:15
    #2 operator new obj-mc-dbg/dist/include/mozilla/mozalloc.h:131:10
    #3 XRE_InitChildProcess(int, char**, XREChildData const*) toolkit/xre/nsEmbedFunctions.cpp:684

In summary, in XRE_InitChildProcess we have:

  1. profiler init
  2. ProcessChild init (creates process name string)
  3. ProcessChild destruction (destroys process name string)
  4. profiler destruction (tries to access process name while doing shutdown serialization)

That was introduced in bug 1465924. (Sorry)

I think we probably should give the process name to the profiler when the ProcessChild is created; unless there is a better way to get a good process name. TBC.

Profiler was previously fetching process name at the time of shutdown
serialization, at which point that name could have already been destroyed.

Now the child process just forwards the name as soon as it is given, so
the profiler can store it for later.

Pushed by
Child forwards its process name to the profiler - r=mstange
Closed: 8 months ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla67
You need to log in before you can comment on or make changes to this bug.