Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NativeLibraryLoader fails due to no write permissions #2302

Open
terranprog opened this issue Aug 18, 2024 · 2 comments
Open

NativeLibraryLoader fails due to no write permissions #2302

terranprog opened this issue Aug 18, 2024 · 2 comments

Comments

@terranprog
Copy link

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
@stephengold
Copy link
Member

Thanks for documenting this issue.

terranprog pushed a commit to terranprog/jmonkeyengine that referenced this issue Aug 19, 2024
…o write permissions

Extract native library to a folder directly beneath the user temp folder. Do not use an intermediate /jme subfolder.
Check the result of the call to mkdir. Use UserCache if creation failed.
Check if the extraction folder is actually writable. If not use the UserCache.
Updated log message: since a previous change we no longer extract to the working directory.
@terranprog
Copy link
Author

I have submitted a PR to fix this:
#2303

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants