Package: devscripts
Version: 2.17.12ubuntu1
Severity: normal
File: /usr/bin/hardening-check
Tags: patch

Dear Maintainer,

When hardening-check runs "readelf", it's possible that a large stderr
will fill the internal pipe before readelf exits, blocking the process
forever. This can happen with things like running hardening-check against
guile's "assembly.go" file:

$ readelf -sW assembly.go

Symbol table '.symtab' contains 872 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000 39720 FUNC    LOCAL  HIDDEN     4 
readelf: Warning: local symbol 0 found at index >= .symtab's sh_info value of 0
...
   871: 000000000003539c 0x3dba0 FUNC    LOCAL  HIDDEN     4 
readelf: Warning: local symbol 871 found at index >= .symtab's sh_info value of 0

The attached patch corrects this by keeping stdout and stderr flushed
while waiting for process termination.

Thanks!

-Kees
--- hardening-check     2018-07-10 07:17:17.360005306 -0700
+++ /home/kees/bin/hardening-check      2018-07-10 07:14:25.205562133 -0700
@@ -9,6 +9,7 @@
 use IPC::Open3;
 use Symbol qw(gensym);
 use Term::ANSIColor;
+use IO::Select;
 
 my $skip_pie = 0;
 my $skip_stackprotector = 0;
@@ -180,19 +181,35 @@
     $stdout = gensym;
     $stderr = gensym;
     $pid = open3(gensym, $stdout, $stderr, @cmd);
-    my $collect = "";
-    while ( <$stdout> ) {
-        $collect .= $_;
+
+    my $selector = IO::Select->new( );
+    $selector->add($stdout);
+    $selector->add($stderr);
+
+    my $collect_out = "";
+    my $collect_err = "";
+
+    while (!eof($stdout) || !eof($stderr)) {
+        my @ready = $selector->can_read();
+        foreach my $fh (@ready) {
+            my $buf;
+            read($fh, $buf, 4096);
+
+            if ($fh == $stdout) {
+                $collect_out .= $buf;
+            } else {
+                $collect_err .= $buf;
+            }
+        }
     }
+
     waitpid($pid, 0);
     my $rc = $?;
     if ($rc != 0) {
-        while ( <$stderr> ) {
-            print STDERR;
-        }
+        print STDERR $collect_err;
         return "";
     }
-    return $collect;
+    return $collect_out;
 }
 
 # Find the libc used in this executable, if any.

Reply via email to