Browse files

rtrlib/rtr: Ensure shadow tables are only freed when initialized (#204)

From the Bug report:
> If rtr_receive_pdu returns an error code, the execution flow is
> redirected to the cleanup label. If ->is_resetting is now true (e.g.,
> because it was set by a CACHE_RESPONSE PDU processed by
> rtr_handle_cache_response_pdu), pfx_table_free_without_notify and
> spki_table_free_without_notify are executing multiple operations on this
> uninitialized data.

This patch ensures the cleanup code can check whether the shadow tables
have been initialized and only frees them if they are.
  • Loading branch information...
mroethke authored and waehlisch committed Dec 14, 2018
1 parent cb3c974 commit db2d254d75b835abb169f2f9e4a8cfbe74a3c365
Showing with 32 additions and 12 deletions.
  1. +32 −12 rtrlib/rtr/packets.c
@@ -1008,8 +1008,8 @@ int rtr_sync_receive_and_store_pdus(struct rtr_socket *rtr_socket){
unsigned int router_key_pdus_size = 0;
unsigned int router_key_pdus_nindex = 0;

struct pfx_table pfx_shadow_table;
struct spki_table spki_shadow_table;
struct pfx_table* pfx_shadow_table = NULL;
struct spki_table* spki_shadow_table = NULL;

//receive LRTR_IPV4/IPV6 PDUs till EOD
do {
@@ -1092,17 +1092,30 @@ int rtr_sync_receive_and_store_pdus(struct rtr_socket *rtr_socket){

if (rtr_socket->is_resetting) {
RTR_DBG1("Reset in progress creating shadow table for atomic reset");
pfx_table_init(&pfx_shadow_table, NULL);
pfx_update_table = &pfx_shadow_table;
pfx_shadow_table = lrtr_malloc(sizeof(struct pfx_table));
if (pfx_shadow_table == NULL) {
RTR_DBG1("Memory allocation for pfx shadow table failed");
retval = RTR_ERROR;
goto cleanup;

pfx_table_init(pfx_shadow_table, NULL);
pfx_update_table = pfx_shadow_table;
if (pfx_table_copy_except_socket(rtr_socket->pfx_table, pfx_update_table, rtr_socket)) {
RTR_DBG1("Creation of pfx shadow table failed");
rtr_change_socket_state(rtr_socket, RTR_ERROR_FATAL);
retval = RTR_ERROR;
goto cleanup;

spki_table_init(&spki_shadow_table, NULL);
spki_update_table = &spki_shadow_table;
spki_shadow_table = lrtr_malloc(sizeof(struct spki_table));
if (spki_shadow_table == NULL) {
RTR_DBG1("Memory allocation for spki shadow table failed");
retval = RTR_ERROR;
goto cleanup;
spki_table_init(spki_shadow_table, NULL);
spki_update_table = spki_shadow_table;
if (spki_table_copy_except_socket(rtr_socket->spki_table, spki_update_table, rtr_socket) != SPKI_SUCCESS) {
RTR_DBG1("Creation of spki shadow table failed");
rtr_change_socket_state(rtr_socket, RTR_ERROR_FATAL);
@@ -1181,19 +1194,19 @@ int rtr_sync_receive_and_store_pdus(struct rtr_socket *rtr_socket){
RTR_DBG1("spki data added");
if (rtr_socket->is_resetting) {
RTR_DBG1("Reset finished. Swapping new table in.");
pfx_table_swap(rtr_socket->pfx_table, &pfx_shadow_table);
spki_table_swap(rtr_socket->spki_table, &spki_shadow_table);
pfx_table_swap(rtr_socket->pfx_table, pfx_shadow_table);
spki_table_swap(rtr_socket->spki_table, spki_shadow_table);

if (rtr_socket->pfx_table->update_fp) {
RTR_DBG1("Calculating and notifying pfx diff");
pfx_table_notify_diff(rtr_socket->pfx_table, &pfx_shadow_table, rtr_socket);
pfx_table_notify_diff(rtr_socket->pfx_table, pfx_shadow_table, rtr_socket);
} else {
RTR_DBG1("No pfx update callback. Skipping diff");

if (rtr_socket->spki_table->update_fp) {
RTR_DBG1("Calculating and notifying spki diff");
spki_table_notify_diff(rtr_socket->spki_table, &spki_shadow_table, rtr_socket);
spki_table_notify_diff(rtr_socket->spki_table, spki_shadow_table, rtr_socket);
} else {
RTR_DBG1("No spki update callback. Skipping diff");
@@ -1222,8 +1235,15 @@ int rtr_sync_receive_and_store_pdus(struct rtr_socket *rtr_socket){

if (rtr_socket->is_resetting) {
RTR_DBG1("Freeing shadow tables.");
if (pfx_shadow_table != NULL) {

if (spki_shadow_table != NULL) {
rtr_socket->is_resetting = false;

0 comments on commit db2d254

Please sign in to comment.