Freeing frag_buffer structure without unlinking it from frag_buffers
linked list may lead to the list being broken when the memory is reused.
The same problem can happen with timers list if frag_buffer is freed
while its embedded retry_timer is still running.
After this change, list_for_each_entry_safe() has to be used in
ipv4_reassemble() as free_fragbuf() is called inside the cycle body.
Signed-off-by: Michal Kubecek <mku...@su...>
---
src/net/ipv4.c | 7 +++++--
1 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/src/net/ipv4.c b/src/net/ipv4.c
index 30c1541..bd41978 100644
--- a/src/net/ipv4.c
+++ b/src/net/ipv4.c
@@ -148,11 +148,13 @@ static void ipv4_frag_expired ( struct retry_timer *timer __unused,
}
/**
- * Free fragment buffer
+ * Unlink and free fragment buffer
*
* @v fragbug Fragment buffer
*/
static void free_fragbuf ( struct frag_buffer *fragbuf ) {
+ list_del ( &fragbuf->list );
+ stop_timer ( &fragbuf->frag_timer );
free ( fragbuf );
}
@@ -165,11 +167,12 @@ static void free_fragbuf ( struct frag_buffer *fragbuf ) {
static struct io_buffer * ipv4_reassemble ( struct io_buffer * iobuf ) {
struct iphdr *iphdr = iobuf->data;
struct frag_buffer *fragbuf;
+ struct frag_buffer *fragtmp;
/**
* Check if the fragment belongs to any fragment series
*/
- list_for_each_entry ( fragbuf, &frag_buffers, list ) {
+ list_for_each_entry_safe ( fragbuf, fragtmp, &frag_buffers, list ) {
if ( fragbuf->ident == iphdr->ident &&
fragbuf->src.s_addr == iphdr->src.s_addr ) {
/**
--
1.7.7
|