[foreign-abi] minimizing the surface of restricted native access

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Mon Dec 2 14:55:34 UTC 2019


Following up on this piece of feedback, Jorn and I came up with a more 
robust strategy; instead of converting an address to an unchecked 
address, the API will instead allow creation of an 'unsafe' native 
memory segment with its own temporal bounds and spatial bounds:

     /**
      * Returns a new native memory segment with given base address and 
size. The returned segment has its own temporal
      * bounds, and can therefore be closed; closing such a segment does 
<em>not</em> result in any resource being
      * deallocated.
      * @param base the desired base address
      * @param byteSize the desired size.
      * @return a new native memory segment with given base address and 
size.
      * @throws IllegalArgumentException if {@code base} does not 
encapsulate a native memory address.
      */
     public static MemorySegment ofNativeUnchecked(MemoryAddress base, 
long byteSize) { ... }


This allows clients to pass an address to be used as a 'base', a desired 
size and obtain a new segment with that base and size. This of course 
overrides whatever size information might have been previously available 
in the input address (hence the unsafety). This method can thus create 
segments which can be used as a target of a MemoryAddress::rebase 
operation, in case the user wants to break free from the restriction of 
the Nothing segment.

I went ahead and implemented the rebase+ofNativeUnchecked approach:

http://cr.openjdk.java.net/~mcimadamore/panama/nothing_segment/

I think the results are pleasing; StdLibTest already showcases a couple 
of calls which require rebasing:

* strcat - result of strcat needs to be rebased against segment 
associated with first parameter of strcat (safe)
* qsort - the upcall needs to rebase its incoming addresses against the 
segment associated with the native array to be sorted (safe)
* Tm struct - since this struct is constructed out of a pointer returned 
by a native call (gmtime), best we can do here is to rebase that pointer 
against a fresh unchecked segment whose size is the (known) size of the 
Tm struct (unsafe)

When writing the patch, I liked the fact that things failed if the 
dereference address was 'not trusted' - and I also appreciated the 
usefulness of veering into unsafe territory, but in a more gentle way 
which still allows for bounds and liveness checks.

Maurizio

On 27/11/2019 18:32, Ioannis Tsakpinis wrote:
>> But what if a client really wants to dereference a_random_  pointer
>> generated by a library? In this case, the client has no well-known
>> segment which can be used as a rebase target, so, what can be done? This
>> is where we need to veer into restricted native access territory, and
>> provide some escape hatch by which an untrusted address can be made
>> trusted again. There are many ways to do that; perhaps the simplest is
>> to add a new method on MemoryAddress:
>>
>> MemoryAddress asUnchecked()
>>
>> which returns a new memory address which point to same location as the
>> original address, but whose access is neither spatially, nor temporally
>> checked.
> This doesn't sound so good.:)


More information about the panama-dev mailing list