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

Commit f654371d authored by Alan Stokes's avatar Alan Stokes
Browse files

Don't include inaccessible data dirs in library paths.

When constructing a classloader for a different app, don't include
it's private data dir in libraryPermittedPath if we don't have access
to it. (Which we often won't, although it depends on target SDK,
whether it has a shared UID, etc.)

This avoids generating SELinux denials at boot and other times,
e.g. when initialising WebView.

Bug: 161356067
Test: Boots, denials not seen, WebView works.
Change-Id: Ib246af979783e80fde3313f8aed6c3b7a886e6b2
parent 5080b250
Loading
Loading
Loading
Loading
+30 −6
Original line number Diff line number Diff line
@@ -802,12 +802,9 @@ public final class LoadedApk {

        makePaths(mActivityThread, isBundledApp, mApplicationInfo, zipPaths, libPaths);

        String libraryPermittedPath = mDataDir;
        if (mActivityThread == null) {
            // In a zygote context where mActivityThread is null we can't access the app data dir
            // and including this in libraryPermittedPath would cause SELinux denials.
            libraryPermittedPath = "";
        }
        // Including an inaccessible dir in libraryPermittedPath would cause SELinux denials
        // when the loader attempts to canonicalise the path. so we don't.
        String libraryPermittedPath = canAccessDataDir() ? mDataDir : "";

        if (isBundledApp) {
            // For bundled apps, add the base directory of the app (e.g.,
@@ -951,6 +948,33 @@ public final class LoadedApk {
        }
    }

    /**
     * Return whether we can access the package's private data directory in order to be able to
     * load code from it.
     */
    private boolean canAccessDataDir() {
        // In a zygote context where mActivityThread is null we can't access the app data dir.
        if (mActivityThread == null) {
            return false;
        }

        // A package can access its own data directory (the common case, so short-circuit it).
        if (Objects.equals(mPackageName, ActivityThread.currentPackageName())) {
            return true;
        }

        // Temporarily disable logging of disk reads on the Looper thread as this is necessary -
        // and the loader will access the directory anyway if we don't check it.
        StrictMode.ThreadPolicy oldPolicy = allowThreadDiskReads();
        try {
            // We are constructing a classloader for a different package. It is likely,
            // but not certain, that we can't acccess its app data dir - so check.
            return new File(mDataDir).canExecute();
        } finally {
            setThreadPolicy(oldPolicy);
        }
    }

    @UnsupportedAppUsage
    public ClassLoader getClassLoader() {
        synchronized (this) {