Loading cmds/installd/commands.c +154 −0 Original line number Diff line number Diff line Loading @@ -936,3 +936,157 @@ int movefiles() done: return 0; } int linklib(const char* dataDir, const char* asecLibDir) { char libdir[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) { LOGE("library dir len too large"); rc = -1; goto out; } if (snprintf(libdir, sizeof(libdir), "%s%s", dataDir, PKG_LIB_POSTFIX) != (ssize_t)libdirLen) { LOGE("library dir not written successfully: %s\n", strerror(errno)); rc = -1; goto out; } if (stat(dataDir, &s) < 0) return -1; if (chown(dataDir, 0, 0) < 0) { LOGE("failed to chown '%s': %s\n", dataDir, strerror(errno)); return -1; } if (chmod(dataDir, 0700) < 0) { LOGE("failed to chmod '%s': %s\n", dataDir, strerror(errno)); rc = -1; goto out; } if (lstat(libdir, &libStat) < 0) { LOGE("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) { rc = -1; goto out; } } else if (S_ISLNK(libStat.st_mode)) { if (unlink(libdir) < 0) { rc = -1; goto out; } } if (symlink(asecLibDir, libdir) < 0) { LOGE("couldn't symlink directory '%s' -> '%s': %s\n", libdir, asecLibDir, strerror(errno)); rc = -errno; goto out; } if (lchown(libdir, AID_SYSTEM, AID_SYSTEM) < 0) { LOGE("cannot chown dir '%s': %s\n", libdir, strerror(errno)); unlink(libdir); rc = -errno; goto out; } out: if (chmod(dataDir, s.st_mode) < 0) { LOGE("failed to chmod '%s': %s\n", dataDir, strerror(errno)); return -errno; } if (chown(dataDir, s.st_uid, s.st_gid) < 0) { LOGE("failed to chown '%s' : %s\n", dataDir, strerror(errno)); return -errno; } return rc; } int unlinklib(const char* dataDir) { char libdir[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) { return -1; } if (snprintf(libdir, sizeof(libdir), "%s%s", dataDir, PKG_LIB_POSTFIX) != (ssize_t)libdirLen) { LOGE("library dir not written successfully: %s\n", strerror(errno)); return -1; } if (stat(dataDir, &s) < 0) { LOGE("couldn't state data dir"); return -1; } if (chown(dataDir, 0, 0) < 0) { LOGE("failed to chown '%s': %s\n", dataDir, strerror(errno)); return -1; } if (chmod(dataDir, 0700) < 0) { LOGE("failed to chmod '%s': %s\n", dataDir, strerror(errno)); rc = -1; goto out; } if (lstat(libdir, &libStat) < 0) { LOGE("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) { rc = -1; goto out; } } else if (S_ISLNK(libStat.st_mode)) { if (unlink(libdir) < 0) { rc = -1; goto out; } } if (mkdir(libdir, 0755) < 0) { LOGE("cannot create dir '%s': %s\n", libdir, strerror(errno)); rc = -errno; goto out; } if (chown(libdir, AID_SYSTEM, AID_SYSTEM) < 0) { LOGE("cannot chown dir '%s': %s\n", libdir, strerror(errno)); unlink(libdir); rc = -errno; goto out; } out: if (chmod(dataDir, s.st_mode) < 0) { LOGE("failed to chmod '%s': %s\n", dataDir, strerror(errno)); return -1; } if (chown(dataDir, s.st_uid, s.st_gid) < 0) { LOGE("failed to chown '%s' : %s\n", dataDir, strerror(errno)); return -1; } return rc; } cmds/installd/installd.c +12 −0 Original line number Diff line number Diff line Loading @@ -101,6 +101,16 @@ static int do_movefiles(char **arg, char reply[REPLY_MAX]) return movefiles(); } static int do_linklib(char **arg, char reply[REPLY_MAX]) { return linklib(arg[0], arg[1]); } static int do_unlinklib(char **arg, char reply[REPLY_MAX]) { return unlinklib(arg[0]); } struct cmdinfo { const char *name; unsigned numargs; Loading @@ -121,6 +131,8 @@ struct cmdinfo cmds[] = { { "getsize", 4, do_get_size }, { "rmuserdata", 2, do_rm_user_data }, { "movefiles", 0, do_movefiles }, { "linklib", 2, do_linklib }, { "unlinklib", 1, do_unlinklib }, }; static int readx(int s, void *_buf, int count) Loading cmds/installd/installd.h +2 −0 Original line number Diff line number Diff line Loading @@ -111,3 +111,5 @@ int get_size(const char *pkgname, const char *apkpath, const char *fwdlock_apkpa 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 unlinklib(const char* libPath); core/tests/coretests/src/android/content/pm/PackageManagerTests.java +39 −5 Original line number Diff line number Diff line Loading @@ -45,6 +45,7 @@ import android.util.DisplayMetrics; import android.util.Log; import java.io.File; import java.io.IOException; import java.io.InputStream; public class PackageManagerTests extends AndroidTestCase { Loading Loading @@ -378,6 +379,18 @@ public class PackageManagerTests extends AndroidTestCase { assertEquals(publicSrcPath, appInstallPath); assertFalse((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0); assertTrue(info.nativeLibraryDir.startsWith(dataDir.getPath())); // Make sure the native library dir is not a symlink final File nativeLibDir = new File(info.nativeLibraryDir); assertTrue("Native library dir should exist at " + info.nativeLibraryDir, nativeLibDir.exists()); try { assertEquals("Native library dir should not be a symlink", info.nativeLibraryDir, nativeLibDir.getCanonicalPath()); } catch (IOException e) { fail("Can't read " + nativeLibDir.getPath()); } } else if (rLoc == INSTALL_LOC_SD){ assertTrue("Application flags (" + info.flags + ") should contain FLAG_EXTERNAL_STORAGE", Loading @@ -391,6 +404,19 @@ public class PackageManagerTests extends AndroidTestCase { assertTrue("The native library path (" + info.nativeLibraryDir + ") should start with " + SECURE_CONTAINERS_PREFIX, info.nativeLibraryDir.startsWith(SECURE_CONTAINERS_PREFIX)); // Make sure the native library in /data/data/<app>/lib is a // symlink to the ASEC final File nativeLibSymLink = new File(info.dataDir, "lib"); assertTrue("Native library symlink should exist at " + nativeLibSymLink.getPath(), nativeLibSymLink.exists()); try { assertEquals(nativeLibSymLink.getPath() + " should be a symlink to " + info.nativeLibraryDir, info.nativeLibraryDir, nativeLibSymLink .getCanonicalPath()); } catch (IOException e) { fail("Can't read " + nativeLibSymLink.getPath()); } } else { // TODO handle error. Install should have failed. fail("Install should have failed"); Loading Loading @@ -1406,13 +1432,21 @@ public class PackageManagerTests extends AndroidTestCase { receiver); assertTrue(retCode); ApplicationInfo info = getPm().getApplicationInfo(ip.pkg.packageName, 0); assertNotNull(info); assertNotNull("ApplicationInfo for recently installed application should exist", info); if ((moveFlags & PackageManager.MOVE_INTERNAL) != 0) { assertTrue((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) == 0); assertTrue(info.nativeLibraryDir.startsWith(info.dataDir)); assertTrue("ApplicationInfo.FLAG_EXTERNAL_STORAGE flag should NOT be set", (info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) == 0); assertTrue("ApplicationInfo.nativeLibraryDir should start with " + info.dataDir, info.nativeLibraryDir.startsWith(info.dataDir)); } else if ((moveFlags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0){ assertTrue((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0); assertTrue(info.nativeLibraryDir.startsWith(SECURE_CONTAINERS_PREFIX)); assertTrue("ApplicationInfo.FLAG_EXTERNAL_STORAGE flag should be set", (info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0); assertTrue("ApplicationInfo.nativeLibraryDir should start with " + SECURE_CONTAINERS_PREFIX, info.nativeLibraryDir.startsWith(SECURE_CONTAINERS_PREFIX)); final File nativeLibSymLink = new File(info.dataDir, "lib"); assertTrue("The data directory should have a 'lib' symlink that points to the ASEC container", nativeLibSymLink.getCanonicalPath().startsWith(SECURE_CONTAINERS_PREFIX)); } } } catch (NameNotFoundException e) { Loading services/java/com/android/server/Installer.java +29 −0 Original line number Diff line number Diff line Loading @@ -327,4 +327,33 @@ class Installer { public int moveFiles() { return execute("movefiles"); } public int linkNativeLibraryDirectory(String dataPath, String nativeLibPath) { if (dataPath == null) { Slog.e(TAG, "unlinkNativeLibraryDirectory dataPath is null"); return -1; } else if (nativeLibPath == null) { Slog.e(TAG, "unlinkNativeLibraryDirectory nativeLibPath is null"); return -1; } StringBuilder builder = new StringBuilder("linklib "); builder.append(dataPath); builder.append(' '); builder.append(nativeLibPath); return execute(builder.toString()); } public int unlinkNativeLibraryDirectory(String dataPath) { if (dataPath == null) { Slog.e(TAG, "unlinkNativeLibraryDirectory dataPath is null"); return -1; } StringBuilder builder = new StringBuilder("unlinklib "); builder.append(dataPath); return execute(builder.toString()); } } Loading
cmds/installd/commands.c +154 −0 Original line number Diff line number Diff line Loading @@ -936,3 +936,157 @@ int movefiles() done: return 0; } int linklib(const char* dataDir, const char* asecLibDir) { char libdir[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) { LOGE("library dir len too large"); rc = -1; goto out; } if (snprintf(libdir, sizeof(libdir), "%s%s", dataDir, PKG_LIB_POSTFIX) != (ssize_t)libdirLen) { LOGE("library dir not written successfully: %s\n", strerror(errno)); rc = -1; goto out; } if (stat(dataDir, &s) < 0) return -1; if (chown(dataDir, 0, 0) < 0) { LOGE("failed to chown '%s': %s\n", dataDir, strerror(errno)); return -1; } if (chmod(dataDir, 0700) < 0) { LOGE("failed to chmod '%s': %s\n", dataDir, strerror(errno)); rc = -1; goto out; } if (lstat(libdir, &libStat) < 0) { LOGE("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) { rc = -1; goto out; } } else if (S_ISLNK(libStat.st_mode)) { if (unlink(libdir) < 0) { rc = -1; goto out; } } if (symlink(asecLibDir, libdir) < 0) { LOGE("couldn't symlink directory '%s' -> '%s': %s\n", libdir, asecLibDir, strerror(errno)); rc = -errno; goto out; } if (lchown(libdir, AID_SYSTEM, AID_SYSTEM) < 0) { LOGE("cannot chown dir '%s': %s\n", libdir, strerror(errno)); unlink(libdir); rc = -errno; goto out; } out: if (chmod(dataDir, s.st_mode) < 0) { LOGE("failed to chmod '%s': %s\n", dataDir, strerror(errno)); return -errno; } if (chown(dataDir, s.st_uid, s.st_gid) < 0) { LOGE("failed to chown '%s' : %s\n", dataDir, strerror(errno)); return -errno; } return rc; } int unlinklib(const char* dataDir) { char libdir[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) { return -1; } if (snprintf(libdir, sizeof(libdir), "%s%s", dataDir, PKG_LIB_POSTFIX) != (ssize_t)libdirLen) { LOGE("library dir not written successfully: %s\n", strerror(errno)); return -1; } if (stat(dataDir, &s) < 0) { LOGE("couldn't state data dir"); return -1; } if (chown(dataDir, 0, 0) < 0) { LOGE("failed to chown '%s': %s\n", dataDir, strerror(errno)); return -1; } if (chmod(dataDir, 0700) < 0) { LOGE("failed to chmod '%s': %s\n", dataDir, strerror(errno)); rc = -1; goto out; } if (lstat(libdir, &libStat) < 0) { LOGE("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) { rc = -1; goto out; } } else if (S_ISLNK(libStat.st_mode)) { if (unlink(libdir) < 0) { rc = -1; goto out; } } if (mkdir(libdir, 0755) < 0) { LOGE("cannot create dir '%s': %s\n", libdir, strerror(errno)); rc = -errno; goto out; } if (chown(libdir, AID_SYSTEM, AID_SYSTEM) < 0) { LOGE("cannot chown dir '%s': %s\n", libdir, strerror(errno)); unlink(libdir); rc = -errno; goto out; } out: if (chmod(dataDir, s.st_mode) < 0) { LOGE("failed to chmod '%s': %s\n", dataDir, strerror(errno)); return -1; } if (chown(dataDir, s.st_uid, s.st_gid) < 0) { LOGE("failed to chown '%s' : %s\n", dataDir, strerror(errno)); return -1; } return rc; }
cmds/installd/installd.c +12 −0 Original line number Diff line number Diff line Loading @@ -101,6 +101,16 @@ static int do_movefiles(char **arg, char reply[REPLY_MAX]) return movefiles(); } static int do_linklib(char **arg, char reply[REPLY_MAX]) { return linklib(arg[0], arg[1]); } static int do_unlinklib(char **arg, char reply[REPLY_MAX]) { return unlinklib(arg[0]); } struct cmdinfo { const char *name; unsigned numargs; Loading @@ -121,6 +131,8 @@ struct cmdinfo cmds[] = { { "getsize", 4, do_get_size }, { "rmuserdata", 2, do_rm_user_data }, { "movefiles", 0, do_movefiles }, { "linklib", 2, do_linklib }, { "unlinklib", 1, do_unlinklib }, }; static int readx(int s, void *_buf, int count) Loading
cmds/installd/installd.h +2 −0 Original line number Diff line number Diff line Loading @@ -111,3 +111,5 @@ int get_size(const char *pkgname, const char *apkpath, const char *fwdlock_apkpa 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 unlinklib(const char* libPath);
core/tests/coretests/src/android/content/pm/PackageManagerTests.java +39 −5 Original line number Diff line number Diff line Loading @@ -45,6 +45,7 @@ import android.util.DisplayMetrics; import android.util.Log; import java.io.File; import java.io.IOException; import java.io.InputStream; public class PackageManagerTests extends AndroidTestCase { Loading Loading @@ -378,6 +379,18 @@ public class PackageManagerTests extends AndroidTestCase { assertEquals(publicSrcPath, appInstallPath); assertFalse((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0); assertTrue(info.nativeLibraryDir.startsWith(dataDir.getPath())); // Make sure the native library dir is not a symlink final File nativeLibDir = new File(info.nativeLibraryDir); assertTrue("Native library dir should exist at " + info.nativeLibraryDir, nativeLibDir.exists()); try { assertEquals("Native library dir should not be a symlink", info.nativeLibraryDir, nativeLibDir.getCanonicalPath()); } catch (IOException e) { fail("Can't read " + nativeLibDir.getPath()); } } else if (rLoc == INSTALL_LOC_SD){ assertTrue("Application flags (" + info.flags + ") should contain FLAG_EXTERNAL_STORAGE", Loading @@ -391,6 +404,19 @@ public class PackageManagerTests extends AndroidTestCase { assertTrue("The native library path (" + info.nativeLibraryDir + ") should start with " + SECURE_CONTAINERS_PREFIX, info.nativeLibraryDir.startsWith(SECURE_CONTAINERS_PREFIX)); // Make sure the native library in /data/data/<app>/lib is a // symlink to the ASEC final File nativeLibSymLink = new File(info.dataDir, "lib"); assertTrue("Native library symlink should exist at " + nativeLibSymLink.getPath(), nativeLibSymLink.exists()); try { assertEquals(nativeLibSymLink.getPath() + " should be a symlink to " + info.nativeLibraryDir, info.nativeLibraryDir, nativeLibSymLink .getCanonicalPath()); } catch (IOException e) { fail("Can't read " + nativeLibSymLink.getPath()); } } else { // TODO handle error. Install should have failed. fail("Install should have failed"); Loading Loading @@ -1406,13 +1432,21 @@ public class PackageManagerTests extends AndroidTestCase { receiver); assertTrue(retCode); ApplicationInfo info = getPm().getApplicationInfo(ip.pkg.packageName, 0); assertNotNull(info); assertNotNull("ApplicationInfo for recently installed application should exist", info); if ((moveFlags & PackageManager.MOVE_INTERNAL) != 0) { assertTrue((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) == 0); assertTrue(info.nativeLibraryDir.startsWith(info.dataDir)); assertTrue("ApplicationInfo.FLAG_EXTERNAL_STORAGE flag should NOT be set", (info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) == 0); assertTrue("ApplicationInfo.nativeLibraryDir should start with " + info.dataDir, info.nativeLibraryDir.startsWith(info.dataDir)); } else if ((moveFlags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0){ assertTrue((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0); assertTrue(info.nativeLibraryDir.startsWith(SECURE_CONTAINERS_PREFIX)); assertTrue("ApplicationInfo.FLAG_EXTERNAL_STORAGE flag should be set", (info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0); assertTrue("ApplicationInfo.nativeLibraryDir should start with " + SECURE_CONTAINERS_PREFIX, info.nativeLibraryDir.startsWith(SECURE_CONTAINERS_PREFIX)); final File nativeLibSymLink = new File(info.dataDir, "lib"); assertTrue("The data directory should have a 'lib' symlink that points to the ASEC container", nativeLibSymLink.getCanonicalPath().startsWith(SECURE_CONTAINERS_PREFIX)); } } } catch (NameNotFoundException e) { Loading
services/java/com/android/server/Installer.java +29 −0 Original line number Diff line number Diff line Loading @@ -327,4 +327,33 @@ class Installer { public int moveFiles() { return execute("movefiles"); } public int linkNativeLibraryDirectory(String dataPath, String nativeLibPath) { if (dataPath == null) { Slog.e(TAG, "unlinkNativeLibraryDirectory dataPath is null"); return -1; } else if (nativeLibPath == null) { Slog.e(TAG, "unlinkNativeLibraryDirectory nativeLibPath is null"); return -1; } StringBuilder builder = new StringBuilder("linklib "); builder.append(dataPath); builder.append(' '); builder.append(nativeLibPath); return execute(builder.toString()); } public int unlinkNativeLibraryDirectory(String dataPath) { if (dataPath == null) { Slog.e(TAG, "unlinkNativeLibraryDirectory dataPath is null"); return -1; } StringBuilder builder = new StringBuilder("unlinklib "); builder.append(dataPath); return execute(builder.toString()); } }