Loading cmds/installd/commands.c +24 −9 Original line number Diff line number Diff line Loading @@ -141,39 +141,54 @@ int renamepkg(const char *oldpkgname, const char *newpkgname) return 0; } int fix_uid(const char *pkgname, uid_t uid, gid_t gid) int fix_uid(const char *pkgname, uid_t uid, uid_t userId) { char pkgdir[PKG_PATH_MAX]; struct stat s; int rc = 0; if ((uid < AID_SYSTEM) || (gid < AID_SYSTEM)) { ALOGE("invalid uid/gid: %d %d\n", uid, gid); if (uid < AID_SYSTEM) { ALOGE("invalid uid: %d\n", uid); return -1; } if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, 0)) { if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, userId)) { ALOGE("cannot create package path\n"); return -1; } if (stat(pkgdir, &s) < 0) return -1; if (s.st_uid != 0 || s.st_gid != 0) { ALOGE("fixing uid of non-root pkg: %s %lu %lu\n", pkgdir, s.st_uid, s.st_gid); if (((s.st_uid != 0) && (s.st_uid != AID_INSTALL)) || ((s.st_gid != 0) && (s.st_gid != AID_INSTALL))) { ALOGE("fixing uid of pkg not owned by install or root: %s %lu %lu\n", pkgdir, s.st_uid, s.st_gid); return -1; } if (chown(pkgdir, AID_INSTALL, AID_INSTALL) < 0) { ALOGE("cannot chown dir '%s': %s\n", pkgdir, strerror(errno)); unlink(pkgdir); return -1; } if (chmod(pkgdir, 0751) < 0) { ALOGE("cannot chmod dir '%s': %s\n", pkgdir, strerror(errno)); unlink(pkgdir); return -errno; return -1; } if (chown(pkgdir, uid, gid) < 0) { if (chown(pkgdir, uid, uid) < 0) { ALOGE("cannot chown dir '%s': %s\n", pkgdir, strerror(errno)); unlink(pkgdir); return -errno; return -1; } #ifdef HAVE_SELINUX if (selinux_android_setfilecon(pkgdir, pkgname, uid) < 0) { ALOGE("cannot setfilecon dir '%s': %s\n", pkgdir, strerror(errno)); unlink(pkgdir); return -1; } #endif return 0; } Loading services/java/com/android/server/pm/Installer.java +2 −2 Original line number Diff line number Diff line Loading @@ -243,14 +243,14 @@ public final class Installer { return execute(builder.toString()); } public int fixUid(String name, int uid, int gid) { public int fixUid(String name, int uid, int userId) { StringBuilder builder = new StringBuilder("fixuid"); builder.append(' '); builder.append(name); builder.append(' '); builder.append(uid); builder.append(' '); builder.append(gid); builder.append(userId); return execute(builder.toString()); } Loading services/java/com/android/server/pm/PackageManagerService.java +155 −129 Original line number Diff line number Diff line Loading @@ -1008,6 +1008,8 @@ public class PackageManagerService extends IPackageManager.Stub { mHandler = new PackageHandler(mHandlerThread.getLooper()); File dataDir = Environment.getDataDirectory(); mAppInstallDir = new File(dataDir, "app"); mAppLibInstallDir = new File(dataDir, "app-lib"); mAppDataDir = new File(dataDir, "data"); mAsecInternalPath = new File(dataDir, "app-asec").getPath(); mUserAppDataDir = new File(dataDir, "user"); Loading Loading @@ -1218,8 +1220,6 @@ public class PackageManagerService extends IPackageManager.Stub { } } mAppInstallDir = new File(dataDir, "app"); mAppLibInstallDir = new File(dataDir, "app-lib"); //look for any incomplete package installations ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackagesLPr(); //clean up list Loading Loading @@ -3576,22 +3576,22 @@ public class PackageManagerService extends IPackageManager.Stub { } } private int createDataDirsLI(String packageName, int uid) { int[] users = sUserManager.getUserIds(); int res = mInstaller.install(packageName, uid, uid); if (res < 0) { return res; private int createDataDirForUserLI(String packageName, int uid, int userId) { if (userId == 0) { return mInstaller.install(packageName, uid, uid); } else { return mInstaller.createUserData(packageName, UserHandle.getUid(userId, uid), userId); } for (int user : users) { if (user != 0) { res = mInstaller.createUserData(packageName, UserHandle.getUid(user, uid), user); } private int createDataDirsLI(String packageName, int uid) { for (int userId : sUserManager.getUserIds()) { int res = createDataDirForUserLI(packageName, uid, userId); if (res < 0) { return res; } } } return res; return 0; } private int removeDataDirsLI(String packageName) { Loading Loading @@ -3930,134 +3930,49 @@ public class PackageManagerService extends IPackageManager.Stub { pkg.applicationInfo.dataDir = dataPath.getPath(); } else { // This is a normal package, need to make its data directory. dataPath = getDataPathForPackage(pkg.packageName, 0); boolean uidError = false; if (dataPath.exists()) { int currentUid = 0; try { StructStat stat = Libcore.os.stat(dataPath.getPath()); currentUid = stat.st_uid; } catch (ErrnoException e) { Slog.e(TAG, "Couldn't stat path " + dataPath.getPath(), e); } // If we have mismatched owners for the data path, we have a problem. if (currentUid != pkg.applicationInfo.uid) { boolean recovered = false; if (currentUid == 0) { // The directory somehow became owned by root. Wow. // This is probably because the system was stopped while // installd was in the middle of messing with its libs // directory. Ask installd to fix that. int ret = mInstaller.fixUid(pkgName, pkg.applicationInfo.uid, pkg.applicationInfo.uid); if (ret >= 0) { recovered = true; String msg = "Package " + pkg.packageName + " unexpectedly changed to uid 0; recovered to " + + pkg.applicationInfo.uid; reportSettingsProblem(Log.WARN, msg); } } if (!recovered && ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0 || (scanMode&SCAN_BOOTING) != 0)) { // If this is a system app, we can at least delete its // current data so the application will still work. int ret = removeDataDirsLI(pkgName); if (ret >= 0) { // TODO: Kill the processes first // Old data gone! String prefix = (parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0 ? "System package " : "Third party package "; String msg = prefix + pkg.packageName + " has changed from uid: " + currentUid + " to " + pkg.applicationInfo.uid + "; old data erased"; reportSettingsProblem(Log.WARN, msg); recovered = true; dataPath = getDataPathForPackage(pkg.packageName, UserHandle.USER_OWNER); // And now re-install the app. ret = createDataDirsLI(pkgName, pkg.applicationInfo.uid); if (ret == -1) { // Ack should not happen! msg = prefix + pkg.packageName + " could not have data directory re-created after delete."; reportSettingsProblem(Log.WARN, msg); mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; return null; } } if (!recovered) { mHasSystemUidErrors = true; } } else if (!recovered) { // If we allow this install to proceed, we will be broken. // Abort, abort! mLastScanError = PackageManager.INSTALL_FAILED_UID_CHANGED; return null; } if (!recovered) { pkg.applicationInfo.dataDir = "/mismatched_uid/settings_" + pkg.applicationInfo.uid + "/fs_" + currentUid; pkg.applicationInfo.nativeLibraryDir = pkg.applicationInfo.dataDir; String msg = "Package " + pkg.packageName + " has mismatched uid: " + currentUid + " on disk, " + pkg.applicationInfo.uid + " in settings"; // writer synchronized (mPackages) { mSettings.mReadMessages.append(msg); mSettings.mReadMessages.append('\n'); uidError = true; if (!pkgSetting.uidError) { reportSettingsProblem(Log.ERROR, msg); } } } } pkg.applicationInfo.dataDir = dataPath.getPath(); } else { if (!ensureDataDirExistsForAllUsers(pkg.packageName, pkg.applicationInfo.uid)) { if (DEBUG_PACKAGE_SCANNING) { if ((parseFlags & PackageParser.PARSE_CHATTY) != 0) if ((parseFlags & PackageParser.PARSE_CHATTY) != 0) { Log.v(TAG, "Want this data dir: " + dataPath); } //invoke installer to do the actual installation int ret = createDataDirsLI(pkgName, pkg.applicationInfo.uid); if (ret < 0) { } // Error from installer mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; return null; } if (dataPath.exists()) { pkg.applicationInfo.dataDir = dataPath.getPath(); } else { Slog.w(TAG, "Unable to create data directory: " + dataPath); pkg.applicationInfo.dataDir = null; pkg.applicationInfo.dataDir = dataPath.getPath(); } final boolean isSystemApp = (parseFlags & PackageParser.PARSE_IS_SYSTEM) != 0; final boolean isBootScan = (scanMode & SCAN_BOOTING) != 0; final boolean uidCorrect = ensureDataDirUidIsCorrectForAllUsers(pkg.packageName, pkg.applicationInfo.uid, isSystemApp, isBootScan); if (!uidCorrect) { pkg.applicationInfo.dataDir = "/mismatched_uid/settings_" + pkg.applicationInfo.uid + "/fs_mismatched"; pkg.applicationInfo.nativeLibraryDir = pkg.applicationInfo.dataDir; } pkgSetting.uidError = !uidCorrect; /* * Set the data dir to the default "/data/data/<package name>/lib" * if we got here without anyone telling us different (e.g., apps * stored on SD card have their native libraries stored in the ASEC * container with the APK). * * This happens during an upgrade from a package settings file that * doesn't have a native library path attribute at all. * Set the native library dir to the default if we got here without * anyone telling us different (e.g., apps stored on SD card have * their native libraries stored in the ASEC container with the * APK). This happens during an upgrade from a package settings file * that doesn't have a native library path attribute at all. */ if (pkg.applicationInfo.nativeLibraryDir == null && pkg.applicationInfo.dataDir != null) { if (pkg.applicationInfo.nativeLibraryDir == null) { if (pkgSetting.nativeLibraryPathString == null) { setInternalAppNativeLibraryPath(pkg, pkgSetting); } else { pkg.applicationInfo.nativeLibraryDir = pkgSetting.nativeLibraryPathString; } } pkgSetting.uidError = uidError; } String path = scanFile.getPath(); Loading Loading @@ -4446,6 +4361,100 @@ public class PackageManagerService extends IPackageManager.Stub { return pkg; } /** * Checks to see whether a package data directory is owned by the correct * user. If it isn't, it will attempt to fix it if it's a system application * or if this is the boot scan. * * @return {@code true} if successful, {@code false} if recovery failed */ private boolean ensureDataDirUidIsCorrectForAllUsers(String packageName, int appUid, boolean isSystemApp, boolean isBootScan) { boolean mismatch = false; for (int userId : sUserManager.getUserIds()) { final File dataPath = getDataPathForPackage(packageName, userId); int currentUid = 0; try { final StructStat stat = Libcore.os.stat(dataPath.getPath()); currentUid = stat.st_uid; } catch (ErrnoException e) { Slog.e(TAG, "Couldn't stat path " + dataPath.getPath(), e); } final int expectedUid = UserHandle.getUid(userId, appUid); // If we have mismatched owners for the data path, we have a // problem. if (currentUid != expectedUid) { if (currentUid == 0) { // The directory somehow became owned by root. Wow. // This is probably because the system was stopped while // installd was in the middle of messing with its libs // directory. Ask installd to fix that. final int ret; synchronized (mInstaller) { ret = mInstaller.fixUid(packageName, expectedUid, userId); } if (ret >= 0) { String msg = "Package " + packageName + " unexpectedly changed to uid 0; recovered to " + expectedUid; reportSettingsProblem(Log.WARN, msg); } else { mismatch = true; String prefix = isSystemApp ? "System package " : "Third party package "; String msg = prefix + packageName + " has changed from uid: " + currentUid + " to " + expectedUid; reportSettingsProblem(Log.WARN, msg); } } } } if (mismatch) { if (isSystemApp || isBootScan) { // If this is a system app, we can at least delete its // current data so the application will still work. int ret; synchronized (mInstallLock) { ret = removeDataDirsLI(packageName); } if (ret >= 0) { // TODO: Kill the processes first // Old data gone! String prefix = isSystemApp ? "System package " : "Third party package "; String msg = prefix + packageName + " old data erased"; reportSettingsProblem(Log.WARN, msg); // And now re-install the app. synchronized (mInstallLock) { ret = createDataDirsLI(packageName, appUid); } if (ret == -1) { // Ack should not happen! msg = prefix + packageName + " could not have data directory re-created after delete."; reportSettingsProblem(Log.WARN, msg); mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; return false; } } else { mHasSystemUidErrors = true; return false; } } else { // If we allow this install to proceed, we will be broken. // Abort, abort! mLastScanError = PackageManager.INSTALL_FAILED_UID_CHANGED; return false; } } return true; } private void setInternalAppNativeLibraryPath(PackageParser.Package pkg, PackageSetting pkgSetting) { final String apkLibPath = getApkName(pkgSetting.codePathString); Loading Loading @@ -7502,6 +7511,22 @@ public class PackageManagerService extends IPackageManager.Stub { PackageRemovedInfo removedInfo; } private boolean ensureDataDirExistsForAllUsers(String packageName, int uid) { boolean exists = true; for (int userId : sUserManager.getUserIds()) { final File dataPath = getDataPathForPackage(packageName, userId); if (!dataPath.exists()) { synchronized (mInstallLock) { if (createDataDirForUserLI(packageName, uid, userId) < 0) { Slog.e(TAG, "Couldn't create data path " + dataPath.getPath()); } } exists &= dataPath.exists(); } } return exists; } /* * Install a non-existing package. */ Loading @@ -7511,7 +7536,8 @@ public class PackageManagerService extends IPackageManager.Stub { // Remember this for later, in case we need to rollback this install String pkgName = pkg.packageName; boolean dataDirExists = getDataPathForPackage(pkg.packageName, 0).exists(); boolean dataDirExists = ensureDataDirExistsForAllUsers(pkg.packageName, pkg.applicationInfo.uid); synchronized(mPackages) { if (mSettings.mRenamedPackages.containsKey(pkgName)) { // A package with the same name is already installed, though Loading Loading
cmds/installd/commands.c +24 −9 Original line number Diff line number Diff line Loading @@ -141,39 +141,54 @@ int renamepkg(const char *oldpkgname, const char *newpkgname) return 0; } int fix_uid(const char *pkgname, uid_t uid, gid_t gid) int fix_uid(const char *pkgname, uid_t uid, uid_t userId) { char pkgdir[PKG_PATH_MAX]; struct stat s; int rc = 0; if ((uid < AID_SYSTEM) || (gid < AID_SYSTEM)) { ALOGE("invalid uid/gid: %d %d\n", uid, gid); if (uid < AID_SYSTEM) { ALOGE("invalid uid: %d\n", uid); return -1; } if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, 0)) { if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, userId)) { ALOGE("cannot create package path\n"); return -1; } if (stat(pkgdir, &s) < 0) return -1; if (s.st_uid != 0 || s.st_gid != 0) { ALOGE("fixing uid of non-root pkg: %s %lu %lu\n", pkgdir, s.st_uid, s.st_gid); if (((s.st_uid != 0) && (s.st_uid != AID_INSTALL)) || ((s.st_gid != 0) && (s.st_gid != AID_INSTALL))) { ALOGE("fixing uid of pkg not owned by install or root: %s %lu %lu\n", pkgdir, s.st_uid, s.st_gid); return -1; } if (chown(pkgdir, AID_INSTALL, AID_INSTALL) < 0) { ALOGE("cannot chown dir '%s': %s\n", pkgdir, strerror(errno)); unlink(pkgdir); return -1; } if (chmod(pkgdir, 0751) < 0) { ALOGE("cannot chmod dir '%s': %s\n", pkgdir, strerror(errno)); unlink(pkgdir); return -errno; return -1; } if (chown(pkgdir, uid, gid) < 0) { if (chown(pkgdir, uid, uid) < 0) { ALOGE("cannot chown dir '%s': %s\n", pkgdir, strerror(errno)); unlink(pkgdir); return -errno; return -1; } #ifdef HAVE_SELINUX if (selinux_android_setfilecon(pkgdir, pkgname, uid) < 0) { ALOGE("cannot setfilecon dir '%s': %s\n", pkgdir, strerror(errno)); unlink(pkgdir); return -1; } #endif return 0; } Loading
services/java/com/android/server/pm/Installer.java +2 −2 Original line number Diff line number Diff line Loading @@ -243,14 +243,14 @@ public final class Installer { return execute(builder.toString()); } public int fixUid(String name, int uid, int gid) { public int fixUid(String name, int uid, int userId) { StringBuilder builder = new StringBuilder("fixuid"); builder.append(' '); builder.append(name); builder.append(' '); builder.append(uid); builder.append(' '); builder.append(gid); builder.append(userId); return execute(builder.toString()); } Loading
services/java/com/android/server/pm/PackageManagerService.java +155 −129 Original line number Diff line number Diff line Loading @@ -1008,6 +1008,8 @@ public class PackageManagerService extends IPackageManager.Stub { mHandler = new PackageHandler(mHandlerThread.getLooper()); File dataDir = Environment.getDataDirectory(); mAppInstallDir = new File(dataDir, "app"); mAppLibInstallDir = new File(dataDir, "app-lib"); mAppDataDir = new File(dataDir, "data"); mAsecInternalPath = new File(dataDir, "app-asec").getPath(); mUserAppDataDir = new File(dataDir, "user"); Loading Loading @@ -1218,8 +1220,6 @@ public class PackageManagerService extends IPackageManager.Stub { } } mAppInstallDir = new File(dataDir, "app"); mAppLibInstallDir = new File(dataDir, "app-lib"); //look for any incomplete package installations ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackagesLPr(); //clean up list Loading Loading @@ -3576,22 +3576,22 @@ public class PackageManagerService extends IPackageManager.Stub { } } private int createDataDirsLI(String packageName, int uid) { int[] users = sUserManager.getUserIds(); int res = mInstaller.install(packageName, uid, uid); if (res < 0) { return res; private int createDataDirForUserLI(String packageName, int uid, int userId) { if (userId == 0) { return mInstaller.install(packageName, uid, uid); } else { return mInstaller.createUserData(packageName, UserHandle.getUid(userId, uid), userId); } for (int user : users) { if (user != 0) { res = mInstaller.createUserData(packageName, UserHandle.getUid(user, uid), user); } private int createDataDirsLI(String packageName, int uid) { for (int userId : sUserManager.getUserIds()) { int res = createDataDirForUserLI(packageName, uid, userId); if (res < 0) { return res; } } } return res; return 0; } private int removeDataDirsLI(String packageName) { Loading Loading @@ -3930,134 +3930,49 @@ public class PackageManagerService extends IPackageManager.Stub { pkg.applicationInfo.dataDir = dataPath.getPath(); } else { // This is a normal package, need to make its data directory. dataPath = getDataPathForPackage(pkg.packageName, 0); boolean uidError = false; if (dataPath.exists()) { int currentUid = 0; try { StructStat stat = Libcore.os.stat(dataPath.getPath()); currentUid = stat.st_uid; } catch (ErrnoException e) { Slog.e(TAG, "Couldn't stat path " + dataPath.getPath(), e); } // If we have mismatched owners for the data path, we have a problem. if (currentUid != pkg.applicationInfo.uid) { boolean recovered = false; if (currentUid == 0) { // The directory somehow became owned by root. Wow. // This is probably because the system was stopped while // installd was in the middle of messing with its libs // directory. Ask installd to fix that. int ret = mInstaller.fixUid(pkgName, pkg.applicationInfo.uid, pkg.applicationInfo.uid); if (ret >= 0) { recovered = true; String msg = "Package " + pkg.packageName + " unexpectedly changed to uid 0; recovered to " + + pkg.applicationInfo.uid; reportSettingsProblem(Log.WARN, msg); } } if (!recovered && ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0 || (scanMode&SCAN_BOOTING) != 0)) { // If this is a system app, we can at least delete its // current data so the application will still work. int ret = removeDataDirsLI(pkgName); if (ret >= 0) { // TODO: Kill the processes first // Old data gone! String prefix = (parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0 ? "System package " : "Third party package "; String msg = prefix + pkg.packageName + " has changed from uid: " + currentUid + " to " + pkg.applicationInfo.uid + "; old data erased"; reportSettingsProblem(Log.WARN, msg); recovered = true; dataPath = getDataPathForPackage(pkg.packageName, UserHandle.USER_OWNER); // And now re-install the app. ret = createDataDirsLI(pkgName, pkg.applicationInfo.uid); if (ret == -1) { // Ack should not happen! msg = prefix + pkg.packageName + " could not have data directory re-created after delete."; reportSettingsProblem(Log.WARN, msg); mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; return null; } } if (!recovered) { mHasSystemUidErrors = true; } } else if (!recovered) { // If we allow this install to proceed, we will be broken. // Abort, abort! mLastScanError = PackageManager.INSTALL_FAILED_UID_CHANGED; return null; } if (!recovered) { pkg.applicationInfo.dataDir = "/mismatched_uid/settings_" + pkg.applicationInfo.uid + "/fs_" + currentUid; pkg.applicationInfo.nativeLibraryDir = pkg.applicationInfo.dataDir; String msg = "Package " + pkg.packageName + " has mismatched uid: " + currentUid + " on disk, " + pkg.applicationInfo.uid + " in settings"; // writer synchronized (mPackages) { mSettings.mReadMessages.append(msg); mSettings.mReadMessages.append('\n'); uidError = true; if (!pkgSetting.uidError) { reportSettingsProblem(Log.ERROR, msg); } } } } pkg.applicationInfo.dataDir = dataPath.getPath(); } else { if (!ensureDataDirExistsForAllUsers(pkg.packageName, pkg.applicationInfo.uid)) { if (DEBUG_PACKAGE_SCANNING) { if ((parseFlags & PackageParser.PARSE_CHATTY) != 0) if ((parseFlags & PackageParser.PARSE_CHATTY) != 0) { Log.v(TAG, "Want this data dir: " + dataPath); } //invoke installer to do the actual installation int ret = createDataDirsLI(pkgName, pkg.applicationInfo.uid); if (ret < 0) { } // Error from installer mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; return null; } if (dataPath.exists()) { pkg.applicationInfo.dataDir = dataPath.getPath(); } else { Slog.w(TAG, "Unable to create data directory: " + dataPath); pkg.applicationInfo.dataDir = null; pkg.applicationInfo.dataDir = dataPath.getPath(); } final boolean isSystemApp = (parseFlags & PackageParser.PARSE_IS_SYSTEM) != 0; final boolean isBootScan = (scanMode & SCAN_BOOTING) != 0; final boolean uidCorrect = ensureDataDirUidIsCorrectForAllUsers(pkg.packageName, pkg.applicationInfo.uid, isSystemApp, isBootScan); if (!uidCorrect) { pkg.applicationInfo.dataDir = "/mismatched_uid/settings_" + pkg.applicationInfo.uid + "/fs_mismatched"; pkg.applicationInfo.nativeLibraryDir = pkg.applicationInfo.dataDir; } pkgSetting.uidError = !uidCorrect; /* * Set the data dir to the default "/data/data/<package name>/lib" * if we got here without anyone telling us different (e.g., apps * stored on SD card have their native libraries stored in the ASEC * container with the APK). * * This happens during an upgrade from a package settings file that * doesn't have a native library path attribute at all. * Set the native library dir to the default if we got here without * anyone telling us different (e.g., apps stored on SD card have * their native libraries stored in the ASEC container with the * APK). This happens during an upgrade from a package settings file * that doesn't have a native library path attribute at all. */ if (pkg.applicationInfo.nativeLibraryDir == null && pkg.applicationInfo.dataDir != null) { if (pkg.applicationInfo.nativeLibraryDir == null) { if (pkgSetting.nativeLibraryPathString == null) { setInternalAppNativeLibraryPath(pkg, pkgSetting); } else { pkg.applicationInfo.nativeLibraryDir = pkgSetting.nativeLibraryPathString; } } pkgSetting.uidError = uidError; } String path = scanFile.getPath(); Loading Loading @@ -4446,6 +4361,100 @@ public class PackageManagerService extends IPackageManager.Stub { return pkg; } /** * Checks to see whether a package data directory is owned by the correct * user. If it isn't, it will attempt to fix it if it's a system application * or if this is the boot scan. * * @return {@code true} if successful, {@code false} if recovery failed */ private boolean ensureDataDirUidIsCorrectForAllUsers(String packageName, int appUid, boolean isSystemApp, boolean isBootScan) { boolean mismatch = false; for (int userId : sUserManager.getUserIds()) { final File dataPath = getDataPathForPackage(packageName, userId); int currentUid = 0; try { final StructStat stat = Libcore.os.stat(dataPath.getPath()); currentUid = stat.st_uid; } catch (ErrnoException e) { Slog.e(TAG, "Couldn't stat path " + dataPath.getPath(), e); } final int expectedUid = UserHandle.getUid(userId, appUid); // If we have mismatched owners for the data path, we have a // problem. if (currentUid != expectedUid) { if (currentUid == 0) { // The directory somehow became owned by root. Wow. // This is probably because the system was stopped while // installd was in the middle of messing with its libs // directory. Ask installd to fix that. final int ret; synchronized (mInstaller) { ret = mInstaller.fixUid(packageName, expectedUid, userId); } if (ret >= 0) { String msg = "Package " + packageName + " unexpectedly changed to uid 0; recovered to " + expectedUid; reportSettingsProblem(Log.WARN, msg); } else { mismatch = true; String prefix = isSystemApp ? "System package " : "Third party package "; String msg = prefix + packageName + " has changed from uid: " + currentUid + " to " + expectedUid; reportSettingsProblem(Log.WARN, msg); } } } } if (mismatch) { if (isSystemApp || isBootScan) { // If this is a system app, we can at least delete its // current data so the application will still work. int ret; synchronized (mInstallLock) { ret = removeDataDirsLI(packageName); } if (ret >= 0) { // TODO: Kill the processes first // Old data gone! String prefix = isSystemApp ? "System package " : "Third party package "; String msg = prefix + packageName + " old data erased"; reportSettingsProblem(Log.WARN, msg); // And now re-install the app. synchronized (mInstallLock) { ret = createDataDirsLI(packageName, appUid); } if (ret == -1) { // Ack should not happen! msg = prefix + packageName + " could not have data directory re-created after delete."; reportSettingsProblem(Log.WARN, msg); mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; return false; } } else { mHasSystemUidErrors = true; return false; } } else { // If we allow this install to proceed, we will be broken. // Abort, abort! mLastScanError = PackageManager.INSTALL_FAILED_UID_CHANGED; return false; } } return true; } private void setInternalAppNativeLibraryPath(PackageParser.Package pkg, PackageSetting pkgSetting) { final String apkLibPath = getApkName(pkgSetting.codePathString); Loading Loading @@ -7502,6 +7511,22 @@ public class PackageManagerService extends IPackageManager.Stub { PackageRemovedInfo removedInfo; } private boolean ensureDataDirExistsForAllUsers(String packageName, int uid) { boolean exists = true; for (int userId : sUserManager.getUserIds()) { final File dataPath = getDataPathForPackage(packageName, userId); if (!dataPath.exists()) { synchronized (mInstallLock) { if (createDataDirForUserLI(packageName, uid, userId) < 0) { Slog.e(TAG, "Couldn't create data path " + dataPath.getPath()); } } exists &= dataPath.exists(); } } return exists; } /* * Install a non-existing package. */ Loading @@ -7511,7 +7536,8 @@ public class PackageManagerService extends IPackageManager.Stub { // Remember this for later, in case we need to rollback this install String pkgName = pkg.packageName; boolean dataDirExists = getDataPathForPackage(pkg.packageName, 0).exists(); boolean dataDirExists = ensureDataDirExistsForAllUsers(pkg.packageName, pkg.applicationInfo.uid); synchronized(mPackages) { if (mSettings.mRenamedPackages.containsKey(pkgName)) { // A package with the same name is already installed, though Loading