diff options
author | Nick Kralevich <nnk@google.com> | 2012-12-12 16:24:31 -0800 |
---|---|---|
committer | Nick Kralevich <nnk@google.com> | 2012-12-14 11:53:10 -0800 |
commit | 92091fa9636403728fe94cc83400495a8612c2d3 (patch) | |
tree | d1a0969ae2cd2bcddd5a0d2dfc2be100a732bd85 | |
parent | 40efbd40606fc31863d3de90f062db431ba7fb47 (diff) | |
download | frameworks_base-92091fa9636403728fe94cc83400495a8612c2d3.zip frameworks_base-92091fa9636403728fe94cc83400495a8612c2d3.tar.gz frameworks_base-92091fa9636403728fe94cc83400495a8612c2d3.tar.bz2 |
App home directories are now 0700 for targetSdkVersion > 17
Pass targetSdkVersion to installd so it knows the appropriate
permissions to apply to the app's home directory.
Bug: 7208882
Change-Id: Ia62ed36b32ee5af01077fb10a586024411be8ed4
-rw-r--r-- | api/current.txt | 1 | ||||
-rw-r--r-- | core/java/android/content/Context.java | 96 | ||||
-rw-r--r-- | core/java/android/os/Build.java | 11 | ||||
-rw-r--r-- | services/java/com/android/server/pm/Installer.java | 18 | ||||
-rw-r--r-- | services/java/com/android/server/pm/PackageManagerService.java | 19 | ||||
-rw-r--r-- | services/java/com/android/server/pm/Settings.java | 6 |
6 files changed, 106 insertions, 45 deletions
diff --git a/api/current.txt b/api/current.txt index 57d65ba..28344b5 100644 --- a/api/current.txt +++ b/api/current.txt @@ -15737,6 +15737,7 @@ package android.os { field public static final int ICE_CREAM_SANDWICH_MR1 = 15; // 0xf field public static final int JELLY_BEAN = 16; // 0x10 field public static final int JELLY_BEAN_MR1 = 17; // 0x11 + field public static final int K = 10000; // 0x2710 } public final class Bundle implements java.lang.Cloneable android.os.Parcelable { diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 7aa2507..257f84e 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -64,30 +64,44 @@ public abstract class Context { */ public static final int MODE_PRIVATE = 0x0000; /** - * @deprecated Creating world-readable files is very dangerous, and likely - * to cause security holes in applications. It is strongly discouraged; - * instead, applications should use more formal mechanism for interactions - * such as {@link ContentProvider}, {@link BroadcastReceiver}, and - * {@link android.app.Service}. There are no guarantees that this - * access mode will remain on a file, such as when it goes through a - * backup and restore. * File creation mode: allow all other applications to have read access * to the created file. + * + * <b>Note:</b> Applications with {@code targetSdkVersion} + * {@link android.os.Build.VERSION_CODES#K} or greater have home directories + * with {@code 0700} permissions. Because an application's home directory + * is no longer world-accessible, world-readable files created within the + * application's home directory will not be accessible to other applications. + * + * @deprecated Creating world-readable files is very dangerous, and likely + * to cause security holes in applications. It is strongly discouraged; + * instead, applications should use more formal mechanism for interactions + * such as {@link ContentProvider}, {@link BroadcastReceiver}, and + * {@link android.app.Service}. There are no guarantees that this + * access mode will remain on a file, such as when it goes through a + * backup and restore. * @see #MODE_PRIVATE * @see #MODE_WORLD_WRITEABLE */ @Deprecated public static final int MODE_WORLD_READABLE = 0x0001; /** - * @deprecated Creating world-writable files is very dangerous, and likely - * to cause security holes in applications. It is strongly discouraged; - * instead, applications should use more formal mechanism for interactions - * such as {@link ContentProvider}, {@link BroadcastReceiver}, and - * {@link android.app.Service}. There are no guarantees that this - * access mode will remain on a file, such as when it goes through a - * backup and restore. * File creation mode: allow all other applications to have write access * to the created file. + * + * <b>Note:</b> Applications with {@code targetSdkVersion} + * {@link android.os.Build.VERSION_CODES#K} or greater have home directories + * with {@code 0700} permissions. Because an application's home directory + * is no longer world-accessible, world-writable files created within the + * application's home directory will not be accessible to other applications. + * + * @deprecated Creating world-writable files is very dangerous, and likely + * to cause security holes in applications. It is strongly discouraged; + * instead, applications should use more formal mechanism for interactions + * such as {@link ContentProvider}, {@link BroadcastReceiver}, and + * {@link android.app.Service}. There are no guarantees that this + * access mode will remain on a file, such as when it goes through a + * backup and restore. * @see #MODE_PRIVATE * @see #MODE_WORLD_READABLE */ @@ -501,18 +515,22 @@ public abstract class Context { throws FileNotFoundException; /** - * Open a private file associated with this Context's application package + * Open a file associated with this Context's application package * for writing. Creates the file if it doesn't already exist. * - * @param name The name of the file to open; can not contain path - * separators. - * @param mode Operating mode. Use 0 or {@link #MODE_PRIVATE} for the - * default operation, {@link #MODE_APPEND} to append to an existing file, - * {@link #MODE_WORLD_READABLE} and {@link #MODE_WORLD_WRITEABLE} to control - * permissions. + * <b>Note:</b> Applications with {@code targetSdkVersion} + * {@link android.os.Build.VERSION_CODES#K} or greater have home directories + * with {@code 0700} permissions. Because an application's home directory + * is no longer world-accessible, files created with {@code mode} + * {@link #MODE_WORLD_READABLE} or {@link #MODE_WORLD_WRITEABLE} will not be + * accessible to other applications. * + * @param name The name of the file to open; can not contain path separators. + * @param mode Operating mode. Use 0 or {@link #MODE_PRIVATE} for the + * default operation, {@link #MODE_APPEND} to append to an existing file, + * {@link #MODE_WORLD_READABLE} and {@link #MODE_WORLD_WRITEABLE} to control + * permissions. * @return FileOutputStream Resulting output stream. - * * @see #MODE_APPEND * @see #MODE_PRIVATE * @see #MODE_WORLD_READABLE @@ -738,14 +756,19 @@ public abstract class Context { * application; you can only set the mode of the entire directory, not * of individual files. * + * <b>Note:</b> Applications with {@code targetSdkVersion} + * {@link android.os.Build.VERSION_CODES#K} or greater have home directories + * with {@code 0700} permissions. Because an application's home directory + * is no longer world-accessible, world-readable / world-writable directories + * created using this method will not be accessible to other applications. + * * @param name Name of the directory to retrieve. This is a directory - * that is created as part of your application data. + * that is created as part of your application data. * @param mode Operating mode. Use 0 or {@link #MODE_PRIVATE} for the - * default operation, {@link #MODE_WORLD_READABLE} and - * {@link #MODE_WORLD_WRITEABLE} to control permissions. - * + * default operation, {@link #MODE_WORLD_READABLE} and + * {@link #MODE_WORLD_WRITEABLE} to control permissions. * @return Returns a File object for the requested directory. The directory - * will have been created if it does not already exist. + * will have been created if it does not already exist. * * @see #openFileOutput(String, int) */ @@ -755,6 +778,13 @@ public abstract class Context { * Open a new private SQLiteDatabase associated with this Context's * application package. Create the database file if it doesn't exist. * + * <b>Note:</b> Applications with {@code targetSdkVersion} + * {@link android.os.Build.VERSION_CODES#K} or greater have home directories + * with {@code 0700} permissions. Because an application's home directory + * is no longer world-accessible, {@code SQLiteDatabase}s created with {@code mode} + * {@link #MODE_WORLD_READABLE} or {@link #MODE_WORLD_WRITEABLE} will not be + * accessible to other applications. + * * @param name The name (unique in the application package) of the database. * @param mode Operating mode. Use 0 or {@link #MODE_PRIVATE} for the * default operation, {@link #MODE_WORLD_READABLE} @@ -762,10 +792,8 @@ public abstract class Context { * Use {@link #MODE_ENABLE_WRITE_AHEAD_LOGGING} to enable write-ahead logging by default. * @param factory An optional factory class that is called to instantiate a * cursor when query is called. - * * @return The contents of a newly created database with the given name. * @throws android.database.sqlite.SQLiteException if the database file could not be opened. - * * @see #MODE_PRIVATE * @see #MODE_WORLD_READABLE * @see #MODE_WORLD_WRITEABLE @@ -782,6 +810,13 @@ public abstract class Context { * <p>Accepts input param: a concrete instance of {@link DatabaseErrorHandler} to be * used to handle corruption when sqlite reports database corruption.</p> * + * <b>Note:</b> Applications with {@code targetSdkVersion} + * {@link android.os.Build.VERSION_CODES#K} or greater have home directories + * with {@code 0700} permissions. Because an application's home directory + * is no longer world-accessible, {@code SQLiteDatabase}s created with {@code mode} + * {@link #MODE_WORLD_READABLE} or {@link #MODE_WORLD_WRITEABLE} will not be + * accessible to other applications. + * * @param name The name (unique in the application package) of the database. * @param mode Operating mode. Use 0 or {@link #MODE_PRIVATE} for the * default operation, {@link #MODE_WORLD_READABLE} @@ -790,10 +825,9 @@ public abstract class Context { * @param factory An optional factory class that is called to instantiate a * cursor when query is called. * @param errorHandler the {@link DatabaseErrorHandler} to be used when sqlite reports database - * corruption. if null, {@link android.database.DefaultDatabaseErrorHandler} is assumed. + * corruption. if null, {@link android.database.DefaultDatabaseErrorHandler} is assumed. * @return The contents of a newly created database with the given name. * @throws android.database.sqlite.SQLiteException if the database file could not be opened. - * * @see #MODE_PRIVATE * @see #MODE_WORLD_READABLE * @see #MODE_WORLD_WRITEABLE diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java index a7f39d5..d69d2a6 100644 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -431,6 +431,17 @@ public class Build { * </ul> */ public static final int JELLY_BEAN_MR1 = 17; + + /** + * Android X.X: "K". Just "K" + * + * <p>Applications targeting this or a later release will get these + * new changes in behavior:</p> + * <ul> + * <li>Application home directory permissions are now {@code 0700}.</li> + * </ul> + */ + public static final int K = CUR_DEVELOPMENT; } /** The type of build, like "user" or "eng". */ diff --git a/services/java/com/android/server/pm/Installer.java b/services/java/com/android/server/pm/Installer.java index 02a2c1b..e96820f 100644 --- a/services/java/com/android/server/pm/Installer.java +++ b/services/java/com/android/server/pm/Installer.java @@ -188,7 +188,12 @@ public final class Installer { } } - public int install(String name, int uid, int gid) { + /** + * @param restrictHomeDir if {@code true}, installd will create the application's + * home directory with {@code 0700} permissions. If false, {@code 0751} will + * be used instead. + */ + public int install(String name, int uid, int gid, boolean restrictHomeDir) { StringBuilder builder = new StringBuilder("install"); builder.append(' '); builder.append(name); @@ -196,6 +201,8 @@ public final class Installer { builder.append(uid); builder.append(' '); builder.append(gid); + builder.append(' '); + builder.append(restrictHomeDir); return execute(builder.toString()); } @@ -263,7 +270,12 @@ public final class Installer { return execute(builder.toString()); } - public int createUserData(String name, int uid, int userId) { + /** + * @param restrictHomeDir if {@code true}, installd will create the application's + * home directory with {@code 0700} permissions. If false, {@code 0751} will + * be used instead. + */ + public int createUserData(String name, int uid, int userId, boolean restrictHomeDir) { StringBuilder builder = new StringBuilder("mkuserdata"); builder.append(' '); builder.append(name); @@ -271,6 +283,8 @@ public final class Installer { builder.append(uid); builder.append(' '); builder.append(userId); + builder.append(' '); + builder.append(restrictHomeDir); 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 2238f17..aa2b461 100644 --- a/services/java/com/android/server/pm/PackageManagerService.java +++ b/services/java/com/android/server/pm/PackageManagerService.java @@ -24,7 +24,6 @@ import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED; import static com.android.internal.util.ArrayUtils.appendInt; import static com.android.internal.util.ArrayUtils.removeInt; -import static libcore.io.OsConstants.S_ISLNK; import static libcore.io.OsConstants.S_IRWXU; import static libcore.io.OsConstants.S_IRGRP; import static libcore.io.OsConstants.S_IXGRP; @@ -111,7 +110,6 @@ import android.os.SystemClock; import android.os.SystemProperties; import android.os.UserHandle; import android.os.Environment.UserEnvironment; -import android.provider.Settings.Secure; import android.security.SystemKeyStore; import android.util.DisplayMetrics; import android.util.EventLog; @@ -148,13 +146,11 @@ import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.Map.Entry; import java.util.Set; import libcore.io.ErrnoException; import libcore.io.IoUtils; import libcore.io.Libcore; -import libcore.io.OsConstants; import libcore.io.StructStat; /** @@ -3582,16 +3578,17 @@ public class PackageManagerService extends IPackageManager.Stub { } } - private int createDataDirsLI(String packageName, int uid) { + private int createDataDirsLI(String packageName, int uid, int targetSdkVersion) { int[] users = sUserManager.getUserIds(); - int res = mInstaller.install(packageName, uid, uid); + boolean restrictHomeDir = (targetSdkVersion >= Build.VERSION_CODES.K); + int res = mInstaller.install(packageName, uid, uid, restrictHomeDir); if (res < 0) { return res; } for (int user : users) { if (user != 0) { res = mInstaller.createUserData(packageName, - UserHandle.getUid(user, uid), user); + UserHandle.getUid(user, uid), user, restrictHomeDir); if (res < 0) { return res; } @@ -3985,7 +3982,8 @@ public class PackageManagerService extends IPackageManager.Stub { recovered = true; // And now re-install the app. - ret = createDataDirsLI(pkgName, pkg.applicationInfo.uid); + ret = createDataDirsLI(pkgName, pkg.applicationInfo.uid, + pkg.applicationInfo.targetSdkVersion); if (ret == -1) { // Ack should not happen! msg = prefix + pkg.packageName @@ -4030,8 +4028,9 @@ public class PackageManagerService extends IPackageManager.Stub { if ((parseFlags & PackageParser.PARSE_CHATTY) != 0) Log.v(TAG, "Want this data dir: " + dataPath); } - //invoke installer to do the actual installation - int ret = createDataDirsLI(pkgName, pkg.applicationInfo.uid); + // invoke installer to do the actual installation + int ret = createDataDirsLI(pkgName, pkg.applicationInfo.uid, + pkg.applicationInfo.targetSdkVersion); if (ret < 0) { // Error from installer mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; diff --git a/services/java/com/android/server/pm/Settings.java b/services/java/com/android/server/pm/Settings.java index 06f11bc..f791a6e 100644 --- a/services/java/com/android/server/pm/Settings.java +++ b/services/java/com/android/server/pm/Settings.java @@ -25,7 +25,6 @@ import static android.Manifest.permission.READ_EXTERNAL_STORAGE; import com.android.internal.util.FastXmlSerializer; import com.android.internal.util.JournaledFile; import com.android.internal.util.XmlUtils; -import com.android.server.IntentResolver; import com.android.server.pm.PackageManagerService.DumpState; import org.xmlpull.v1.XmlPullParser; @@ -46,6 +45,7 @@ import android.content.pm.UserInfo; import android.content.pm.PackageUserState; import android.content.pm.VerifierDeviceIdentity; import android.os.Binder; +import android.os.Build; import android.os.Environment; import android.os.FileUtils; import android.os.Process; @@ -2335,9 +2335,11 @@ final class Settings { for (PackageSetting ps : mPackages.values()) { // Only system apps are initially installed. ps.setInstalled((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0, userHandle); + boolean restrictHomeDir = (ps.pkg.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.K); // Need to create a data directory for all apps under this user. installer.createUserData(ps.name, - UserHandle.getUid(userHandle, ps.appId), userHandle); + UserHandle.getUid(userHandle, ps.appId), userHandle, + restrictHomeDir); } readDefaultPreferredAppsLPw(userHandle); writePackageRestrictionsLPr(userHandle); |