Change theme
Help
Press space for more information.
Show links for this issue (Shortcut: i, l)
Copy issue ID
Previous Issue (Shortcut: k)
Next Issue (Shortcut: j)
Sign in to use full features.
Vote: I am impacted
Notification menu
Refresh (Shortcut: Shift+r)
Go home (Shortcut: u)
Pending code changes (auto-populated)
View issue level access limits(Press Alt + Right arrow for more information)
Unintended behavior
View staffing
Description
The logs had been already provided in 317915129.
-----------------------------------------------------------------------------------------------------------------------------------
Dear Google development teams,
Platform: Android 14 AOSP (android-14.0.0_r11) at TV platform, kernel version: 5.15
What happened:
MediaProvider process (com.android.providers.media.module) is hung with great CPU usage while application tries to call Files.listFiles() Java API for the directory of an unmounted partition.
How to reproduce:
After plugging an external HDD with 4 partitions into a TV device, the device detects 4 partitions mounted and then shows corresponding 4 folder icons on our USB player app.
We find that those 4 folder icons cannot be disappeared immediately after unplugging the external HDD. Unmount events of each partition are one by one raised from kernel to userspace with a time interval about 7~800 ms, so our app clears up those 4 folder icons slowly due to delayed delivery of unmount intents.
When the external HDD is just unplugged and our app is yet not received any unmount intents, those 4 folder icons of each partition still remains existing and allows user to select. After trying entering one of the folders, our app would call Files.listFiles() to query all documents under the partition. However, this API would have no returns and lead our app stuck. Meanwhile, we observe MediaProvider process runs with great CPU usage. After profiling the process, 2 functions are the culprits:
- addDirectoryEntriesFromLowerFs (ReaddirHelper.cpp)
This function keeps calling readdir() C API to get the files under specified directory; in this case, we find readdir() always returns DIR result of same path for searching under unmounted partition. We're not sure if this problem shall be fixed by kernel or the flow of addDirectoryEntriesFromLowerFs().
- Scan.walkFileTree (ModernMediaScanner.java)
This function calls Files.walkFileTree() to do traversal of specified directory; in this case, FileTreeWalker receives IOException (IO error) and then Files notifies Scan with visitFileFailed(), but Scan returns CONTINUE. Hence Files falls into an infinite loop of searching same file and receiving IOException.
PLEASE help to check if any vulnerabilities of these functions.
We're looking forward to your feedback.
==========================================================================
Remarks:
We've tried to modify the flows of 2 functions above, and the problem seems to be resolved.
- ReaddirHelper.cpp
void addDirectoryEntriesFromLowerFs(DIR* dirp, bool (*const filter)(const dirent&),
std::vector<std::shared_ptr<DirectoryEntry>>* directory_entries) {
+++ char prev_path_name[256] = {};
while (1) {
errno = 0;
const struct dirent* entry = readdir(dirp);
--- if (entry == nullptr) {
+++ if (entry == nullptr || strcmp(entry->d_name, prev_path_name) == 0) {
if (errno) {
PLOG(ERROR) << "DEBUG: readdir(): readdir failed with %d" << errno;
directory_entries->resize(0);
directory_entries->push_back(std::make_shared<DirectoryEntry>("", errno));
}
break;
}
+++ strncpy(prev_path_name, entry->d_name, sizeof(prev_path_name) - 1);
// Ignore '.' & '..' to maintain consistency with directory entries
// returned by MediaProvider.
- ModernMediaScanner.java
@Override
public FileVisitResult visitFileFailed(Path file, IOException exc)
throws IOException {
Log.w(TAG, "Failed to visit " + file + ": " + exc);
--- return FileVisitResult.CONTINUE;
+++ return FileVisitResult.TERMINATE;
}