White-list grandfathered sync adapters

Sync adapters were able to access the synced account without the accounts
permission which circumvents our permission model. Therefore, we require
sync adapters that don't have access to the account to get user consent.
This can be noisy, therefore we will white-list sync adapters installed
before we started checking for account access because they already know
the account (they run before) which is the genie is out of the bottle.

bug:31162498

Change-Id: I815e521778892ec592d53d086273743f1711bd17
This commit is contained in:
Svet Ganov
2016-09-01 10:24:11 -07:00
committed by Svetoslav Ganov
parent 57bd22ffc1
commit 65712b0ad3
2 changed files with 43 additions and 1 deletions

View File

@@ -645,6 +645,37 @@ public class SyncManager {
mContext.startService(startServiceIntent);
}
});
// Sync adapters were able to access the synced account without the accounts
// permission which circumvents our permission model. Therefore, we require
// sync adapters that don't have access to the account to get user consent.
// This can be noisy, therefore we will white-list sync adapters installed
// before we started checking for account access because they already know
// the account (they run before) which is the genie is out of the bottle.
whiteListExistingSyncAdaptersIfNeeded();
}
private void whiteListExistingSyncAdaptersIfNeeded() {
if (!mSyncStorageEngine.shouldGrantSyncAdaptersAccountAccess()) {
return;
}
List<UserInfo> users = mUserManager.getUsers(true);
final int userCount = users.size();
for (int i = 0; i < userCount; i++) {
UserHandle userHandle = users.get(i).getUserHandle();
final int userId = userHandle.getIdentifier();
for (RegisteredServicesCache.ServiceInfo<SyncAdapterType> service
: mSyncAdapters.getAllServices(userId)) {
String packageName = service.componentName.getPackageName();
for (Account account : mAccountManager.getAccountsByTypeAsUser(
service.type.accountType, userHandle)) {
if (!canAccessAccount(account, packageName, userId)) {
mAccountManager.updateAppPermission(account,
AccountManager.ACCOUNT_ACCESS_TOKEN, service.uid, true);
}
}
}
}
}
private boolean isDeviceProvisioned() {

View File

@@ -137,7 +137,7 @@ public class SyncStorageEngine extends Handler {
private static final boolean SYNC_ENABLED_DEFAULT = false;
// the version of the accounts xml file format
private static final int ACCOUNTS_VERSION = 2;
private static final int ACCOUNTS_VERSION = 3;
private static HashMap<String, String> sAuthorityRenames;
private static PeriodicSyncAddedListener mPeriodicSyncAddedListener;
@@ -408,6 +408,8 @@ public class SyncStorageEngine extends Handler {
private OnSyncRequestListener mSyncRequestListener;
private OnAuthorityRemovedListener mAuthorityRemovedListener;
private boolean mGrantSyncAdaptersAccountAccess;
private SyncStorageEngine(Context context, File dataDir) {
mContext = context;
sSyncStorageEngine = this;
@@ -1410,6 +1412,10 @@ public class SyncStorageEngine extends Handler {
}
}
public boolean shouldGrantSyncAdaptersAccountAccess() {
return mGrantSyncAdaptersAccountAccess;
}
/**
* public for testing
*/
@@ -1464,6 +1470,11 @@ public class SyncStorageEngine extends Handler {
} catch (NumberFormatException e) {
version = 0;
}
if (version < 3) {
mGrantSyncAdaptersAccountAccess = true;
}
String nextIdString = parser.getAttributeValue(null, XML_ATTR_NEXT_AUTHORITY_ID);
try {
int id = (nextIdString == null) ? 0 : Integer.parseInt(nextIdString);