jmonkeyengine icon indicating copy to clipboard operation
jmonkeyengine copied to clipboard

NativeLibraryLoader fails due to no write permissions

Open terranprog opened this issue 1 year ago • 2 comments

Running Linux. I am getting an exception when jme tries to extract a native library to a temp folder.

Aug 15, 2024 5:40:32 PM com.jme3.system.JmeDesktopSystem initialize
INFO: Running on jMonkeyEngine 3.7.0-beta1.2.2
 * Branch: HEAD
 * Git Hash: 5cadb88
 * Build Date: 2024-07-30
Exception in thread "AWT-EventQueue-0" java.io.UncheckedIOException: Failed to extract native library to: /tmp/jme3/natives_8946616b/libbulletjme-x86_64.so
	at com.jme3.system.NativeLibraryLoader.loadNativeLibrary(NativeLibraryLoader.java:534)
	at com.jme3.system.JmeDesktopSystem.initialize(JmeDesktopSystem.java:290)
	at com.jme3.system.JmeDesktopSystem.newContext(JmeDesktopSystem.java:212)
	at com.jme3.system.JmeSystem.newContext(JmeSystem.java:175)
	at com.jme3.app.LegacyApplication.createCanvas(LegacyApplication.java:560)
	at scamsoft.minecraft.terrain3d.Terrain3D.<init>(Terrain3D.java:112)
	at scamsoft.minecraft.terrain3d.gui.TerrainGui.lambda$main$12(TerrainGui.java:886)
	at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:318)
	at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:773)
	at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:720)
	at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:714)
	at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
	at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
	at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:742)
	at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
	at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
	at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
	at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
	at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
	at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
Caused by: java.nio.file.NoSuchFileException: /tmp/jme3/natives_8946616b/libbulletjme-x86_64.so
	at java.base/sun.nio.fs.UnixException.translateToIOException(UnixException.java:92)
	at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:106)
	at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:111)
	at java.base/sun.nio.fs.UnixFileSystemProvider.newByteChannel(UnixFileSystemProvider.java:218)
	at java.base/java.nio.file.spi.FileSystemProvider.newOutputStream(FileSystemProvider.java:484)
	at java.base/java.nio.file.Files.newOutputStream(Files.java:228)
	at java.base/java.nio.file.Files.copy(Files.java:3160)
	at com.jme3.system.NativeLibraryLoader.loadNativeLibrary(NativeLibraryLoader.java:506)

The application is running as a non-root user.

The /tmp/jme folder has permissions drwxr-xr-x 5 root root

In other words:

  • root has ownership of /tmp/jme
  • root has write permissions
  • other users have read permissions but not write

The logic in NativeLibraryLoader.getExtractionFolder() has a couple of holes that are causing this to fail.

  • The code checks if the user has write permission to the temp folder (/tmp) but doesn't check write permissions to the /tmp/jme subfolder (it assumes write permissions exist)
  • There is logic to catch any exceptions while creating the temp folder and to call setExtractionFolderToUserCache() instead. The problem is that the call to extractionFolder.mkdir() does not throw an exception if it fails; but instead returns false. And the JME code does not check the result of this call.

Some suggestions for improvements:

  • The /tmp/jme folder is shared between all jme applications. This is probably not a good idea as it seems that whatever user creates the /tmp/jme folder does not give write permissions to other users. A better scheme would be to create completely independent temp folders e.g. /tmp/jme_natives_[hash]
  • Calls to mkdir should be checked for failure and handled accordingly e.g. throw an exception so setExtractionFolderToUserCache() will be called instead

terranprog avatar Aug 18 '24 07:08 terranprog

Thanks for documenting this issue.

stephengold avatar Aug 18 '24 17:08 stephengold

I have submitted a PR to fix this: #2303

terranprog avatar Aug 19 '24 12:08 terranprog