You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

55 lines
1.9 KiB

  1. From 8312eaa576014cd9b965012af51bc1f967b12423 Mon Sep 17 00:00:00 2001
  2. From: Daniel Axtens <dja@axtens.net>
  3. Date: Tue, 1 Jan 2019 17:10:49 +1100
  4. Subject: [PATCH] iso9660: Fail when expected Rockridge extensions is missing
  5. A corrupted or malicious ISO9660 image can cause read_CE() to loop
  6. forever.
  7. read_CE() calls parse_rockridge(), expecting a Rockridge extension
  8. to be read. However, parse_rockridge() is structured as a while
  9. loop starting with a sanity check, and if the sanity check fails
  10. before the loop has run, the function returns ARCHIVE_OK without
  11. advancing the position in the file. This causes read_CE() to retry
  12. indefinitely.
  13. Make parse_rockridge() return ARCHIVE_WARN if it didn't read an
  14. extension. As someone with no real knowledge of the format, this
  15. seems more apt than ARCHIVE_FATAL, but both the call-sites escalate
  16. it to a fatal error immediately anyway.
  17. Found with a combination of AFL, afl-rb (FairFuzz) and qsym.
  18. ---
  19. libarchive/archive_read_support_format_iso9660.c | 11 ++++++++++-
  20. 1 file changed, 10 insertions(+), 1 deletion(-)
  21. diff --git a/libarchive/archive_read_support_format_iso9660.c b/libarchive/archive_read_support_format_iso9660.c
  22. index 28acfefbb..bad8f1dfe 100644
  23. --- a/libarchive/archive_read_support_format_iso9660.c
  24. +++ b/libarchive/archive_read_support_format_iso9660.c
  25. @@ -2102,6 +2102,7 @@ parse_rockridge(struct archive_read *a, struct file_info *file,
  26. const unsigned char *p, const unsigned char *end)
  27. {
  28. struct iso9660 *iso9660;
  29. + int entry_seen = 0;
  30. iso9660 = (struct iso9660 *)(a->format->data);
  31. @@ -2257,8 +2258,16 @@ parse_rockridge(struct archive_read *a, struct file_info *file,
  32. }
  33. p += p[2];
  34. + entry_seen = 1;
  35. + }
  36. +
  37. + if (entry_seen)
  38. + return (ARCHIVE_OK);
  39. + else {
  40. + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
  41. + "Tried to parse Rockridge extensions, but none found");
  42. + return (ARCHIVE_WARN);
  43. }
  44. - return (ARCHIVE_OK);
  45. }
  46. static int