Bug 217681

Summary: gen_kheaders.sh gets stuck in an infinite loop
Product: File System Reporter: Maksim Paimushkin (maxim.paymushkin)
Component: btrfsAssignee: BTRFS virtual assignee (fs_btrfs)
Status: RESOLVED CODE_FIX    
Severity: normal CC: dsterba, fdmanana, rob
Priority: P3    
Hardware: All   
OS: Linux   
URL: https://github.com/landley/toybox/issues/306
Kernel Version: 5.15, 6.1, 6.4.3 Subsystem:
Regression: No Bisected commit-id:

Description Maksim Paimushkin 2023-07-18 21:00:55 UTC
The issue on GitHub was created a long time ago
https://github.com/landley/toybox/issues/306

Google uses "toybox" instead of "GNU tools" to build the Android kernel, the main problem is only with BTRFS, the build process gets stuck in an infinite loop when it calls the "gen_kheaders.sh" script.

Could anyone suggest a quick solution - fix gen_kheaders.sh with adding 'sort -z' or fix BTRFS behavior?

As mentioned on Github, this opens the door for DDoS attacks on BTRFS filesystems to spawn multiple zombie processes using the "readdir" function.
Comment 1 Rob Landley 2023-07-19 09:29:16 UTC
Here's a simple standalone reproducer for the bug:

#include <sys/types.h>
#include <dirent.h>
#include <stdio.h>

int main(int argc, char *argv[])
{
  DIR *dir = opendir(".");
  struct dirent *dd;

  while ((dd = readdir(dir))) {
    printf("%s\n", dd->d_name);
    rename(dd->d_name, "TEMPFILE");
    rename("TEMPFILE", dd->d_name);
  }
  closedir(dir);
}

Run in a directory with multiple files, it completes fine on ext4 or tmpfs but runs endlessly on btrfs, where it performs a denial-of-service attack against itself. Another process could presumably perform this denial of service against any readdir() loop on btrfs.
Comment 2 Filipe David Manana 2023-08-13 12:06:27 UTC
Fix here:

https://lore.kernel.org/linux-btrfs/c9ceb0e15d92d0634600603b38965d9b6d986b6d.1691923900.git.fdmanana@suse.com/

Thanks for the report.
Comment 3 David Sterba 2023-08-14 14:28:18 UTC
Patch merged, thanks.