* [Qemu-devel] [PATCH v2 0/2] net: check payload length and minor updates @ 2016-02-23 16:08 P J P 2016-02-23 16:08 ` [Qemu-devel] [PATCH v2 1/2] net: check packet payload length P J P 2016-02-23 16:08 ` [Qemu-devel] [PATCH v2 2/2] net: minor indentation updates P J P 0 siblings, 2 replies; 7+ messages in thread From: P J P @ 2016-02-23 16:08 UTC (permalink / raw) To: Qemu Developers; +Cc: Jason Wang, Prasad J Pandit, Markus Armbruster, Liu Ling From: Prasad J Pandit <pjp@fedoraproject.org> The 'net_checksum_calculate' routine reads payload length from the packet. It could exceed the given data length value and lead to OOB memory access. While fixing that I also came across couple of minor coding style glitches. This series fixes both these issues as per review in -> https://lists.gnu.org/archive/html/qemu-devel/2016-02/msg03799.html -> https://lists.gnu.org/archive/html/qemu-devel/2016-02/msg04062.html Thank you. -- Prasad J Pandit (2): net: check packet payload length net: minor indentation updates net/checksum.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) -- 2.5.0 ^ permalink raw reply [flat|nested] 7+ messages in thread
* [Qemu-devel] [PATCH v2 1/2] net: check packet payload length 2016-02-23 16:08 [Qemu-devel] [PATCH v2 0/2] net: check payload length and minor updates P J P @ 2016-02-23 16:08 ` P J P 2016-02-26 6:10 ` Jason Wang 2016-02-23 16:08 ` [Qemu-devel] [PATCH v2 2/2] net: minor indentation updates P J P 1 sibling, 1 reply; 7+ messages in thread From: P J P @ 2016-02-23 16:08 UTC (permalink / raw) To: Qemu Developers; +Cc: Jason Wang, Prasad J Pandit, Markus Armbruster, Liu Ling From: Prasad J Pandit <pjp@fedoraproject.org> While computing IP checksum, 'net_checksum_calculate' reads payload length from the packet. It could exceed the given 'data' buffer size. Add a check to avoid it. Reported-by: Liu Ling <liuling-it@360.cn> Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org> --- net/checksum.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) Update as per review: -> https://lists.gnu.org/archive/html/qemu-devel/2016-02/msg04062.html diff --git a/net/checksum.c b/net/checksum.c index 14c0855..bd89083 100644 --- a/net/checksum.c +++ b/net/checksum.c @@ -59,6 +59,11 @@ void net_checksum_calculate(uint8_t *data, int length) int hlen, plen, proto, csum_offset; uint16_t csum; + /* Ensure data has complete L2 & L3 headers. */ + if (length < 14 + 20) { + return; + } + if ((data[14] & 0xf0) != 0x40) return; /* not IPv4 */ hlen = (data[14] & 0x0f) * 4; @@ -76,8 +81,9 @@ void net_checksum_calculate(uint8_t *data, int length) return; } - if (plen < csum_offset+2) - return; + if (plen < csum_offset + 2 || plen + hlen >= length) { + return; + } data[14+hlen+csum_offset] = 0; data[14+hlen+csum_offset+1] = 0; -- 2.5.0 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [Qemu-devel] [PATCH v2 1/2] net: check packet payload length 2016-02-23 16:08 ` [Qemu-devel] [PATCH v2 1/2] net: check packet payload length P J P @ 2016-02-26 6:10 ` Jason Wang 2016-03-01 6:48 ` P J P 0 siblings, 1 reply; 7+ messages in thread From: Jason Wang @ 2016-02-26 6:10 UTC (permalink / raw) To: P J P, Qemu Developers; +Cc: Liu Ling, Prasad J Pandit, Markus Armbruster On 02/24/2016 12:08 AM, P J P wrote: > From: Prasad J Pandit <pjp@fedoraproject.org> > > While computing IP checksum, 'net_checksum_calculate' reads > payload length from the packet. It could exceed the given 'data' > buffer size. Add a check to avoid it. > > Reported-by: Liu Ling <liuling-it@360.cn> > Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org> > --- > net/checksum.c | 10 ++++++++-- > 1 file changed, 8 insertions(+), 2 deletions(-) > > Update as per review: > -> https://lists.gnu.org/archive/html/qemu-devel/2016-02/msg04062.html > > diff --git a/net/checksum.c b/net/checksum.c > index 14c0855..bd89083 100644 > --- a/net/checksum.c > +++ b/net/checksum.c > @@ -59,6 +59,11 @@ void net_checksum_calculate(uint8_t *data, int length) > int hlen, plen, proto, csum_offset; > uint16_t csum; > I must say this is still far from perfect, since it has too assumptions . But I agree we can fix OOB first. > + /* Ensure data has complete L2 & L3 headers. */ > + if (length < 14 + 20) { > + return; > + } > + > if ((data[14] & 0xf0) != 0x40) > return; /* not IPv4 */ > hlen = (data[14] & 0x0f) * 4; > @@ -76,8 +81,9 @@ void net_checksum_calculate(uint8_t *data, int length) > return; > } > > - if (plen < csum_offset+2) > - return; > + if (plen < csum_offset + 2 || plen + hlen >= length) { > + return; > + } Should we count mac header here? Did "plen + hlen >= length" imply "14 + hlen + csum_offset + 1" < length? Looks not. Consider a TCP packet can report evil plen (e.g 20) but just have 10 bytes payload in fact. In this case: hlen = 20, plen = 20, csum_offset = 16, length = 44 which can pass all the above tests, but 14 + hlen + csum_offset = 50 which is greater than length. > > data[14+hlen+csum_offset] = 0; > data[14+hlen+csum_offset+1] = 0; ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [Qemu-devel] [PATCH v2 1/2] net: check packet payload length 2016-02-26 6:10 ` Jason Wang @ 2016-03-01 6:48 ` P J P 2016-03-02 3:21 ` Jason Wang 0 siblings, 1 reply; 7+ messages in thread From: P J P @ 2016-03-01 6:48 UTC (permalink / raw) To: Jason Wang; +Cc: Liu Ling, Qemu Developers, Markus Armbruster Hello Jason, +-- On Fri, 26 Feb 2016, Jason Wang wrote --+ | Should we count mac header here? Did "plen + hlen >= length" imply "14 + | hlen + csum_offset + 1" < length? | | Looks not. Consider a TCP packet can report evil plen (e.g 20) but just | have 10 bytes payload in fact. In this case: | | hlen = 20, plen = 20, csum_offset = 16, length = 44 which can pass all | the above tests, but 14 + hlen + csum_offset = 50 which is greater than | length. Ummn, not sure. hlen + plen = total length(IP + TCP/UDP), 20+20 != 44. 'length' is also used to read and allocate requisite buffers in other parts from where net_checksum_calculate() is called, === etsec->tx_buffer = g_realloc(etsec->tx_buffer, etsec->tx_buffer_len + bd->length); ... /* Update buffer length */ etsec->tx_buffer_len += bd->length; process_tx_fcb(etsec); -> net_checksum_calculate(etsec->tx_buffer + 8, etsec->tx_buffer_len - 8); OR memcpy(tmpbuf, page + txreq.offset, txreq.size); net_checksum_calculate(tmpbuf, txreq.size); === - With 'length < 14 + 20', we ensure that L2 & L3 headers are complete. 44 - 34 = 10, TCP/UDP header is incomplete. I think 'plen=20 != 10' hints at an error in other parts of the code? Also if data buffer has more space than actual data, OOB access may not occur. -- Prasad J Pandit / Red Hat Product Security Team 47AF CE69 3A90 54AA 9045 1053 DD13 3D32 FE5B 041F ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [Qemu-devel] [PATCH v2 1/2] net: check packet payload length 2016-03-01 6:48 ` P J P @ 2016-03-02 3:21 ` Jason Wang 2016-03-02 12:01 ` P J P 0 siblings, 1 reply; 7+ messages in thread From: Jason Wang @ 2016-03-02 3:21 UTC (permalink / raw) To: P J P; +Cc: Markus Armbruster, Qemu Developers, Liu Ling On 03/01/2016 02:48 PM, P J P wrote: > Hello Jason, > > +-- On Fri, 26 Feb 2016, Jason Wang wrote --+ > | Should we count mac header here? Did "plen + hlen >= length" imply "14 + > | hlen + csum_offset + 1" < length? > | > | Looks not. Consider a TCP packet can report evil plen (e.g 20) but just > | have 10 bytes payload in fact. In this case: > | > | hlen = 20, plen = 20, csum_offset = 16, length = 44 which can pass all > | the above tests, but 14 + hlen + csum_offset = 50 which is greater than > | length. > > Ummn, not sure. hlen + plen = total length(IP + TCP/UDP), 20+20 != 44. > 'length' is also used to read and allocate requisite buffers in other parts > from where net_checksum_calculate() is called, > > === > etsec->tx_buffer = g_realloc(etsec->tx_buffer, > etsec->tx_buffer_len + bd->length); > ... > /* Update buffer length */ > etsec->tx_buffer_len += bd->length; > > process_tx_fcb(etsec); > -> net_checksum_calculate(etsec->tx_buffer + 8, > etsec->tx_buffer_len - 8); > > OR > > memcpy(tmpbuf, page + txreq.offset, txreq.size); > net_checksum_calculate(tmpbuf, txreq.size); > === > > - With 'length < 14 + 20', we ensure that L2 & L3 headers are complete. How about L4, since we will calculate L4 checksum I believe? And it looks like the following check: plen + hlen >= length only count L3 header plus payload? > 44 - 34 = 10, TCP/UDP header is incomplete. > > I think 'plen=20 != 10' hints at an error in other parts of the code? Well, the point is. If we want depend on callers to do all the checks, we need fix all the callers. Otherwise, we need to do all the check in net_checksum_calculate() itself (E.g to handle all kinds of evil packets). > Also if > data buffer has more space than actual data, OOB access may not occur. > > -- > Prasad J Pandit / Red Hat Product Security Team > 47AF CE69 3A90 54AA 9045 1053 DD13 3D32 FE5B 041F > ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [Qemu-devel] [PATCH v2 1/2] net: check packet payload length 2016-03-02 3:21 ` Jason Wang @ 2016-03-02 12:01 ` P J P 0 siblings, 0 replies; 7+ messages in thread From: P J P @ 2016-03-02 12:01 UTC (permalink / raw) To: Jason Wang; +Cc: Markus Armbruster, Qemu Developers, Liu Ling Hello Jason, +-- On Wed, 2 Mar 2016, Jason Wang wrote --+ | How about L4, since we will calculate L4 checksum I believe? And it | looks like the following check: | | plen + hlen >= length | only count L3 header plus payload? Yes, I've sent a revised patch v3. Thank you. -- Prasad J Pandit / Red Hat Product Security Team 47AF CE69 3A90 54AA 9045 1053 DD13 3D32 FE5B 041F ^ permalink raw reply [flat|nested] 7+ messages in thread
* [Qemu-devel] [PATCH v2 2/2] net: minor indentation updates 2016-02-23 16:08 [Qemu-devel] [PATCH v2 0/2] net: check payload length and minor updates P J P 2016-02-23 16:08 ` [Qemu-devel] [PATCH v2 1/2] net: check packet payload length P J P @ 2016-02-23 16:08 ` P J P 1 sibling, 0 replies; 7+ messages in thread From: P J P @ 2016-02-23 16:08 UTC (permalink / raw) To: Qemu Developers; +Cc: Jason Wang, Prasad J Pandit, Markus Armbruster, Liu Ling From: Prasad J Pandit <pjp@fedoraproject.org> Due indentation and braces were missing at places, added them. Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org> --- net/checksum.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) Update as per review: -> https://lists.gnu.org/archive/html/qemu-devel/2016-02/msg03799.html diff --git a/net/checksum.c b/net/checksum.c index bd89083..c3f1f71 100644 --- a/net/checksum.c +++ b/net/checksum.c @@ -38,8 +38,9 @@ uint32_t net_checksum_add_cont(int len, uint8_t *buf, int seq) uint16_t net_checksum_finish(uint32_t sum) { - while (sum>>16) - sum = (sum & 0xFFFF)+(sum >> 16); + while (sum >> 16) { + sum = (sum & 0xFFFF) + (sum >> 16); + } return ~sum; } @@ -63,22 +64,23 @@ void net_checksum_calculate(uint8_t *data, int length) if (length < 14 + 20) { return; } + if ((data[14] & 0xf0) != 0x40) { + return; /* not IPv4 */ + } - if ((data[14] & 0xf0) != 0x40) - return; /* not IPv4 */ hlen = (data[14] & 0x0f) * 4; plen = (data[16] << 8 | data[17]) - hlen; proto = data[23]; switch (proto) { case PROTO_TCP: - csum_offset = 16; - break; + csum_offset = 16; + break; case PROTO_UDP: - csum_offset = 6; - break; + csum_offset = 6; + break; default: - return; + return; } if (plen < csum_offset + 2 || plen + hlen >= length) { -- 2.5.0 ^ permalink raw reply related [flat|nested] 7+ messages in thread
end of thread, other threads:[~2016-03-02 12:02 UTC | newest] Thread overview: 7+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2016-02-23 16:08 [Qemu-devel] [PATCH v2 0/2] net: check payload length and minor updates P J P 2016-02-23 16:08 ` [Qemu-devel] [PATCH v2 1/2] net: check packet payload length P J P 2016-02-26 6:10 ` Jason Wang 2016-03-01 6:48 ` P J P 2016-03-02 3:21 ` Jason Wang 2016-03-02 12:01 ` P J P 2016-02-23 16:08 ` [Qemu-devel] [PATCH v2 2/2] net: minor indentation updates P J P
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).