Don't allow read truncation or appending for file operations. If a caller attempts to read a file with the truncation or append bits and doesn't specify the write bit as well, silently drop the invalid bits to prevent unintended changes. Bug: 414387646 Test: atest CtsContentProviderTestCases Flag: EXEMPT security fix (cherry picked from commit f8099b069367df749a4c101b5d7f9020d83cb660) Cherrypick-From: https://googleplex-android-review.googlesource.com/q/commit:2ccfca86a433f9b7391187aff39cac4d3a251f1e Merged-In: I1a8993d99d1f381e1122b304d223a5c10e4578ce Change-Id: I1a8993d99d1f381e1122b304d223a5c10e4578ce
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java index 385d6cfd..d27b7d5 100644 --- a/core/java/android/content/ContentProvider.java +++ b/core/java/android/content/ContentProvider.java
@@ -590,13 +590,14 @@ throws FileNotFoundException { uri = validateIncomingUri(uri); uri = maybeGetUriWithoutUserId(uri); - enforceFilePermission(attributionSource, uri, mode); + final String updatedMode = validateFileMode(mode); + enforceFilePermission(attributionSource, uri, updatedMode); traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "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 { @@ -611,13 +612,14 @@ throws FileNotFoundException { uri = validateIncomingUri(uri); uri = maybeGetUriWithoutUserId(uri); - enforceFilePermission(attributionSource, uri, mode); + final String updatedMode = validateFileMode(mode); + enforceFilePermission(attributionSource, uri, updatedMode); traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "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 { @@ -782,6 +784,25 @@ } } + 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) {