diff options
author | Chris Tate <ctate@google.com> | 2010-11-16 18:44:06 -0800 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2010-11-16 18:44:06 -0800 |
commit | 0de1ed5bdf6f9603673632fa880dccd3b8ca1f97 (patch) | |
tree | 715bcdd7fc179f0290f7cdbb4dce8382c14340a8 | |
parent | 68f0a32d103d3861103bce3763b222bde99c0a4c (diff) | |
parent | 44ab8453e1c4c46790f792a46d026fa1017d8cfe (diff) | |
download | frameworks_base-0de1ed5bdf6f9603673632fa880dccd3b8ca1f97.zip frameworks_base-0de1ed5bdf6f9603673632fa880dccd3b8ca1f97.tar.gz frameworks_base-0de1ed5bdf6f9603673632fa880dccd3b8ca1f97.tar.bz2 |
Merge "Permission fix: don't require BACKUP perm for self-restores"
4 files changed, 75 insertions, 23 deletions
diff --git a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java index b5fddfa..ac0e410 100644 --- a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java +++ b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java @@ -217,8 +217,7 @@ public final class Bmgr { // The rest of the 'list' options work with a restore session on the current transport try { - String curTransport = mBmgr.getCurrentTransport(); - mRestore = mBmgr.beginRestoreSession(curTransport); + mRestore = mBmgr.beginRestoreSession(null, null); if (mRestore == null) { System.err.println(BMGR_NOT_RUNNING_ERR); return; @@ -349,8 +348,7 @@ public final class Bmgr { private void doRestorePackage(String pkg) { try { - String curTransport = mBmgr.getCurrentTransport(); - mRestore = mBmgr.beginRestoreSession(curTransport); + mRestore = mBmgr.beginRestoreSession(pkg, null); if (mRestore == null) { System.err.println(BMGR_NOT_RUNNING_ERR); return; @@ -378,8 +376,7 @@ public final class Bmgr { try { boolean didRestore = false; - String curTransport = mBmgr.getCurrentTransport(); - mRestore = mBmgr.beginRestoreSession(curTransport); + mRestore = mBmgr.beginRestoreSession(null, null); if (mRestore == null) { System.err.println(BMGR_NOT_RUNNING_ERR); return; diff --git a/core/java/android/app/backup/BackupManager.java b/core/java/android/app/backup/BackupManager.java index 52dd707..80656a1 100644 --- a/core/java/android/app/backup/BackupManager.java +++ b/core/java/android/app/backup/BackupManager.java @@ -138,8 +138,8 @@ public class BackupManager { if (sService != null) { RestoreSession session = null; try { - String transport = sService.getCurrentTransport(); - IRestoreSession binder = sService.beginRestoreSession(transport); + IRestoreSession binder = sService.beginRestoreSession(mContext.getPackageName(), + null); session = new RestoreSession(mContext, binder); result = session.restorePackage(mContext.getPackageName(), observer); } catch (RemoteException e) { @@ -163,8 +163,8 @@ public class BackupManager { checkServiceBinder(); if (sService != null) { try { - String transport = sService.getCurrentTransport(); - IRestoreSession binder = sService.beginRestoreSession(transport); + // All packages, current transport + IRestoreSession binder = sService.beginRestoreSession(null, null); session = new RestoreSession(mContext, binder); } catch (RemoteException e) { Log.w(TAG, "beginRestoreSession() couldn't connect"); diff --git a/core/java/android/app/backup/IBackupManager.aidl b/core/java/android/app/backup/IBackupManager.aidl index 23d6351..8af59df 100644 --- a/core/java/android/app/backup/IBackupManager.aidl +++ b/core/java/android/app/backup/IBackupManager.aidl @@ -144,13 +144,25 @@ interface IBackupManager { String selectBackupTransport(String transport); /** - * Begin a restore session with the given transport (which may differ from the - * currently-active backup transport). + * Begin a restore session. Either or both of packageName and transportID + * may be null. If packageName is non-null, then only the given package will be + * considered for restore. If transportID is null, then the restore will use + * the current active transport. + * <p> + * This method requires the android.permission.BACKUP permission <i>except</i> + * when transportID is null and packageName is the name of the caller's own + * package. In that case, the restore session returned is suitable for supporting + * the BackupManager.requestRestore() functionality via RestoreSession.restorePackage() + * without requiring the app to hold any special permission. * - * @param transport The name of the transport to use for the restore operation. + * @param packageName The name of the single package for which a restore will + * be requested. May be null, in which case all packages in the restore + * set can be restored. + * @param transportID The name of the transport to use for the restore operation. + * May be null, in which case the current active transport is used. * @return An interface to the restore session, or null on error. */ - IRestoreSession beginRestoreSession(String transportID); + IRestoreSession beginRestoreSession(String packageName, String transportID); /** * Notify the backup manager that a BackupAgent has completed the operation diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java index 6a86076..bebd013 100644 --- a/services/java/com/android/server/BackupManagerService.java +++ b/services/java/com/android/server/BackupManagerService.java @@ -2399,15 +2399,45 @@ class BackupManagerService extends IBackupManager.Stub { } // Hand off a restore session - public IRestoreSession beginRestoreSession(String transport) { - mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, "beginRestoreSession"); + public IRestoreSession beginRestoreSession(String packageName, String transport) { + if (DEBUG) Slog.v(TAG, "beginRestoreSession: pkg=" + packageName + + " transport=" + transport); + + boolean needPermission = true; + if (transport == null) { + transport = mCurrentTransport; + + if (packageName != null) { + PackageInfo app = null; + try { + app = mPackageManager.getPackageInfo(packageName, 0); + } catch (NameNotFoundException nnf) { + Slog.w(TAG, "Asked to restore nonexistent pkg " + packageName); + throw new IllegalArgumentException("Package " + packageName + " not found"); + } + + if (app.applicationInfo.uid == Binder.getCallingUid()) { + // So: using the current active transport, and the caller has asked + // that its own package will be restored. In this narrow use case + // we do not require the caller to hold the permission. + needPermission = false; + } + } + } + + if (needPermission) { + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, + "beginRestoreSession"); + } else { + if (DEBUG) Slog.d(TAG, "restoring self on current transport; no permission needed"); + } synchronized(this) { if (mActiveRestoreSession != null) { Slog.d(TAG, "Restore session requested but one already active"); return null; } - mActiveRestoreSession = new ActiveRestoreSession(transport); + mActiveRestoreSession = new ActiveRestoreSession(packageName, transport); } return mActiveRestoreSession; } @@ -2427,10 +2457,12 @@ class BackupManagerService extends IBackupManager.Stub { class ActiveRestoreSession extends IRestoreSession.Stub { private static final String TAG = "RestoreSession"; + private String mPackageName; private IBackupTransport mRestoreTransport = null; RestoreSet[] mRestoreSets = null; - ActiveRestoreSession(String transport) { + ActiveRestoreSession(String packageName, String transport) { + mPackageName = packageName; mRestoreTransport = getTransport(transport); } @@ -2466,11 +2498,16 @@ class BackupManagerService extends IBackupManager.Stub { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, "performRestore"); - if (DEBUG) Slog.d(TAG, "performRestore token=" + Long.toHexString(token) + if (DEBUG) Slog.d(TAG, "restoreAll token=" + Long.toHexString(token) + " observer=" + observer); if (mRestoreTransport == null || mRestoreSets == null) { - Slog.e(TAG, "Ignoring performRestore() with no restore set"); + Slog.e(TAG, "Ignoring restoreAll() with no restore set"); + return -1; + } + + if (mPackageName != null) { + Slog.e(TAG, "Ignoring restoreAll() on single-package session"); return -1; } @@ -2495,6 +2532,14 @@ class BackupManagerService extends IBackupManager.Stub { public synchronized int restorePackage(String packageName, IRestoreObserver observer) { if (DEBUG) Slog.v(TAG, "restorePackage pkg=" + packageName + " obs=" + observer); + if (mPackageName != null) { + if (! mPackageName.equals(packageName)) { + Slog.e(TAG, "Ignoring attempt to restore pkg=" + packageName + + " on session for package " + mPackageName); + return -1; + } + } + PackageInfo app = null; try { app = mPackageManager.getPackageInfo(packageName, 0); @@ -2529,6 +2574,7 @@ class BackupManagerService extends IBackupManager.Stub { // the app has never been backed up from this device -- there's nothing // to do but return failure. if (token == 0) { + if (DEBUG) Slog.w(TAG, "No data available for this package; not restoring"); return -1; } @@ -2543,9 +2589,6 @@ class BackupManagerService extends IBackupManager.Stub { } public synchronized void endRestoreSession() { - mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, - "endRestoreSession"); - if (DEBUG) Slog.d(TAG, "endRestoreSession"); synchronized (this) { |