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

Commit d0c5f515 authored by Dianne Hackborn's avatar Dianne Hackborn
Browse files

Fix issue #6295373: "Package com.google.android.apps.authenticator2 has...

...mismatched uid: X on disk, Y in settings" errors on Froyo and Gingerbread

Deal more gracefully with the uid changing in three ways:

1. If the uid on disk has become root, then have installd change it to
   the application's uid.  This is to correct a potential case where
   installd was interrupted while linking or unlinking the libs dir,
   during which it temporarily changes the owner of the dir to root
   so that a malicious app can not get in its way.  So if the uid on
   disk has become root, we assume we can safely just change it back
   to the correct uid.

2. When scaning packages at boot, use the same "delete and rebuild data
   directory" code for third party applications as we have for system
   applications.  This allows us to at least end up in a state where the
   app will run, even if its data is lost.

3. But we really don't want to get in to case 2, so if an application
   update is being installed and we find that the uid we now have for
   the app is different than the one on disk, fail the update.  This will
   protect against for example a developer changing the sharedUserId of
   their app and getting into this bad state.

Bug: 6295373
Change-Id: Ic802fdd818ac62449ff3c61d1fff1aa4d4942f39
parent 0646411c
Loading
Loading
Loading
Loading
+39 −2
Original line number Diff line number Diff line
@@ -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) {
+6 −0
Original line number Diff line number Diff line
@@ -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 },
+1 −0
Original line number Diff line number Diff line
@@ -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);
+8 −0
Original line number Diff line number Diff line
@@ -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)}
+11 −0
Original line number Diff line number Diff line
@@ -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(' ');
Loading