Просмотр исходного кода

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 лет назад: 14
Родитель
Сommit
916bdba909
2 измененных файлов с 9 добавлено и 5 удалено
  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>.
   * Add Pre-Depends on tar >= 1.23 (satisfied in stable) to dpkg due to it
     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 ]
   * 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/fs.h>
 #include <sys/ioctl.h>
+#include <sys/vfs.h>
 #endif
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -374,8 +375,12 @@ pkg_sorter_by_listfile_phys_offs(const void *a, const void *b)
 static void
 pkg_files_optimize_load(struct pkg_array *array)
 {
+  struct statfs fs;
   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
    * scanning them later will minimize disk drive head movements. */
@@ -402,12 +407,9 @@ pkg_files_optimize_load(struct pkg_array *array)
     if (fd < 0)
       continue;
 
-    if (!blocksize && ioctl(fd, FIGETBSZ, &blocksize) < 0)
-      break;
-
     memset(&fm, 0, sizeof(fm));
     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_extent_count = 1;