-
Notifications
You must be signed in to change notification settings - Fork 78
Add jffi.extract.name for specific file #99
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
Conversation
I am unsure how important the missing verification might be. In the extreme, if the directory used is not under tight control, a malicious application could exploit this by installing its own library at that location. However if the path is secure, the file should also be secure even if it unpacks lazily. The concern is whether users will take appropriate precautions and how much we should protect them from the worst case. Verification would be tricky. A checksum or hash of the library would seem to be a natural mechanism, but the file could be modified between the time that its hash is calculated and the library is loaded into the JVM (a TOC-to-TOU exploit). We could call something to verify the library's identity after it has loaded, but by then the exploit is already in place and anything we call could be simulated by mimicking what our own binary does. So, this may be a "buyer beware" sort of feature. |
Thanks! Do you think that a minimal check could be to verify the library size? Also, regarding the retained solution I'm wondering if a boolean property won't be enough. The described behaviors would be the same, but this would avoid the JFFI user to determine a library name and also a library extension according to the platform. |
You know, that's a good point, Just because there's a TOCTOU issue doesn't mean we shouldn't at least perform some minimum checks.
Well this is also a fair point, but I am reluctant to add a simple boolean (maybe jffi.extract.tempname=false?) and then a few weeks from now someone comes back and asks for a way to set the name. A few justifications for going all the way to a name property:
I am stretching a bit on the last one but I still feel like having a simple name property is best. Perhaps to avoid the extension issue, we allow user to provide a simple name and add any platform-specific extension that is needed? |
I believe so long as you specify the name and not only the dir you will have to fingerprint this. Not for security but to make sure you do not run two versions of JRuby which require different versions of jffi. If it is only the dir and the name is versioned then perhaps than can be omitted (unless you want a security check). |
Obviously if you are using this as a library and not from JRuby the same concern will likely apply. |
I have pushed another commit that enhances this feature:
|
LGTM, thanks. I think the blank property is a good trick, and it should really simplify my use case. I also agree with your arguments against a single boolean field. I can now test the PR in its current form. Will do that tomorrow. |
81539d2
to
7b4daba
Compare
So I tried but I'm facing an issue:
I tried with:
and also
Note that I have mixed JFFI 1.3.2-SNAPSHOT with JNR-FFI 2.2.1. |
This might be a commit I attempted and reverted for #93 which changed the version numbers we use to load the native libraries out of the jar. I have merged that change to this branch. |
I am running into some issues as well on MacOS and will get back to you once they are fixed. |
@david-bouyssie Ok my issues may only be with the jffi tests. jnr-ffi appears to be running green with the reverted commit. Could you give it another try (on this branch)? |
Yes sure, will do that later this week-end. |
@david-bouyssie Were you able to give this a try? |
Not yet, but should be able this evening. |
So, the previous issue is now solved but now I have another unclear issue: If I stop the JVM and re-run my app (without deleting the jffi DLL), then it works fine. So it looks like the file is extracted, but is not well loaded, like if it was stuck in a while loop. |
@david-bouyssie Ok something must be wrong with how I am calculating the SHA. I will investigate (and add a test this time). |
I found the source of the bug (a bad refactoring on my part) and some additional small issues I will fix up. |
Normally the library is extracted to a temp directory with an appropriately-mangled temp name, but on platforms that cannot delete the file before exiting the JVM this leaves those library files to accumulate. This change builds on the jffi.extract.dir property and adds jffi.extract.name to specify a specific filename to use every time, reusing any existing file at that location. Depending on how these two properties are combined, the file will be extracted as follows: * Set neither: file will be extracted with a temp name under the default temp dir, with attempt to delete and no reuse. * Set both: file will be the given name in the given path, reused if existing or extracted otherwise. * Set only dir: file will be extracted with a temp name under the specified directory, with attempt to delete and no reuse. * Set only name: file will be extracted with the given name under the default temp dir, reused if existing or extracted otherwise. Note that this does not verify that the loaded file matches the one bundled with jffi. This is left up to the user, since any verification of the existing file will be subject to TOC-to-TOU vulnerability. It is not possible to have the JVM atomically verify and load the given file. This partially addresses jnr#97 by allowing Windows users to specify a known file path to reuse across runs.
8e55e36
to
193f414
Compare
* New: specify blank name (-Djffi.extract.name) to use default name of "jffi-#.#.ext" with current jffi version and platform- specific ext. * New: existing library will be verified using SHA-256 hash of library contained in jffi jars.
This minimally verifies that the three main ways to reference the JNI library are all tested.
c3598ac
to
46ecfbe
Compare
This test will break the instant the version is updated but the archived binaries do not match. It could be restored in the future but it does not provide a lot of value unless it can reflect the version at the time the binary was built.
46ecfbe
to
bfd6e5e
Compare
@david-bouyssie Thanks for your patience and sorry about having you test broken code. The main bug was that I refactored out a call to InputStream.available used as a terminating condition in a loop, forgetting that it will update as the stream progresses until it reaches zero. There were other minor issues with the verification of the file:
I have manually confirmed the digest hash check and various configurations and added two additional full test runs that use a temp file or a specific file. Try again please? 🙇♂️ |
No problem, actually I'm glad to see it was not my mistake 😄 I'll try today. |
LGTM 🚀 |
Normally the library is extracted to a temp directory with an
appropriately-mangled temp name, but on platforms that cannot
delete the file before exiting the JVM this leaves those library
files to accumulate.
This change builds on the jffi.extract.dir property and adds
jffi.extract.name to specify a specific filename to use every
time, reusing any existing file at that location.
Depending on how these two properties are combined, the file will
be extracted as follows:
default temp dir, with attempt to delete and no reuse.
reused if existing or extracted otherwise.
specified directory, with attempt to delete and no reuse.
the default temp dir, reused if existing or extracted otherwise.
Note that this does not verify that the loaded file matches the
one bundled with jffi. This is left up to the user, since any
verification of the existing file will be subject to TOC-to-TOU
vulnerability. It is not possible to have the JVM atomically
verify and load the given file.
This partially addresses #97 by allowing Windows users to specify
a known file path to reuse across runs.