am 6ec91731: DO NOT MERGE : Permission fix: don\'t require BACKUP perm for self-restores

* commit '6ec91731cbf6ee1a9a914d341fab9567d1599018':
  DO NOT MERGE : Permission fix: don't require BACKUP perm for self-restores
This commit is contained in:
Chris Tate
2011-01-09 13:04:01 -08:00
committed by Android Git Automerger
4 changed files with 75 additions and 23 deletions

View File

@@ -217,8 +217,7 @@ public final class Bmgr {
// The rest of the 'list' options work with a restore session on the current transport // The rest of the 'list' options work with a restore session on the current transport
try { try {
String curTransport = mBmgr.getCurrentTransport(); mRestore = mBmgr.beginRestoreSession(null, null);
mRestore = mBmgr.beginRestoreSession(curTransport);
if (mRestore == null) { if (mRestore == null) {
System.err.println(BMGR_NOT_RUNNING_ERR); System.err.println(BMGR_NOT_RUNNING_ERR);
return; return;
@@ -349,8 +348,7 @@ public final class Bmgr {
private void doRestorePackage(String pkg) { private void doRestorePackage(String pkg) {
try { try {
String curTransport = mBmgr.getCurrentTransport(); mRestore = mBmgr.beginRestoreSession(pkg, null);
mRestore = mBmgr.beginRestoreSession(curTransport);
if (mRestore == null) { if (mRestore == null) {
System.err.println(BMGR_NOT_RUNNING_ERR); System.err.println(BMGR_NOT_RUNNING_ERR);
return; return;
@@ -378,8 +376,7 @@ public final class Bmgr {
try { try {
boolean didRestore = false; boolean didRestore = false;
String curTransport = mBmgr.getCurrentTransport(); mRestore = mBmgr.beginRestoreSession(null, null);
mRestore = mBmgr.beginRestoreSession(curTransport);
if (mRestore == null) { if (mRestore == null) {
System.err.println(BMGR_NOT_RUNNING_ERR); System.err.println(BMGR_NOT_RUNNING_ERR);
return; return;

View File

@@ -138,8 +138,8 @@ public class BackupManager {
if (sService != null) { if (sService != null) {
RestoreSession session = null; RestoreSession session = null;
try { try {
String transport = sService.getCurrentTransport(); IRestoreSession binder = sService.beginRestoreSession(mContext.getPackageName(),
IRestoreSession binder = sService.beginRestoreSession(transport); null);
session = new RestoreSession(mContext, binder); session = new RestoreSession(mContext, binder);
result = session.restorePackage(mContext.getPackageName(), observer); result = session.restorePackage(mContext.getPackageName(), observer);
} catch (RemoteException e) { } catch (RemoteException e) {
@@ -163,8 +163,8 @@ public class BackupManager {
checkServiceBinder(); checkServiceBinder();
if (sService != null) { if (sService != null) {
try { try {
String transport = sService.getCurrentTransport(); // All packages, current transport
IRestoreSession binder = sService.beginRestoreSession(transport); IRestoreSession binder = sService.beginRestoreSession(null, null);
session = new RestoreSession(mContext, binder); session = new RestoreSession(mContext, binder);
} catch (RemoteException e) { } catch (RemoteException e) {
Log.w(TAG, "beginRestoreSession() couldn't connect"); Log.w(TAG, "beginRestoreSession() couldn't connect");

View File

@@ -144,13 +144,25 @@ interface IBackupManager {
String selectBackupTransport(String transport); String selectBackupTransport(String transport);
/** /**
* Begin a restore session with the given transport (which may differ from the * Begin a restore session. Either or both of packageName and transportID
* currently-active backup transport). * 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. * @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 * Notify the backup manager that a BackupAgent has completed the operation

View File

@@ -2398,15 +2398,45 @@ class BackupManagerService extends IBackupManager.Stub {
} }
// Hand off a restore session // Hand off a restore session
public IRestoreSession beginRestoreSession(String transport) { public IRestoreSession beginRestoreSession(String packageName, String transport) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, "beginRestoreSession"); 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) { synchronized(this) {
if (mActiveRestoreSession != null) { if (mActiveRestoreSession != null) {
Slog.d(TAG, "Restore session requested but one already active"); Slog.d(TAG, "Restore session requested but one already active");
return null; return null;
} }
mActiveRestoreSession = new ActiveRestoreSession(transport); mActiveRestoreSession = new ActiveRestoreSession(packageName, transport);
} }
return mActiveRestoreSession; return mActiveRestoreSession;
} }
@@ -2426,10 +2456,12 @@ class BackupManagerService extends IBackupManager.Stub {
class ActiveRestoreSession extends IRestoreSession.Stub { class ActiveRestoreSession extends IRestoreSession.Stub {
private static final String TAG = "RestoreSession"; private static final String TAG = "RestoreSession";
private String mPackageName;
private IBackupTransport mRestoreTransport = null; private IBackupTransport mRestoreTransport = null;
RestoreSet[] mRestoreSets = null; RestoreSet[] mRestoreSets = null;
ActiveRestoreSession(String transport) { ActiveRestoreSession(String packageName, String transport) {
mPackageName = packageName;
mRestoreTransport = getTransport(transport); mRestoreTransport = getTransport(transport);
} }
@@ -2465,11 +2497,16 @@ class BackupManagerService extends IBackupManager.Stub {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
"performRestore"); "performRestore");
if (DEBUG) Slog.d(TAG, "performRestore token=" + Long.toHexString(token) if (DEBUG) Slog.d(TAG, "restoreAll token=" + Long.toHexString(token)
+ " observer=" + observer); + " observer=" + observer);
if (mRestoreTransport == null || mRestoreSets == null) { 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; return -1;
} }
@@ -2494,6 +2531,14 @@ class BackupManagerService extends IBackupManager.Stub {
public synchronized int restorePackage(String packageName, IRestoreObserver observer) { public synchronized int restorePackage(String packageName, IRestoreObserver observer) {
if (DEBUG) Slog.v(TAG, "restorePackage pkg=" + packageName + " obs=" + 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; PackageInfo app = null;
try { try {
app = mPackageManager.getPackageInfo(packageName, 0); app = mPackageManager.getPackageInfo(packageName, 0);
@@ -2528,6 +2573,7 @@ class BackupManagerService extends IBackupManager.Stub {
// the app has never been backed up from this device -- there's nothing // the app has never been backed up from this device -- there's nothing
// to do but return failure. // to do but return failure.
if (token == 0) { if (token == 0) {
if (DEBUG) Slog.w(TAG, "No data available for this package; not restoring");
return -1; return -1;
} }
@@ -2542,9 +2588,6 @@ class BackupManagerService extends IBackupManager.Stub {
} }
public synchronized void endRestoreSession() { public synchronized void endRestoreSession() {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
"endRestoreSession");
if (DEBUG) Slog.d(TAG, "endRestoreSession"); if (DEBUG) Slog.d(TAG, "endRestoreSession");
synchronized (this) { synchronized (this) {