Quellcode durchsuchen

dpkg: Use statfs() to retrieve the infodb filesystem block size

This fixes two related issues when the FIGETBSZ ioctl fails, it avoids
a file descriptor leak because we can get the block size before the
loop, and avoids a segfault when sorting the package array due to the
cliendata possibly being NULL on some of the package entries because
we can bail out before performing the actual sorting.

We use the Linux specific statfs(2), because it does way less work than
statvfs(3) and the surrounding code is already non-portable due to its
dependency on FIEMAP.

LP: #872734
Guillem Jover vor 14 Jahren
Ursprung
Commit
916bdba909
2 geänderte Dateien mit 9 neuen und 5 gelöschten Zeilen
  1. 2 0
      debian/changelog
  2. 7 5
      src/filesdb.c

+ 2 - 0
debian/changelog

@@ -24,6 +24,8 @@ dpkg (1.16.2) UNRELEASED; urgency=low
     Based on a patch by Kyle Willmon <kylewillmon@gmail.com>.
     Based on a patch by Kyle Willmon <kylewillmon@gmail.com>.
   * Add Pre-Depends on tar >= 1.23 (satisfied in stable) to dpkg due to it
   * Add Pre-Depends on tar >= 1.23 (satisfied in stable) to dpkg due to it
     using the ‘--warning=no-timestamp’ option. Closes: 642802
     using the ‘--warning=no-timestamp’ option. Closes: 642802
+  * Do not segfault on GNU/Linux when dpkg cannot retrieve the block size
+    for the filesystem containing the info database. LP: #872734
 
 
   [ Raphaël Hertzog ]
   [ Raphaël Hertzog ]
   * Update Dpkg::Shlibs to look into multiarch paths when cross-building
   * Update Dpkg::Shlibs to look into multiarch paths when cross-building

+ 7 - 5
src/filesdb.c

@@ -26,6 +26,7 @@
 #include <linux/fiemap.h>
 #include <linux/fiemap.h>
 #include <linux/fs.h>
 #include <linux/fs.h>
 #include <sys/ioctl.h>
 #include <sys/ioctl.h>
+#include <sys/vfs.h>
 #endif
 #endif
 #include <sys/types.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/stat.h>
@@ -374,8 +375,12 @@ pkg_sorter_by_listfile_phys_offs(const void *a, const void *b)
 static void
 static void
 pkg_files_optimize_load(struct pkg_array *array)
 pkg_files_optimize_load(struct pkg_array *array)
 {
 {
+  struct statfs fs;
   int i;
   int i;
-  int blocksize = 0;
+
+  /* Get the filesystem block size. */
+  if (statfs(pkgadmindir(), &fs) < 0)
+    return;
 
 
   /* Sort packages by the physical location of their list files, so that
   /* Sort packages by the physical location of their list files, so that
    * scanning them later will minimize disk drive head movements. */
    * scanning them later will minimize disk drive head movements. */
@@ -402,12 +407,9 @@ pkg_files_optimize_load(struct pkg_array *array)
     if (fd < 0)
     if (fd < 0)
       continue;
       continue;
 
 
-    if (!blocksize && ioctl(fd, FIGETBSZ, &blocksize) < 0)
-      break;
-
     memset(&fm, 0, sizeof(fm));
     memset(&fm, 0, sizeof(fm));
     fm.fiemap.fm_start = 0;
     fm.fiemap.fm_start = 0;
-    fm.fiemap.fm_length = blocksize;
+    fm.fiemap.fm_length = fs.f_bsize;
     fm.fiemap.fm_flags = 0;
     fm.fiemap.fm_flags = 0;
     fm.fiemap.fm_extent_count = 1;
     fm.fiemap.fm_extent_count = 1;