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

Improve handling of dynamicaly extracted native library #985

Closed
nextgens opened this issue Jul 7, 2018 · 9 comments
Closed

Improve handling of dynamicaly extracted native library #985

nextgens opened this issue Jul 7, 2018 · 9 comments

Comments

@nextgens
Copy link

nextgens commented Jul 7, 2018

  1. Problem Statement

JNA creates a temporary folder at a known location (harcoded path: /tmp/jna) to do its deed.
Unlike the system's temporary folder, it doesn't set the sticky bit on it... so on multi user systems, several problems arise :

  1. Suggested changes

I've located at least two separate occurences of the problem:

static File getTempDir() throws IOException {
(runtime error + security vulnerability)
private void createDir() throws FileNotFoundException {
(just a security vulnerability)

In both cases, the easy fix is to make the directory name "instance" specific with an unpredictable path:
https://docs.oracle.com/javase/7/docs/api/java/nio/file/Files.html#createTempDirectory(java.lang.String,%20java.nio.file.attribute.FileAttribute...)

  1. Version information

Seems irrelevant... but it does affect 4.5.1

@neilcsmith-net
Copy link
Contributor

Just saw this while looking at something else. Do you really get a directory at /tmp/jna/!?

@twall
Copy link
Contributor

twall commented Jul 9, 2018 via email

@matthiasblaesing
Copy link
Member

Ok - if someone wants to improve the situation, I'm all for it, BUT:

The problem does not exist in the described manner. At least for the last five years, JNA uses java.io.tmpdir and creates a directory there with the scheme jna-<hashCodeOfUsername>. A collision is highly unlikely. So the referenced bug is most probably not from a multi-user system, but a system, that uses the same user with different JNA versions. This should be improved.

For the security impact: Yes it is a race condition - an attacker can create a colliding directory with a library file, that has access permissions, that are wider than the umask of the calling user (if the umask of the user is that wide open, he/she has worse problems). It is a timing attack, as the file needs to be rewritten after JNA has expanded its embedded library. This should be improved.

If someone wants to take this on, this is what I suggest:

  • add an alternative expansion strategy for native libraries
  • the alternative could use the users home directory, create a hidden directory there with a directory per native version

That comment is relevant for Native, TlbImp is not used at normal runtime and is expected to be called with an output directory and if not present, then yes, an attacker could change your generated bindings.

@matthiasblaesing matthiasblaesing changed the title temporary path collision on multi-user systems Improve handling of dynamicaly extracted native library Jul 13, 2018
matthiasblaesing added a commit to matthiasblaesing/jna that referenced this issue Sep 15, 2018
…ive library.

On Mac OS X systems `~/Library/Application Support/JNA/temp` and on
other Unix like systems `$XDG_CACHE_DIR/JNA/temp` (Default value is:
`~/.cache/JNA/temp`) is used.

Behaviour on windows is unchanged, as since Vista the tempdir is by
default inside the user profile directory.

Closes: java-native-access#985
@matthiasblaesing
Copy link
Member

PR #1013 should address the problems. Please have a look at it.

@nextgens
Copy link
Author

Hmm, it will still break when the same user runs separate JVMs with different versions of JNA... You forgot the "per native version" part :)

@neilcsmith-net
Copy link
Contributor

Well, what is "per native version"? Wouldn't the ideal thing be for this all to be process segregated? In which case, I'm wondering whether a hash of the resource URL from the ClassLoader could be added to the folder or file name?

@nextgens
Copy link
Author

I'd just pick a non-deterministic (random) value and call it a day. In our specific case on freenet, we have problems with the test-suite running the same code with different JVMs concurrently... and that seems to fail on occasion (probably because there's a race where the files get renamed/deleted and loaded by another JVM)

@matthiasblaesing
Copy link
Member

matthiasblaesing commented Sep 18, 2018

I strongly doubt, that your problem is related to the extraction logic. From Native#extractFromResourcePath:

                File dir = getTempDir();
                lib = File.createTempFile(JNA_TMPLIB_PREFIX, Platform.isWindows()?".dll":null, dir);
                if (!Boolean.getBoolean("jnidispatch.preserve")) {
                    lib.deleteOnExit();
                }
                fos = new FileOutputStream(lib);
                int count;
                byte[] buf = new byte[1024];
                while ((count = is.read(buf, 0, buf.length)) > 0) {
                    fos.write(buf, 0, count);
                }

For your argumentation it is relevant, that File#createTempFile is used. This:

  • A secure random is used to generate a random long
  • That is combined with prefix and suffix (the random part is shorted to at be at least 5 chars long) to the filename
  • It is then checked if the file already exists, if it exists, the filename will be regenerated
  • If a non-existing name is found, the final file is created via FileSystem#createFileExclusively. If the file could not be exclusively created, an IOException is raised

I don't see how this can clash - sure SecureRandom can create the same number twice.

So you claim there is a security problem - that is fixed by my patch, as it moves the files into the users home -- if that is not secured, all is lost. You further claim there is an issue when creating the temp file, I don't see how this is possible with the construction above.

Please provide stack traces and reasoning why you think there is an issue in JNA.

matthiasblaesing added a commit to matthiasblaesing/jna that referenced this issue Sep 20, 2018
…ive library.

On Mac OS X systems `~/Library/Caches/JNA/temp` and on
other Unix like systems `$XDG_CACHE_DIR/JNA/temp` (Default value is:
`~/.cache/JNA/temp`) is used.

Behaviour on windows is unchanged, as since Vista the tempdir is by
default inside the user profile directory.

Closes: java-native-access#985
matthiasblaesing added a commit to matthiasblaesing/jna that referenced this issue Sep 20, 2018
…ive library.

On Mac OS X systems `~/Library/Caches/JNA/temp` and on
other Unix like systems `$XDG_CACHE_DIR/JNA/temp` (Default value is:
`~/.cache/JNA/temp`) is used.

Behaviour on windows is unchanged, as since Vista the tempdir is by
default inside the user profile directory.

Closes: java-native-access#985
@matthiasblaesing
Copy link
Member

@nextgens I merged the changeset as it improves the situation. I would be interested in your original problem - stacktraces/detailed logs would be helpful. Feel free to take this to the google group.

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

4 participants