aboutsummaryrefslogtreecommitdiff
path: root/src/cadet
diff options
context:
space:
mode:
authorBart Polot <bart@net.in.tum.de>2014-07-22 16:00:36 +0000
committerBart Polot <bart@net.in.tum.de>2014-07-22 16:00:36 +0000
commitb6e0aac51cd54c83eaefaff1f4c7145732127393 (patch)
treec235d8dfcdd223a628ad5ca70b1534b3356ec54d /src/cadet
parent09335b5d3364817416be8f0657c98f2c4d290fc3 (diff)
downloadgnunet-b6e0aac51cd54c83eaefaff1f4c7145732127393.tar.gz
gnunet-b6e0aac51cd54c83eaefaff1f4c7145732127393.zip
- make sure connection is destroyed and no use-after-free happens
Diffstat (limited to 'src/cadet')
-rw-r--r--src/cadet/gnunet-service-cadet_connection.c34
-rw-r--r--src/cadet/gnunet-service-cadet_peer.c63
-rw-r--r--src/cadet/gnunet-service-cadet_peer.h19
3 files changed, 68 insertions, 48 deletions
diff --git a/src/cadet/gnunet-service-cadet_connection.c b/src/cadet/gnunet-service-cadet_connection.c
index d310501bb..5c28f9e4c 100644
--- a/src/cadet/gnunet-service-cadet_connection.c
+++ b/src/cadet/gnunet-service-cadet_connection.c
@@ -564,8 +564,10 @@ send_ack (struct CadetConnection *c, unsigned int buffer, int fwd, int force)
564 * @param fwd Was this a FWD going message? 564 * @param fwd Was this a FWD going message?
565 * @param size Size of the message. 565 * @param size Size of the message.
566 * @param wait Time spent waiting for core (only the time for THIS message) 566 * @param wait Time spent waiting for core (only the time for THIS message)
567 *
568 * @return #GNUNET_YES if connection was destroyed, #GNUNET_NO otherwise.
567 */ 569 */
568static void 570static int
569conn_message_sent (void *cls, 571conn_message_sent (void *cls,
570 struct CadetConnection *c, int sent, 572 struct CadetConnection *c, int sent,
571 uint16_t type, uint32_t pid, int fwd, size_t size, 573 uint16_t type, uint32_t pid, int fwd, size_t size,
@@ -609,7 +611,7 @@ conn_message_sent (void *cls,
609 LOG (GNUNET_ERROR_TYPE_ERROR, "Message %s sent on NULL connection!\n", 611 LOG (GNUNET_ERROR_TYPE_ERROR, "Message %s sent on NULL connection!\n",
610 GC_m2s (type)); 612 GC_m2s (type));
611 } 613 }
612 return; 614 return GNUNET_NO;
613 } 615 }
614 LOG (GNUNET_ERROR_TYPE_DEBUG, " C_P- %p %u\n", c, c->pending_messages); 616 LOG (GNUNET_ERROR_TYPE_DEBUG, " C_P- %p %u\n", c, c->pending_messages);
615 c->pending_messages--; 617 c->pending_messages--;
@@ -617,7 +619,7 @@ conn_message_sent (void *cls,
617 { 619 {
618 LOG (GNUNET_ERROR_TYPE_DEBUG, "! destroying connection!\n"); 620 LOG (GNUNET_ERROR_TYPE_DEBUG, "! destroying connection!\n");
619 GCC_destroy (c); 621 GCC_destroy (c);
620 return; 622 return GNUNET_YES;
621 } 623 }
622 /* Send ACK if needed, after accounting for sent ID in fc->queue_n */ 624 /* Send ACK if needed, after accounting for sent ID in fc->queue_n */
623 switch (type) 625 switch (type)
@@ -674,7 +676,7 @@ conn_message_sent (void *cls,
674 LOG (GNUNET_ERROR_TYPE_DEBUG, "! message sent!\n"); 676 LOG (GNUNET_ERROR_TYPE_DEBUG, "! message sent!\n");
675 677
676 if (NULL == c->perf) 678 if (NULL == c->perf)
677 return; /* Only endpoints are interested in timing. */ 679 return GNUNET_NO; /* Only endpoints are interested in timing. */
678 680
679 p = c->perf; 681 p = c->perf;
680 usecsperbyte = ((double) wait.rel_value_us) / size; 682 usecsperbyte = ((double) wait.rel_value_us) / size;
@@ -695,6 +697,7 @@ conn_message_sent (void *cls,
695 p->avg /= p->size; 697 p->avg /= p->size;
696 } 698 }
697 p->idx = (p->idx + 1) % AVG_MSGS; 699 p->idx = (p->idx + 1) % AVG_MSGS;
700 return GNUNET_NO;
698} 701}
699 702
700 703
@@ -1209,8 +1212,7 @@ poll_sent (void *cls,
1209 LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL canceled on shutdown\n"); 1212 LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL canceled on shutdown\n");
1210 return; 1213 return;
1211 } 1214 }
1212 LOG (GNUNET_ERROR_TYPE_DEBUG, 1215 LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL sent for , scheduling new one!\n");
1213 " *** POLL sent for , scheduling new one!\n");
1214 fc->poll_msg = NULL; 1216 fc->poll_msg = NULL;
1215 fc->poll_time = GNUNET_TIME_STD_BACKOFF (fc->poll_time); 1217 fc->poll_time = GNUNET_TIME_STD_BACKOFF (fc->poll_time);
1216 fc->poll_task = GNUNET_SCHEDULER_add_delayed (fc->poll_time, 1218 fc->poll_task = GNUNET_SCHEDULER_add_delayed (fc->poll_time,
@@ -1806,8 +1808,7 @@ GCC_handle_broken (void* cls,
1806 struct GNUNET_CADET_ConnectionBroken *msg; 1808 struct GNUNET_CADET_ConnectionBroken *msg;
1807 struct CadetConnection *c; 1809 struct CadetConnection *c;
1808 struct CadetTunnel *t; 1810 struct CadetTunnel *t;
1809 unsigned int del; 1811 int destroyed;
1810 int pending;
1811 int fwd; 1812 int fwd;
1812 1813
1813 msg = (struct GNUNET_CADET_ConnectionBroken *) message; 1814 msg = (struct GNUNET_CADET_ConnectionBroken *) message;
@@ -1845,28 +1846,21 @@ GCC_handle_broken (void* cls,
1845 c->state = CADET_CONNECTION_BROKEN; 1846 c->state = CADET_CONNECTION_BROKEN;
1846 GCT_remove_connection (t, c); 1847 GCT_remove_connection (t, c);
1847 c->t = NULL; 1848 c->t = NULL;
1848 pending = c->pending_messages; 1849 destroyed = GNUNET_NO;
1849 1850
1850 /* GCP_connection_pop will destroy the connection when the last message 1851 /* GCP_connection_pop could destroy the connection! */
1851 * is popped! Do not use 'c' after the call. */ 1852 while (NULL != (out_msg = GCP_connection_pop (neighbor, c, &destroyed)))
1852 while (NULL != (out_msg = GCP_connection_pop (neighbor, c, &del)))
1853 { 1853 {
1854 pending -= del + 1; /* Substract the deleted messages + the popped one */
1855 GCT_resend_message (out_msg, t); 1854 GCT_resend_message (out_msg, t);
1856 } 1855 }
1857 /* All pending messages should have been popped, 1856 /* All pending messages should have been popped,
1858 * and the connection destroyed by the continuation. 1857 * and the connection destroyed by the continuation.
1859 * If last message was just deleted, then continuation wasn't called.
1860 */ 1858 */
1861 if (0 < pending || 0 < del) 1859 if (GNUNET_YES != destroyed)
1862 { 1860 {
1863 GNUNET_break (0 == pending); 1861 GNUNET_break (0);
1864 GCC_destroy (c); 1862 GCC_destroy (c);
1865 } 1863 }
1866 else
1867 {
1868 GNUNET_break (0 == pending); /* If negative: counter error! */
1869 }
1870 } 1864 }
1871 else 1865 else
1872 { 1866 {
diff --git a/src/cadet/gnunet-service-cadet_peer.c b/src/cadet/gnunet-service-cadet_peer.c
index 90b70aa8e..ce22c20da 100644
--- a/src/cadet/gnunet-service-cadet_peer.c
+++ b/src/cadet/gnunet-service-cadet_peer.c
@@ -1074,8 +1074,8 @@ queue_send (void *cls, size_t size, void *buf)
1074 queue->payload_id, GCC_2s (c), c, GC_f2s (queue->fwd), data_size); 1074 queue->payload_id, GCC_2s (c), c, GC_f2s (queue->fwd), data_size);
1075 } 1075 }
1076 1076
1077 /* Free queue, but cls was freed by send_core_* */ 1077 /* Free queue, but cls was freed by send_core_*. */
1078 GCP_queue_destroy (queue, GNUNET_NO, GNUNET_YES, pid); 1078 (void) GCP_queue_destroy (queue, GNUNET_NO, GNUNET_YES, pid);
1079 1079
1080 /* If more data in queue, send next */ 1080 /* If more data in queue, send next */
1081 queue = peer_get_first_message (peer); 1081 queue = peer_get_first_message (peer);
@@ -1121,16 +1121,23 @@ queue_send (void *cls, size_t size, void *buf)
1121 * Free a transmission that was already queued with all resources 1121 * Free a transmission that was already queued with all resources
1122 * associated to the request. 1122 * associated to the request.
1123 * 1123 *
1124 * If connection was marked to be destroyed, and this was the last queued
1125 * message on it, the connection will be free'd as a result.
1126 *
1124 * @param queue Queue handler to cancel. 1127 * @param queue Queue handler to cancel.
1125 * @param clear_cls Is it necessary to free associated cls? 1128 * @param clear_cls Is it necessary to free associated cls?
1126 * @param sent Was it really sent? (Could have been canceled) 1129 * @param sent Was it really sent? (Could have been canceled)
1127 * @param pid PID, if relevant (was sent and was a payload message). 1130 * @param pid PID, if relevant (was sent and was a payload message).
1131 *
1132 * @return #GNUNET_YES if connection was destroyed as a result,
1133 * #GNUNET_NO otherwise.
1128 */ 1134 */
1129void 1135int
1130GCP_queue_destroy (struct CadetPeerQueue *queue, int clear_cls, 1136GCP_queue_destroy (struct CadetPeerQueue *queue, int clear_cls,
1131 int sent, uint32_t pid) 1137 int sent, uint32_t pid)
1132{ 1138{
1133 struct CadetPeer *peer; 1139 struct CadetPeer *peer;
1140 int connection_destroyed;
1134 1141
1135 peer = queue->peer; 1142 peer = queue->peer;
1136 LOG (GNUNET_ERROR_TYPE_DEBUG, "queue destroy %s\n", GC_m2s (queue->type)); 1143 LOG (GNUNET_ERROR_TYPE_DEBUG, "queue destroy %s\n", GC_m2s (queue->type));
@@ -1168,11 +1175,18 @@ GCP_queue_destroy (struct CadetPeerQueue *queue, int clear_cls,
1168 1175
1169 if (NULL != queue->callback) 1176 if (NULL != queue->callback)
1170 { 1177 {
1178 struct GNUNET_TIME_Relative core_wait_time;
1179
1171 LOG (GNUNET_ERROR_TYPE_DEBUG, " calling callback\n"); 1180 LOG (GNUNET_ERROR_TYPE_DEBUG, " calling callback\n");
1172 queue->callback (queue->callback_cls, 1181 core_wait_time = GNUNET_TIME_absolute_get_duration (queue->start_waiting);
1173 queue->c, sent, queue->type, pid, 1182 connection_destroyed = queue->callback (queue->callback_cls,
1174 queue->fwd, queue->size, 1183 queue->c, sent, queue->type, pid,
1175 GNUNET_TIME_absolute_get_duration (queue->start_waiting)); 1184 queue->fwd, queue->size,
1185 core_wait_time);
1186 }
1187 else
1188 {
1189 connection_destroyed = GNUNET_NO;
1176 } 1190 }
1177 1191
1178 if (NULL == peer_get_first_message (peer) && NULL != peer->core_transmit) 1192 if (NULL == peer_get_first_message (peer) && NULL != peer->core_transmit)
@@ -1182,6 +1196,7 @@ GCP_queue_destroy (struct CadetPeerQueue *queue, int clear_cls,
1182 } 1196 }
1183 1197
1184 GNUNET_free (queue); 1198 GNUNET_free (queue);
1199 return connection_destroyed;
1185} 1200}
1186 1201
1187 1202
@@ -1309,20 +1324,23 @@ GCP_queue_cancel (struct CadetPeer *peer, struct CadetConnection *c)
1309 struct CadetPeerQueue *q; 1324 struct CadetPeerQueue *q;
1310 struct CadetPeerQueue *next; 1325 struct CadetPeerQueue *next;
1311 struct CadetPeerQueue *prev; 1326 struct CadetPeerQueue *prev;
1327 int connection_destroyed;
1312 1328
1329 connection_destroyed = GNUNET_NO;
1313 for (q = peer->queue_head; NULL != q; q = next) 1330 for (q = peer->queue_head; NULL != q; q = next)
1314 { 1331 {
1315 prev = q->prev; 1332 prev = q->prev;
1316 if (q->c == c) 1333 if (q->c == c)
1317 { 1334 {
1318 LOG (GNUNET_ERROR_TYPE_DEBUG, "GMP queue cancel %s\n", GC_m2s (q->type)); 1335 LOG (GNUNET_ERROR_TYPE_DEBUG, "GMP queue cancel %s\n", GC_m2s (q->type));
1336 GNUNET_break (GNUNET_NO == connection_destroyed);
1319 if (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY == q->type) 1337 if (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY == q->type)
1320 { 1338 {
1321 q->c = NULL; 1339 q->c = NULL;
1322 } 1340 }
1323 else 1341 else
1324 { 1342 {
1325 GCP_queue_destroy (q, GNUNET_YES, GNUNET_NO, 0); 1343 connection_destroyed = GCP_queue_destroy (q, GNUNET_YES, GNUNET_NO, 0);
1326 } 1344 }
1327 1345
1328 /* Get next from prev, q->next might be already freed: 1346 /* Get next from prev, q->next might be already freed:
@@ -1338,13 +1356,11 @@ GCP_queue_cancel (struct CadetPeer *peer, struct CadetConnection *c)
1338 next = q->next; 1356 next = q->next;
1339 } 1357 }
1340 } 1358 }
1341 if (NULL == peer->queue_head) 1359
1360 if (NULL == peer->queue_head && NULL != peer->core_transmit)
1342 { 1361 {
1343 if (NULL != peer->core_transmit) 1362 GNUNET_CORE_notify_transmit_ready_cancel (peer->core_transmit);
1344 { 1363 peer->core_transmit = NULL;
1345 GNUNET_CORE_notify_transmit_ready_cancel (peer->core_transmit);
1346 peer->core_transmit = NULL;
1347 }
1348 } 1364 }
1349} 1365}
1350 1366
@@ -1382,28 +1398,28 @@ connection_get_first_message (struct CadetPeer *peer, struct CadetConnection *c)
1382 * Get the first message for a connection and unqueue it. 1398 * Get the first message for a connection and unqueue it.
1383 * 1399 *
1384 * Only tunnel (or higher) level messages are unqueued. Connection specific 1400 * Only tunnel (or higher) level messages are unqueued. Connection specific
1385 * messages are destroyed and the count given to the caller. 1401 * messages are silently destroyed upon encounter.
1386 * 1402 *
1387 * @param peer Neighboring peer. 1403 * @param peer Neighboring peer.
1388 * @param c Connection. 1404 * @param c Connection.
1389 * @param del[out] How many messages have been deleted without returning. 1405 * @param destroyed[in/out] Was the connection destroyed (prev/as a result)?.
1390 * Can be NULL.
1391 * 1406 *
1392 * @return First message for this connection. 1407 * @return First message for this connection.
1393 */ 1408 */
1394struct GNUNET_MessageHeader * 1409struct GNUNET_MessageHeader *
1395GCP_connection_pop (struct CadetPeer *peer, 1410GCP_connection_pop (struct CadetPeer *peer,
1396 struct CadetConnection *c, 1411 struct CadetConnection *c,
1397 unsigned int *del) 1412 int *destroyed)
1398{ 1413{
1399 struct CadetPeerQueue *q; 1414 struct CadetPeerQueue *q;
1400 struct CadetPeerQueue *next; 1415 struct CadetPeerQueue *next;
1401 struct GNUNET_MessageHeader *msg; 1416 struct GNUNET_MessageHeader *msg;
1417 int dest;
1402 1418
1403 if (NULL != del) *del = 0;
1404 LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection pop on connection %p\n", c); 1419 LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection pop on connection %p\n", c);
1405 for (q = peer->queue_head; NULL != q; q = next) 1420 for (q = peer->queue_head; NULL != q; q = next)
1406 { 1421 {
1422 GNUNET_break (NULL == destroyed || GNUNET_NO == *destroyed);
1407 next = q->next; 1423 next = q->next;
1408 if (q->c != c) 1424 if (q->c != c)
1409 continue; 1425 continue;
@@ -1415,14 +1431,17 @@ GCP_connection_pop (struct CadetPeer *peer,
1415 case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN: 1431 case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN:
1416 case GNUNET_MESSAGE_TYPE_CADET_ACK: 1432 case GNUNET_MESSAGE_TYPE_CADET_ACK:
1417 case GNUNET_MESSAGE_TYPE_CADET_POLL: 1433 case GNUNET_MESSAGE_TYPE_CADET_POLL:
1418 GCP_queue_destroy (q, GNUNET_YES, GNUNET_NO, 0); 1434 dest = GCP_queue_destroy (q, GNUNET_YES, GNUNET_NO, 0);
1419 if (NULL != del) *del = *del + 1; 1435 if (NULL != destroyed && GNUNET_YES == dest)
1436 *destroyed = GNUNET_YES;
1420 continue; 1437 continue;
1421 1438
1422 case GNUNET_MESSAGE_TYPE_CADET_KX: 1439 case GNUNET_MESSAGE_TYPE_CADET_KX:
1423 case GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED: 1440 case GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED:
1424 msg = (struct GNUNET_MessageHeader *) q->cls; 1441 msg = (struct GNUNET_MessageHeader *) q->cls;
1425 GCP_queue_destroy (q, GNUNET_NO, GNUNET_NO, 0); 1442 dest = GCP_queue_destroy (q, GNUNET_NO, GNUNET_NO, 0);
1443 if (NULL != destroyed && GNUNET_YES == dest)
1444 *destroyed = GNUNET_YES;
1426 return msg; 1445 return msg;
1427 1446
1428 default: 1447 default:
diff --git a/src/cadet/gnunet-service-cadet_peer.h b/src/cadet/gnunet-service-cadet_peer.h
index e581685fa..ea64665d4 100644
--- a/src/cadet/gnunet-service-cadet_peer.h
+++ b/src/cadet/gnunet-service-cadet_peer.h
@@ -63,8 +63,10 @@ struct CadetPeerQueue;
63 * @param fwd Was this a FWD going message? 63 * @param fwd Was this a FWD going message?
64 * @param size Size of the message. 64 * @param size Size of the message.
65 * @param wait Time spent waiting for core (only the time for THIS message) 65 * @param wait Time spent waiting for core (only the time for THIS message)
66 *
67 * @return #GNUNET_YES if connection was destroyed, #GNUNET_NO otherwise.
66 */ 68 */
67typedef void (*GCP_sent) (void *cls, 69typedef int (*GCP_sent) (void *cls,
68 struct CadetConnection *c, int sent, 70 struct CadetConnection *c, int sent,
69 uint16_t type, uint32_t pid, int fwd, size_t size, 71 uint16_t type, uint32_t pid, int fwd, size_t size,
70 struct GNUNET_TIME_Relative wait); 72 struct GNUNET_TIME_Relative wait);
@@ -125,12 +127,18 @@ GCP_connect (struct CadetPeer *peer);
125 * Free a transmission that was already queued with all resources 127 * Free a transmission that was already queued with all resources
126 * associated to the request. 128 * associated to the request.
127 * 129 *
130 * If connection was marked to be destroyed, and this was the last queued
131 * message on it, the connection will be free'd as a result.
132 *
128 * @param queue Queue handler to cancel. 133 * @param queue Queue handler to cancel.
129 * @param clear_cls Is it necessary to free associated cls? 134 * @param clear_cls Is it necessary to free associated cls?
130 * @param sent Was it really sent? (Could have been canceled) 135 * @param sent Was it really sent? (Could have been canceled)
131 * @param pid PID, if relevant (was sent and was a payload message). 136 * @param pid PID, if relevant (was sent and was a payload message).
137 *
138 * @return #GNUNET_YES if connection was destroyed as a result,
139 * #GNUNET_NO otherwise.
132 */ 140 */
133void 141int
134GCP_queue_destroy (struct CadetPeerQueue *queue, int clear_cls, 142GCP_queue_destroy (struct CadetPeerQueue *queue, int clear_cls,
135 int sent, uint32_t pid); 143 int sent, uint32_t pid);
136 144
@@ -170,19 +178,18 @@ GCP_queue_cancel (struct CadetPeer *peer, struct CadetConnection *c);
170 * Get the first message for a connection and unqueue it. 178 * Get the first message for a connection and unqueue it.
171 * 179 *
172 * Only tunnel (or higher) level messages are unqueued. Connection specific 180 * Only tunnel (or higher) level messages are unqueued. Connection specific
173 * messages are destroyed and the count given to the caller. 181 * messages are silently destroyed upon encounter.
174 * 182 *
175 * @param peer Neighboring peer. 183 * @param peer Neighboring peer.
176 * @param c Connection. 184 * @param c Connection.
177 * @param del[out] How many messages have been deleted without returning. 185 * @param destroyed[out] Was the connection destroyed as a result?.
178 * Can be NULL.
179 * 186 *
180 * @return First message for this connection. 187 * @return First message for this connection.
181 */ 188 */
182struct GNUNET_MessageHeader * 189struct GNUNET_MessageHeader *
183GCP_connection_pop (struct CadetPeer *peer, 190GCP_connection_pop (struct CadetPeer *peer,
184 struct CadetConnection *c, 191 struct CadetConnection *c,
185 unsigned int *del); 192 int *destroyed);
186 193
187/** 194/**
188 * Unlock a possibly locked queue for a connection. 195 * Unlock a possibly locked queue for a connection.