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.