Skip to content

Commit 690d20b

Browse files
author
Dianne Hackborn
committed
Fix issue # 3227963: SecurityException: Neither user 10023 nor...
...current process has android.permission.WAKE_LOCK When updating a system app, we would actually uninstall the package of the system app, which also meant removing its uid...! It was just luck that we would get the same uid when installing the update after that. During that time, if anyone tried to do anything related to that uid, it would be unknown. This change tweaks how we go about replacing system apps by making it more like normal apps -- to make this work, if we need to disable the system app, we generate a new PackageSetting from the current system app and replace it into our data structures, so we can update that without trashing the current correct information about the (still actually there) system app. Also fixed a problem where we were not killing the currently running app before installing, like we do when updating a normal application. And fixed a problem where we were not deleting the /data .apk when uninstalling a system app update. And added a new option to the "pm" command to clear the data associated with an app. Change-Id: I0e879677849aa42950a3c360bf78ad820e87674b
1 parent 3ce8648 commit 690d20b

File tree

2 files changed

+118
-33
lines changed

2 files changed

+118
-33
lines changed

cmds/pm/src/com/android/commands/pm/Pm.java

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,11 @@
1818

1919
import com.android.internal.content.PackageHelper;
2020

21+
import android.app.ActivityManagerNative;
2122
import android.content.ComponentName;
2223
import android.content.pm.ApplicationInfo;
2324
import android.content.pm.FeatureInfo;
25+
import android.content.pm.IPackageDataObserver;
2426
import android.content.pm.IPackageDeleteObserver;
2527
import android.content.pm.IPackageInstallObserver;
2628
import android.content.pm.IPackageManager;
@@ -100,6 +102,11 @@ public void run(String[] args) {
100102
return;
101103
}
102104

105+
if ("clear".equals(op)) {
106+
runClear();
107+
return;
108+
}
109+
103110
if ("enable".equals(op)) {
104111
runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
105112
return;
@@ -809,6 +816,55 @@ private boolean deletePackage(String pkg, int unInstallFlags) {
809816
return obs.result;
810817
}
811818

819+
class ClearDataObserver extends IPackageDataObserver.Stub {
820+
boolean finished;
821+
boolean result;
822+
823+
@Override
824+
public void onRemoveCompleted(String packageName, boolean succeeded) throws RemoteException {
825+
synchronized (this) {
826+
finished = true;
827+
result = succeeded;
828+
notifyAll();
829+
}
830+
}
831+
832+
}
833+
834+
private void runClear() {
835+
String pkg = nextArg();
836+
if (pkg == null) {
837+
System.err.println("Error: no package specified");
838+
showUsage();
839+
return;
840+
}
841+
842+
ClearDataObserver obs = new ClearDataObserver();
843+
try {
844+
if (!ActivityManagerNative.getDefault().clearApplicationUserData(pkg, obs)) {
845+
System.err.println("Failed");
846+
}
847+
848+
synchronized (obs) {
849+
while (!obs.finished) {
850+
try {
851+
obs.wait();
852+
} catch (InterruptedException e) {
853+
}
854+
}
855+
}
856+
857+
if (obs.result) {
858+
System.err.println("Success");
859+
} else {
860+
System.err.println("Failed");
861+
}
862+
} catch (RemoteException e) {
863+
System.err.println(e.toString());
864+
System.err.println(PM_NOT_RUNNING_ERR);
865+
}
866+
}
867+
812868
private static String enabledSettingToString(int state) {
813869
switch (state) {
814870
case PackageManager.COMPONENT_ENABLED_STATE_DEFAULT:
@@ -944,6 +1000,7 @@ private static void showUsage() {
9441000
System.err.println(" pm path PACKAGE");
9451001
System.err.println(" pm install [-l] [-r] [-t] [-i INSTALLER_PACKAGE_NAME] [-s] [-f] PATH");
9461002
System.err.println(" pm uninstall [-k] PACKAGE");
1003+
System.err.println(" pm clear PACKAGE");
9471004
System.err.println(" pm enable PACKAGE_OR_COMPONENT");
9481005
System.err.println(" pm disable PACKAGE_OR_COMPONENT");
9491006
System.err.println(" pm setInstallLocation [0/auto] [1/internal] [2/external]");
@@ -986,6 +1043,8 @@ private static void showUsage() {
9861043
System.err.println(" -k: keep the data and cache directories around.");
9871044
System.err.println("after the package removal.");
9881045
System.err.println("");
1046+
System.err.println("The clear command deletes all data associated with a package.");
1047+
System.err.println("");
9891048
System.err.println("The enable and disable commands change the enabled state of");
9901049
System.err.println("a given package or component (written as \"package/class\").");
9911050
System.err.println("");

services/java/com/android/server/PackageManagerService.java

Lines changed: 59 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -3663,17 +3663,6 @@ void removePackageLI(PackageParser.Package pkg, boolean chatty) {
36633663
mAppDirs.remove(pkg.mPath);
36643664
}
36653665

3666-
PackageSetting ps = (PackageSetting)pkg.mExtras;
3667-
if (ps != null && ps.sharedUser != null) {
3668-
// XXX don't do this until the data is removed.
3669-
if (false) {
3670-
ps.sharedUser.packages.remove(ps);
3671-
if (ps.sharedUser.packages.size() == 0) {
3672-
// Remove.
3673-
}
3674-
}
3675-
}
3676-
36773666
int N = pkg.providers.size();
36783667
StringBuilder r = null;
36793668
int i;
@@ -5695,12 +5684,26 @@ private void replaceSystemPackageLI(PackageParser.Package deletedPackage,
56955684
return;
56965685
}
56975686
}
5687+
5688+
killApplication(packageName, oldPkg.applicationInfo.uid);
5689+
56985690
res.removedInfo.uid = oldPkg.applicationInfo.uid;
56995691
res.removedInfo.removedPackage = packageName;
57005692
// Remove existing system package
57015693
removePackageLI(oldPkg, true);
57025694
synchronized (mPackages) {
5703-
mSettings.disableSystemPackageLP(packageName);
5695+
if (!mSettings.disableSystemPackageLP(packageName) && deletedPackage != null) {
5696+
// We didn't need to disable the .apk as a current system package,
5697+
// which means we are replacing another update that is already
5698+
// installed. We need to make sure to delete the older one's .apk.
5699+
res.removedInfo.args = createInstallArgs(isExternal(pkg)
5700+
? PackageManager.INSTALL_EXTERNAL : PackageManager.INSTALL_INTERNAL,
5701+
deletedPackage.applicationInfo.sourceDir,
5702+
deletedPackage.applicationInfo.publicSourceDir,
5703+
deletedPackage.applicationInfo.nativeLibraryDir);
5704+
} else {
5705+
res.removedInfo.args = null;
5706+
}
57045707
}
57055708

57065709
// Successfully disabled the old package. Now proceed with re-installation
@@ -5739,17 +5742,6 @@ private void replaceSystemPackageLI(PackageParser.Package deletedPackage,
57395742
}
57405743
mSettings.writeLP();
57415744
}
5742-
} else {
5743-
// If this is an update to an existing update, setup
5744-
// to remove the existing update.
5745-
synchronized (mPackages) {
5746-
PackageSetting ps = mSettings.getDisabledSystemPkg(packageName);
5747-
if (ps != null && ps.codePathString != null &&
5748-
!ps.codePathString.equals(oldPkgSetting.codePathString)) {
5749-
res.removedInfo.args = createInstallArgs(0, oldPkgSetting.codePathString,
5750-
oldPkgSetting.resourcePathString, oldPkgSetting.nativeLibraryPathString);
5751-
}
5752-
}
57535745
}
57545746
}
57555747

@@ -6252,24 +6244,21 @@ private boolean deleteSystemPackageLI(PackageParser.Package p,
62526244
ps = mSettings.getDisabledSystemPkg(p.packageName);
62536245
}
62546246
if (ps == null) {
6255-
Slog.w(TAG, "Attempt to delete system package "+ p.packageName);
6247+
Slog.w(TAG, "Attempt to delete unknown system package "+ p.packageName);
62566248
return false;
62576249
} else {
62586250
Log.i(TAG, "Deleting system pkg from data partition");
62596251
}
62606252
// Delete the updated package
62616253
outInfo.isRemovedPackageSystemUpdate = true;
6262-
final boolean deleteCodeAndResources;
62636254
if (ps.versionCode < p.mVersionCode) {
6264-
// Delete code and resources for downgrades
6265-
deleteCodeAndResources = true;
6255+
// Delete data for downgrades
62666256
flags &= ~PackageManager.DONT_DELETE_DATA;
62676257
} else {
62686258
// Preserve data by setting flag
6269-
deleteCodeAndResources = false;
62706259
flags |= PackageManager.DONT_DELETE_DATA;
62716260
}
6272-
boolean ret = deleteInstalledPackageLI(p, deleteCodeAndResources, flags, outInfo,
6261+
boolean ret = deleteInstalledPackageLI(p, true, flags, outInfo,
62736262
writeSettings);
62746263
if (!ret) {
62756264
return false;
@@ -7850,6 +7839,12 @@ static final class PackageSetting extends PackageSettingBase {
78507839
pkgFlags);
78517840
}
78527841

7842+
PackageSetting(PackageSetting orig) {
7843+
super(orig.name, orig.realName, orig.codePath, orig.resourcePath,
7844+
orig.nativeLibraryPathString, orig.versionCode, orig.pkgFlags);
7845+
copyFrom(orig);
7846+
}
7847+
78537848
@Override
78547849
public String toString() {
78557850
return "PackageSetting{"
@@ -8062,21 +8057,29 @@ SharedUserSetting getSharedUserLP(String name,
80628057
return s;
80638058
}
80648059

8065-
int disableSystemPackageLP(String name) {
8060+
boolean disableSystemPackageLP(String name) {
80668061
PackageSetting p = mPackages.get(name);
80678062
if(p == null) {
80688063
Log.w(TAG, "Package:"+name+" is not an installed package");
8069-
return -1;
8064+
return false;
80708065
}
80718066
PackageSetting dp = mDisabledSysPackages.get(name);
80728067
// always make sure the system package code and resource paths dont change
8073-
if(dp == null) {
8068+
if (dp == null) {
80748069
if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
80758070
p.pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
80768071
}
80778072
mDisabledSysPackages.put(name, p);
8073+
8074+
// a little trick... when we install the new package, we don't
8075+
// want to modify the existing PackageSetting for the built-in
8076+
// version. so at this point we need a new PackageSetting that
8077+
// is okay to much with.
8078+
PackageSetting newp = new PackageSetting(p);
8079+
replacePackageLP(name, newp);
8080+
return true;
80788081
}
8079-
return removePackageLP(name);
8082+
return false;
80808083
}
80818084

80828085
PackageSetting enableSystemPackageLP(String name) {
@@ -8410,6 +8413,19 @@ private int removePackageLP(String name) {
84108413
return -1;
84118414
}
84128415

8416+
private void replacePackageLP(String name, PackageSetting newp) {
8417+
PackageSetting p = mPackages.get(name);
8418+
if (p != null) {
8419+
if (p.sharedUser != null) {
8420+
p.sharedUser.packages.remove(p);
8421+
p.sharedUser.packages.add(newp);
8422+
} else {
8423+
replaceUserIdLP(p.userId, newp);
8424+
}
8425+
}
8426+
mPackages.put(name, newp);
8427+
}
8428+
84138429
private boolean addUserIdLP(int uid, Object obj, Object name) {
84148430
if (uid >= FIRST_APPLICATION_UID + MAX_APPLICATION_UIDS) {
84158431
return false;
@@ -8472,6 +8488,16 @@ private void removeUserIdLP(int uid) {
84728488
}
84738489
}
84748490

8491+
private void replaceUserIdLP(int uid, Object obj) {
8492+
if (uid >= FIRST_APPLICATION_UID) {
8493+
int N = mUserIds.size();
8494+
final int index = uid - FIRST_APPLICATION_UID;
8495+
if (index < N) mUserIds.set(index, obj);
8496+
} else {
8497+
mOtherUserIds.put(uid, obj);
8498+
}
8499+
}
8500+
84758501
void writeLP() {
84768502
//Debug.startMethodTracing("/data/system/packageprof", 8 * 1024 * 1024);
84778503

0 commit comments

Comments
 (0)