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

Commit ec451647 authored by Narayan Kamath's avatar Narayan Kamath
Browse files

Fix native crashes when APKs can't be opened.

There was lax / incomplete error checking around the
construction of Apk handles. This change changes the ApkHandle
API and makes it throw IOException if the zipfile couldn't
be opened.

Additionally :
- Fix a resource leak in DefaultContainerService
- Report errors correctly during package moves.

bug: 15563874
Change-Id: Ic71a10709eb82b8f53405bbfb2320e80aa96b771
parent 7165bd6d
Loading
Loading
Loading
Loading
+17 −7
Original line number Original line Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.internal.content;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager;
import android.util.Slog;
import android.util.Slog;


import java.io.Closeable;
import java.io.File;
import java.io.File;
import java.io.IOException;
import java.io.IOException;


@@ -39,20 +40,29 @@ public class NativeLibraryHelper {
     *
     *
     * @hide
     * @hide
     */
     */
    public static class ApkHandle {
    public static class ApkHandle implements Closeable {
        final String apkPath;
        final String apkPath;
        final long apkHandle;
        final long apkHandle;


        public ApkHandle(String path) {
        public static ApkHandle create(String path) throws IOException {
            apkPath = path;
            final long handle = nativeOpenApk(path);
            apkHandle = nativeOpenApk(apkPath);
            if (handle == 0) {
                throw new IOException("Unable to open APK: " + path);
            }
            }


        public ApkHandle(File apkFile) {
            return new ApkHandle(path, handle);
            apkPath = apkFile.getPath();
            apkHandle = nativeOpenApk(apkPath);
        }
        }


        public static ApkHandle create(File path) throws IOException {
            return create(path.getAbsolutePath());
        }

        private ApkHandle(String apkPath, long apkHandle) {
            this.apkPath = apkPath;
            this.apkHandle = apkHandle;
        }

        @Override
        public void close() {
        public void close() {
            nativeClose(apkHandle);
            nativeClose(apkHandle);
        }
        }
+29 −19
Original line number Original line Diff line number Diff line
@@ -49,6 +49,7 @@ import android.util.Slog;


import com.android.internal.app.IMediaContainerService;
import com.android.internal.app.IMediaContainerService;
import com.android.internal.content.NativeLibraryHelper;
import com.android.internal.content.NativeLibraryHelper;
import com.android.internal.content.NativeLibraryHelper.ApkHandle;
import com.android.internal.content.PackageHelper;
import com.android.internal.content.PackageHelper;


import java.io.BufferedInputStream;
import java.io.BufferedInputStream;
@@ -106,8 +107,27 @@ public class DefaultContainerService extends IntentService {
                return null;
                return null;
            }
            }



            if (isExternal) {
                // Make sure the sdcard is mounted.
                String status = Environment.getExternalStorageState();
                if (!status.equals(Environment.MEDIA_MOUNTED)) {
                    Slog.w(TAG, "Make sure sdcard is mounted.");
                    return null;
                }
            }

            ApkHandle handle = null;
            try {
                handle = ApkHandle.create(packageURI.getPath());
                return copyResourceInner(packageURI, cid, key, resFileName, publicResFileName,
                return copyResourceInner(packageURI, cid, key, resFileName, publicResFileName,
                    isExternal, isForwardLocked, abiOverride);
                        isExternal, isForwardLocked, handle, abiOverride);
            } catch (IOException ioe) {
                Slog.w(TAG, "Problem opening APK: " + packageURI.getPath());
                return null;
            } finally {
                IoUtils.closeQuietly(handle);
            }
        }
        }


        /**
        /**
@@ -328,21 +348,11 @@ public class DefaultContainerService extends IntentService {


    private String copyResourceInner(Uri packageURI, String newCid, String key, String resFileName,
    private String copyResourceInner(Uri packageURI, String newCid, String key, String resFileName,
            String publicResFileName, boolean isExternal, boolean isForwardLocked,
            String publicResFileName, boolean isExternal, boolean isForwardLocked,
            String abiOverride) {
            ApkHandle handle, String abiOverride) {

        if (isExternal) {
            // Make sure the sdcard is mounted.
            String status = Environment.getExternalStorageState();
            if (!status.equals(Environment.MEDIA_MOUNTED)) {
                Slog.w(TAG, "Make sure sdcard is mounted.");
                return null;
            }
        }

        // The .apk file
        // The .apk file
        String codePath = packageURI.getPath();
        String codePath = packageURI.getPath();
        File codeFile = new File(codePath);
        File codeFile = new File(codePath);
        NativeLibraryHelper.ApkHandle handle = new NativeLibraryHelper.ApkHandle(codePath);

        String[] abiList = Build.SUPPORTED_ABIS;
        String[] abiList = Build.SUPPORTED_ABIS;
        if (abiOverride != null) {
        if (abiOverride != null) {
            abiList = new String[] { abiOverride };
            abiList = new String[] { abiOverride };
@@ -849,14 +859,14 @@ public class DefaultContainerService extends IntentService {


    private int calculateContainerSize(File apkFile, boolean forwardLocked,
    private int calculateContainerSize(File apkFile, boolean forwardLocked,
            String abiOverride) throws IOException {
            String abiOverride) throws IOException {
        NativeLibraryHelper.ApkHandle handle = new NativeLibraryHelper.ApkHandle(apkFile);
        ApkHandle handle = null;
        try {
            handle = ApkHandle.create(apkFile);
            final int abi = NativeLibraryHelper.findSupportedAbi(handle,
            final int abi = NativeLibraryHelper.findSupportedAbi(handle,
                    (abiOverride != null) ? new String[] { abiOverride } : Build.SUPPORTED_ABIS);
                    (abiOverride != null) ? new String[] { abiOverride } : Build.SUPPORTED_ABIS);

        try {
            return calculateContainerSize(handle, apkFile, abi, forwardLocked);
            return calculateContainerSize(handle, apkFile, abi, forwardLocked);
        } finally {
        } finally {
            handle.close();
            IoUtils.closeQuietly(handle);
        }
        }
    }
    }


+27 −18
Original line number Original line Diff line number Diff line
@@ -5019,8 +5019,9 @@ public class PackageManagerService extends IPackageManager.Stub {
         *        only for non-system apps and system app upgrades.
         *        only for non-system apps and system app upgrades.
         */
         */
        if (pkg.applicationInfo.nativeLibraryDir != null) {
        if (pkg.applicationInfo.nativeLibraryDir != null) {
            final NativeLibraryHelper.ApkHandle handle = new NativeLibraryHelper.ApkHandle(scanFile);
            ApkHandle handle = null;
            try {
            try {
                handle = ApkHandle.create(scanFile.getPath());
                // Enable gross and lame hacks for apps that are built with old
                // Enable gross and lame hacks for apps that are built with old
                // SDK tools. We must scan their APKs for renderscript bitcode and
                // SDK tools. We must scan their APKs for renderscript bitcode and
                // not launch them if it's present. Don't bother checking on devices
                // not launch them if it's present. Don't bother checking on devices
@@ -5135,7 +5136,7 @@ public class PackageManagerService extends IPackageManager.Stub {
            } catch (IOException ioe) {
            } catch (IOException ioe) {
                Slog.e(TAG, "Unable to get canonical file " + ioe.toString());
                Slog.e(TAG, "Unable to get canonical file " + ioe.toString());
            } finally {
            } finally {
                handle.close();
                IoUtils.closeQuietly(handle);
            }
            }
        }
        }
        pkg.mScanPath = path;
        pkg.mScanPath = path;
@@ -8768,10 +8769,11 @@ public class PackageManagerService extends IPackageManager.Stub {
                nativeLibraryFile.delete();
                nativeLibraryFile.delete();
            }
            }
            final NativeLibraryHelper.ApkHandle handle = new NativeLibraryHelper.ApkHandle(codeFile);
            String[] abiList = (abiOverride != null) ?
            String[] abiList = (abiOverride != null) ?
                    new String[] { abiOverride } : Build.SUPPORTED_ABIS;
                    new String[] { abiOverride } : Build.SUPPORTED_ABIS;
            ApkHandle handle = null;
            try {
            try {
                handle = ApkHandle.create(codeFile);
                if (Build.SUPPORTED_64_BIT_ABIS.length > 0 &&
                if (Build.SUPPORTED_64_BIT_ABIS.length > 0 &&
                        abiOverride == null &&
                        abiOverride == null &&
                        NativeLibraryHelper.hasRenderscriptBitcode(handle)) {
                        NativeLibraryHelper.hasRenderscriptBitcode(handle)) {
@@ -8786,7 +8788,7 @@ public class PackageManagerService extends IPackageManager.Stub {
                Slog.e(TAG, "Copying native libraries failed", e);
                Slog.e(TAG, "Copying native libraries failed", e);
                ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
                ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
            } finally {
            } finally {
                handle.close();
                IoUtils.closeQuietly(handle);
            }
            }
            return ret;
            return ret;
@@ -12229,25 +12231,32 @@ public class PackageManagerService extends IPackageManager.Stub {
                                    final File newNativeDir = new File(newNativePath);
                                    final File newNativeDir = new File(newNativePath);
                                    if (!isForwardLocked(pkg) && !isExternal(pkg)) {
                                    if (!isForwardLocked(pkg) && !isExternal(pkg)) {
                                        // NOTE: We do not report any errors from the APK scan and library
                                        ApkHandle handle = null;
                                        // copy at this point.
                                        try {
                                        NativeLibraryHelper.ApkHandle handle =
                                            handle = ApkHandle.create(newCodePath);
                                                new NativeLibraryHelper.ApkHandle(newCodePath);
                                            final int abi = NativeLibraryHelper.findSupportedAbi(
                                            final int abi = NativeLibraryHelper.findSupportedAbi(
                                                    handle, Build.SUPPORTED_ABIS);
                                                    handle, Build.SUPPORTED_ABIS);
                                            if (abi >= 0) {
                                            if (abi >= 0) {
                                                NativeLibraryHelper.copyNativeBinariesIfNeededLI(
                                                NativeLibraryHelper.copyNativeBinariesIfNeededLI(
                                                        handle, newNativeDir, Build.SUPPORTED_ABIS[abi]);
                                                        handle, newNativeDir, Build.SUPPORTED_ABIS[abi]);
                                            }
                                            }
                                        handle.close();
                                        } catch (IOException ioe) {
                                            Slog.w(TAG, "Unable to extract native libs for package :"
                                                    + mp.packageName, ioe);
                                            returnCode = PackageManager.MOVE_FAILED_INTERNAL_ERROR;
                                        } finally {
                                            IoUtils.closeQuietly(handle);
                                        }
                                    }
                                    }
                                    final int[] users = sUserManager.getUserIds();
                                    final int[] users = sUserManager.getUserIds();
                                    if (returnCode == PackageManager.MOVE_SUCCEEDED) {
                                        for (int user : users) {
                                        for (int user : users) {
                                            if (mInstaller.linkNativeLibraryDirectory(pkg.packageName,
                                            if (mInstaller.linkNativeLibraryDirectory(pkg.packageName,
                                                    newNativePath, user) < 0) {
                                                    newNativePath, user) < 0) {
                                                returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
                                                returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
                                            }
                                            }
                                        }
                                        }
                                    }
                                    if (returnCode == PackageManager.MOVE_SUCCEEDED) {
                                    if (returnCode == PackageManager.MOVE_SUCCEEDED) {
                                        pkg.mPath = newCodePath;
                                        pkg.mPath = newCodePath;