Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cfe38cdb authored by Jiyong Park's avatar Jiyong Park Committed by malchev
Browse files

Fix: vendor public libraries are accessible via System.loadLibrary

This CL fixes the problem that vendor public libraries (libs that are
listed in /vendor/etc/public.libraries.txt) are not loadable via
System.loadLibrary(). (Note that the libs were accessible via dlopen()
though.)

The problem was happening because when System.loadLibary() is called,
the classloader first checks whether the lib is found and accessible in
its own native lib search paths. The native lib search paths basically
come from the java.library.path property, which in turn is from
namespace.default.search.path in /system/etc/ld.config.txt. When VNDK is
enforced starting from P, namespace.default.search.path does not have
paths other than /system/lib because otherwise system process can have
unlimited access to libs in vendor partition. The linker namespace is
dynamically configured by the libnativeloader so that only the public
vendor libs are accessible. However, as a side effect of removing
/vendor/lib from namespace.default.search.path, the classloader always
fails to find any lib under /vendor/lib even if the lib is a public one.

In order to solve the problem, while keeping rest of the non-public
vendor libs from apps, /vendor/lib (and /odm/lib and /product/lib as
well) is added to the classloader AFTER native loader is created for the
classloader.

Bug: 93333337
Test: m -j
Test: System.loadLibrary("adsprpc") is successful in Pixel (because
libadsprpc.so is in Pixel's vendor public lib list)
Test: atest cts/tests/tests/jni
Change-Id: Iac12384548cbdd51234568082d02eeba466c160c
parent 7d2d403a
Loading
Loading
Loading
Loading
+38 −0
Original line number Diff line number Diff line
@@ -745,6 +745,44 @@ public final class LoadedApk {
            }
        }

        // /vendor/lib, /odm/lib and /product/lib are added to the native lib search
        // paths of the classloader. Note that this is done AFTER the classloader is
        // created by ApplicationLoaders.getDefault().getClassLoader(...). The
        // reason is because if we have added the paths when creating the classloader
        // above, the paths are also added to the search path of the linker namespace
        // 'classloader-namespace', which will allow ALL libs in the paths to apps.
        // Since only the libs listed in <partition>/etc/public.libraries.txt can be
        // available to apps, we shouldn't add the paths then.
        //
        // However, we need to add the paths to the classloader (Java) though. This
        // is because when a native lib is requested via System.loadLibrary(), the
        // classloader first tries to find the requested lib in its own native libs
        // search paths. If a lib is not found in one of the paths, dlopen() is not
        // called at all. This can cause a problem that a vendor public native lib
        // is accessible when directly opened via dlopen(), but inaccesible via
        // System.loadLibrary(). In order to prevent the problem, we explicitly
        // add the paths only to the classloader, and not to the native loader
        // (linker namespace).
        List<String> extraLibPaths = new ArrayList<>(3);
        String abiSuffix = VMRuntime.getRuntime().is64Bit() ? "64" : "";
        if (!defaultSearchPaths.contains("/vendor/lib")) {
            extraLibPaths.add("/vendor/lib" + abiSuffix);
        }
        if (!defaultSearchPaths.contains("/odm/lib")) {
            extraLibPaths.add("/odm/lib" + abiSuffix);
        }
        if (!defaultSearchPaths.contains("/product/lib")) {
            extraLibPaths.add("/product/lib" + abiSuffix);
        }
        if (!extraLibPaths.isEmpty()) {
            StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
            try {
                ApplicationLoaders.getDefault().addNative(mClassLoader, extraLibPaths);
            } finally {
                StrictMode.setThreadPolicy(oldPolicy);
            }
        }

        if (addedPaths != null && addedPaths.size() > 0) {
            final String add = TextUtils.join(File.pathSeparator, addedPaths);
            ApplicationLoaders.getDefault().addPath(mClassLoader, add);