server/tftp_rom: fix dataspace leak

ROM dataspace and LwIP buffers are freed at session destruction.

Fixes #10
This commit is contained in:
Emery Hemingway
2016-03-08 13:30:00 +01:00
committed by Norman Feske
parent aadf20d39a
commit 58b58f1008

View File

@@ -64,12 +64,16 @@ class Tftp_rom::Session_component :
typedef Genode::String<128> Filename; typedef Genode::String<128> Filename;
Filename const _filename; Filename const _filename;
Rom_dataspace_capability _dataspace; Ram_dataspace_capability _dataspace;
Signal_context_capability _sigh; Signal_context_capability _sigh;
udp_pcb *_pcb; /* lwIP UDP context */ udp_pcb *_pcb; /* lwIP UDP context */
pbuf *_chain_head = NULL; /* lwIP buffer chain head */ pbuf *_chain_head = NULL;
pbuf *_chain_tail = NULL; /* lwIP buffer chain tail */ pbuf *_chain_tail = NULL;
/*
* References to both ends of the buffer chain
* are retained to make concatenation faster.
*/
unsigned long const _start; /* start of session */ unsigned long const _start; /* start of session */
@@ -85,7 +89,10 @@ class Tftp_rom::Session_component :
{ {
unlock(); unlock();
_ack_timeout = 0; _ack_timeout = 0;
pbuf_free(_chain_head); if (_chain_head != NULL) {
pbuf_free(_chain_head);
_chain_head = NULL;
}
} }
inline void timeout() inline void timeout()
@@ -139,7 +146,19 @@ class Tftp_rom::Session_component :
initial_request(); initial_request();
} }
~Session_component() { if (_pcb != NULL) udp_remove(_pcb); } ~Session_component()
{
using namespace Genode;
if (_pcb != NULL)
udp_remove(_pcb);
if (_chain_head != NULL)
pbuf_free(_chain_head);
if (_dataspace.valid())
env()->ram_session()->free(_dataspace);
}
/************************************** /**************************************
** Members available to lwIP thread ** ** Members available to lwIP thread **
@@ -210,9 +229,13 @@ class Tftp_rom::Session_component :
finalize(); finalize();
} }
/* data pointer is invalid after pbuf_cat */ if (_chain_head == NULL)
if (_chain_head == NULL) _chain_head = _chain_tail = data; _chain_head = _chain_tail = data;
else pbuf_chain(_chain_tail, data); else {
/* data pointer is invalid after pbuf_cat */
pbuf_cat(_chain_tail, data);
_chain_tail = _chain_tail->next;
}
if (done) /* construct the dataspace */ { if (done) /* construct the dataspace */ {
@@ -225,9 +248,8 @@ class Tftp_rom::Session_component :
for (pbuf *link = _chain_head; link != NULL; link = link->next) for (pbuf *link = _chain_head; link != NULL; link = link->next)
rom_len += link->len-4; rom_len += link->len-4;
Genode::Dataspace_capability ds = _dataspace = Genode::env()->ram_session()->alloc(rom_len);
Genode::env()->ram_session()->alloc(rom_len); uint8_t *rom_addr = Genode::env()->rm_session()->attach(_dataspace);
uint8_t *rom_addr = Genode::env()->rm_session()->attach(ds);
uint8_t *p = rom_addr; uint8_t *p = rom_addr;
for (pbuf *link = _chain_head; link != NULL; link = link->next) { for (pbuf *link = _chain_head; link != NULL; link = link->next) {
@@ -236,7 +258,6 @@ class Tftp_rom::Session_component :
p += len; p += len;
} }
_dataspace = Genode::static_cap_cast<Genode::Rom_dataspace>(ds);
Genode::env()->rm_session()->detach(rom_addr); Genode::env()->rm_session()->detach(rom_addr);
PLOG("%s retrieved", _filename.string()); PLOG("%s retrieved", _filename.string());
finalize(); finalize();
@@ -282,7 +303,9 @@ class Tftp_rom::Session_component :
Rom_dataspace_capability dataspace() override Rom_dataspace_capability dataspace() override
{ {
if (!done()) lock(); if (!done()) lock();
return _dataspace;
Dataspace_capability ds = _dataspace;
return static_cap_cast<Genode::Rom_dataspace>(ds);
}; };
void sigh(Signal_context_capability sigh) override { _sigh = sigh; } void sigh(Signal_context_capability sigh) override { _sigh = sigh; }