Skip to content

Commit 92e421a

Browse files
committed
Merge tag 'android-security-13.0.0_r12' into HEAD
Android Security 13.0.0 Release 12 (10993242) Change-Id: Iba6d6a3130a5ecda8a26d1f304b53ff17b4d46c8
2 parents 094cf26 + d203ccf commit 92e421a

File tree

20 files changed

+349
-43
lines changed

20 files changed

+349
-43
lines changed

cmds/incidentd/src/IncidentService.cpp

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -500,9 +500,13 @@ status_t IncidentService::onTransact(uint32_t code, const Parcel& data, Parcel*
500500

501501
switch (code) {
502502
case SHELL_COMMAND_TRANSACTION: {
503-
int in = data.readFileDescriptor();
504-
int out = data.readFileDescriptor();
505-
int err = data.readFileDescriptor();
503+
unique_fd in, out, err;
504+
if (status_t status = data.readUniqueFileDescriptor(&in); status != OK) return status;
505+
506+
if (status_t status = data.readUniqueFileDescriptor(&out); status != OK) return status;
507+
508+
if (status_t status = data.readUniqueFileDescriptor(&err); status != OK) return status;
509+
506510
int argc = data.readInt32();
507511
Vector<String8> args;
508512
for (int i = 0; i < argc && data.dataAvail() > 0; i++) {
@@ -512,15 +516,15 @@ status_t IncidentService::onTransact(uint32_t code, const Parcel& data, Parcel*
512516
sp<IResultReceiver> resultReceiver =
513517
IResultReceiver::asInterface(data.readStrongBinder());
514518

515-
FILE* fin = fdopen(in, "r");
516-
FILE* fout = fdopen(out, "w");
517-
FILE* ferr = fdopen(err, "w");
519+
FILE* fin = fdopen(in.release(), "r");
520+
FILE* fout = fdopen(out.release(), "w");
521+
FILE* ferr = fdopen(err.release(), "w");
518522

519523
if (fin == NULL || fout == NULL || ferr == NULL) {
520524
resultReceiver->send(NO_MEMORY);
521525
} else {
522-
err = command(fin, fout, ferr, args);
523-
resultReceiver->send(err);
526+
status_t result = command(fin, fout, ferr, args);
527+
resultReceiver->send(result);
524528
}
525529

526530
if (fin != NULL) {

core/java/android/app/IActivityTaskManager.aidl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,7 @@ interface IActivityTaskManager {
241241
* {@link android.view.WindowManagerPolicyConstants#KEYGUARD_GOING_AWAY_FLAG_TO_SHADE}
242242
* etc.
243243
*/
244+
@JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.CONTROL_KEYGUARD)")
244245
void keyguardGoingAway(int flags);
245246

246247
void suppressResizeConfigChanges(boolean suppress);

core/java/android/app/IUriGrantsManager.aidl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,7 @@ interface IUriGrantsManager {
3939
void clearGrantedUriPermissions(in String packageName, int userId);
4040
ParceledListSlice getUriPermissions(in String packageName, boolean incoming,
4141
boolean persistedOnly);
42+
43+
int checkGrantUriPermission_ignoreNonSystem(
44+
int sourceUid, String targetPkg, in Uri uri, int modeFlags, int userId);
4245
}

core/java/android/app/Notification.java

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2138,6 +2138,10 @@ public Action build() {
21382138
}
21392139
}
21402140

2141+
private void visitUris(@NonNull Consumer<Uri> visitor) {
2142+
visitIconUri(visitor, getIcon());
2143+
}
2144+
21412145
@Override
21422146
public Action clone() {
21432147
return new Action(
@@ -2823,7 +2827,7 @@ public void visitUris(@NonNull Consumer<Uri> visitor) {
28232827

28242828
if (actions != null) {
28252829
for (Action action : actions) {
2826-
visitIconUri(visitor, action.getIcon());
2830+
action.visitUris(visitor);
28272831
}
28282832
}
28292833

@@ -2846,18 +2850,14 @@ public void visitUris(@NonNull Consumer<Uri> visitor) {
28462850
visitor.accept(Uri.parse(extras.getString(EXTRA_BACKGROUND_IMAGE_URI)));
28472851
}
28482852

2849-
ArrayList<Person> people = extras.getParcelableArrayList(EXTRA_PEOPLE_LIST);
2853+
ArrayList<Person> people = extras.getParcelableArrayList(EXTRA_PEOPLE_LIST,
2854+
Person.class);
28502855
if (people != null && !people.isEmpty()) {
28512856
for (Person p : people) {
28522857
visitor.accept(p.getIconUri());
28532858
}
28542859
}
28552860

2856-
final Person person = extras.getParcelable(EXTRA_MESSAGING_PERSON, Person.class);
2857-
if (person != null) {
2858-
visitor.accept(person.getIconUri());
2859-
}
2860-
28612861
final RemoteInputHistoryItem[] history = extras.getParcelableArray(
28622862
Notification.EXTRA_REMOTE_INPUT_HISTORY_ITEMS,
28632863
RemoteInputHistoryItem.class);
@@ -2869,10 +2869,16 @@ public void visitUris(@NonNull Consumer<Uri> visitor) {
28692869
}
28702870
}
28712871
}
2872-
}
28732872

2874-
if (isStyle(MessagingStyle.class) && extras != null) {
2875-
final Parcelable[] messages = extras.getParcelableArray(EXTRA_MESSAGES);
2873+
// Extras for MessagingStyle. We visit them even if not isStyle(MessagingStyle), since
2874+
// Notification Listeners might use directly (without the isStyle check).
2875+
final Person person = extras.getParcelable(EXTRA_MESSAGING_PERSON, Person.class);
2876+
if (person != null) {
2877+
visitor.accept(person.getIconUri());
2878+
}
2879+
2880+
final Parcelable[] messages = extras.getParcelableArray(EXTRA_MESSAGES,
2881+
Parcelable.class);
28762882
if (!ArrayUtils.isEmpty(messages)) {
28772883
for (MessagingStyle.Message message : MessagingStyle.Message
28782884
.getMessagesFromBundleArray(messages)) {
@@ -2885,7 +2891,8 @@ public void visitUris(@NonNull Consumer<Uri> visitor) {
28852891
}
28862892
}
28872893

2888-
final Parcelable[] historic = extras.getParcelableArray(EXTRA_HISTORIC_MESSAGES);
2894+
final Parcelable[] historic = extras.getParcelableArray(EXTRA_HISTORIC_MESSAGES,
2895+
Parcelable.class);
28892896
if (!ArrayUtils.isEmpty(historic)) {
28902897
for (MessagingStyle.Message message : MessagingStyle.Message
28912898
.getMessagesFromBundleArray(historic)) {
@@ -2898,20 +2905,24 @@ public void visitUris(@NonNull Consumer<Uri> visitor) {
28982905
}
28992906
}
29002907

2901-
visitIconUri(visitor, extras.getParcelable(EXTRA_CONVERSATION_ICON));
2902-
}
2908+
visitIconUri(visitor, extras.getParcelable(EXTRA_CONVERSATION_ICON, Icon.class));
29032909

2904-
if (isStyle(CallStyle.class) & extras != null) {
2905-
Person callPerson = extras.getParcelable(EXTRA_CALL_PERSON);
2910+
// Extras for CallStyle (same reason for visiting without checking isStyle).
2911+
Person callPerson = extras.getParcelable(EXTRA_CALL_PERSON, Person.class);
29062912
if (callPerson != null) {
29072913
visitor.accept(callPerson.getIconUri());
29082914
}
2909-
visitIconUri(visitor, extras.getParcelable(EXTRA_VERIFICATION_ICON));
2915+
visitIconUri(visitor, extras.getParcelable(EXTRA_VERIFICATION_ICON, Icon.class));
29102916
}
29112917

29122918
if (mBubbleMetadata != null) {
29132919
visitIconUri(visitor, mBubbleMetadata.getIcon());
29142920
}
2921+
2922+
if (extras != null && extras.containsKey(WearableExtender.EXTRA_WEARABLE_EXTENSIONS)) {
2923+
WearableExtender extender = new WearableExtender(this);
2924+
extender.visitUris(visitor);
2925+
}
29152926
}
29162927

29172928
/**
@@ -11630,6 +11641,12 @@ private void setFlag(int mask, boolean value) {
1163011641
mFlags &= ~mask;
1163111642
}
1163211643
}
11644+
11645+
private void visitUris(@NonNull Consumer<Uri> visitor) {
11646+
for (Action action : mActions) {
11647+
action.visitUris(visitor);
11648+
}
11649+
}
1163311650
}
1163411651

1163511652
/**

core/java/android/os/PersistableBundle.java

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import android.annotation.NonNull;
2222
import android.annotation.Nullable;
2323
import android.util.ArrayMap;
24+
import android.util.Slog;
2425
import android.util.TypedXmlPullParser;
2526
import android.util.TypedXmlSerializer;
2627
import android.util.Xml;
@@ -50,6 +51,8 @@
5051
*/
5152
public final class PersistableBundle extends BaseBundle implements Cloneable, Parcelable,
5253
XmlUtils.WriteMapCallback {
54+
private static final String TAG = "PersistableBundle";
55+
5356
private static final String TAG_PERSISTABLEMAP = "pbundle_as_map";
5457

5558
/** An unmodifiable {@code PersistableBundle} that is always {@link #isEmpty() empty}. */
@@ -118,7 +121,11 @@ public PersistableBundle(PersistableBundle b) {
118121
* @hide
119122
*/
120123
public PersistableBundle(Bundle b) {
121-
this(b.getItemwiseMap());
124+
this(b, true);
125+
}
126+
127+
private PersistableBundle(Bundle b, boolean throwException) {
128+
this(b.getItemwiseMap(), throwException);
122129
}
123130

124131
/**
@@ -127,7 +134,7 @@ public PersistableBundle(Bundle b) {
127134
* @param map a Map containing only those items that can be persisted.
128135
* @throws IllegalArgumentException if any element of #map cannot be persisted.
129136
*/
130-
private PersistableBundle(ArrayMap<String, Object> map) {
137+
private PersistableBundle(ArrayMap<String, Object> map, boolean throwException) {
131138
super();
132139
mFlags = FLAG_DEFUSABLE;
133140

@@ -136,16 +143,23 @@ private PersistableBundle(ArrayMap<String, Object> map) {
136143

137144
// Now verify each item throwing an exception if there is a violation.
138145
final int N = mMap.size();
139-
for (int i=0; i<N; i++) {
146+
for (int i = N - 1; i >= 0; --i) {
140147
Object value = mMap.valueAt(i);
141148
if (value instanceof ArrayMap) {
142149
// Fix up any Maps by replacing them with PersistableBundles.
143-
mMap.setValueAt(i, new PersistableBundle((ArrayMap<String, Object>) value));
150+
mMap.setValueAt(i,
151+
new PersistableBundle((ArrayMap<String, Object>) value, throwException));
144152
} else if (value instanceof Bundle) {
145-
mMap.setValueAt(i, new PersistableBundle(((Bundle) value)));
153+
mMap.setValueAt(i, new PersistableBundle((Bundle) value, throwException));
146154
} else if (!isValidType(value)) {
147-
throw new IllegalArgumentException("Bad value in PersistableBundle key="
148-
+ mMap.keyAt(i) + " value=" + value);
155+
final String errorMsg = "Bad value in PersistableBundle key="
156+
+ mMap.keyAt(i) + " value=" + value;
157+
if (throwException) {
158+
throw new IllegalArgumentException(errorMsg);
159+
} else {
160+
Slog.wtfStack(TAG, errorMsg);
161+
mMap.removeAt(i);
162+
}
149163
}
150164
}
151165
}
@@ -268,6 +282,15 @@ public void saveToXml(XmlSerializer out) throws IOException, XmlPullParserExcept
268282
/** @hide */
269283
public void saveToXml(TypedXmlSerializer out) throws IOException, XmlPullParserException {
270284
unparcel();
285+
// Explicitly drop invalid types an attacker may have added before persisting.
286+
for (int i = mMap.size() - 1; i >= 0; --i) {
287+
final Object value = mMap.valueAt(i);
288+
if (!isValidType(value)) {
289+
Slog.e(TAG, "Dropping bad data before persisting: "
290+
+ mMap.keyAt(i) + "=" + value);
291+
mMap.removeAt(i);
292+
}
293+
}
271294
XmlUtils.writeMapXml(mMap, out, this);
272295
}
273296

@@ -322,9 +345,12 @@ public static PersistableBundle restoreFromXml(TypedXmlPullParser in) throws IOE
322345
while (((event = in.next()) != XmlPullParser.END_DOCUMENT) &&
323346
(event != XmlPullParser.END_TAG || in.getDepth() < outerDepth)) {
324347
if (event == XmlPullParser.START_TAG) {
348+
// Don't throw an exception when restoring from XML since an attacker could try to
349+
// input invalid data in the persisted file.
325350
return new PersistableBundle((ArrayMap<String, Object>)
326351
XmlUtils.readThisArrayMapXml(in, startTag, tagName,
327-
new MyReadMapCallback()));
352+
new MyReadMapCallback()),
353+
/* throwException */ false);
328354
}
329355
}
330356
return new PersistableBundle(); // An empty mutable PersistableBundle

core/java/com/android/internal/app/IAppOpsService.aidl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ interface IAppOpsService {
5252
int checkAudioOperation(int code, int usage, int uid, String packageName);
5353
boolean shouldCollectNotes(int opCode);
5454
void setCameraAudioRestriction(int mode);
55+
void startWatchingModeWithFlags(int op, String packageName, int flags,
56+
IAppOpsCallback callback);
5557
// End of methods also called by native code.
5658
// Any new method exposed to native must be added after the last one, do not reorder
5759

@@ -110,8 +112,6 @@ interface IAppOpsService {
110112
void startWatchingStarted(in int[] ops, IAppOpsStartedCallback callback);
111113
void stopWatchingStarted(IAppOpsStartedCallback callback);
112114

113-
void startWatchingModeWithFlags(int op, String packageName, int flags, IAppOpsCallback callback);
114-
115115
void startWatchingNoted(in int[] ops, IAppOpsNotedCallback callback);
116116
void stopWatchingNoted(IAppOpsNotedCallback callback);
117117

packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1933,8 +1933,7 @@ private void updateInputRestrictedLocked() {
19331933
*/
19341934
private void doKeyguardLocked(Bundle options) {
19351935
// if another app is disabling us, don't show
1936-
if (!mExternallyEnabled
1937-
&& !mLockPatternUtils.isUserInLockdown(KeyguardUpdateMonitor.getCurrentUser())) {
1936+
if (!mExternallyEnabled) {
19381937
if (DEBUG) Log.d(TAG, "doKeyguard: not showing because externally disabled");
19391938

19401939
mNeedToReshowWhenReenabled = true;

packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,13 @@ package com.android.systemui.media.controls.pipeline
1919
import android.app.Notification
2020
import android.app.Notification.EXTRA_SUBSTITUTE_APP_NAME
2121
import android.app.PendingIntent
22+
import android.app.UriGrantsManager
2223
import android.app.smartspace.SmartspaceConfig
2324
import android.app.smartspace.SmartspaceManager
2425
import android.app.smartspace.SmartspaceSession
2526
import android.app.smartspace.SmartspaceTarget
2627
import android.content.BroadcastReceiver
28+
import android.content.ContentProvider
2729
import android.content.ContentResolver
2830
import android.content.Context
2931
import android.content.Intent
@@ -677,10 +679,13 @@ class MediaDataManager(
677679
Log.d(TAG, "adding track for $userId from browser: $desc")
678680
}
679681

682+
val currentEntry = mediaEntries.get(packageName)
683+
val appUid = currentEntry?.appUid ?: Process.INVALID_UID
684+
680685
// Album art
681686
var artworkBitmap = desc.iconBitmap
682687
if (artworkBitmap == null && desc.iconUri != null) {
683-
artworkBitmap = loadBitmapFromUri(desc.iconUri!!)
688+
artworkBitmap = loadBitmapFromUriForUser(desc.iconUri!!, userId, appUid, packageName)
684689
}
685690
val artworkIcon =
686691
if (artworkBitmap != null) {
@@ -689,9 +694,7 @@ class MediaDataManager(
689694
null
690695
}
691696

692-
val currentEntry = mediaEntries.get(packageName)
693697
val instanceId = currentEntry?.instanceId ?: logger.getNewInstanceId()
694-
val appUid = currentEntry?.appUid ?: Process.INVALID_UID
695698
val isExplicit =
696699
desc.extras?.getLong(MediaConstants.METADATA_KEY_IS_EXPLICIT) ==
697700
MediaConstants.METADATA_VALUE_ATTRIBUTE_PRESENT &&
@@ -1231,6 +1234,30 @@ class MediaDataManager(
12311234
false
12321235
}
12331236
}
1237+
1238+
/** Returns a bitmap if the user can access the given URI, else null */
1239+
private fun loadBitmapFromUriForUser(
1240+
uri: Uri,
1241+
userId: Int,
1242+
appUid: Int,
1243+
packageName: String,
1244+
): Bitmap? {
1245+
try {
1246+
val ugm = UriGrantsManager.getService()
1247+
ugm.checkGrantUriPermission_ignoreNonSystem(
1248+
appUid,
1249+
packageName,
1250+
ContentProvider.getUriWithoutUserId(uri),
1251+
Intent.FLAG_GRANT_READ_URI_PERMISSION,
1252+
ContentProvider.getUserIdFromUri(uri, userId)
1253+
)
1254+
return loadBitmapFromUri(uri)
1255+
} catch (e: SecurityException) {
1256+
Log.e(TAG, "Failed to get URI permission: $e")
1257+
}
1258+
return null
1259+
}
1260+
12341261
/**
12351262
* Load a bitmap from a URI
12361263
*

0 commit comments

Comments
 (0)