JDK-8191278 : MappedByteBuffer bulk access memory failures are not handled gracefully
  • Type: Bug
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: 8,9,10,11,12,13
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • Submitted: 2017-11-15
  • Updated: 2021-09-07
  • Resolved: 2019-06-25
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 13 JDK 14
13.0.9Fixed 14 b03Fixed
Related Reports
Duplicate :  
Duplicate :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
There are 50+ instances of Unsafe.copyMemory
and 20+ instances of Unsafe.copySwapMemoy in generated Direct*Buffer* code, these accesses are not guarded for graceful dealing as per current implementation or plan (JDK-4454115 , JDK-8154592), this CR is for tracking and handling these cases.
Fix Request (11u) I'd like to backport this changes to fix crash happens on memory mapped file operations. The patch applies almost cleanly except stubGenerator_arm.cpp due to miss of JEP 340 (One AArch64 Port, Not Two), and some copyright year conflicts. A set of follow up is required to fix build of various platforms (8226871, 8229254, 8226878)

[~snazarki], can you please add a fix request comment for 11u (or amend the 13u request)? Removing jdk11u-fix-request label for the time being.

Fix Request (13u) I'd like to backport this changes to fix crash happens on memory mapped file operations. The patch applies cleanly after 8263361backport.

no failures in jdk14 atr.

URL: http://hg.openjdk.java.net/jdk/jdk/rev/3f3dc00a69a5 User: jcm Date: 2019-06-25 19:15:00 +0000

will push this changeset to jdk 14 eod. http://cr.openjdk.java.net/~jcm/8191278/webrev.06_final/open.changeset

only unsafe copy implementation that is in cpp is copyswap. as it is very unsafe to predict the generated code for this, the code range will not be gracefully handled.

implemented fast graceful exit for all platform. except s390(it doesn't implement the unsafe_copy intrinsic) tested aarch64, arm32 bit, x86 32 bit manually , and all other platform in mach5. except ppc.

with above change test passes in all modes for aarch64.

probably use same stub implementation arraycopy for native unsafe copy. so that it is one place implementation for all unsafe array copy.

Note: as per arm docs, unaligned access checks happen before other permission checks(yet to verify in a machine). so skipping faulting instructions for bulk access may cause unaligned faults in arm ports.

may be something like this for fast exit. http://cr.openjdk.java.net/~jcm/temp/fastfail.00/src/hotspot/os/windows/os_windows.cpp.udiff.html http://cr.openjdk.java.net/~jcm/temp/fastfail.00/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp.udiff.html http://cr.openjdk.java.net/~jcm/temp/fastfail.00/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp.udiff.html

Compiler side: Improving failover handling may require adding new entry and jumping to that on first (Signal/exception)(Dean suggested this when it was sent last time for review) this may require extensive stub walk to handle all callee save registers properly. Similar changes may be required for non intrinsic case.

Hi [~hseigel], this implementation works with c2 compiler intrinsic[1] [1] http://cr.openjdk.java.net/~jcm/8191278/webrev.01/

will do error checking with forced safepoinging in compile exclude code for test case purposes.

exception don't get delivered to handler even with a forced safepoint in xcomp mode. checking.

or just check if we are in stub routine and continue. for completeness. the effect of instructions with sideeffects should be studied and taken care. (or else it may loop for ever).

proposed fix: use same mechanism as runtime, set flag before intrinsic stub call, reset after the call. and use that to handle failure.

sure, Tobias

sure, Tobias

Jamsheed, could you please have a look? Thanks.

The following webrev fixes the problem for interpreted code and includes a jtreg regression test for both Unsafe_copyMemory() and Unsafe_copySwapMemory(): http://cr.openjdk.java.net/~hseigel/bug_8191278/webrev/index.html When run with the above fix, the test passes on Linux and Mac. It fails on Solaris and WIndows because of errors in the test. The test fails on Solaris because the bogus memory access does not cause a SIGBUS. It fails on Windows because the second File.write() call gets a FileSystemException. When run with '-Xcomp -XX:-TieredCompilation", the test fails everywhere because unsafe_copymemory() is an intrinsic. On Linux, for example, the test fails because when the SIGBUS occurs on Linux x64, control is transferred to this code in JVM_handle_linux_signal(): } else if (sig == SIGBUS /* && info->si_code == BUS_OBJERR */) { // BugId 4454115: A read from a MappedByteBuffer can fault // here if the underlying file has been truncated. // Do not crash the VM in such a case. CodeBlob* cb = CodeCache::find_blob_unsafe(pc); CompiledMethod* nm = (cb != NULL) ? cb->as_compiled_method_or_null() : NULL; if (nm != NULL && nm->has_unsafe_access()) { address next_pc = Assembler::locate_next_instruction(pc); stub = SharedRuntime::handle_unsafe_access(thread, next_pc); } Unfortunately, "CompiledMethod* nm" gets set to NULL and so handle_unsafe_access() is not executed. Transferring this bug to the compiler team to fix the unsafe_copy_memory() intrinsic issue.

The single element ops use MemoryAccess to guard the access. This needs to be extended to the bulk operations as well.

Mikhailo - this is important for java.nio.MappedByteBuffer, the relevant paragraph in the spec starts at "All or part of a mapped byte buffer may become inaccessible ...". Recovery via the handle_unsafe_access stub has been in place since the original implementation (in 1.4) so there is an exception when accessing specific elements of a buffer that is no longer inaccessible but we lack guards for the bulk (copy) operations. This issue is not about direct usages of Unsafe.copyMemory.

Runtime Triage: Unsafe operations are intentionally not safe. Closing as WNF.

JDK-8168628 is another example where the underlying issue is that copyMemory is not guarded. We need to get this fixed in HotSpot to avoid this and several reports of crashes with bulk transfer operations (single element put/get are okay as they are guarded).