Usage of global scope by Linker is unsafe for pointers to `static` data in loaded library

some-java-user-99206970363698485155 at vodafonemail.de some-java-user-99206970363698485155 at vodafonemail.de
Sat Sep 21 15:54:55 UTC 2024


Hello,

as mentioned in the Javadoc, for downcalls and upcalls Linker uses the 
global scope for the result respectively the arguments. This is 
problematic for pointers to `static` data in C because it leads to 
unsafe code.
Specifically, consider this case:

 1. Load a library using SymbolLookup
 2. Obtain the address of a function in that library
 3. Call that function using Linker; the function returns a pointer to
    `static` data
 4. Use the function result

If I understand it correctly that pointer to the `static` data actually 
points within the data of the loaded library (and not some newly 
allocated heap memory). But I am not that familiar with C, so please 
correct me if I am wrong.

The problem is now if you accidentally unload the library by closing the 
Arena which was used for loading it, either explicitly or by the garbage 
collector in case of Arena.ofAuto(), while the function result is still 
is use.
Because the Linker used the global scope, if you use the `static` data 
returned by the function it will crash the JVM because it is not 
detected that the original Arena had been closed, and the library had 
been unloaded.


What makes this worse is that if you are just given a SymbolLookup, or 
even a MemorySegment obtained from it, you don't have access to the 
original Arena used to load the library, so you cannot even manually fix 
this unsafety this by using `MemorySegment#reinterpet` to change the Arena.


Maybe it would therefore be safer if Linker for downcalls used the scope 
of the given function pointer MemorySegment, instead of the global 
scope. What do you think?
For upcall arguments I am not sure if there is a way to fix this unsafety.


If the behavior for downcalls cannot be changed, could you then please 
at least add a 'restricted' `MemorySegment#withScope(Scope)` (maybe with 
additional 'cleanup' argument) or similar, so that you can manually 
change the scope of the downcall result, without needing a reference to 
the original Arena (which is currently required for 
`MemorySegment#reinterpet`)?
Though personally I would prefer if the default downcall behavior was 
changed, because manually having to change the scope of the downcall 
result every time is error-prone and easy to forget.


Kind regards
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/panama-dev/attachments/20240921/958cd33f/attachment.htm>


More information about the panama-dev mailing list