Skip to content

Commit 034fe7c

Browse files
authored
Merge commit from fork
The behavior of the official provider has changed overtime, especially with how it limits read access to android_id. We replicate this behavior here.
1 parent 37388d5 commit 034fe7c

1 file changed

Lines changed: 74 additions & 7 deletions

File tree

‎play-services-core/src/main/java/org/microg/gms/gservices/GServicesProvider.java‎

Lines changed: 74 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,29 @@
1616

1717
package org.microg.gms.gservices;
1818

19+
import static android.os.Build.VERSION.SDK_INT;
20+
21+
import android.app.admin.DevicePolicyManager;
1922
import android.content.ContentProvider;
2023
import android.content.ContentValues;
24+
import android.content.pm.PackageManager;
2125
import android.database.Cursor;
2226
import android.database.MatrixCursor;
2327
import android.net.Uri;
28+
import android.os.Binder;
29+
import android.os.Process;
2430
import android.util.Log;
2531

32+
import androidx.core.content.ContextCompat;
33+
34+
import java.util.Arrays;
2635
import java.util.HashMap;
2736
import java.util.HashSet;
2837
import java.util.Iterator;
2938
import java.util.Map;
3039
import java.util.Set;
3140

32-
import static android.os.Build.VERSION.SDK_INT;
41+
import org.microg.gms.utils.ExtendedPackageInfo;
3342

3443
/**
3544
* Originally found in Google Services Framework (com.google.android.gsf), this provides a generic
@@ -56,16 +65,61 @@ public boolean onCreate() {
5665
return true;
5766
}
5867

59-
private String getCallingPackageName() {
60-
if (SDK_INT >= 19) {
61-
return getCallingPackage();
62-
} else {
63-
return "unknown";
68+
private boolean callerIsGoogle() {
69+
try {
70+
String packageName = getCallingPackage();
71+
if (packageName == null) return false;
72+
PackageManager packageManager = getContext().getPackageManager();
73+
return new ExtendedPackageInfo(packageManager, packageName).isGooglePackage();
74+
} catch (Exception e) {
75+
return false;
76+
}
77+
}
78+
79+
private boolean callerIsOwner() {
80+
try {
81+
String packageName = getCallingPackage();
82+
if (packageName == null) return false;
83+
DevicePolicyManager devicePolicyManager = ContextCompat.getSystemService(getContext(), DevicePolicyManager.class);
84+
return devicePolicyManager.isDeviceOwnerApp(packageName) || (SDK_INT >= 21 && devicePolicyManager.isProfileOwnerApp(packageName));
85+
} catch (Exception e) {
86+
return false;
87+
}
88+
}
89+
90+
/**
91+
* Instead of checking if the permissions is granted, we only check if it was requested.
92+
* <p>
93+
* This is because:
94+
* <ul>
95+
* <li>
96+
* this is a permission with protectionLevel normal and requesting should usually
97+
* silently grant it, as Android no longer asks users to confirm install-time
98+
* permissions on installation
99+
* </li>
100+
* <li>
101+
* on some Android versions, requesting a permission that is not declared yet will not
102+
* grant that permission if the declaring app is installed later
103+
* </li>
104+
* </ul>
105+
*/
106+
private boolean callerHasReadPermissionRequested() {
107+
String packageName = getCallingPackage();
108+
if (packageName == null) return false;
109+
try {
110+
String[] requestedPermissions = getContext().getPackageManager().getPackageInfo(packageName, PackageManager.GET_PERMISSIONS).requestedPermissions;
111+
return requestedPermissions != null && Arrays.asList(requestedPermissions).contains("com.google.android.providers.gsf.permission.READ_GSERVICES");
112+
} catch (PackageManager.NameNotFoundException e) {
113+
return false;
64114
}
65115
}
66116

67117
@Override
68118
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
119+
if (Binder.getCallingUid() != Process.myUid() && !callerIsGoogle() && !callerHasReadPermissionRequested()) {
120+
Log.w(TAG, "Rejected read access for package " + getCallingPackage());
121+
return null;
122+
}
69123
MatrixCursor cursor = new MatrixCursor(new String[]{"name", "value"});
70124
if (PREFIX_URI.equals(uri)) {
71125
for (String prefix : selectionArgs) {
@@ -92,6 +146,15 @@ public Cursor query(Uri uri, String[] projection, String selection, String[] sel
92146
value = databaseHelper.get(name);
93147
cache.put(name, value);
94148
}
149+
if ("android_id".equals(name)) {
150+
// Only Google and device/profile owner can access android_id
151+
if (Binder.getCallingUid() != Process.myUid() && !callerIsGoogle() && !callerIsOwner()) {
152+
Log.w(TAG, "Rejected access to android_id for package " + getCallingPackage());
153+
value = null;
154+
} else {
155+
Log.d(TAG, "Granted access to android_id for package " + getCallingPackage());
156+
}
157+
}
95158
if (value != null) {
96159
cursor.addRow(new String[]{name, value});
97160
}
@@ -118,7 +181,11 @@ public int delete(Uri uri, String selection, String[] selectionArgs) {
118181

119182
@Override
120183
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
121-
Log.d(TAG, "update caller=" + getCallingPackageName() + " table=" + uri.getLastPathSegment()
184+
if (Binder.getCallingUid() != Process.myUid() && !callerIsGoogle()) {
185+
Log.w(TAG, "Rejected write access for package " + getCallingPackage());
186+
return 0;
187+
}
188+
Log.d(TAG, "update caller=" + getCallingPackage() + " table=" + uri.getLastPathSegment()
122189
+ " name=" + values.getAsString("name") + " value=" + values.getAsString("value"));
123190
if (uri.equals(MAIN_URI)) {
124191
databaseHelper.put("main", values);

0 commit comments

Comments
 (0)