am 0876ab0a: Merge "Fix issue #6295373: "Package com.google.android.apps.authenticator2 has..." into jb-dev

* commit '0876ab0ac17518c479e9dffe025884870a586d9c':
  Fix issue #6295373: "Package com.google.android.apps.authenticator2 has...
This commit is contained in:
Dianne Hackborn
2012-06-08 11:04:13 -07:00
committed by Android Git Automerger
6 changed files with 96 additions and 8 deletions

View File

@ -106,6 +106,43 @@ int renamepkg(const char *oldpkgname, const char *newpkgname)
return 0;
}
int fix_uid(const char *pkgname, uid_t uid, gid_t gid)
{
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);
return -1;
}
if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, 0)) {
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 %d %d\n", pkgdir, s.st_uid, s.st_gid);
return -1;
}
if (chmod(pkgdir, 0751) < 0) {
ALOGE("cannot chmod dir '%s': %s\n", pkgdir, strerror(errno));
unlink(pkgdir);
return -errno;
}
if (chown(pkgdir, uid, gid) < 0) {
ALOGE("cannot chown dir '%s': %s\n", pkgdir, strerror(errno));
unlink(pkgdir);
return -errno;
}
return 0;
}
int delete_user_data(const char *pkgname, uid_t persona)
{
char pkgdir[PKG_PATH_MAX];
@ -950,7 +987,7 @@ int linklib(const char* dataDir, const char* asecLibDir)
out:
if (chmod(dataDir, s.st_mode) < 0) {
ALOGE("failed to chmod '%s': %s\n", dataDir, strerror(errno));
return -errno;
rc = -errno;
}
if (chown(dataDir, s.st_uid, s.st_gid) < 0) {
@ -1027,7 +1064,7 @@ int unlinklib(const char* dataDir)
out:
if (chmod(dataDir, s.st_mode) < 0) {
ALOGE("failed to chmod '%s': %s\n", dataDir, strerror(errno));
return -1;
rc = -1;
}
if (chown(dataDir, s.st_uid, s.st_gid) < 0) {

View File

@ -57,6 +57,11 @@ static int do_rename(char **arg, char reply[REPLY_MAX])
return renamepkg(arg[0], arg[1]); /* oldpkgname, newpkgname */
}
static int do_fixuid(char **arg, char reply[REPLY_MAX])
{
return fix_uid(arg[0], atoi(arg[1]), atoi(arg[2])); /* pkgname, uid, gid */
}
static int do_free_cache(char **arg, char reply[REPLY_MAX]) /* TODO int:free_size */
{
return free_cache((int64_t)atoll(arg[0])); /* free_size */
@ -141,6 +146,7 @@ struct cmdinfo cmds[] = {
{ "rmdex", 1, do_rm_dex },
{ "remove", 2, do_remove },
{ "rename", 2, do_rename },
{ "fixuid", 3, do_fixuid },
{ "freecache", 1, do_free_cache },
{ "rmcache", 1, do_rm_cache },
{ "protect", 2, do_protect },

View File

@ -143,6 +143,7 @@ char *build_string3(char *s1, char *s2, char *s3);
int install(const char *pkgname, uid_t uid, gid_t gid);
int uninstall(const char *pkgname, uid_t persona);
int renamepkg(const char *oldpkgname, const char *newpkgname);
int fix_uid(const char *pkgname, uid_t uid, gid_t gid);
int delete_user_data(const char *pkgname, uid_t persona);
int make_user_data(const char *pkgname, uid_t uid, uid_t persona);
int delete_persona(uid_t persona);

View File

@ -519,6 +519,14 @@ public abstract class PackageManager {
*/
public static final int INSTALL_FAILED_PACKAGE_CHANGED = -23;
/**
* Installation return code: this is passed to the {@link IPackageInstallObserver} by
* {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if
* the new package is assigned a different UID than it previously held.
* @hide
*/
public static final int INSTALL_FAILED_UID_CHANGED = -24;
/**
* Installation parse return code: this is passed to the {@link IPackageInstallObserver} by
* {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)}

View File

@ -243,6 +243,17 @@ class Installer {
return execute(builder.toString());
}
public int fixUid(String name, int uid, int gid) {
StringBuilder builder = new StringBuilder("fixuid");
builder.append(' ');
builder.append(name);
builder.append(' ');
builder.append(uid);
builder.append(' ');
builder.append(gid);
return execute(builder.toString());
}
public int deleteCacheFiles(String name) {
StringBuilder builder = new StringBuilder("rmcache");
builder.append(' ');

View File

@ -191,6 +191,7 @@ public class PackageManagerService extends IPackageManager.Stub {
static final int SCAN_NO_PATHS = 1<<5;
static final int SCAN_UPDATE_TIME = 1<<6;
static final int SCAN_DEFER_DEX = 1<<7;
static final int SCAN_BOOTING = 1<<8;
static final int REMOVE_CHATTY = 1<<16;
@ -924,7 +925,7 @@ public class PackageManagerService extends IPackageManager.Stub {
// Set flag to monitor and not change apk file paths when
// scanning install directories.
int scanMode = SCAN_MONITOR | SCAN_NO_PATHS | SCAN_DEFER_DEX;
int scanMode = SCAN_MONITOR | SCAN_NO_PATHS | SCAN_DEFER_DEX | SCAN_BOOTING;
if (mNoDexOpt) {
Slog.w(TAG, "Running ENG build: no pre-dexopt!");
scanMode |= SCAN_NO_DEX;
@ -3750,17 +3751,34 @@ public class PackageManagerService extends IPackageManager.Stub {
} else {
// This is a normal package, need to make its data directory.
dataPath = getDataPathForPackage(pkg.packageName, 0);
boolean uidError = false;
if (dataPath.exists()) {
// XXX should really do this check for each user.
mOutPermissions[1] = 0;
FileUtils.getPermissions(dataPath.getPath(), mOutPermissions);
// If we have mismatched owners for the data path, we have a problem.
if (mOutPermissions[1] != pkg.applicationInfo.uid) {
boolean recovered = false;
if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
if (mOutPermissions[1] == 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 = mInstaller.remove(pkgName, 0);
@ -3769,7 +3787,9 @@ public class PackageManagerService extends IPackageManager.Stub {
// Remove the data directories for all users
sUserManager.removePackageForAllUsers(pkgName);
// Old data gone!
String msg = "System package " + pkg.packageName
String prefix = (parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0
? "System package " : "Third party package ";
String msg = prefix + pkg.packageName
+ " has changed from uid: "
+ mOutPermissions[1] + " to "
+ pkg.applicationInfo.uid + "; old data erased";
@ -3781,7 +3801,7 @@ public class PackageManagerService extends IPackageManager.Stub {
pkg.applicationInfo.uid);
if (ret == -1) {
// Ack should not happen!
msg = "System package " + pkg.packageName
msg = prefix + pkg.packageName
+ " could not have data directory re-created after delete.";
reportSettingsProblem(Log.WARN, msg);
mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
@ -3794,6 +3814,11 @@ public class PackageManagerService extends IPackageManager.Stub {
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_"