diff options
-rw-r--r-- | cmds/installd/commands.c | 108 | ||||
-rw-r--r-- | cmds/installd/installd.c | 20 | ||||
-rw-r--r-- | cmds/installd/installd.h | 17 | ||||
-rw-r--r-- | core/java/android/accounts/AccountManagerService.java | 15 | ||||
-rw-r--r-- | core/java/android/app/ApplicationContext.java | 38 | ||||
-rw-r--r-- | core/java/android/content/SyncStorageEngine.java | 15 | ||||
-rw-r--r-- | core/java/android/os/Environment.java | 48 | ||||
-rw-r--r-- | packages/SettingsProvider/AndroidManifest.xml | 3 | ||||
-rw-r--r-- | packages/VpnServices/src/com/android/server/vpn/VpnServiceBinder.java | 17 | ||||
-rw-r--r-- | services/java/com/android/server/BackupManagerService.java | 24 | ||||
-rw-r--r-- | services/java/com/android/server/Installer.java | 40 | ||||
-rw-r--r-- | services/java/com/android/server/PackageManagerService.java | 78 | ||||
-rw-r--r-- | vpn/java/android/net/vpn/VpnManager.java | 14 |
13 files changed, 337 insertions, 100 deletions
diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c index 70a1206..dcae0c7 100644 --- a/cmds/installd/commands.c +++ b/cmds/installd/commands.c @@ -16,7 +16,7 @@ #include "installd.h" -int install(const char *pkgname, uid_t uid, gid_t gid) +int install(const char *pkgname, int encrypted_fs_flag, uid_t uid, gid_t gid) { char pkgdir[PKG_PATH_MAX]; char libdir[PKG_PATH_MAX]; @@ -26,10 +26,18 @@ int install(const char *pkgname, uid_t uid, gid_t gid) return -1; } - if (create_pkg_path(pkgdir, PKG_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX)) - return -1; - if (create_pkg_path(libdir, PKG_LIB_PREFIX, pkgname, PKG_LIB_POSTFIX)) - return -1; + + if (encrypted_fs_flag == USE_UNENCRYPTED_FS) { + if (create_pkg_path(pkgdir, PKG_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX)) + return -1; + if (create_pkg_path(libdir, PKG_LIB_PREFIX, pkgname, PKG_LIB_POSTFIX)) + return -1; + } else { + if (create_pkg_path(pkgdir, PKG_SEC_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX)) + return -1; + if (create_pkg_path(libdir, PKG_SEC_LIB_PREFIX, pkgname, PKG_LIB_POSTFIX)) + return -1; + } if (mkdir(pkgdir, 0755) < 0) { LOGE("cannot create dir '%s': %s\n", pkgdir, strerror(errno)); @@ -54,41 +62,58 @@ int install(const char *pkgname, uid_t uid, gid_t gid) return 0; } -int uninstall(const char *pkgname) +int uninstall(const char *pkgname, int encrypted_fs_flag) { char pkgdir[PKG_PATH_MAX]; - if (create_pkg_path(pkgdir, PKG_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX)) - return -1; + if (encrypted_fs_flag == USE_UNENCRYPTED_FS) { + if (create_pkg_path(pkgdir, PKG_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX)) + return -1; + } else { + if (create_pkg_path(pkgdir, PKG_SEC_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX)) + return -1; + } /* delete contents AND directory, no exceptions */ return delete_dir_contents(pkgdir, 1, 0); } -int delete_user_data(const char *pkgname) +int delete_user_data(const char *pkgname, int encrypted_fs_flag) { char pkgdir[PKG_PATH_MAX]; - if (create_pkg_path(pkgdir, PKG_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX)) - return -1; + if (encrypted_fs_flag == USE_UNENCRYPTED_FS) { + if (create_pkg_path(pkgdir, PKG_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX)) + return -1; + } else { + if (create_pkg_path(pkgdir, PKG_SEC_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX)) + return -1; + } /* delete contents, excluding "lib", but not the directory itself */ return delete_dir_contents(pkgdir, 0, "lib"); } -int delete_cache(const char *pkgname) +int delete_cache(const char *pkgname, int encrypted_fs_flag) { char cachedir[PKG_PATH_MAX]; - if (create_pkg_path(cachedir, CACHE_DIR_PREFIX, pkgname, CACHE_DIR_POSTFIX)) - return -1; + if (encrypted_fs_flag == USE_UNENCRYPTED_FS) { + if (create_pkg_path(cachedir, CACHE_DIR_PREFIX, pkgname, CACHE_DIR_POSTFIX)) + return -1; + } else { + if (create_pkg_path(cachedir, CACHE_SEC_DIR_PREFIX, pkgname, CACHE_DIR_POSTFIX)) + return -1; + } /* delete contents, not the directory, no exceptions */ return delete_dir_contents(cachedir, 0, 0); } - -static int disk_free(void) +/* TODO(oam): depending on use case (ecryptfs or dmcrypt) + * change implementation + */ +static int disk_free() { struct statfs sfs; if (statfs(PKG_DIR_PREFIX, &sfs) == 0) { @@ -98,7 +123,6 @@ static int disk_free(void) } } - /* Try to ensure free_size bytes of storage are available. * Returns 0 on success. * This is rather simple-minded because doing a full LRU would @@ -120,6 +144,39 @@ int free_cache(int free_size) LOGI("free_cache(%d) avail %d\n", free_size, avail); if (avail >= free_size) return 0; + /* First try encrypted dir */ + d = opendir(PKG_SEC_DIR_PREFIX); + if (d == NULL) { + LOGE("cannot open %s\n", PKG_SEC_DIR_PREFIX); + } else { + dfd = dirfd(d); + + while ((de = readdir(d))) { + if (de->d_type != DT_DIR) continue; + name = de->d_name; + + /* always skip "." and ".." */ + if (name[0] == '.') { + if (name[1] == 0) continue; + if ((name[1] == '.') && (name[2] == 0)) continue; + } + + subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY); + if (subfd < 0) continue; + + delete_dir_contents_fd(subfd, "cache"); + close(subfd); + + avail = disk_free(); + if (avail >= free_size) { + closedir(d); + return 0; + } + } + closedir(d); + } + + /* Next try unencrypted dir... */ d = opendir(PKG_DIR_PREFIX); if (d == NULL) { LOGE("cannot open %s\n", PKG_DIR_PREFIX); @@ -131,7 +188,7 @@ int free_cache(int free_size) if (de->d_type != DT_DIR) continue; name = de->d_name; - /* always skip "." and ".." */ + /* always skip "." and ".." */ if (name[0] == '.') { if (name[1] == 0) continue; if ((name[1] == '.') && (name[2] == 0)) continue; @@ -150,10 +207,11 @@ int free_cache(int free_size) } } closedir(d); + + /* Fail case - not possible to free space */ return -1; } - /* used by move_dex, rm_dex, etc to ensure that the provided paths * don't point anywhere other than at the APK_DIR_PREFIX */ @@ -288,7 +346,7 @@ static int calculate_dir_size(int dfd) int get_size(const char *pkgname, const char *apkpath, const char *fwdlock_apkpath, - int *_codesize, int *_datasize, int *_cachesize) + int *_codesize, int *_datasize, int *_cachesize, int encrypted_fs_flag) { DIR *d; int dfd; @@ -324,8 +382,14 @@ int get_size(const char *pkgname, const char *apkpath, } } - if (create_pkg_path(path, PKG_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX)) { - goto done; + if (encrypted_fs_flag == 0) { + if (create_pkg_path(path, PKG_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX)) { + goto done; + } + } else { + if (create_pkg_path(path, PKG_SEC_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX)) { + goto done; + } } d = opendir(path); diff --git a/cmds/installd/installd.c b/cmds/installd/installd.c index 7c7441f..5bc6c86 100644 --- a/cmds/installd/installd.c +++ b/cmds/installd/installd.c @@ -29,7 +29,7 @@ static int do_ping(char **arg, char reply[REPLY_MAX]) static int do_install(char **arg, char reply[REPLY_MAX]) { - return install(arg[0], atoi(arg[1]), atoi(arg[2])); /* pkgname, uid, gid */ + return install(arg[0], atoi(arg[1]), atoi(arg[2]), atoi(arg[3])); /* pkgname, uid, gid */ } static int do_dexopt(char **arg, char reply[REPLY_MAX]) @@ -50,7 +50,7 @@ static int do_rm_dex(char **arg, char reply[REPLY_MAX]) static int do_remove(char **arg, char reply[REPLY_MAX]) { - return uninstall(arg[0]); /* pkgname */ + return uninstall(arg[0], atoi(arg[1])); /* pkgname */ } static int do_free_cache(char **arg, char reply[REPLY_MAX]) /* TODO int:free_size */ @@ -60,7 +60,7 @@ static int do_free_cache(char **arg, char reply[REPLY_MAX]) /* TODO int:free_siz static int do_rm_cache(char **arg, char reply[REPLY_MAX]) { - return delete_cache(arg[0]); /* pkgname */ + return delete_cache(arg[0], atoi(arg[1])); /* pkgname */ } static int do_protect(char **arg, char reply[REPLY_MAX]) @@ -76,7 +76,7 @@ static int do_get_size(char **arg, char reply[REPLY_MAX]) int res = 0; /* pkgdir, apkpath */ - res = get_size(arg[0], arg[1], arg[2], &codesize, &datasize, &cachesize); + res = get_size(arg[0], arg[1], arg[2], &codesize, &datasize, &cachesize, atoi(arg[3])); sprintf(reply,"%d %d %d", codesize, datasize, cachesize); return res; @@ -84,7 +84,7 @@ static int do_get_size(char **arg, char reply[REPLY_MAX]) static int do_rm_user_data(char **arg, char reply[REPLY_MAX]) { - return delete_user_data(arg[0]); /* pkgname */ + return delete_user_data(arg[0], atoi(arg[1])); /* pkgname */ } struct cmdinfo { @@ -95,16 +95,16 @@ struct cmdinfo { struct cmdinfo cmds[] = { { "ping", 0, do_ping }, - { "install", 3, do_install }, + { "install", 4, do_install }, { "dexopt", 3, do_dexopt }, { "movedex", 2, do_move_dex }, { "rmdex", 1, do_rm_dex }, - { "remove", 1, do_remove }, + { "remove", 2, do_remove }, { "freecache", 1, do_free_cache }, - { "rmcache", 1, do_rm_cache }, + { "rmcache", 2, do_rm_cache }, { "protect", 2, do_protect }, - { "getsize", 3, do_get_size }, - { "rmuserdata", 1, do_rm_user_data }, + { "getsize", 4, do_get_size }, + { "rmuserdata", 2, do_rm_user_data }, }; static int readx(int s, void *_buf, int count) diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h index db3badd..1679d14 100644 --- a/cmds/installd/installd.h +++ b/cmds/installd/installd.h @@ -48,16 +48,23 @@ /* elements combined with a valid package name to form paths */ #define PKG_DIR_PREFIX "/data/data/" +#define PKG_SEC_DIR_PREFIX "/data/secure/data/" #define PKG_DIR_POSTFIX "" #define PKG_LIB_PREFIX "/data/data/" +#define PKG_SEC_LIB_PREFIX "/data/secure/data/" #define PKG_LIB_POSTFIX "/lib" #define CACHE_DIR_PREFIX "/data/data/" +#define CACHE_SEC_DIR_PREFIX "/data/secure/data/" #define CACHE_DIR_POSTFIX "/cache" #define APK_DIR_PREFIX "/data/app/" +/* Encrypted File SYstems constants */ +#define USE_ENCRYPTED_FS 1 +#define USE_UNENCRYPTED_FS 0 + /* other handy constants */ #define PROTECTED_DIR_PREFIX "/data/app-private/" @@ -87,14 +94,14 @@ int delete_dir_contents_fd(int dfd, const char *name); /* commands.c */ -int install(const char *pkgname, uid_t uid, gid_t gid); -int uninstall(const char *pkgname); -int delete_user_data(const char *pkgname); -int delete_cache(const char *pkgname); +int install(const char *pkgname, int encrypted_fs_flag, uid_t uid, gid_t gid); +int uninstall(const char *pkgname, int encrypted_fs_flag); +int delete_user_data(const char *pkgname, int encrypted_fs_flag); +int delete_cache(const char *pkgname, int encrypted_fs_flag); int move_dex(const char *src, const char *dst); int rm_dex(const char *path); int protect(char *pkgname, gid_t gid); int get_size(const char *pkgname, const char *apkpath, const char *fwdlock_apkpath, - int *codesize, int *datasize, int *cachesize); + int *codesize, int *datasize, int *cachesize, int encrypted_fs_flag); int free_cache(int free_size); int dexopt(const char *apk_path, uid_t uid, int is_public); diff --git a/core/java/android/accounts/AccountManagerService.java b/core/java/android/accounts/AccountManagerService.java index 1a8d9b6..e6941e6 100644 --- a/core/java/android/accounts/AccountManagerService.java +++ b/core/java/android/accounts/AccountManagerService.java @@ -38,6 +38,7 @@ import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.os.Binder; import android.os.Bundle; +import android.os.Environment; import android.os.Handler; import android.os.HandlerThread; import android.os.IBinder; @@ -52,6 +53,7 @@ import android.text.TextUtils; import android.util.Log; import android.util.Pair; +import java.io.File; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; @@ -1322,9 +1324,20 @@ public class AccountManagerService } } + private static String getDatabaseName() { + if(Environment.isEncryptedFilesystemEnabled()) { + // Hard-coded path in case of encrypted file system + return Environment.getSystemSecureDirectory().getPath() + File.separator + DATABASE_NAME; + } else { + // Regular path in case of non-encrypted file system + return DATABASE_NAME; + } + } + private class DatabaseHelper extends SQLiteOpenHelper { + public DatabaseHelper(Context context) { - super(context, DATABASE_NAME, null, DATABASE_VERSION); + super(context, AccountManagerService.getDatabaseName(), null, DATABASE_VERSION); } @Override diff --git a/core/java/android/app/ApplicationContext.java b/core/java/android/app/ApplicationContext.java index 1e04abf..b3d16e9 100644 --- a/core/java/android/app/ApplicationContext.java +++ b/core/java/android/app/ApplicationContext.java @@ -466,14 +466,7 @@ class ApplicationContext extends Context { @Override public SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory) { - File dir = getDatabasesDir(); - if (!dir.isDirectory() && dir.mkdir()) { - FileUtils.setPermissions(dir.getPath(), - FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH, - -1, -1); - } - - File f = makeFilename(dir, name); + File f = validateFilePath(name, true); SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(f, factory); setFilePermissionsFromMode(f.getPath(), mode, 0); return db; @@ -482,7 +475,7 @@ class ApplicationContext extends Context { @Override public boolean deleteDatabase(String name) { try { - File f = makeFilename(getDatabasesDir(), name); + File f = validateFilePath(name, false); return f.delete(); } catch (Exception e) { } @@ -491,7 +484,7 @@ class ApplicationContext extends Context { @Override public File getDatabasePath(String name) { - return makeFilename(getDatabasesDir(), name); + return validateFilePath(name, false); } @Override @@ -1454,12 +1447,35 @@ class ApplicationContext extends Context { FileUtils.setPermissions(name, perms, -1, -1); } + private File validateFilePath(String name, boolean createDirectory) { + File dir; + File f; + + if (name.charAt(0) == File.separatorChar) { + String dirPath = name.substring(0, name.lastIndexOf(File.separatorChar)); + dir = new File(dirPath); + name = name.substring(name.lastIndexOf(File.separatorChar)); + f = new File(dir, name); + } else { + dir = getDatabasesDir(); + f = makeFilename(dir, name); + } + + if (createDirectory && !dir.isDirectory() && dir.mkdir()) { + FileUtils.setPermissions(dir.getPath(), + FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH, + -1, -1); + } + + return f; + } + private File makeFilename(File base, String name) { if (name.indexOf(File.separatorChar) < 0) { return new File(base, name); } throw new IllegalArgumentException( - "File " + name + " contains a path separator"); + "File " + name + " contains a path separator"); } // ---------------------------------------------------------------------- diff --git a/core/java/android/content/SyncStorageEngine.java b/core/java/android/content/SyncStorageEngine.java index be70909..b6bb7db 100644 --- a/core/java/android/content/SyncStorageEngine.java +++ b/core/java/android/content/SyncStorageEngine.java @@ -16,16 +16,11 @@ package android.content; -import com.android.internal.os.AtomicFile; -import com.android.internal.util.ArrayUtils; -import com.android.internal.util.FastXmlSerializer; - import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; import android.accounts.Account; -import android.backup.IBackupManager; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteException; @@ -37,11 +32,15 @@ import android.os.Message; import android.os.Parcel; import android.os.RemoteCallbackList; import android.os.RemoteException; -import android.os.ServiceManager; +import android.os.SystemProperties; import android.util.Log; import android.util.SparseArray; import android.util.Xml; +import com.android.internal.os.AtomicFile; +import com.android.internal.util.ArrayUtils; +import com.android.internal.util.FastXmlSerializer; + import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; @@ -258,7 +257,9 @@ public class SyncStorageEngine extends Handler { mCal = Calendar.getInstance(TimeZone.getTimeZone("GMT+0")); - File dataDir = Environment.getDataDirectory(); + // This call will return the correct directory whether Encrypted File Systems is + // enabled or not. + File dataDir = Environment.getSecureDataDirectory(); File systemDir = new File(dataDir, "system"); File syncDir = new File(systemDir, "sync"); mAccountInfoFile = new AtomicFile(new File(syncDir, "accounts.xml")); diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java index f761e8e..6212b17 100644 --- a/core/java/android/os/Environment.java +++ b/core/java/android/os/Environment.java @@ -26,6 +26,8 @@ public class Environment { private static final File ROOT_DIRECTORY = getDirectory("ANDROID_ROOT", "/system"); + private static final String SYSTEM_PROPERTY_EFS_ENABLED = "persist.security.efs.enabled"; + /** * Gets the Android root directory. */ @@ -33,9 +35,55 @@ public class Environment { return ROOT_DIRECTORY; } + /** + * Gets the system directory available for secure storage. + * If Encrypted File system is enabled, it returns an encrypted directory (/data/secure/system). + * Otherwise, it returns the unencrypted /data/system directory. + * @return File object representing the secure storage system directory. + * @hide + */ + public static File getSystemSecureDirectory() { + if (isEncryptedFilesystemEnabled()) { + return new File(SECURE_DATA_DIRECTORY, "system"); + } else { + return new File(DATA_DIRECTORY, "system"); + } + } + + /** + * Gets the data directory for secure storage. + * If Encrypted File system is enabled, it returns an encrypted directory (/data/secure). + * Otherwise, it returns the unencrypted /data directory. + * @return File object representing the data directory for secure storage. + * @hide + */ + public static File getSecureDataDirectory() { + if (isEncryptedFilesystemEnabled()) { + return SECURE_DATA_DIRECTORY; + } else { + return DATA_DIRECTORY; + } + } + + /** + * Returns whether the Encrypted File System feature is enabled on the device or not. + * @return <code>true</code> if Encrypted File System feature is enabled, <code>false</code> + * if disabled. + * @hide + */ + public static boolean isEncryptedFilesystemEnabled() { + return SystemProperties.getBoolean(SYSTEM_PROPERTY_EFS_ENABLED, false); + } + private static final File DATA_DIRECTORY = getDirectory("ANDROID_DATA", "/data"); + /** + * @hide + */ + private static final File SECURE_DATA_DIRECTORY + = getDirectory("ANDROID_SECURE_DATA", "/data/secure"); + private static final File EXTERNAL_STORAGE_DIRECTORY = getDirectory("EXTERNAL_STORAGE", "/sdcard"); diff --git a/packages/SettingsProvider/AndroidManifest.xml b/packages/SettingsProvider/AndroidManifest.xml index 1e1d729..a542518 100644 --- a/packages/SettingsProvider/AndroidManifest.xml +++ b/packages/SettingsProvider/AndroidManifest.xml @@ -9,7 +9,8 @@ android:process="system" android:backupAgent="SettingsBackupAgent" android:killAfterRestore="false" - android:icon="@drawable/ic_launcher_settings"> + android:icon="@drawable/ic_launcher_settings" + android:neverEncrypt="true"> <provider android:name="SettingsProvider" android:authorities="settings" android:multiprocess="false" diff --git a/packages/VpnServices/src/com/android/server/vpn/VpnServiceBinder.java b/packages/VpnServices/src/com/android/server/vpn/VpnServiceBinder.java index e5be847..eeafd5a 100644 --- a/packages/VpnServices/src/com/android/server/vpn/VpnServiceBinder.java +++ b/packages/VpnServices/src/com/android/server/vpn/VpnServiceBinder.java @@ -26,7 +26,9 @@ import android.net.vpn.PptpProfile; import android.net.vpn.VpnManager; import android.net.vpn.VpnProfile; import android.net.vpn.VpnState; +import android.os.Environment; import android.os.IBinder; +import android.os.SystemProperties; import android.util.Log; import java.io.File; @@ -45,11 +47,18 @@ public class VpnServiceBinder extends Service { private static final String TAG = VpnServiceBinder.class.getSimpleName(); private static final boolean DBG = true; - private static final String STATES_FILE_PATH = "/data/misc/vpn/.states"; + private static final String STATES_FILE_RELATIVE_PATH = "/misc/vpn/.states"; // The actual implementation is delegated to the VpnService class. private VpnService<? extends VpnProfile> mService; + // TODO(oam): Test VPN when EFS is enabled (will do later)... + private static String getStateFilePath() { + // This call will return the correcu directory whether Encrypted FS is enabled or not + // Disabled: /data/misc/vpn/.states Enabled: /data/secure/misc/vpn/.states + return Environment.getSecureDataDirectory().getPath() + STATES_FILE_RELATIVE_PATH; + } + private final IBinder mBinder = new IVpnService.Stub() { public boolean connect(VpnProfile p, String username, String password) { return VpnServiceBinder.this.connect(p, username, password); @@ -84,14 +93,14 @@ public class VpnServiceBinder extends Service { void saveStates() throws IOException { if (DBG) Log.d("VpnServiceBinder", " saving states"); ObjectOutputStream oos = - new ObjectOutputStream(new FileOutputStream(STATES_FILE_PATH)); + new ObjectOutputStream(new FileOutputStream(getStateFilePath())); oos.writeObject(mService); oos.close(); } void removeStates() { try { - File f = new File(STATES_FILE_PATH); + File f = new File(getStateFilePath()); if (f.exists()) f.delete(); } catch (Throwable e) { if (DBG) Log.d("VpnServiceBinder", " remove states: " + e); @@ -134,7 +143,7 @@ public class VpnServiceBinder extends Service { private void checkSavedStates() { try { ObjectInputStream ois = new ObjectInputStream(new FileInputStream( - STATES_FILE_PATH)); + getStateFilePath())); mService = (VpnService<? extends VpnProfile>) ois.readObject(); mService.recover(this); ois.close(); diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java index c3b591e..1171416 100644 --- a/services/java/com/android/server/BackupManagerService.java +++ b/services/java/com/android/server/BackupManagerService.java @@ -22,6 +22,10 @@ import android.app.IActivityManager; import android.app.IApplicationThread; import android.app.IBackupAgent; import android.app.PendingIntent; +import android.backup.IBackupManager; +import android.backup.IRestoreObserver; +import android.backup.IRestoreSession; +import android.backup.RestoreSet; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; @@ -31,11 +35,10 @@ import android.content.ServiceConnection; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageDataObserver; import android.content.pm.PackageInfo; -import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageManager; import android.content.pm.Signature; +import android.content.pm.PackageManager.NameNotFoundException; import android.net.Uri; -import android.provider.Settings; import android.os.Binder; import android.os.Bundle; import android.os.Environment; @@ -47,20 +50,15 @@ import android.os.PowerManager; import android.os.Process; import android.os.RemoteException; import android.os.SystemClock; +import android.os.SystemProperties; +import android.provider.Settings; import android.util.EventLog; import android.util.Log; import android.util.SparseArray; -import android.backup.IBackupManager; -import android.backup.IRestoreObserver; -import android.backup.IRestoreSession; -import android.backup.RestoreSet; - import com.android.internal.backup.BackupConstants; -import com.android.internal.backup.LocalTransport; import com.android.internal.backup.IBackupTransport; - -import com.android.server.PackageManagerBackupAgent; +import com.android.internal.backup.LocalTransport; import com.android.server.PackageManagerBackupAgent.Metadata; import java.io.EOFException; @@ -70,7 +68,6 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; import java.io.RandomAccessFile; -import java.lang.String; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -232,7 +229,10 @@ class BackupManagerService extends IBackupManager.Stub { Settings.Secure.BACKUP_ENABLED, 0) != 0; mProvisioned = Settings.Secure.getInt(context.getContentResolver(), Settings.Secure.BACKUP_PROVISIONED, 0) != 0; - mBaseStateDir = new File(Environment.getDataDirectory(), "backup"); + // If Encrypted file systems is enabled or disabled, this call will return the + // correct directory. + mBaseStateDir = new File(Environment.getSecureDataDirectory(), "backup"); + mBaseStateDir.mkdirs(); mDataDir = Environment.getDownloadCacheDirectory(); // Alarm receivers for scheduled backups & initialization operations diff --git a/services/java/com/android/server/Installer.java b/services/java/com/android/server/Installer.java index fe3ad15..6a7d432 100644 --- a/services/java/com/android/server/Installer.java +++ b/services/java/com/android/server/Installer.java @@ -166,11 +166,17 @@ class Installer { } } - public int install(String name, int uid, int gid) { + public int install(String name, boolean useEncryptedFilesystem, int uid, int gid) { StringBuilder builder = new StringBuilder("install"); builder.append(' '); builder.append(name); builder.append(' '); + if (useEncryptedFilesystem) { + builder.append('1'); + } else { + builder.append('0'); + } + builder.append(' '); builder.append(uid); builder.append(' '); builder.append(gid); @@ -203,24 +209,42 @@ class Installer { return execute(builder.toString()); } - public int remove(String name) { + public int remove(String name, boolean useEncryptedFilesystem) { StringBuilder builder = new StringBuilder("remove"); builder.append(' '); builder.append(name); + builder.append(' '); + if (useEncryptedFilesystem) { + builder.append('1'); + } else { + builder.append('0'); + } return execute(builder.toString()); } - public int deleteCacheFiles(String name) { + public int deleteCacheFiles(String name, boolean useEncryptedFilesystem) { StringBuilder builder = new StringBuilder("rmcache"); builder.append(' '); builder.append(name); + builder.append(' '); + if (useEncryptedFilesystem) { + builder.append('1'); + } else { + builder.append('0'); + } return execute(builder.toString()); } - public int clearUserData(String name) { + public int clearUserData(String name, boolean useEncryptedFilesystem) { StringBuilder builder = new StringBuilder("rmuserdata"); builder.append(' '); builder.append(name); + builder.append(' '); + if (useEncryptedFilesystem) { + builder.append('1'); + } else { + builder.append('0'); + } return execute(builder.toString()); } @@ -249,7 +273,7 @@ class Installer { } public int getSizeInfo(String pkgName, String apkPath, - String fwdLockApkPath, PackageStats pStats) { + String fwdLockApkPath, PackageStats pStats, boolean useEncryptedFilesystem) { StringBuilder builder = new StringBuilder("getsize"); builder.append(' '); builder.append(pkgName); @@ -257,6 +281,12 @@ class Installer { builder.append(apkPath); builder.append(' '); builder.append(fwdLockApkPath != null ? fwdLockApkPath : "!"); + builder.append(' '); + if (useEncryptedFilesystem) { + builder.append('1'); + } else { + builder.append('0'); + } String s = transaction(builder.toString()); String res[] = s.split(" "); diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java index 5ed2d35..9f01c61 100644 --- a/services/java/com/android/server/PackageManagerService.java +++ b/services/java/com/android/server/PackageManagerService.java @@ -122,6 +122,8 @@ class PackageManagerService extends IPackageManager.Stub { private static final boolean GET_CERTIFICATES = true; + private static final String SYSTEM_PROPERTY_EFS_ENABLED = "persist.security.efs.enabled"; + private static final int REMOVE_EVENTS = FileObserver.CLOSE_WRITE | FileObserver.DELETE | FileObserver.MOVED_FROM; private static final int ADD_EVENTS = @@ -160,6 +162,10 @@ class PackageManagerService extends IPackageManager.Stub { // This is where all application persistent data goes. final File mAppDataDir; + // If Encrypted File System feature is enabled, all application persistent data + // should go here instead. + final File mSecureAppDataDir; + // This is the object monitoring the framework dir. final FileObserver mFrameworkInstallObserver; @@ -422,6 +428,7 @@ class PackageManagerService extends IPackageManager.Stub { File dataDir = Environment.getDataDirectory(); mAppDataDir = new File(dataDir, "data"); + mSecureAppDataDir = new File(dataDir, "secure/data"); mDrmAppPrivateInstallDir = new File(dataDir, "app-private"); if (mInstaller == null) { @@ -431,6 +438,7 @@ class PackageManagerService extends IPackageManager.Stub { File miscDir = new File(dataDir, "misc"); miscDir.mkdirs(); mAppDataDir.mkdirs(); + mSecureAppDataDir.mkdirs(); mDrmAppPrivateInstallDir.mkdirs(); } @@ -573,7 +581,7 @@ class PackageManagerService extends IPackageManager.Stub { mAppInstallDir.mkdirs(); // scanDirLI() assumes this dir exists } //look for any incomplete package installations - ArrayList<String> deletePkgsList = mSettings.getListOfIncompleteInstallPackages(); + ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackages(); //clean up list for(int i = 0; i < deletePkgsList.size(); i++) { //clean up here @@ -628,20 +636,20 @@ class PackageManagerService extends IPackageManager.Stub { } } - void cleanupInstallFailedPackage(String packageName) { + void cleanupInstallFailedPackage(PackageSetting pkgSettings) { if (mInstaller != null) { - int retCode = mInstaller.remove(packageName); + boolean useSecureFS = useEncryptedFilesystemForPackage(pkgSettings.pkg); + int retCode = mInstaller.remove(pkgSettings.name, useSecureFS); if (retCode < 0) { Log.w(TAG, "Couldn't remove app data directory for package: " - + packageName + ", retcode=" + retCode); + + pkgSettings.name + ", retcode=" + retCode); } } else { //for emulator - PackageParser.Package pkg = mPackages.get(packageName); - File dataDir = new File(pkg.applicationInfo.dataDir); + File dataDir = new File(pkgSettings.pkg.applicationInfo.dataDir); dataDir.delete(); } - mSettings.removePackageLP(packageName); + mSettings.removePackageLP(pkgSettings.name); } void readPermissions() { @@ -2155,6 +2163,11 @@ class PackageManagerService extends IPackageManager.Stub { return performed ? DEX_OPT_PERFORMED : DEX_OPT_SKIPPED; } + + private static boolean useEncryptedFilesystemForPackage(PackageParser.Package pkg) { + return Environment.isEncryptedFilesystemEnabled() && + ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_NEVER_ENCRYPT) == 0); + } private PackageParser.Package scanPackageLI( File scanFile, File destCodeFile, File destResourceFile, @@ -2364,8 +2377,9 @@ class PackageManagerService extends IPackageManager.Stub { } if (removeExisting) { + boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(pkg); if (mInstaller != null) { - int ret = mInstaller.remove(pkgName); + int ret = mInstaller.remove(pkgName, useEncryptedFSDir); if (ret != 0) { String msg = "System package " + pkg.packageName + " could not have data directory erased after signature change."; @@ -2395,7 +2409,12 @@ class PackageManagerService extends IPackageManager.Stub { pkg.applicationInfo.dataDir = dataPath.getPath(); } else { // This is a normal package, need to make its data directory. - dataPath = new File(mAppDataDir, pkgName); + boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(pkg); + if (useEncryptedFSDir) { + dataPath = new File(mSecureAppDataDir, pkgName); + } else { + dataPath = new File(mAppDataDir, pkgName); + } if (dataPath.exists()) { mOutPermissions[1] = 0; FileUtils.getPermissions(dataPath.getPath(), mOutPermissions); @@ -2408,7 +2427,7 @@ class PackageManagerService extends IPackageManager.Stub { // If this is a system app, we can at least delete its // current data so the application will still work. if (mInstaller != null) { - int ret = mInstaller.remove(pkgName); + int ret = mInstaller.remove(pkgName, useEncryptedFSDir); if(ret >= 0) { // Old data gone! String msg = "System package " + pkg.packageName @@ -2419,7 +2438,7 @@ class PackageManagerService extends IPackageManager.Stub { recovered = true; // And now re-install the app. - ret = mInstaller.install(pkgName, pkg.applicationInfo.uid, + ret = mInstaller.install(pkgName, useEncryptedFSDir, pkg.applicationInfo.uid, pkg.applicationInfo.uid); if (ret == -1) { // Ack should not happen! @@ -2459,7 +2478,7 @@ class PackageManagerService extends IPackageManager.Stub { Log.v(TAG, "Want this data dir: " + dataPath); //invoke installer to do the actual installation if (mInstaller != null) { - int ret = mInstaller.install(pkgName, pkg.applicationInfo.uid, + int ret = mInstaller.install(pkgName, useEncryptedFSDir, pkg.applicationInfo.uid, pkg.applicationInfo.uid); if(ret < 0) { // Error from installer @@ -3822,7 +3841,13 @@ class PackageManagerService extends IPackageManager.Stub { PackageParser.Package pkg, boolean forwardLocked, boolean newInstall, String installerPackageName, PackageInstalledInfo res) { // Remember this for later, in case we need to rollback this install - boolean dataDirExists = (new File(mAppDataDir, pkgName)).exists(); + boolean dataDirExists; + + if (useEncryptedFilesystemForPackage(pkg)) { + dataDirExists = (new File(mSecureAppDataDir, pkgName)).exists(); + } else { + dataDirExists = (new File(mAppDataDir, pkgName)).exists(); + } res.name = pkgName; synchronized(mPackages) { if (mPackages.containsKey(pkgName) || mAppDirs.containsKey(destFilePath)) { @@ -4552,8 +4577,9 @@ class PackageManagerService extends IPackageManager.Stub { deletedPs = mSettings.mPackages.get(packageName); } if ((flags&PackageManager.DONT_DELETE_DATA) == 0) { + boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(p); if (mInstaller != null) { - int retCode = mInstaller.remove(packageName); + int retCode = mInstaller.remove(packageName, useEncryptedFSDir); if (retCode < 0) { Log.w(TAG, "Couldn't remove app data or cache directory for package: " + packageName + ", retcode=" + retCode); @@ -4795,6 +4821,8 @@ class PackageManagerService extends IPackageManager.Stub { p = ps.pkg; } } + boolean useEncryptedFSDir = false; + if(!dataOnly) { //need to check this only for fully installed applications if (p == null) { @@ -4806,9 +4834,10 @@ class PackageManagerService extends IPackageManager.Stub { Log.w(TAG, "Package " + packageName + " has no applicationInfo."); return false; } + useEncryptedFSDir = useEncryptedFilesystemForPackage(p); } if (mInstaller != null) { - int retCode = mInstaller.clearUserData(packageName); + int retCode = mInstaller.clearUserData(packageName, useEncryptedFSDir); if (retCode < 0) { Log.w(TAG, "Couldn't remove cache files for package: " + packageName); @@ -4859,8 +4888,9 @@ class PackageManagerService extends IPackageManager.Stub { Log.w(TAG, "Package " + packageName + " has no applicationInfo."); return false; } + boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(p); if (mInstaller != null) { - int retCode = mInstaller.deleteCacheFiles(packageName); + int retCode = mInstaller.deleteCacheFiles(packageName, useEncryptedFSDir); if (retCode < 0) { Log.w(TAG, "Couldn't remove cache files for package: " + packageName); @@ -4922,9 +4952,10 @@ class PackageManagerService extends IPackageManager.Stub { } publicSrcDir = isForwardLocked(p) ? applicationInfo.publicSourceDir : null; } + boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(p); if (mInstaller != null) { int res = mInstaller.getSizeInfo(packageName, p.mPath, - publicSrcDir, pStats); + publicSrcDir, pStats, useEncryptedFSDir); if (res < 0) { return false; } else { @@ -6132,11 +6163,18 @@ class PackageManagerService extends IPackageManager.Stub { Settings() { File dataDir = Environment.getDataDirectory(); File systemDir = new File(dataDir, "system"); + // TODO(oam): This secure dir creation needs to be moved somewhere else (later) + File systemSecureDir = new File(dataDir, "secure/system"); systemDir.mkdirs(); + systemSecureDir.mkdirs(); FileUtils.setPermissions(systemDir.toString(), FileUtils.S_IRWXU|FileUtils.S_IRWXG |FileUtils.S_IROTH|FileUtils.S_IXOTH, -1, -1); + FileUtils.setPermissions(systemSecureDir.toString(), + FileUtils.S_IRWXU|FileUtils.S_IRWXG + |FileUtils.S_IROTH|FileUtils.S_IXOTH, + -1, -1); mSettingsFilename = new File(systemDir, "packages.xml"); mBackupSettingsFilename = new File(systemDir, "packages-backup.xml"); } @@ -6807,15 +6845,15 @@ class PackageManagerService extends IPackageManager.Stub { return mReadMessages.toString(); } - ArrayList<String> getListOfIncompleteInstallPackages() { + ArrayList<PackageSetting> getListOfIncompleteInstallPackages() { HashSet<String> kList = new HashSet<String>(mPackages.keySet()); Iterator<String> its = kList.iterator(); - ArrayList<String> ret = new ArrayList<String>(); + ArrayList<PackageSetting> ret = new ArrayList<PackageSetting>(); while(its.hasNext()) { String key = its.next(); PackageSetting ps = mPackages.get(key); if(ps.getInstallStatus() == PKG_INSTALL_INCOMPLETE) { - ret.add(key); + ret.add(ps); } } return ret; diff --git a/vpn/java/android/net/vpn/VpnManager.java b/vpn/java/android/net/vpn/VpnManager.java index 6df612e..311221c 100644 --- a/vpn/java/android/net/vpn/VpnManager.java +++ b/vpn/java/android/net/vpn/VpnManager.java @@ -16,11 +16,15 @@ package android.net.vpn; +import java.io.File; + import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; +import android.os.Environment; +import android.os.SystemProperties; import android.util.Log; /** @@ -65,7 +69,7 @@ public class VpnManager { /** Error code to indicate a successful connection. */ public static final int VPN_ERROR_NO_ERROR = 0; - public static final String PROFILES_PATH = "/data/misc/vpn/profiles"; + private static final String PROFILES_PATH = "/misc/vpn/profiles"; private static final String PACKAGE_PREFIX = VpnManager.class.getPackage().getName() + "."; @@ -77,7 +81,13 @@ public class VpnManager { private static final String ACTION_VPN_SETTINGS = PACKAGE_PREFIX + "SETTINGS"; - private static final String TAG = VpnManager.class.getSimpleName(); + public static final String TAG = VpnManager.class.getSimpleName(); + + // TODO(oam): Test VPN when EFS is enabled (will do later)... + public static String getProfilePath() { + // This call will return the correct path if Encrypted FS is enabled or not. + return Environment.getSecureDataDirectory().getPath() + PROFILES_PATH; + } /** * Returns all supported VPN types. |