Validate input for ContentService#setIsSyncable

The syncable parameter value cannot be set to
SYNCABLE_NO_ACCOUNT_ACCESS which is a synthetic state that
is computed but never persisted. It just means that the sync
adapter cannot access the account regardless of its current
syncable state and we want to keep its current syncable state
to start from there once account access is granted.

bug:31794527

Change-Id: I606c4b517977d0b0d3e7ffe753dfd235a875fcd7
This commit is contained in:
Svet Ganov
2016-10-17 19:29:58 -07:00
committed by Svetoslav Ganov
parent c81e1f15d2
commit 96b9c75cec
2 changed files with 19 additions and 3 deletions

View File

@@ -838,7 +838,7 @@ public final class ContentService extends IContentService.Stub {
SyncManager syncManager = getSyncManager(); SyncManager syncManager = getSyncManager();
if (syncManager != null) { if (syncManager != null) {
return syncManager.computeSyncable( return syncManager.computeSyncable(
account, userId, providerName); account, userId, providerName, false);
} }
} finally { } finally {
restoreCallingIdentity(identityToken); restoreCallingIdentity(identityToken);
@@ -854,6 +854,8 @@ public final class ContentService extends IContentService.Stub {
mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS, mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS,
"no permission to write the sync settings"); "no permission to write the sync settings");
syncable = normalizeSyncable(syncable);
int userId = UserHandle.getCallingUserId(); int userId = UserHandle.getCallingUserId();
long identityToken = clearCallingIdentity(); long identityToken = clearCallingIdentity();
try { try {
@@ -1156,6 +1158,15 @@ public final class ContentService extends IContentService.Stub {
} }
} }
private static int normalizeSyncable(int syncable) {
if (syncable > 0) {
return SyncStorageEngine.AuthorityInfo.SYNCABLE;
} else if (syncable == 0) {
return SyncStorageEngine.AuthorityInfo.NOT_SYNCABLE;
}
return SyncStorageEngine.AuthorityInfo.UNDEFINED;
}
/** /**
* Hide this class since it is not part of api, * Hide this class since it is not part of api,
* but current unittest framework requires it to be public * but current unittest framework requires it to be public

View File

@@ -1001,7 +1001,12 @@ public class SyncManager {
} }
} }
public int computeSyncable(Account account, int userId, String authority) { private int computeSyncable(Account account, int userId, String authority) {
return computeSyncable(account, userId, authority, true);
}
public int computeSyncable(Account account, int userId, String authority,
boolean checkAccountAccess) {
final int status = getIsSyncable(account, userId, authority); final int status = getIsSyncable(account, userId, authority);
if (status == AuthorityInfo.NOT_SYNCABLE) { if (status == AuthorityInfo.NOT_SYNCABLE) {
return AuthorityInfo.NOT_SYNCABLE; return AuthorityInfo.NOT_SYNCABLE;
@@ -1025,7 +1030,7 @@ public class SyncManager {
} catch (RemoteException e) { } catch (RemoteException e) {
/* ignore - local call */ /* ignore - local call */
} }
if (!canAccessAccount(account, owningPackage, owningUid)) { if (checkAccountAccess && !canAccessAccount(account, owningPackage, owningUid)) {
Log.w(TAG, "Access to " + account + " denied for package " Log.w(TAG, "Access to " + account + " denied for package "
+ owningPackage + " in UID " + syncAdapterInfo.uid); + owningPackage + " in UID " + syncAdapterInfo.uid);
return AuthorityInfo.SYNCABLE_NO_ACCOUNT_ACCESS; return AuthorityInfo.SYNCABLE_NO_ACCOUNT_ACCESS;