* [patch] [gdbserver] Fix memory corruption
@ 2011-03-01 21:34 Jan Kratochvil
2011-03-02 15:35 ` Pedro Alves
0 siblings, 1 reply; 5+ messages in thread
From: Jan Kratochvil @ 2011-03-01 21:34 UTC (permalink / raw)
To: gdb-patches
Hi,
gdb.server/ext-run.exp always crashes during the nightly regression tests:
info os processes
memory clobbered past end of allocated block
Remote communication error. Target disconnected.: Connection reset by peer.
(gdb) FAIL: gdb.server/ext-run.exp: get process list (pattern 1)
Probably OK to check in but I rather ask.
To make it easily reproducible one can disable try_rle() by patching it:
+return 1;
/* Don't go past '~'. */
So that putpkt_binary_1's cnt == 16383 will overrun PBUFSIZ 16384 by 4 bytes.
Thanks,
Jan
gdb/gdbserver/
2011-03-01 Jan Kratochvil <jan.kratochvil@redhat.com>
* remote-utils.c (putpkt_binary_1): Calculate BUF2 size dynamically.
--- a/gdb/gdbserver/remote-utils.c
+++ b/gdb/gdbserver/remote-utils.c
@@ -725,7 +725,7 @@ putpkt_binary_1 (char *buf, int cnt, int is_notif)
char *p;
int cc;
- buf2 = xmalloc (PBUFSIZ);
+ buf2 = xmalloc (1 + cnt + 4);
/* Copy the packet into buffer BUF2, encapsulating it
and giving it a checksum. */
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [patch] [gdbserver] Fix memory corruption 2011-03-01 21:34 [patch] [gdbserver] Fix memory corruption Jan Kratochvil @ 2011-03-02 15:35 ` Pedro Alves 2011-03-02 16:51 ` Jan Kratochvil 0 siblings, 1 reply; 5+ messages in thread From: Pedro Alves @ 2011-03-02 15:35 UTC (permalink / raw) To: gdb-patches; +Cc: Jan Kratochvil On Tuesday 01 March 2011 21:34:28, Jan Kratochvil wrote: > Hi, > > gdb.server/ext-run.exp always crashes during the nightly regression tests: > info os processes > memory clobbered past end of allocated block > Remote communication error. Target disconnected.: Connection reset by peer. > (gdb) FAIL: gdb.server/ext-run.exp: get process list (pattern 1) > > Probably OK to check in but I rather ask. > > To make it easily reproducible one can disable try_rle() by patching it: > +return 1; > /* Don't go past '~'. */ I can't reproduce it. > > So that putpkt_binary_1's cnt == 16383 will overrun PBUFSIZ 16384 by 4 bytes. How did you get that large of a `cnt' in the first place? The largest I get is 16379. gdb does: /* Request only enough to fit in a single packet. The actual data may not, since we don't know how much of it will need to be escaped; the target is free to respond with slightly less data. We subtract five to account for the response type and the protocol frame. */ n = min (get_remote_packet_size () - 5, len); snprintf (rs->buf, get_remote_packet_size () - 4, "qXfer:%s:read:%s:%s,%s", object_name, annex ? annex : "", phex_nz (offset, sizeof offset), phex_nz (n, sizeof n)); that is, you shouldn't get a read request that big. It looks like server.c:handle_qxfer's len caping is forgetting to account for the $, # and checksum (should be fixed), but I don't think that's the real cause in your example, since it only pushes back to gdb as much data as it requested. gdb's putpkt_binary reads: /* Send a packet to the remote machine, with error checking. The data of the packet is in BUF. The string in BUF can be at most get_remote_packet_size () - 5 to account for the $, # and checksum, and for a possible /0 if we are debugging (remote_debug) and want to print the sent packet as a string. */ gdbserver's version does not have that comment, although it should. Both versions lack an assertion catching the case of trying to send too much for the packet buffer size. > > > Thanks, > Jan > > > gdb/gdbserver/ > 2011-03-01 Jan Kratochvil <jan.kratochvil@redhat.com> > > * remote-utils.c (putpkt_binary_1): Calculate BUF2 size dynamically. > > --- a/gdb/gdbserver/remote-utils.c > +++ b/gdb/gdbserver/remote-utils.c > @@ -725,7 +725,7 @@ putpkt_binary_1 (char *buf, int cnt, int is_notif) > char *p; > int cc; > > - buf2 = xmalloc (PBUFSIZ); > + buf2 = xmalloc (1 + cnt + 4); > > /* Copy the packet into buffer BUF2, encapsulating it > and giving it a checksum. */ > -- Pedro Alves ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [patch] [gdbserver] Fix memory corruption 2011-03-02 15:35 ` Pedro Alves @ 2011-03-02 16:51 ` Jan Kratochvil 2011-03-02 18:00 ` Pedro Alves 0 siblings, 1 reply; 5+ messages in thread From: Jan Kratochvil @ 2011-03-02 16:51 UTC (permalink / raw) To: Pedro Alves; +Cc: gdb-patches On Wed, 02 Mar 2011 16:35:16 +0100, Pedro Alves wrote: > On Tuesday 01 March 2011 21:34:28, Jan Kratochvil wrote: > > To make it easily reproducible one can disable try_rle() by patching it: > > +return 1; > > /* Don't go past '~'. */ > > I can't reproduce it. You may need also -lmcheck for gdbserver. > > So that putpkt_binary_1's cnt == 16383 will overrun PBUFSIZ 16384 by 4 bytes. > > How did you get that large of a `cnt' in the first place? The largest > I get is 16379. remote_escape_output is called with OUT_MAXLEN == PBUFSIZ - 2 == 16382 and returns it +1, therefore 16383. #8 0x0000000000404ca3 in putpkt_binary_1 (buf=0x258f2c0 "mmn"..., cnt=16381, is_notif=0) at remote-utils.c:801 801 free (buf2); Maybe your system does not have # cat /proc/*/cmdline|tr -cd '$#}*'|wc -c 84 > gdb does: > > /* Request only enough to fit in a single packet. The actual data > may not, since we don't know how much of it will need to be escaped; > the target is free to respond with slightly less data. We subtract > five to account for the response type and the protocol frame. */ > n = min (get_remote_packet_size () - 5, len); > snprintf (rs->buf, get_remote_packet_size () - 4, "qXfer:%s:read:%s:%s,%s", > object_name, annex ? annex : "", > phex_nz (offset, sizeof offset), > phex_nz (n, sizeof n)); > > that is, you shouldn't get a read request that big. Yes, the request is just for 16378 but gdbserver returns more. > It looks like server.c:handle_qxfer's len caping is forgetting > to account for the $, # and checksum (should be fixed), but I don't > think that's the real cause in your example, since it only pushes back > to gdb as much data as it requested. Before starting to chase off-by-one here and off-by-one there what is the practical purpose of such strict packet limits? When TCP is in use shouldn't the code all around just support arbitrary packet sizes? To get rid any constant buffer sizes etc. Then there still can remain some vague fragmentation on the GDB client side but both sides should be able to accept arbitrary packet sizes, shouldn't they? Thanks, Jan ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [patch] [gdbserver] Fix memory corruption 2011-03-02 16:51 ` Jan Kratochvil @ 2011-03-02 18:00 ` Pedro Alves 2011-03-07 20:26 ` Jan Kratochvil 0 siblings, 1 reply; 5+ messages in thread From: Pedro Alves @ 2011-03-02 18:00 UTC (permalink / raw) To: Jan Kratochvil; +Cc: gdb-patches On Wednesday 02 March 2011 16:51:35, Jan Kratochvil wrote: > On Wed, 02 Mar 2011 16:35:16 +0100, Pedro Alves wrote: > > I can't reproduce it. > > You may need also -lmcheck for gdbserver. > Maybe your system does not have > # cat /proc/*/cmdline|tr -cd '$#}*'|wc -c > 84 Ah! Yes, that's the reason. Thanks. I had tried valgrind before and nothing complained. Running a bunch of "tail -f }}}}}}}}}}}}}}}}}}/a" processes helped. :-) > > > > So that putpkt_binary_1's cnt == 16383 will overrun PBUFSIZ 16384 by 4 bytes. > > > > How did you get that large of a `cnt' in the first place? The largest > > I get is 16379. > > remote_escape_output is called with OUT_MAXLEN == PBUFSIZ - 2 == 16382 and > returns it +1, therefore 16383. > #8 0x0000000000404ca3 in putpkt_binary_1 (buf=0x258f2c0 "mmn"..., cnt=16381, is_notif=0) at remote-utils.c:801 > 801 free (buf2); > > Yes, the request is just for 16378 but gdbserver returns more. I see now. > Before starting to chase off-by-one here and off-by-one there what is the > practical purpose of such strict packet limits? The remote protocol is designed to be implementable in tiny chips as well, where you typically have a static buffer for the incoming packet buffer. malloc is a luxury you don't have in many of those scenarios. So for outgoing packets, gdb needs to be careful about that. For incoming packets, gdb dynamically grows the buffer as it finds its receiving larger packets. So I think your patch is indeed okay. I wouldn't mind a comment explaining the magic numbers, or replacing them with 'strlen ("$#NN")' like in remote.c: /* Compute the size of the actual payload by subtracting out the packet header and footer overhead: "$M<memaddr>,<len>:...#nn". */ payload_size -= strlen ("$,:#NN"); > When TCP is in use shouldn't the code all around just support arbitrary packet > sizes? To get rid any constant buffer sizes etc. Then there still can remain > some vague fragmentation on the GDB client side but both sides should be able > to accept arbitrary packet sizes, shouldn't they? FYI, gdbserver works with rs232 as well. -- Pedro Alves ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [patch] [gdbserver] Fix memory corruption 2011-03-02 18:00 ` Pedro Alves @ 2011-03-07 20:26 ` Jan Kratochvil 0 siblings, 0 replies; 5+ messages in thread From: Jan Kratochvil @ 2011-03-07 20:26 UTC (permalink / raw) To: Pedro Alves; +Cc: gdb-patches On Wed, 02 Mar 2011 19:00:45 +0100, Pedro Alves wrote: > On Wednesday 02 March 2011 16:51:35, Jan Kratochvil wrote: > > Before starting to chase off-by-one here and off-by-one there what is the > > practical purpose of such strict packet limits? > > The remote protocol is designed to be implementable in tiny chips as > well, where you typically have a static buffer for the incoming packet > buffer. malloc is a luxury you don't have in many of those scenarios. > So for outgoing packets, gdb needs to be careful about that. For > incoming packets, gdb dynamically grows the buffer as it finds its > receiving larger packets. But FSF gdbserver can receive arbitrarily large packets and allocate everything dynamically. It can also send arbitrarily large responses. Thanks for the info, although for next updates, not this one. > So I think your patch is indeed okay. > I wouldn't mind a comment explaining the magic numbers, or replacing > them with 'strlen ("$#NN")' like in remote.c: Done. Checked in. Thanks, Jan http://sourceware.org/ml/gdb-cvs/2011-03/msg00106.html --- src/gdb/gdbserver/ChangeLog 2011/03/06 07:40:52 1.465 +++ src/gdb/gdbserver/ChangeLog 2011/03/07 20:15:12 1.466 @@ -1,3 +1,7 @@ +2011-03-07 Jan Kratochvil <jan.kratochvil@redhat.com> + + * remote-utils.c (putpkt_binary_1): Calculate BUF2 size dynamically. + 2011-03-06 Yao Qi <yao@codesourcery.com> * Makefile.in (REQUIRED_SUBDIRS): Remove $(LIBCOMMON_DIR). --- src/gdb/gdbserver/remote-utils.c 2011/01/25 10:09:19 1.84 +++ src/gdb/gdbserver/remote-utils.c 2011/03/07 20:15:12 1.85 @@ -725,7 +725,7 @@ char *p; int cc; - buf2 = xmalloc (PBUFSIZ); + buf2 = xmalloc (strlen ("$") + cnt + strlen ("#nn") + 1); /* Copy the packet into buffer BUF2, encapsulating it and giving it a checksum. */ ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2011-03-07 20:18 UTC | newest] Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2011-03-01 21:34 [patch] [gdbserver] Fix memory corruption Jan Kratochvil 2011-03-02 15:35 ` Pedro Alves 2011-03-02 16:51 ` Jan Kratochvil 2011-03-02 18:00 ` Pedro Alves 2011-03-07 20:26 ` Jan Kratochvil
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox