Skip to content

Commit 4ecc512

Browse files
committed
gpg: Fix possible memory corruption in the armor parser.
* g10/armor.c (armor_filter): Fix faulty double increment. * common/iobuf.c (underflow_target): Assert that the filter implementations behave well. -- This fixes a bug in a code path which can only be reached with special crafted input data and would then error out at an upper layer due to corrupt input (every second byte in the buffer is unitialized garbage). No fuzzing has yet hit this case and we don't have a test case for this code path. However memory corruption can never be tolerated as it always has the protential for remode code execution. Reported-by: 8b79fe4dd0581c1cd000e1fbecba9f39e16a396a Fixes-commit: c27c741 which fixed Fixes-commit: 7d0efec Backported-from-master: 115d138 The bug was introduced on 1999-01-07 by me: * armor.c: Rewrote large parts. which I fixed on 1999-03-02 but missed to fix the other case: * armor.c (armor_filter): Fixed armor bypassing. Below is base64+gzipped test data which can be used with valgrind to show access to uninitalized memory in write(2) in the unpatched code. --8<---------------cut here---------------start------------->8--- H4sICIDd+WgCA3h4AO3QMQ6CQBCG0djOKbY3G05gscYFSRAJt/AExp6Di0cQG0ze a//MV0zOq3Pt+jFN3ZTKfLvP9ZLafqifJUe8juOjeZbVtSkbRPmRgICAgICAgICA gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA gICAgICAgICAgICAgICAgICAgICAgICAgMCXF6dYDgAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC7E14AAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwZ94aieId3+8EAA== --8<---------------cut here---------------end--------------->8---
1 parent ff30683 commit 4ecc512

File tree

2 files changed

+9
-3
lines changed

2 files changed

+9
-3
lines changed

common/iobuf.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2043,6 +2043,8 @@ underflow_target (iobuf_t a, int clear_pending_eof, size_t target)
20432043
rc = 0;
20442044
else
20452045
{
2046+
size_t tmplen;
2047+
20462048
/* If no buffered data and drain buffer has been setup, and drain
20472049
* buffer is largish, read data directly to drain buffer. */
20482050
if (a->d.len == 0
@@ -2055,8 +2057,10 @@ underflow_target (iobuf_t a, int clear_pending_eof, size_t target)
20552057
log_debug ("iobuf-%d.%d: underflow: A->FILTER (%lu bytes, to external drain)\n",
20562058
a->no, a->subno, (ulong)len);
20572059

2058-
rc = a->filter (a->filter_ov, IOBUFCTRL_UNDERFLOW, a->chain,
2060+
tmplen = len; /* Used to check for bugs in the filter. */
2061+
rc = a->filter (a->filter_ov, IOBUFCTRL_UNDERFLOW, a->chain,
20592062
a->e_d.buf, &len);
2063+
log_assert (len <= tmplen);
20602064
a->e_d.used = len;
20612065
len = 0;
20622066
}
@@ -2066,8 +2070,10 @@ underflow_target (iobuf_t a, int clear_pending_eof, size_t target)
20662070
log_debug ("iobuf-%d.%d: underflow: A->FILTER (%lu bytes)\n",
20672071
a->no, a->subno, (ulong)len);
20682072

2073+
tmplen = len; /* Used to check for bugs in the filter. */
20692074
rc = a->filter (a->filter_ov, IOBUFCTRL_UNDERFLOW, a->chain,
20702075
&a->d.buf[a->d.len], &len);
2076+
log_assert (len <= tmplen);
20712077
}
20722078
}
20732079
a->d.len += len;

g10/armor.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1302,8 +1302,8 @@ armor_filter( void *opaque, int control,
13021302
n = 0;
13031303
if( afx->buffer_len ) {
13041304
/* Copy the data from AFX->BUFFER to BUF. */
1305-
for(; n < size && afx->buffer_pos < afx->buffer_len; n++ )
1306-
buf[n++] = afx->buffer[afx->buffer_pos++];
1305+
for(; n < size && afx->buffer_pos < afx->buffer_len;)
1306+
buf[n++] = afx->buffer[afx->buffer_pos++];
13071307
if( afx->buffer_pos >= afx->buffer_len )
13081308
afx->buffer_len = 0;
13091309
}

0 commit comments

Comments
 (0)