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

java.lang.UnsatisfiedLinkError: apple.security.KeychainStore._scanKeychain()V #1388

Closed
rsaulo opened this issue Jun 16, 2019 · 13 comments
Closed
Assignees

Comments

@rsaulo
Copy link

rsaulo commented Jun 16, 2019

I'm trying to generate a native image from our app that uses KeyChain on OSX.
Using the command :
native-image --no-server -H:+ReportExceptionStackTraces -H:ReflectionConfigurationFiles=../../reflect.json --enable-all-security-services -H:+JNI --report-unsupported-elements-at-runtime -jar fepweb-signer-1.3.0.jar

The build is OK without erros, but when trying to execute receives :

Exception in thread "main" java.lang.UnsatisfiedLinkError: apple.security.KeychainStore.scanKeychain()V [symbol: Java_apple_security_KeychainStore__1scanKeychain or Java_apple_security_KeychainStore__1scanKeychain_]
at com.oracle.svm.jni.access.JNINativeLinkage.getOrFindEntryPoint(JNINativeLinkage.java:145)
at com.oracle.svm.jni.JNIGeneratedMethodSupport.nativeCallAddress(JNIGeneratedMethodSupport.java:57)
at apple.security.KeychainStore._scanKeychain(KeychainStore.java)
at apple.security.KeychainStore.engineLoad(KeychainStore.java:773)
at java.security.KeyStore.load(KeyStore.java:1445)

Tried to put all libs to java.library.path but does not change anything. Any help?

@SergejIsbrecht
Copy link

Do you have the source available to reproduce?

Did you try using the agent in order to generate the JNI / Reflection configuration files? It looks like you try to use JNI, but there is no configuration file set for it, while create the native-image.

The documentation for JNI:
https://github.com/oracle/graal/blob/9a580f75cb618ee64eb36d92720b7488cb75dd4d/substratevm/JNI.md

The documentation for the JVM agent:
https://github.com/oracle/graal/blob/9a580f75cb618ee64eb36d92720b7488cb75dd4d/substratevm/CONFIGURE.md

@rsaulo
Copy link
Author

rsaulo commented Jun 17, 2019

Hi, I had tried with your suggestion and generated the configuration files, but the error is the same.

The relevante code is below :
KeyStore keyStore = keyStore.getInstance("KeychainStore"); keyStore.load(in, null);

My JNI config file is below, generated by the agent, the agent does not create the _scanKeychain method (maybe this is the problem??) and I manually added to the file, but the error continues..

[ { "name":"apple.security.KeychainStore", "methods":[ {"name":"createKeyEntry","parameterTypes":["java.lang.String","long","long","long[]","byte[][]"] }, {"name":"_scanKeychain","parameterTypes":[] }, {"name":"createTrustedCertEntry","parameterTypes":["java.lang.String","long","long","byte[]"] } ] }, { "name":"byte[]" } ]

@rsaulo
Copy link
Author

rsaulo commented Jun 17, 2019

Hi, I'm going deep on this and discovered that KeychainStore has a System.loadLibrary in a static block :

static {
    AccessController.doPrivileged(
        new PrivilegedAction<Void>() {
            public Void run() {
                System.loadLibrary("osxsecurity");
                return null;
            }
        });
    try {
        PKCS8ShroudedKeyBag_OID = new ObjectIdentifier(keyBag);
        pbeWithSHAAnd3KeyTripleDESCBC_OID = new ObjectIdentifier(pbeWithSHAAnd3KeyTripleDESCBC);
    } catch (IOException ioe) {
        // should not happen
    }
}

I think this is the problem? There is a workaround?

@SergejIsbrecht
Copy link

Disclosure: I do not have OSX, therefore I can not reproduce it. Furthermore I do not have any experience with JNI.

  • does the program run as expected, when using the default JVM?
  • do you know there the libosxsecurity.dylib / osxsecurity.dylib is placed? Is it included in -Djava.library.path=/path/to/lib . If not try generating the native-image with -Djava.library.path=/path/to/lib set.

But I think, if the lib is not found, where would be first following Exception:
Exception in thread "main" java.lang.UnsatisfiedLinkError: no osxsecurity in java.library.path

@SergejIsbrecht
Copy link

@rsaulo , I did some further digging. I create a little JNI myself:

From the java file I generated a header file and implemented the method in a c file.

#include <jni.h>        // JNI header provided by JDK
#include <stdio.h>      // C Standard IO Header
#include "de_graalvm_Main.h"   // Generated

// Implementation of the native method sayHello()
JNIEXPORT void JNICALL Java_de_graalvm_Main_sayHello(JNIEnv *env, jobject thisObj) {
   printf("Hello World!\n");
   return;
} 

Main

package de.graalvm;

public class Main {
  static {
    System.loadLibrary("helloworld");
  }

  public static void main(String[] args) throws Exception {
    new Main().sayHello();
  }

  private native void sayHello();
}

When I create the native-image, it will pass the generation and will run as expected:
./de.graalvm.main -Djava.library.path=./de/graalvm/

If I were to change the header-file and the c file to:
JNIEXPORT void JNICALL Java_de_graalvm_Main_sayHello2(JNIEnv *env, jobject thisObj)

the native-image generation will go through, but I get the same error as you get:

sergej@sergej-P50:~/Development/Development/maventest/src/main/java$ ./de.graalvm.main -Djava.library.path=./de/graalvm/
Exception in thread "main" java.lang.UnsatisfiedLinkError: de.graalvm.Main.sayHello()V [symbol: Java_de_graalvm_Main_sayHello or Java_de_graalvm_Main_sayHello__]
        at com.oracle.svm.jni.access.JNINativeLinkage.getOrFindEntryPoint(JNINativeLinkage.java:145)
        at com.oracle.svm.jni.JNIGeneratedMethodSupport.nativeCallAddress(JNIGeneratedMethodSupport.java:57)
        at de.graalvm.Main.sayHello(Main.java)
        at de.graalvm.Main.main(Main.java:9)

Conclusion:
It seems that Java_apple_security_KeychainStore__1scanKeychain is not included in the .so file "osxsecurity".

I actually do not how to investigate this problem further. Maybe look into the .so file, if posible?

@SergejIsbrecht
Copy link

So I got the latest GraalVM 19.0.2 JVM for OSX. The KeyChainStore does look a little bit different, than yours.

    static {
        AccessController.doPrivileged(new PrivilegedAction<Void>() {
            public Void run() {
                System.loadLibrary("osx");
                return null;
            }
        });

        try {
            PKCS8ShroudedKeyBag_OID = new ObjectIdentifier(keyBag);
            pbeWithSHAAnd3KeyTripleDESCBC_OID = new ObjectIdentifier(pbeWithSHAAnd3KeyTripleDESCBC);
        } catch (IOException var1) {
        }

    }

The distribution also contains the "osx" librabry
./Contents/Home/jre/lib/libosx.dylib

I looked at the disassembly of libosx.dylib and found following entry:
.text:000030fc <_Java_apple_security_KeychainStore__1scanKeychain>:

This is exactly the same entry you require.

Problem:

  • the compiled java source does not match with dynamically liked librabry. I would suggest compiling the source with a GraalVM distribution, then generate a native-image and start with ./yourExecutable -Djava.library.path=<directory_path_where_libosx.dylib_is>

Example:
./de.graalvm.main -Djava.library.path=./de/graalvm/

You can also peek into your osxsecurity, if you find it, with https://onlinedisassembler.com/ . You can search for the substring scanKeychain in the symbols. You should not be abled to find "Java_apple_security_KeychainStore__1scanKeychain" in the disassembly your osxsecurity file.

@rsaulo
Copy link
Author

rsaulo commented Jun 22, 2019

Hi, first thanks in advance for your help!!

I did that you suggested, already using GraalVM 19.0.2, compiled with GraalVM build native image and the same error again...

My build command :

native-image --no-server -H:+ReportExceptionStackTraces -H:ReflectionConfigurationFiles=../../graalvm-config/reflect-config.json -H:JNIConfigurationFiles=../../graalvm-config/jni-config.json --enable-all-security-services -H:+JNI -Djava.library.path=/Library/Java/JavaVirtualMachines/graalvm-ce-19.0.2/Contents/Home/jre/lib/ -jar fepweb-signer-1.3.0.jar

Executing :
./fepweb-signer-1.3.0 -Djava.library.path=/Library/Java/JavaVirtualMachines/graalvm-ce-19.0.2/Contents/Home/jre/lib/

My JVM lib dir has the osx lib :

$ ls /Library/Java/JavaVirtualMachines/graalvm-ce-19.0.2/Contents/Home/jre/lib/libosx.dylib
-rwxr-xr-x@ 1 rogerio staff 55576 May 23 15:50 /Library/Java/JavaVirtualMachines/graalvm-ce-19.0.2/Contents/Home/jre/lib/libosx.dylib

I do not understand why the env does not find the lib...

@SergejIsbrecht
Copy link

Last shot, when I am out of ideas. I would need some OSX system to reproduce it.

What you could also try is to set JAVA_HOME / GRAALVM_HOME to the GraalVM distribution and use the native-image application to generate the native-image. As I understand it, the native-image application will fork JVM process in order to generate the native-image. If you have set something other than the GraalVM, it might include the wrong class files in the image (only guessing, because I do not know how it actually works per-se).

When the image is generated, please try using the command again:
./fepweb-signer-1.3.0 -Djava.library.path=/Library/Java/JavaVirtualMachines/graalvm-ce-19.0.2/Contents/Home/jre/lib/

If it is still not working try ./fepweb-signer-1.3.0 -Djava.library.path=/ , which should generate the following stacktrace. In the stacktrace we will see, which library is not found.

Exception in thread "main" java.lang.UnsatisfiedLinkError: no osx in java.library.path
        at com.oracle.svm.core.jdk.NativeLibrarySupport.loadLibrary(NativeLibrarySupport.java:118)
        at java.lang.ClassLoader.loadLibrary(Target_java_lang_ClassLoader.java:126)
        at java.lang.Runtime.loadLibrary0(Runtime.java:870)
        at java.lang.Runtime.loadLibrary(Runtime.java:240)
        at java.lang.System.loadLibrary(System.java:365)
        at de.graalvm.Main.<clinit>(Main.java:5)
        at com.oracle.svm.core.hub.ClassInitializationInfo.invokeClassInitializer(ClassInitializationInfo.java:347)
        at com.oracle.svm.core.hub.ClassInitializationInfo.initialize(ClassInitializationInfo.java:267)
        at java.lang.Class.ensureInitialized(DynamicHub.java:437)

When you get an error again, please post the stacktrace you get.

I am all out of ideas, when you still get following issue. It somehow tries to load the wrong lib during runtime.

Exception in thread "main" java.lang.UnsatisfiedLinkError: apple.security.KeychainStore.scanKeychain()V [symbol: Java_apple_security_KeychainStore__1scanKeychain or Java_apple_security_KeychainStore__1scanKeychain_]

@rsaulo
Copy link
Author

rsaulo commented Jun 24, 2019

Hi!!
Done what you suggest and same error, I really do not know what is going on...

rogerio @ jars $ export JAVA_HOME=/Library/Java/JavaVirtualMachines/graalvm-ce-19.0.2/Contents/Home/
rogerio @ jars $ export GRAALVM_HOME=/Library/Java/JavaVirtualMachines/graalvm-ce-19.0.2/Contents/Home/
rogerio @ jars $ java -version
openjdk version "1.8.0_212"
OpenJDK Runtime Environment (build 1.8.0_212-20190523183630.graal2.jdk8u-src-tar-gz-b03)
OpenJDK 64-Bit GraalVM CE 19.0.2 (build 25.212-b03-jvmci-19-b04, mixed mode)
rogerio @ jars $ native-image --no-server -H:+ReportExceptionStackTraces -H:ReflectionConfigurationFiles=../../graalvm-config/reflect-config.json -H:JNIConfigurationFiles=../../graalvm-config/jni-config.json --enable-all-security-services -H:+JNI -jar fepweb-signer-1.3.0.jar
[fepweb-signer-1.3.0:6353] classlist: 3,295.41 ms
[fepweb-signer-1.3.0:6353] (cap): 2,680.66 ms
[fepweb-signer-1.3.0:6353] setup: 4,032.97 ms
[fepweb-signer-1.3.0:6353] (typeflow): 8,061.19 ms
[fepweb-signer-1.3.0:6353] (objects): 7,346.60 ms
[fepweb-signer-1.3.0:6353] (features): 673.83 ms
[fepweb-signer-1.3.0:6353] analysis: 16,378.24 ms
[fepweb-signer-1.3.0:6353] (clinit): 271.33 ms
[fepweb-signer-1.3.0:6353] universe: 636.63 ms
[fepweb-signer-1.3.0:6353] (parse): 1,040.81 ms
[fepweb-signer-1.3.0:6353] (inline): 2,600.07 ms
[fepweb-signer-1.3.0:6353] (compile): 9,674.32 ms
[fepweb-signer-1.3.0:6353] compile: 14,319.96 ms
[fepweb-signer-1.3.0:6353] image: 1,902.43 ms
[fepweb-signer-1.3.0:6353] write: 518.09 ms
[fepweb-signer-1.3.0:6353] [total]: 41,351.66 ms
rogerio @ jars $ ./fepweb-signer-1.3.0 -Djava.library.path=/Library/Java/JavaVirtualMachines/graalvm-ce-19.0.2/Contents/Home/jre/lib/
Exception in thread "main" java.lang.UnsatisfiedLinkError: apple.security.KeychainStore.scanKeychain()V [symbol: Java_apple_security_KeychainStore__1scanKeychain or Java_apple_security_KeychainStore__1scanKeychain_]
at com.oracle.svm.jni.access.JNINativeLinkage.getOrFindEntryPoint(JNINativeLinkage.java:145)
at com.oracle.svm.jni.JNIGeneratedMethodSupport.nativeCallAddress(JNIGeneratedMethodSupport.java:57)
at apple.security.KeychainStore._scanKeychain(KeychainStore.java)
at apple.security.KeychainStore.engineLoad(KeychainStore.java:773)
at java.security.KeyStore.load(KeyStore.java:1445)
at br.com.pfm.digitalsignatures.extension.FEPWebHostExtension.(FEPWebHostExtension.java:74)
at br.com.pfm.digitalsignatures.extension.FEPWebHostExtension.main(FEPWebHostExtension.java:95)

Executing with ./fepweb-signer-1.3.0 -Djava.library.path=/ does not return the lib that the VM is looking for..

rogerio @ jars $ ./fepweb-signer-1.3.0 -Djava.library.path=/
WARNING: The sunec native library, required by the SunEC provider, could not be loaded. This library is usually shipped as part of the JDK and can be found under <JAVA_HOME>/jre/lib//libsunec.so. It is loaded at run time via System.loadLibrary("sunec"), the first time services from SunEC are accessed. To use this provider's services the java.library.path system property needs to be set accordingly to point to a location that contains libsunec.so. Note that if java.library.path is not set it defaults to the current working directory.
Exception in thread "main" java.lang.UnsatisfiedLinkError: apple.security.KeychainStore.scanKeychain()V [symbol: Java_apple_security_KeychainStore__1scanKeychain or Java_apple_security_KeychainStore__1scanKeychain_]
at com.oracle.svm.jni.access.JNINativeLinkage.getOrFindEntryPoint(JNINativeLinkage.java:145)
at com.oracle.svm.jni.JNIGeneratedMethodSupport.nativeCallAddress(JNIGeneratedMethodSupport.java:57)
at apple.security.KeychainStore._scanKeychain(KeychainStore.java)
at apple.security.KeychainStore.engineLoad(KeychainStore.java:773)
at java.security.KeyStore.load(KeyStore.java:1445)
at br.com.pfm.digitalsignatures.extension.FEPWebHostExtension.(FEPWebHostExtension.java:74)
at br.com.pfm.digitalsignatures.extension.FEPWebHostExtension.main(FEPWebHostExtension.java:95)

@CedricGatay
Copy link

@rsaulo did you find any workaround for this ?

@thelongestusernameofall

@rsaulo Hi rsaulo,
I have met same error as yours. Google search lead me here. Finally, I've found a solution for it. Wish it could help you too.

First: the case
error message in my case:

╰─$ ./test.so
Exception in thread "main" java.lang.UnsatisfiedLinkError: PuffsVM.setup()I [symbol: Java_PuffsVM_setup or Java_PuffsVM_setup__]
	at com.oracle.svm.jni.access.JNINativeLinkage.getOrFindEntryPoint(JNINativeLinkage.java:153)
	at com.oracle.svm.jni.JNIGeneratedMethodSupport.nativeCallAddress(JNIGeneratedMethodSupport.java:57)
	at PuffsVM.setup(PuffsVM.java)
	at Test.main(Test.java:8)

which obviously the same as yours.

Then: solution

a. by running with this command:
DYLD_PRINT_LIBRARIES=1 ./test.so
I figured out that the libPuffsVM.dylib, which contains the need symbol Java_PuffsVM_setup, actually didn't loaded while test.so running.
You can also confirm that by image list command with lldb debugging run the test.so;

b. by running with this command:
DYLD_INSERT_LIBRARIES=libPuffsVM.dylib ./test.so
(which run well without error)

I confirmed that, let the dylib been loaded with the executable do fix the error.

c. solve it using the insert_dylib tool, to modify the executable, test.so in my case.
from here https://github.com/Tyilo/insert_dylib, download insert_dylib source code. and compile an insert_dylib tool.

d. command like insert_dylib libPuffsVM.dylib test.so
and it prints Added LC_LOAD_DYLIB to test.so_patched;
then mv test.so_patched test.so
and run ./test.so;
no error there.

(forgive my English.)

@selhagani selhagani self-assigned this Jan 16, 2024
@selhagani
Copy link
Member

Hi Rsaulo, I understand that this is an old issue but if you're still interested please do let me know if you found the solution to your issue. I see some suggestions in the comments. Perhaps those solve the issue. Thank you.

@selhagani
Copy link
Member

I am closing this issue because it's been over 2 weeks since my last interaction and I haven't received any updates yet.

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

5 participants