am 3617eb6c: am e57c5ae4: am 355d65b9: am c015f8e1: am 940b951d: am d0fd622e: am d96863a0: Backport path validation changes.
* commit '3617eb6c97c41c4e9f4120d9eac5ce1730506d3e':
Backport path validation changes.
diff --git a/src/com/android/providers/media/MediaProvider.java b/src/com/android/providers/media/MediaProvider.java
index f1121be..0265a1e 100755
--- a/src/com/android/providers/media/MediaProvider.java
+++ b/src/com/android/providers/media/MediaProvider.java
@@ -104,6 +104,8 @@
import libcore.io.ErrnoException;
import libcore.io.IoUtils;
import libcore.io.Libcore;
+import libcore.io.OsConstants;
+import libcore.io.StructStat;
/**
* Media content provider. See {@link android.provider.MediaStore} for details.
@@ -4460,15 +4462,65 @@
if (modeBits == MODE_READ_ONLY) {
file = Environment.maybeTranslateEmulatedPathToInternal(file);
}
-
} else if (path.startsWith(sCachePath)) {
getContext().enforceCallingOrSelfPermission(
ACCESS_CACHE_FILESYSTEM, "Cache path: " + path);
+ } else if (isWrite) {
+ // don't write to non-cache, non-sdcard files.
+ throw new FileNotFoundException("Can't access " + file);
+ } else {
+ checkWorldReadAccess(path);
}
return ParcelFileDescriptor.open(file, modeBits);
}
+ /**
+ * Check whether the path is a world-readable file
+ */
+ private void checkWorldReadAccess(String path) throws FileNotFoundException {
+
+ try {
+ StructStat stat = Libcore.os.stat(path);
+ int accessBits = OsConstants.S_IROTH;
+ if (OsConstants.S_ISREG(stat.st_mode) &&
+ ((stat.st_mode & accessBits) == accessBits)) {
+ checkLeadingPathComponentsWorldExecutable(path);
+ return;
+ }
+ } catch (ErrnoException e) {
+ // couldn't stat the file, either it doesn't exist or isn't
+ // accessible to us
+ }
+
+ throw new FileNotFoundException("Can't access " + path);
+ }
+
+ private void checkLeadingPathComponentsWorldExecutable(String filePath)
+ throws FileNotFoundException {
+ File parent = new File(filePath).getParentFile();
+
+ int accessBits = OsConstants.S_IXOTH;
+
+ while (parent != null) {
+ if (! parent.exists()) {
+ // parent dir doesn't exist, give up
+ throw new FileNotFoundException("access denied");
+ }
+ try {
+ StructStat stat = Libcore.os.stat(parent.getPath());
+ if ((stat.st_mode & accessBits) != accessBits) {
+ // the parent dir doesn't have the appropriate access
+ throw new FileNotFoundException("Can't access " + filePath);
+ }
+ } catch (ErrnoException e1) {
+ // couldn't stat() parent
+ throw new FileNotFoundException("Can't access " + filePath);
+ }
+ parent = parent.getParentFile();
+ }
+ }
+
private class ThumbData {
DatabaseHelper helper;
SQLiteDatabase db;