summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmds/installd/commands.c146
-rw-r--r--cmds/installd/installd.c4
-rw-r--r--cmds/installd/installd.h3
-rw-r--r--core/tests/coretests/apks/install_bad_dex/AndroidManifest.xml2
-rwxr-xr-xcore/tests/coretests/src/android/content/pm/PackageManagerTests.java27
-rw-r--r--services/java/com/android/server/pm/Installer.java4
-rw-r--r--services/java/com/android/server/pm/PackageManagerService.java83
7 files changed, 167 insertions, 102 deletions
diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c
index a276225..8e4d7ed 100644
--- a/cmds/installd/commands.c
+++ b/cmds/installd/commands.c
@@ -36,6 +36,7 @@ int install(const char *pkgname, uid_t uid, gid_t gid)
char pkgdir[PKG_PATH_MAX];
char libsymlink[PKG_PATH_MAX];
char applibdir[PKG_PATH_MAX];
+ struct stat libStat;
if ((uid < AID_SYSTEM) || (gid < AID_SYSTEM)) {
ALOGE("invalid uid/gid: %d %d\n", uid, gid);
@@ -67,6 +68,25 @@ int install(const char *pkgname, uid_t uid, gid_t gid)
return -1;
}
+ if (lstat(libsymlink, &libStat) < 0) {
+ if (errno != ENOENT) {
+ ALOGE("couldn't stat lib dir: %s\n", strerror(errno));
+ return -1;
+ }
+ } else {
+ if (S_ISDIR(libStat.st_mode)) {
+ if (delete_dir_contents(libsymlink, 1, 0) < 0) {
+ ALOGE("couldn't delete lib directory during install for: %s", libsymlink);
+ return -1;
+ }
+ } else if (S_ISLNK(libStat.st_mode)) {
+ if (unlink(libsymlink) < 0) {
+ ALOGE("couldn't unlink lib directory during install for: %s", libsymlink);
+ return -1;
+ }
+ }
+ }
+
if (symlink(applibdir, libsymlink) < 0) {
ALOGE("couldn't symlink directory '%s' -> '%s': %s\n", libsymlink, applibdir,
strerror(errno));
@@ -140,7 +160,7 @@ int fix_uid(const char *pkgname, uid_t uid, gid_t gid)
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);
+ ALOGE("fixing uid of non-root pkg: %s %lu %lu\n", pkgdir, s.st_uid, s.st_gid);
return -1;
}
@@ -165,18 +185,30 @@ int delete_user_data(const char *pkgname, uid_t persona)
if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, persona))
return -1;
- /* delete contents, excluding "lib", but not the directory itself */
- return delete_dir_contents(pkgdir, 0, "lib");
+ /* delete contents AND directory, no exceptions */
+ return delete_dir_contents(pkgdir, 1, NULL);
}
int make_user_data(const char *pkgname, uid_t uid, uid_t persona)
{
char pkgdir[PKG_PATH_MAX];
+ char applibdir[PKG_PATH_MAX];
+ char libsymlink[PKG_PATH_MAX];
+ struct stat libStat;
// Create the data dir for the package
if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, persona)) {
return -1;
}
+ if (create_pkg_path(libsymlink, pkgname, PKG_LIB_POSTFIX, persona)) {
+ ALOGE("cannot create package lib symlink origin path\n");
+ return -1;
+ }
+ if (create_pkg_path_in_dir(applibdir, &android_app_lib_dir, pkgname, PKG_DIR_POSTFIX)) {
+ ALOGE("cannot create package lib symlink dest path\n");
+ return -1;
+ }
+
if (mkdir(pkgdir, 0751) < 0) {
ALOGE("cannot create dir '%s': %s\n", pkgdir, strerror(errno));
return -errno;
@@ -186,8 +218,41 @@ int make_user_data(const char *pkgname, uid_t uid, uid_t persona)
unlink(pkgdir);
return -errno;
}
+
+ if (lstat(libsymlink, &libStat) < 0) {
+ if (errno != ENOENT) {
+ ALOGE("couldn't stat lib dir for non-primary: %s\n", strerror(errno));
+ unlink(pkgdir);
+ return -1;
+ }
+ } else {
+ if (S_ISDIR(libStat.st_mode)) {
+ if (delete_dir_contents(libsymlink, 1, 0) < 0) {
+ ALOGE("couldn't delete lib directory during install for non-primary: %s",
+ libsymlink);
+ unlink(pkgdir);
+ return -1;
+ }
+ } else if (S_ISLNK(libStat.st_mode)) {
+ if (unlink(libsymlink) < 0) {
+ ALOGE("couldn't unlink lib directory during install for non-primary: %s",
+ libsymlink);
+ unlink(pkgdir);
+ return -1;
+ }
+ }
+ }
+
+ if (symlink(applibdir, libsymlink) < 0) {
+ ALOGE("couldn't symlink directory for non-primary '%s' -> '%s': %s\n", libsymlink,
+ applibdir, strerror(errno));
+ unlink(pkgdir);
+ return -1;
+ }
+
if (chown(pkgdir, uid, uid) < 0) {
ALOGE("cannot chown dir '%s': %s\n", pkgdir, strerror(errno));
+ unlink(libsymlink);
unlink(pkgdir);
return -errno;
}
@@ -195,6 +260,7 @@ int make_user_data(const char *pkgname, uid_t uid, uid_t persona)
#ifdef HAVE_SELINUX
if (selinux_android_setfilecon(pkgdir, pkgname, uid) < 0) {
ALOGE("cannot setfilecon dir '%s': %s\n", pkgdir, strerror(errno));
+ unlink(libsymlink);
unlink(pkgdir);
return -errno;
}
@@ -254,7 +320,7 @@ int clone_persona_data(uid_t src_persona, uid_t target_persona, int copy)
/* Get the file stat */
if (stat(pkg_path, &s) < 0) continue;
/* Get the uid of the package */
- ALOGI("Adding datadir for uid = %d\n", s.st_uid);
+ ALOGI("Adding datadir for uid = %lu\n", s.st_uid);
uid = (uid_t) s.st_uid % PER_USER_RANGE;
/* Create the directory for the target */
make_user_data(name, uid + target_persona * PER_USER_RANGE,
@@ -991,75 +1057,71 @@ done:
return 0;
}
-int linklib(const char* dataDir, const char* asecLibDir)
+int linklib(const char* pkgname, const char* asecLibDir, int userId)
{
- char libdir[PKG_PATH_MAX];
+ char pkgdir[PKG_PATH_MAX];
+ char libsymlink[PKG_PATH_MAX];
struct stat s, libStat;
int rc = 0;
- const size_t libdirLen = strlen(dataDir) + strlen(PKG_LIB_POSTFIX);
- if (libdirLen >= PKG_PATH_MAX) {
- ALOGE("library dir len too large");
+ if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, userId)) {
+ ALOGE("cannot create package path\n");
return -1;
}
-
- if (snprintf(libdir, sizeof(libdir), "%s%s", dataDir, PKG_LIB_POSTFIX) != (ssize_t)libdirLen) {
- ALOGE("library dir not written successfully: %s\n", strerror(errno));
+ if (create_pkg_path(libsymlink, pkgname, PKG_LIB_POSTFIX, userId)) {
+ ALOGE("cannot create package lib symlink origin path\n");
return -1;
}
- if (stat(dataDir, &s) < 0) return -1;
+ if (stat(pkgdir, &s) < 0) return -1;
- if (chown(dataDir, AID_INSTALL, AID_INSTALL) < 0) {
- ALOGE("failed to chown '%s': %s\n", dataDir, strerror(errno));
+ if (chown(pkgdir, AID_INSTALL, AID_INSTALL) < 0) {
+ ALOGE("failed to chown '%s': %s\n", pkgdir, strerror(errno));
return -1;
}
- if (chmod(dataDir, 0700) < 0) {
- ALOGE("linklib() 1: failed to chmod '%s': %s\n", dataDir, strerror(errno));
+ if (chmod(pkgdir, 0700) < 0) {
+ ALOGE("linklib() 1: failed to chmod '%s': %s\n", pkgdir, strerror(errno));
rc = -1;
goto out;
}
- if (lstat(libdir, &libStat) < 0) {
- ALOGE("couldn't stat lib dir: %s\n", strerror(errno));
- rc = -1;
- goto out;
- }
-
- if (S_ISDIR(libStat.st_mode)) {
- if (delete_dir_contents(libdir, 1, 0) < 0) {
+ if (lstat(libsymlink, &libStat) < 0) {
+ if (errno != ENOENT) {
+ ALOGE("couldn't stat lib dir: %s\n", strerror(errno));
rc = -1;
goto out;
}
- } else if (S_ISLNK(libStat.st_mode)) {
- if (unlink(libdir) < 0) {
- rc = -1;
- goto out;
+ } else {
+ if (S_ISDIR(libStat.st_mode)) {
+ if (delete_dir_contents(libsymlink, 1, 0) < 0) {
+ rc = -1;
+ goto out;
+ }
+ } else if (S_ISLNK(libStat.st_mode)) {
+ if (unlink(libsymlink) < 0) {
+ ALOGE("couldn't unlink lib dir: %s\n", strerror(errno));
+ rc = -1;
+ goto out;
+ }
}
}
- if (symlink(asecLibDir, libdir) < 0) {
- ALOGE("couldn't symlink directory '%s' -> '%s': %s\n", libdir, asecLibDir, strerror(errno));
- rc = -errno;
- goto out;
- }
-
- if (lchown(libdir, AID_SYSTEM, AID_SYSTEM) < 0) {
- ALOGE("cannot chown dir '%s': %s\n", libdir, strerror(errno));
- unlink(libdir);
+ if (symlink(asecLibDir, libsymlink) < 0) {
+ ALOGE("couldn't symlink directory '%s' -> '%s': %s\n", libsymlink, asecLibDir,
+ strerror(errno));
rc = -errno;
goto out;
}
out:
- if (chmod(dataDir, s.st_mode) < 0) {
- ALOGE("linklib() 2: failed to chmod '%s': %s\n", dataDir, strerror(errno));
+ if (chmod(pkgdir, s.st_mode) < 0) {
+ ALOGE("linklib() 2: failed to chmod '%s': %s\n", pkgdir, strerror(errno));
rc = -errno;
}
- if (chown(dataDir, s.st_uid, s.st_gid) < 0) {
- ALOGE("failed to chown '%s' : %s\n", dataDir, strerror(errno));
+ if (chown(pkgdir, s.st_uid, s.st_gid) < 0) {
+ ALOGE("failed to chown '%s' : %s\n", pkgdir, strerror(errno));
return -errno;
}
diff --git a/cmds/installd/installd.c b/cmds/installd/installd.c
index 19298a3..21d674a 100644
--- a/cmds/installd/installd.c
+++ b/cmds/installd/installd.c
@@ -123,7 +123,7 @@ static int do_movefiles(char **arg, char reply[REPLY_MAX])
static int do_linklib(char **arg, char reply[REPLY_MAX])
{
- return linklib(arg[0], arg[1]);
+ return linklib(arg[0], arg[1], atoi(arg[2]));
}
struct cmdinfo {
@@ -146,7 +146,7 @@ struct cmdinfo cmds[] = {
{ "getsize", 5, do_get_size },
{ "rmuserdata", 2, do_rm_user_data },
{ "movefiles", 0, do_movefiles },
- { "linklib", 2, do_linklib },
+ { "linklib", 3, do_linklib },
{ "mkuserdata", 3, do_mk_user_data },
{ "rmuser", 1, do_rm_user },
{ "cloneuserdata", 3, do_clone_user_data },
diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h
index 2540dbe..0500c23 100644
--- a/cmds/installd/installd.h
+++ b/cmds/installd/installd.h
@@ -188,6 +188,7 @@ char *build_string2(char *s1, char *s2);
char *build_string3(char *s1, char *s2, char *s3);
int ensure_dir(const char* path, mode_t mode, uid_t uid, gid_t gid);
+int ensure_media_user_dirs(userid_t userid);
/* commands.c */
@@ -209,4 +210,4 @@ int get_size(const char *pkgname, int persona, const char *apkpath, const char *
int free_cache(int64_t free_size);
int dexopt(const char *apk_path, uid_t uid, int is_public);
int movefiles();
-int linklib(const char* target, const char* source);
+int linklib(const char* target, const char* source, int userId);
diff --git a/core/tests/coretests/apks/install_bad_dex/AndroidManifest.xml b/core/tests/coretests/apks/install_bad_dex/AndroidManifest.xml
index fe4dd8e..76f0fe5 100644
--- a/core/tests/coretests/apks/install_bad_dex/AndroidManifest.xml
+++ b/core/tests/coretests/apks/install_bad_dex/AndroidManifest.xml
@@ -14,7 +14,7 @@
limitations under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.frameworks.coretests.install_loc">
+ package="com.android.frameworks.coretests.install_bad_dex">
<application android:hasCode="true">
<activity
diff --git a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
index 56070ee..04f8009 100755
--- a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
+++ b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
@@ -981,19 +981,22 @@ public class PackageManagerTests extends AndroidTestCase {
try {
DeleteObserver observer = new DeleteObserver(pkgName);
- getPm().deletePackage(pkgName, observer, flags);
+ getPm().deletePackage(pkgName, observer, flags | PackageManager.DELETE_ALL_USERS);
observer.waitForCompletion(MAX_WAIT_TIME);
assertUninstalled(info);
// Verify we received the broadcast
- long waitTime = 0;
- while ((!receiver.isDone()) && (waitTime < MAX_WAIT_TIME)) {
- receiver.wait(WAIT_TIME_INCR);
- waitTime += WAIT_TIME_INCR;
- }
- if (!receiver.isDone()) {
- throw new Exception("Timed out waiting for PACKAGE_REMOVED notification");
+ // TODO replace this with a CountDownLatch
+ synchronized (receiver) {
+ long waitTime = 0;
+ while ((!receiver.isDone()) && (waitTime < MAX_WAIT_TIME)) {
+ receiver.wait(WAIT_TIME_INCR);
+ waitTime += WAIT_TIME_INCR;
+ }
+ if (!receiver.isDone()) {
+ throw new Exception("Timed out waiting for PACKAGE_REMOVED notification");
+ }
}
return receiver.received;
} finally {
@@ -1331,7 +1334,7 @@ public class PackageManagerTests extends AndroidTestCase {
}
DeleteObserver observer = new DeleteObserver(packageName);
- getPm().deletePackage(packageName, observer, 0);
+ getPm().deletePackage(packageName, observer, PackageManager.DELETE_ALL_USERS);
observer.waitForCompletion(MAX_WAIT_TIME);
try {
@@ -1357,7 +1360,7 @@ public class PackageManagerTests extends AndroidTestCase {
if (info != null) {
DeleteObserver observer = new DeleteObserver(pkgName);
- getPm().deletePackage(pkgName, observer, 0);
+ getPm().deletePackage(pkgName, observer, PackageManager.DELETE_ALL_USERS);
observer.waitForCompletion(MAX_WAIT_TIME);
assertUninstalled(info);
}
@@ -3126,7 +3129,7 @@ public class PackageManagerTests extends AndroidTestCase {
int rawResId = apk2;
Uri packageURI = getInstallablePackage(rawResId, outFile);
PackageParser.Package pkg = parsePackage(packageURI);
- getPm().deletePackage(pkg.packageName, null, 0);
+ getPm().deletePackage(pkg.packageName, null, PackageManager.DELETE_ALL_USERS);
// Check signatures now
int match = mContext.getPackageManager().checkSignatures(
ip1.pkg.packageName, pkg.packageName);
@@ -3265,7 +3268,7 @@ public class PackageManagerTests extends AndroidTestCase {
PackageManager pm = mContext.getPackageManager();
// Delete app2
PackageParser.Package pkg = getParsedPackage(apk2Name, apk2);
- getPm().deletePackage(pkg.packageName, null, 0);
+ getPm().deletePackage(pkg.packageName, null, PackageManager.DELETE_ALL_USERS);
// Check signatures now
int match = mContext.getPackageManager().checkSignatures(
ip1.pkg.packageName, pkg.packageName);
diff --git a/services/java/com/android/server/pm/Installer.java b/services/java/com/android/server/pm/Installer.java
index 8b1e80f..71a6a01 100644
--- a/services/java/com/android/server/pm/Installer.java
+++ b/services/java/com/android/server/pm/Installer.java
@@ -369,7 +369,7 @@ public final class Installer {
* @param nativeLibPath target native library path
* @return -1 on error
*/
- public int linkNativeLibraryDirectory(String dataPath, String nativeLibPath) {
+ public int linkNativeLibraryDirectory(String dataPath, String nativeLibPath, int userId) {
if (dataPath == null) {
Slog.e(TAG, "linkNativeLibraryDirectory dataPath is null");
return -1;
@@ -382,6 +382,8 @@ public final class Installer {
builder.append(dataPath);
builder.append(' ');
builder.append(nativeLibPath);
+ builder.append(' ');
+ builder.append(userId);
return execute(builder.toString());
}
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index f59e30d..2d69c74 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -4088,39 +4088,42 @@ public class PackageManagerService extends IPackageManager.Stub {
Log.i(TAG, "removed obsolete native libraries for system package "
+ path);
}
- } else if (!isForwardLocked(pkg) && !isExternal(pkg)) {
- // Update native library dir if it starts with /data/data
- if (nativeLibraryDir.getPath().startsWith(dataPathString)) {
- setInternalAppNativeLibraryPath(pkg, pkgSetting);
- nativeLibraryDir = new File(pkg.applicationInfo.nativeLibraryDir);
- }
+ } else {
+ if (!isForwardLocked(pkg) && !isExternal(pkg)) {
+ /*
+ * Update native library dir if it starts with
+ * /data/data
+ */
+ if (nativeLibraryDir.getPath().startsWith(dataPathString)) {
+ setInternalAppNativeLibraryPath(pkg, pkgSetting);
+ nativeLibraryDir = new File(pkg.applicationInfo.nativeLibraryDir);
+ }
- try {
- if (copyNativeLibrariesForInternalApp(scanFile, nativeLibraryDir) != PackageManager.INSTALL_SUCCEEDED) {
- Slog.e(TAG, "Unable to copy native libraries");
+ try {
+ if (copyNativeLibrariesForInternalApp(scanFile, nativeLibraryDir) != PackageManager.INSTALL_SUCCEEDED) {
+ Slog.e(TAG, "Unable to copy native libraries");
+ mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
+ return null;
+ }
+ } catch (IOException e) {
+ Slog.e(TAG, "Unable to copy native libraries", e);
mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
return null;
}
- } catch (IOException e) {
- Slog.e(TAG, "Unable to copy native libraries", e);
- mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
- return null;
}
- if (mInstaller.linkNativeLibraryDirectory(dataPathString,
- pkg.applicationInfo.nativeLibraryDir) == -1) {
- Slog.e(TAG, "Unable to link native library directory");
- mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
- return null;
- }
- } else {
Slog.i(TAG, "Linking native library dir for " + path);
- int ret = mInstaller.linkNativeLibraryDirectory(dataPathString,
- pkg.applicationInfo.nativeLibraryDir);
- if (ret < 0) {
- Slog.w(TAG, "Failed linking native library dir for " + path);
- mLastScanError = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
- return null;
+ final int[] userIds = sUserManager.getUserIds();
+ synchronized (mInstallLock) {
+ for (int userId : userIds) {
+ if (mInstaller.linkNativeLibraryDirectory(pkg.packageName,
+ pkg.applicationInfo.nativeLibraryDir, userId) < 0) {
+ Slog.w(TAG, "Failed linking native library dir (user=" + userId
+ + ")");
+ mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
+ return null;
+ }
+ }
}
}
} catch (IOException ioe) {
@@ -6350,12 +6353,12 @@ public class PackageManagerService extends IPackageManager.Stub {
ret = PackageManager.INSTALL_FAILED_INVALID_URI;
} else if (loc == PackageHelper.RECOMMEND_MEDIA_UNAVAILABLE) {
ret = PackageManager.INSTALL_FAILED_MEDIA_UNAVAILABLE;
- } else if (loc == PackageHelper.RECOMMEND_FAILED_VERSION_DOWNGRADE) {
- ret = PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE;
} else {
// Override with defaults if needed.
loc = installLocationPolicy(pkgLite, flags);
- if (!onSd && !onInt) {
+ if (loc == PackageHelper.RECOMMEND_FAILED_VERSION_DOWNGRADE) {
+ ret = PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE;
+ } else if (!onSd && !onInt) {
// Override install location with flags
if (loc == PackageHelper.RECOMMEND_INSTALL_EXTERNAL) {
// Set the flag to install on external media.
@@ -9959,20 +9962,14 @@ public class PackageManagerService extends IPackageManager.Stub {
final File newNativeDir = new File(newNativePath);
if (!isForwardLocked(pkg) && !isExternal(pkg)) {
- synchronized (mInstallLock) {
- if (mInstaller.linkNativeLibraryDirectory(
- pkg.applicationInfo.dataDir, newNativePath) < 0) {
- returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
- }
- }
- NativeLibraryHelper.copyNativeBinariesIfNeededLI(new File(
- newCodePath), newNativeDir);
- } else {
- synchronized (mInstallLock) {
- if (mInstaller.linkNativeLibraryDirectory(
- pkg.applicationInfo.dataDir, newNativePath) < 0) {
- returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
- }
+ NativeLibraryHelper.copyNativeBinariesIfNeededLI(
+ new File(newCodePath), newNativeDir);
+ }
+ final int[] users = sUserManager.getUserIds();
+ for (int user : users) {
+ if (mInstaller.linkNativeLibraryDirectory(pkg.packageName,
+ newNativePath, user) < 0) {
+ returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
}
}