From 96b9c75cec453cd0228c5993bd691b7d5783bc7d Mon Sep 17 00:00:00 2001 From: Svet Ganov Date: Mon, 17 Oct 2016 19:29:58 -0700 Subject: [PATCH] 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 --- .../com/android/server/content/ContentService.java | 13 ++++++++++++- .../com/android/server/content/SyncManager.java | 9 +++++++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java index 4e236d164a69f..07276298d66d8 100644 --- a/services/core/java/com/android/server/content/ContentService.java +++ b/services/core/java/com/android/server/content/ContentService.java @@ -838,7 +838,7 @@ public final class ContentService extends IContentService.Stub { SyncManager syncManager = getSyncManager(); if (syncManager != null) { return syncManager.computeSyncable( - account, userId, providerName); + account, userId, providerName, false); } } finally { restoreCallingIdentity(identityToken); @@ -854,6 +854,8 @@ public final class ContentService extends IContentService.Stub { mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS, "no permission to write the sync settings"); + syncable = normalizeSyncable(syncable); + int userId = UserHandle.getCallingUserId(); long identityToken = clearCallingIdentity(); 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, * but current unittest framework requires it to be public diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java index 131da0bc9d663..653d2410f8007 100644 --- a/services/core/java/com/android/server/content/SyncManager.java +++ b/services/core/java/com/android/server/content/SyncManager.java @@ -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); if (status == AuthorityInfo.NOT_SYNCABLE) { return AuthorityInfo.NOT_SYNCABLE; @@ -1025,7 +1030,7 @@ public class SyncManager { } catch (RemoteException e) { /* ignore - local call */ } - if (!canAccessAccount(account, owningPackage, owningUid)) { + if (checkAccountAccess && !canAccessAccount(account, owningPackage, owningUid)) { Log.w(TAG, "Access to " + account + " denied for package " + owningPackage + " in UID " + syncAdapterInfo.uid); return AuthorityInfo.SYNCABLE_NO_ACCOUNT_ACCESS;