Loading core/java/android/app/INotificationManager.aidl +0 −1 Original line number Diff line number Diff line Loading @@ -164,7 +164,6 @@ interface INotificationManager void setOnNotificationPostedTrimFromListener(in INotificationListener token, int trim); void setInterruptionFilter(String pkg, int interruptionFilter); void updateNotificationChannelGroupFromPrivilegedListener(in INotificationListener token, String pkg, in UserHandle user, in NotificationChannelGroup group); void updateNotificationChannelFromPrivilegedListener(in INotificationListener token, String pkg, in UserHandle user, in NotificationChannel channel); ParceledListSlice getNotificationChannelsFromPrivilegedListener(in INotificationListener token, String pkg, in UserHandle user); ParceledListSlice getNotificationChannelGroupsFromPrivilegedListener(in INotificationListener token, String pkg, in UserHandle user); Loading core/java/android/content/ContentProvider.java +25 −4 Original line number Diff line number Diff line Loading @@ -464,13 +464,14 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall throws FileNotFoundException { uri = validateIncomingUri(uri); uri = maybeGetUriWithoutUserId(uri); enforceFilePermission(attributionSource, uri, mode); final String updatedMode = validateFileMode(mode); enforceFilePermission(attributionSource, uri, updatedMode); traceBegin(TRACE_TAG_DATABASE, "openFile: ", uri.getAuthority()); final AttributionSource original = setCallingAttributionSource( attributionSource); try { return mInterface.openFile( uri, mode, CancellationSignal.fromTransport(cancellationSignal)); uri, updatedMode, CancellationSignal.fromTransport(cancellationSignal)); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } finally { Loading @@ -485,13 +486,14 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall throws FileNotFoundException { uri = validateIncomingUri(uri); uri = maybeGetUriWithoutUserId(uri); enforceFilePermission(attributionSource, uri, mode); final String updatedMode = validateFileMode(mode); enforceFilePermission(attributionSource, uri, updatedMode); traceBegin(TRACE_TAG_DATABASE, "openAssetFile: ", uri.getAuthority()); final AttributionSource original = setCallingAttributionSource( attributionSource); try { return mInterface.openAssetFile( uri, mode, CancellationSignal.fromTransport(cancellationSignal)); uri, updatedMode, CancellationSignal.fromTransport(cancellationSignal)); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } finally { Loading Loading @@ -653,6 +655,25 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall } } private String validateFileMode(String mode) { // We currently only support the following modes: r, w, wt, wa, rw, rwt // Note: ideally, we should check against the allowed modes and throw a // SecurityException if the mode doesn't match any of them but to avoid app compat // issues, we're silently dropping bits which allow modifying files when the write bit // is not specified. if (mode != null && mode.indexOf('w') == -1) { // Don't allow truncation without write if (mode.indexOf('t') != -1) { mode = mode.replace("t", ""); } // Don't allow appending without write if (mode.indexOf('a') != -1) { mode = mode.replace("a", ""); } } return mode; } @Override public int checkUriPermission(@NonNull AttributionSource attributionSource, Uri uri, int uid, int modeFlags) { Loading core/java/android/os/RecoverySystem.java +7 −0 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ import android.content.IntentFilter; import android.content.IntentSender; import android.content.pm.PackageManager; import android.hardware.display.DisplayManager; import android.os.image.DynamicSystemManager; import android.provider.Settings; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; Loading Loading @@ -956,9 +957,15 @@ public class RecoverySystem { public static void rebootWipeUserData(Context context, boolean shutdown, String reason, boolean force, boolean wipeEuicc) throws IOException { UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE); DynamicSystemManager dsuManager = (DynamicSystemManager) context.getSystemService(Context.DYNAMIC_SYSTEM_SERVICE); if (!force && um.hasUserRestriction(UserManager.DISALLOW_FACTORY_RESET)) { throw new SecurityException("Wiping data is not allowed for this user."); } if (dsuManager.isInUse()) { throw new SecurityException("Wiping data is not allowed while in DSU mode."); } final ConditionVariable condition = new ConditionVariable(); Intent intent = new Intent("android.intent.action.MASTER_CLEAR_NOTIFICATION"); Loading core/java/android/view/inputmethod/InputMethodInfo.java +71 −2 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ import android.content.res.TypedArray; import android.content.res.XmlResourceParser; import android.graphics.drawable.Drawable; import android.inputmethodservice.InputMethodService; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; import android.util.AttributeSet; Loading @@ -47,6 +48,7 @@ import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; Loading @@ -71,6 +73,24 @@ import java.util.List; public final class InputMethodInfo implements Parcelable { static final String TAG = "InputMethodInfo"; /** * The maximum allowed size in bytes for an input method's metadata XML file * (typically {@code inputmethod.xml} referenced by * {@link android.inputmethodservice.InputMethod#SERVICE_META_DATA}). * This limit is enforced to prevent {@link OutOfMemoryError OutOfMemoryErrors} * when the Android system parses input method manifests. * <p> * An excessively large metadata file, whether due to misconfiguration or * malicious intent, could consume an unreasonable amount of memory in the * system process, potentially leading to instability or denial of service. * </p> * <p> * The current recommended value is 200 KB (200 * 1024 bytes), which is * significantly larger than typical input method metadata files. * </p> */ private static final int MAX_METADATA_SIZE_BYTES = 200 * 1024; // 200 KB /** * The Service that implements this input method component. */ Loading Loading @@ -195,14 +215,14 @@ public final class InputMethodInfo implements Parcelable { XmlResourceParser parser = null; final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); try { Resources res = pm.getResourcesForApplication(si.applicationInfo); validateXmlMetaData(si, res); parser = si.loadXmlMetaData(pm, InputMethod.SERVICE_META_DATA); if (parser == null) { throw new XmlPullParserException("No " + InputMethod.SERVICE_META_DATA + " meta-data"); } Resources res = pm.getResourcesForApplication(si.applicationInfo); AttributeSet attrs = Xml.asAttributeSet(parser); int type; Loading Loading @@ -310,6 +330,55 @@ public final class InputMethodInfo implements Parcelable { mIsVrOnly = isVrOnly; } /** * Validates the XML metadata for an input method service to prevent OOM errors * from excessively large XML files. * * @param si The ServiceInfo of the input method. * @param res The input method app resources. * @throws IOException if there's an issue reading the resource. * @throws NameNotFoundException if the application's resources cannot be found. * @throws XmlPullParserException if the metadata file exceeds the size limit. */ private static void validateXmlMetaData(@NonNull ServiceInfo si, @NonNull Resources res) throws IOException, NameNotFoundException, XmlPullParserException { final Bundle metaData = si.metaData; if (metaData == null) { // No metadata, skip validation. return; } final int resourceId = metaData.getInt(InputMethod.SERVICE_META_DATA); if (resourceId == 0) { // No metadata, skip validation. return; } // Validate file size using InputStream.skip() long totalBytesSkipped = 0; // Loop to ensure we skip the required number of bytes, as a single // call to skip() is not guaranteed to skip the full amount. try (InputStream is = res.openRawResource(resourceId)) { while (totalBytesSkipped < MAX_METADATA_SIZE_BYTES) { long bytesSkipped = is.skip(MAX_METADATA_SIZE_BYTES - totalBytesSkipped); if (bytesSkipped <= 0) { // end of the stream. break; } totalBytesSkipped += bytesSkipped; } // If we successfully skipped exactly MAX_METADATA_SIZE_BYTES if (totalBytesSkipped == MAX_METADATA_SIZE_BYTES) { // try to read one more byte. if (is.read() != -1) { throw new XmlPullParserException( "Input method metadata exceeds maximum allowed limit of 200KB for " + si.packageName + ". InputMethod will not be loaded. "); } } } } InputMethodInfo(Parcel source) { mId = source.readString(); mSettingsActivityName = source.readString(); Loading libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java +1 −1 Original line number Diff line number Diff line Loading @@ -91,7 +91,7 @@ import java.util.ArrayList; /** The default handler that handles anything not already handled. */ public class DefaultTransitionHandler implements Transitions.TransitionHandler { private static final int MAX_ANIMATION_DURATION = 3000; private static final int MAX_ANIMATION_DURATION = 1500; /** * Restrict ability of activities overriding transition animation in a way such that Loading Loading
core/java/android/app/INotificationManager.aidl +0 −1 Original line number Diff line number Diff line Loading @@ -164,7 +164,6 @@ interface INotificationManager void setOnNotificationPostedTrimFromListener(in INotificationListener token, int trim); void setInterruptionFilter(String pkg, int interruptionFilter); void updateNotificationChannelGroupFromPrivilegedListener(in INotificationListener token, String pkg, in UserHandle user, in NotificationChannelGroup group); void updateNotificationChannelFromPrivilegedListener(in INotificationListener token, String pkg, in UserHandle user, in NotificationChannel channel); ParceledListSlice getNotificationChannelsFromPrivilegedListener(in INotificationListener token, String pkg, in UserHandle user); ParceledListSlice getNotificationChannelGroupsFromPrivilegedListener(in INotificationListener token, String pkg, in UserHandle user); Loading
core/java/android/content/ContentProvider.java +25 −4 Original line number Diff line number Diff line Loading @@ -464,13 +464,14 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall throws FileNotFoundException { uri = validateIncomingUri(uri); uri = maybeGetUriWithoutUserId(uri); enforceFilePermission(attributionSource, uri, mode); final String updatedMode = validateFileMode(mode); enforceFilePermission(attributionSource, uri, updatedMode); traceBegin(TRACE_TAG_DATABASE, "openFile: ", uri.getAuthority()); final AttributionSource original = setCallingAttributionSource( attributionSource); try { return mInterface.openFile( uri, mode, CancellationSignal.fromTransport(cancellationSignal)); uri, updatedMode, CancellationSignal.fromTransport(cancellationSignal)); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } finally { Loading @@ -485,13 +486,14 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall throws FileNotFoundException { uri = validateIncomingUri(uri); uri = maybeGetUriWithoutUserId(uri); enforceFilePermission(attributionSource, uri, mode); final String updatedMode = validateFileMode(mode); enforceFilePermission(attributionSource, uri, updatedMode); traceBegin(TRACE_TAG_DATABASE, "openAssetFile: ", uri.getAuthority()); final AttributionSource original = setCallingAttributionSource( attributionSource); try { return mInterface.openAssetFile( uri, mode, CancellationSignal.fromTransport(cancellationSignal)); uri, updatedMode, CancellationSignal.fromTransport(cancellationSignal)); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } finally { Loading Loading @@ -653,6 +655,25 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall } } private String validateFileMode(String mode) { // We currently only support the following modes: r, w, wt, wa, rw, rwt // Note: ideally, we should check against the allowed modes and throw a // SecurityException if the mode doesn't match any of them but to avoid app compat // issues, we're silently dropping bits which allow modifying files when the write bit // is not specified. if (mode != null && mode.indexOf('w') == -1) { // Don't allow truncation without write if (mode.indexOf('t') != -1) { mode = mode.replace("t", ""); } // Don't allow appending without write if (mode.indexOf('a') != -1) { mode = mode.replace("a", ""); } } return mode; } @Override public int checkUriPermission(@NonNull AttributionSource attributionSource, Uri uri, int uid, int modeFlags) { Loading
core/java/android/os/RecoverySystem.java +7 −0 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ import android.content.IntentFilter; import android.content.IntentSender; import android.content.pm.PackageManager; import android.hardware.display.DisplayManager; import android.os.image.DynamicSystemManager; import android.provider.Settings; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; Loading Loading @@ -956,9 +957,15 @@ public class RecoverySystem { public static void rebootWipeUserData(Context context, boolean shutdown, String reason, boolean force, boolean wipeEuicc) throws IOException { UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE); DynamicSystemManager dsuManager = (DynamicSystemManager) context.getSystemService(Context.DYNAMIC_SYSTEM_SERVICE); if (!force && um.hasUserRestriction(UserManager.DISALLOW_FACTORY_RESET)) { throw new SecurityException("Wiping data is not allowed for this user."); } if (dsuManager.isInUse()) { throw new SecurityException("Wiping data is not allowed while in DSU mode."); } final ConditionVariable condition = new ConditionVariable(); Intent intent = new Intent("android.intent.action.MASTER_CLEAR_NOTIFICATION"); Loading
core/java/android/view/inputmethod/InputMethodInfo.java +71 −2 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ import android.content.res.TypedArray; import android.content.res.XmlResourceParser; import android.graphics.drawable.Drawable; import android.inputmethodservice.InputMethodService; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; import android.util.AttributeSet; Loading @@ -47,6 +48,7 @@ import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; Loading @@ -71,6 +73,24 @@ import java.util.List; public final class InputMethodInfo implements Parcelable { static final String TAG = "InputMethodInfo"; /** * The maximum allowed size in bytes for an input method's metadata XML file * (typically {@code inputmethod.xml} referenced by * {@link android.inputmethodservice.InputMethod#SERVICE_META_DATA}). * This limit is enforced to prevent {@link OutOfMemoryError OutOfMemoryErrors} * when the Android system parses input method manifests. * <p> * An excessively large metadata file, whether due to misconfiguration or * malicious intent, could consume an unreasonable amount of memory in the * system process, potentially leading to instability or denial of service. * </p> * <p> * The current recommended value is 200 KB (200 * 1024 bytes), which is * significantly larger than typical input method metadata files. * </p> */ private static final int MAX_METADATA_SIZE_BYTES = 200 * 1024; // 200 KB /** * The Service that implements this input method component. */ Loading Loading @@ -195,14 +215,14 @@ public final class InputMethodInfo implements Parcelable { XmlResourceParser parser = null; final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); try { Resources res = pm.getResourcesForApplication(si.applicationInfo); validateXmlMetaData(si, res); parser = si.loadXmlMetaData(pm, InputMethod.SERVICE_META_DATA); if (parser == null) { throw new XmlPullParserException("No " + InputMethod.SERVICE_META_DATA + " meta-data"); } Resources res = pm.getResourcesForApplication(si.applicationInfo); AttributeSet attrs = Xml.asAttributeSet(parser); int type; Loading Loading @@ -310,6 +330,55 @@ public final class InputMethodInfo implements Parcelable { mIsVrOnly = isVrOnly; } /** * Validates the XML metadata for an input method service to prevent OOM errors * from excessively large XML files. * * @param si The ServiceInfo of the input method. * @param res The input method app resources. * @throws IOException if there's an issue reading the resource. * @throws NameNotFoundException if the application's resources cannot be found. * @throws XmlPullParserException if the metadata file exceeds the size limit. */ private static void validateXmlMetaData(@NonNull ServiceInfo si, @NonNull Resources res) throws IOException, NameNotFoundException, XmlPullParserException { final Bundle metaData = si.metaData; if (metaData == null) { // No metadata, skip validation. return; } final int resourceId = metaData.getInt(InputMethod.SERVICE_META_DATA); if (resourceId == 0) { // No metadata, skip validation. return; } // Validate file size using InputStream.skip() long totalBytesSkipped = 0; // Loop to ensure we skip the required number of bytes, as a single // call to skip() is not guaranteed to skip the full amount. try (InputStream is = res.openRawResource(resourceId)) { while (totalBytesSkipped < MAX_METADATA_SIZE_BYTES) { long bytesSkipped = is.skip(MAX_METADATA_SIZE_BYTES - totalBytesSkipped); if (bytesSkipped <= 0) { // end of the stream. break; } totalBytesSkipped += bytesSkipped; } // If we successfully skipped exactly MAX_METADATA_SIZE_BYTES if (totalBytesSkipped == MAX_METADATA_SIZE_BYTES) { // try to read one more byte. if (is.read() != -1) { throw new XmlPullParserException( "Input method metadata exceeds maximum allowed limit of 200KB for " + si.packageName + ". InputMethod will not be loaded. "); } } } } InputMethodInfo(Parcel source) { mId = source.readString(); mSettingsActivityName = source.readString(); Loading
libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java +1 −1 Original line number Diff line number Diff line Loading @@ -91,7 +91,7 @@ import java.util.ArrayList; /** The default handler that handles anything not already handled. */ public class DefaultTransitionHandler implements Transitions.TransitionHandler { private static final int MAX_ANIMATION_DURATION = 3000; private static final int MAX_ANIMATION_DURATION = 1500; /** * Restrict ability of activities overriding transition animation in a way such that Loading