-
Notifications
You must be signed in to change notification settings - Fork 218
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
Remove execute permission on native .so file #1081
Conversation
Removes the execute permission on the `.so` native library file created in the java tmp directory. This permission is not required for java to load the library file successfully.
What happens exactly ? My understanding is that the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This PR does not fix the problem.
I tested this. The permissions didn't seem to matter. The noexec
on the filesystem did matter, though. I tested using a different shared library, which was more readily accessible to me, but I believe the error would likely be the same for JLine. When the filesystem was mounted with noexec
, this was the stack trace:
jshell> System.load("/mnt/tmp/libaccumulo.so")
| Exception java.lang.UnsatisfiedLinkError: /mnt/tmp/libaccumulo.so: /mnt/tmp/libaccumulo.so: failed to map segment from shared object
| at NativeLibraries.load (Native Method)
| at NativeLibraries$NativeLibraryImpl.open (NativeLibraries.java:388)
| at NativeLibraries.loadLibrary (NativeLibraries.java:232)
| at NativeLibraries.loadLibrary (NativeLibraries.java:174)
| at ClassLoader.loadLibrary (ClassLoader.java:2394)
| at Runtime.load0 (Runtime.java:755)
| at System.load (System.java:1957)
| at (#4:1)
File Permission | Filesystem Mount Option | Result |
---|---|---|
744 | loop,noexec | Stacktrace |
644 | loop,noexec | Stacktrace |
744 | loop | Normal |
644 | loop | Normal |
I read somewhere that dlopen
, the system call Java uses to load the library, enforces noexec
itself. I couldn't find an authoritative source for that (maybe this?), but that matches the behavior I observed.
Looking at /lib
and /usr/lib
on my system, it does appear that the convention is to have libraries executable, even if they don't have a main function as an entry point.
So, I don't think this PR is going to do anything to fix the problem. However, I think the comment is wrong... I don't think the executable flag is actually necessary for Java to load the library... it's just convention. The real problem is that /tmp
isn't really a suitable location for putting these kinds of files.
All of this leads me to believe that a different solution is warranted. Perhaps $XDG_RUNTIME_DIR/jline/
is a better directory for this file to be extracted and loaded from (that resolves to /run/user/$(id -u)/jline/
on my system)? Or perhaps it is better for jline to create ~/.jline-tmpXXXX
directory in the user's home directory? I saw some people attempt to load libraries directly from memory, but I don't think that's the best option, even if it worked, and I'm not sure it does (or should).
Another option is to provide a separate system property like jline.native.tmpdir
or a similarly named property, which defaults to the value of java.io.tmpdir
, but can be configured independently if the user wishes.
Ultimately, I think the best option (along with a dedicated property for configuring the path separately from java.io.tmpdir
) is to make loading the native code optional... if it loading the native library code doesn't work, can JLine be made to fall back a lower-performing operational mode without crashing the application? I'm not actually even sure what the native code is supposed to do, or whether it's really all that important. But it doesn't seem like it should require loading native code to work for most users.
So I reviewed my test code and my test conditions weren't correct. With a tmp directory set with noexec permissions, I can see the .so file get created with execute permissions. The code returns a log message:
Which seems to be generated here: jline3/native/src/main/java/org/jline/nativ/JLineNativeLoader.java Lines 258 to 263 in 1f56fba
My original concern was that our application would fall over after jline failed to load the native library. However that failure seems to have been unrelated. Given that @ctubbsii was able to replicate this with an unrelated library file I agree that the issue is coming up from the underlying system loader so the change in this PR doesn't seem warranted. |
JLine uses the |
@gnodet I didn't realize a different property already existed! That helps as a workaround. Thanks! I'm still concerned about the unchecked RuntimeException that gets thrown at
There are several classes that call |
Removes the execute permission on the
.so
native library file created in the java tmp directory.This permission is not required for java to load the library file successfully.
JLine creates two files in a temp directory location when being used in an interactive application.
The
.so
file has read, write, and execute permissions set on it.The temp directory path set by
java.io.tmpdir
is typically /tmp or /var/tmp.However these directories are commonly set with the
noexec
flag to conform with security best practices.example: https://www.stigviewer.com/stig/red_hat_enterprise_linux_8/2023-12-01/finding/V-230513
When the
noexec
flag is set, JLine is prevented from creating the native lib file and functioning correctly.However after removing the execute permission from file creation, the native library file was able to be loaded successfully without issue.