aboutsummaryrefslogtreecommitdiff
path: root/src/transport
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2011-07-14 16:44:45 +0000
committerChristian Grothoff <christian@grothoff.org>2011-07-14 16:44:45 +0000
commitb247968ea031953cc33f88372962b9bb69052b8a (patch)
treef5b15d286d95a8f0d5c7b662352092452016d367 /src/transport
parent8766ccd1af741881379c16f1c2947edd32819e62 (diff)
downloadgnunet-b247968ea031953cc33f88372962b9bb69052b8a.tar.gz
gnunet-b247968ea031953cc33f88372962b9bb69052b8a.zip
fixing use-after free and/or possible bad recursion on disconnect
Diffstat (limited to 'src/transport')
-rw-r--r--src/transport/gnunet-service-transport.c62
1 files changed, 33 insertions, 29 deletions
diff --git a/src/transport/gnunet-service-transport.c b/src/transport/gnunet-service-transport.c
index dd367d38a..1141bdb64 100644
--- a/src/transport/gnunet-service-transport.c
+++ b/src/transport/gnunet-service-transport.c
@@ -566,6 +566,11 @@ struct NeighbourList
566 int public_key_valid; 566 int public_key_valid;
567 567
568 /** 568 /**
569 * Are we already in the process of disconnecting this neighbour?
570 */
571 int in_disconnect;
572
573 /**
569 * Performance data for the peer. 574 * Performance data for the peer.
570 */ 575 */
571 struct GNUNET_TRANSPORT_ATS_Information *ats; 576 struct GNUNET_TRANSPORT_ATS_Information *ats;
@@ -1614,21 +1619,16 @@ transmit_send_continuation (void *cls,
1614 n = find_neighbour (&mq->neighbour_id); 1619 n = find_neighbour (&mq->neighbour_id);
1615 if (mq->client != NULL) 1620 if (mq->client != NULL)
1616 transmit_send_ok (mq->client, n, target, result); 1621 transmit_send_ok (mq->client, n, target, result);
1617 if (n != NULL) 1622 GNUNET_assert (n != NULL);
1618 { 1623 GNUNET_CONTAINER_DLL_remove (n->cont_head,
1619 GNUNET_CONTAINER_DLL_remove (n->cont_head, 1624 n->cont_tail,
1620 n->cont_tail, 1625 mq);
1621 mq);
1622 }
1623 GNUNET_free (mq); 1626 GNUNET_free (mq);
1624 if (n != NULL) 1627 if (result == GNUNET_OK)
1625 { 1628 try_transmission_to_peer (n);
1626 if (result == GNUNET_OK) 1629 else if (GNUNET_SCHEDULER_NO_TASK == n->retry_task)
1627 try_transmission_to_peer (n); 1630 n->retry_task = GNUNET_SCHEDULER_add_now (&retry_transmission_task,
1628 else if (GNUNET_SCHEDULER_NO_TASK == n->retry_task) 1631 n);
1629 n->retry_task = GNUNET_SCHEDULER_add_now (&retry_transmission_task,
1630 n);
1631 }
1632} 1632}
1633 1633
1634 1634
@@ -4853,6 +4853,8 @@ disconnect_neighbour (struct NeighbourList *n, int check)
4853 struct ForeignAddressList *peer_addresses; 4853 struct ForeignAddressList *peer_addresses;
4854 struct ForeignAddressList *peer_pos; 4854 struct ForeignAddressList *peer_pos;
4855 4855
4856 if (GNUNET_YES == n->in_disconnect)
4857 return;
4856 if (GNUNET_YES == check) 4858 if (GNUNET_YES == check)
4857 { 4859 {
4858 rpos = n->plugins; 4860 rpos = n->plugins;
@@ -4861,7 +4863,7 @@ disconnect_neighbour (struct NeighbourList *n, int check)
4861 peer_addresses = rpos->addresses; 4863 peer_addresses = rpos->addresses;
4862 while (peer_addresses != NULL) 4864 while (peer_addresses != NULL)
4863 { 4865 {
4864 // Do not disconnect if: an address is connected or an inbound address exists 4866 /* Do not disconnect if: an address is connected or an inbound address exists */
4865 if ((GNUNET_YES == peer_addresses->connected) || (peer_addresses->addrlen == 0)) 4867 if ((GNUNET_YES == peer_addresses->connected) || (peer_addresses->addrlen == 0))
4866 { 4868 {
4867#if DEBUG_TRANSPORT 4869#if DEBUG_TRANSPORT
@@ -4884,20 +4886,7 @@ disconnect_neighbour (struct NeighbourList *n, int check)
4884 "Disconnecting from `%4s'\n", 4886 "Disconnecting from `%4s'\n",
4885 GNUNET_i2s (&n->id)); 4887 GNUNET_i2s (&n->id));
4886#endif 4888#endif
4887 4889 n->in_disconnect = GNUNET_YES; /* prevent recursive entry */
4888 /* remove n from neighbours list */
4889 nprev = NULL;
4890 npos = neighbours;
4891 while ((npos != NULL) && (npos != n))
4892 {
4893 nprev = npos;
4894 npos = npos->next;
4895 }
4896 GNUNET_assert (npos != NULL);
4897 if (nprev == NULL)
4898 neighbours = n->next;
4899 else
4900 nprev->next = n->next;
4901 4890
4902 /* notify all clients about disconnect */ 4891 /* notify all clients about disconnect */
4903 if (GNUNET_YES == n->received_pong) 4892 if (GNUNET_YES == n->received_pong)
@@ -4989,6 +4978,21 @@ disconnect_neighbour (struct NeighbourList *n, int check)
4989 GNUNET_NO); 4978 GNUNET_NO);
4990 n->piter = NULL; 4979 n->piter = NULL;
4991 } 4980 }
4981
4982 /* remove n from neighbours list */
4983 nprev = NULL;
4984 npos = neighbours;
4985 while ((npos != NULL) && (npos != n))
4986 {
4987 nprev = npos;
4988 npos = npos->next;
4989 }
4990 GNUNET_assert (npos != NULL);
4991 if (nprev == NULL)
4992 neighbours = n->next;
4993 else
4994 nprev->next = n->next;
4995
4992 /* finally, free n itself */ 4996 /* finally, free n itself */
4993 GNUNET_STATISTICS_update (stats, 4997 GNUNET_STATISTICS_update (stats,
4994 gettext_noop ("# active neighbours"), 4998 gettext_noop ("# active neighbours"),