Page MenuHome GnuPG

gnupg hangs on truncated output
Closed, ResolvedPublic

Description

In Debian bug #503853 a problem has been reported, that gnupg hangs on truncated
output:

% echo '1234' | gpg --sign > foo

<I enter my passphrase>

% ls -l foo
-rw-r--r-- 1 wisq wisq 98 2008-10-28 15:19 foo
% dd if=foo of=bar bs=1 count=97
97+0 records in
97+0 records out
97 bytes (97 B) copied, 0.000480021 s, 202 kB/s
% gpg --verify bar

<hangs>

CPU usage then is 100%. Can this be catched and fixed?

Details

External Link
http://bugs.debian.org/503853
Version
1.4.9

Event Timeline

dleidert set External Link to http://bugs.debian.org/503853.
dleidert added projects: Debian, Bug Report.
dleidert added a subscriber: dleidert.

Even with the example file inthe Debina BTS, I can't replicate it with 1.4.8,
1.4.9. the current 1.4 svn version or gpg2. It is either a problem of libz or
more likely due to the amd64 CPUI. Unfortunately I don't have such a box
running right now.

Running gpg with "--debug 8" may help to track the problem down.

I see this then:

gpg: Optionen werden aus '/home/dl/.gnupg/gpg.conf' gelesen
gpg: DBG: begin inflate: avail_in=0, avail_out=8192, inbuf=2048
gpg: DBG: enter inflate: avail_in=96, avail_out=8192
gpg: DBG: leave inflate: avail_in=0, avail_out=8093, zrc=0
gpg: DBG: enter inflate: avail_in=1, avail_out=8093
gpg: DBG: leave inflate: avail_in=0, avail_out=8092, zrc=0
gpg: DBG: enter inflate: avail_in=1, avail_out=8092
gpg: DBG: leave inflate: avail_in=0, avail_out=8091, zrc=0
gpg: DBG: enter inflate: avail_in=1, avail_out=8091
gpg: DBG: leave inflate: avail_in=0, avail_out=8090, zrc=0
gpg: DBG: enter inflate: avail_in=1, avail_out=8090
gpg: DBG: leave inflate: avail_in=0, avail_out=8089, zrc=0
gpg: DBG: enter inflate: avail_in=1, avail_out=8089
gpg: DBG: leave inflate: avail_in=0, avail_out=8088, zrc=0
[...]
gpg: DBG: leave inflate: avail_in=0, avail_out=2, zrc=0
gpg: DBG: enter inflate: avail_in=1, avail_out=2
gpg: DBG: leave inflate: avail_in=0, avail_out=1, zrc=0
gpg: DBG: enter inflate: avail_in=1, avail_out=1
gpg: DBG: leave inflate: avail_in=0, avail_out=0, zrc=0
gpg: DBG: do_uncompress: returning 8192 bytes
gpg: DBG: begin inflate: avail_in=0, avail_out=8192, inbuf=2048
gpg: DBG: enter inflate: avail_in=1, avail_out=8192
gpg: DBG: leave inflate: avail_in=0, avail_out=8191, zrc=0
gpg: DBG: enter inflate: avail_in=1, avail_out=8191
gpg: DBG: leave inflate: avail_in=0, avail_out=8190, zrc=0
gpg: DBG: enter inflate: avail_in=1, avail_out=8190

Looks like a loop(?).

JFTR: I have only tested on an amd64 box. But I can check this later with an
i386 box too.

Might be a zlib problem; see also T1011 .

i386: no loop

[..]
gpg: DBG: leave inflate: avail_in=0, avail_out=0, zrc=0
gpg: DBG: do_uncompress: returning 8192 bytes
gpg: [don't know]: garbled packet detected

Hm. Comparing --debug-all on both architectures I see clear differences. Not
sure if they count. But the value for length on the amd64 box, when it re-enters
the loop looks weired:

gpg: DBG: parse_packet(iob=1): type=2 length=70 (parse.../../g10/mainproc.c.1236)
gpg: DBG: mpi_alloc(192)
gpg: DBG: mpi_alloc_limb_space(192)
gpg: DBG: mpi_alloc(192)
gpg: DBG: mpi_alloc_limb_space(192)
gpg: DBG: parse_packet(iob=1): type=63 length=18446744073709551615 (new_ctb)
(parse.../../g10/mainproc.c.1236)
gpg: DBG: iobuf-1.1: underflow: req=8192
gpg: DBG: begin inflate: avail_in=0, avail_out=8192, inbuf=2048
gpg: DBG: iobuf-1.0: underflow: eof (no filter)
gpg: DBG: enter inflate: avail_in=1, avail_out=8192
gpg: DBG: leave inflate: avail_in=0, avail_out=8191, zrc=0

Well that value is 0xFFFFFFFFFFFFFFFF.

Found the cuplrit:

if (pktlen == 0xffffffff) {
    /* with a some probability this is caused by a problem in the
     * the uncompressing layer - in some error cases it just loops
     * and spits out 0xff bytes. */
    log_error ("%s: garbled packet detected\n", iobuf_where(inp) );

g10_exit (2);

}

pktlen is an unsigned long and thus the test above does not work with 64 bit values.

I see. Then comparing the value to ULONG_MAX should solve the issue, right?

Fixed in SVN using

if (pktlen == (unsigned long)(-1))