gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r31240 - in gnunet/src: set util


From: gnunet
Subject: [GNUnet-SVN] r31240 - in gnunet/src: set util
Date: Mon, 9 Dec 2013 21:27:32 +0100

Author: dold
Date: 2013-12-09 21:27:32 +0100 (Mon, 09 Dec 2013)
New Revision: 31240

Modified:
   gnunet/src/set/gnunet-service-set.c
   gnunet/src/set/gnunet-service-set.h
   gnunet/src/set/gnunet-service-set_union.c
   gnunet/src/set/test_set_union_result_full.c
   gnunet/src/util/mq.c
Log:
- fix use after free in set union (#3178)


Modified: gnunet/src/set/gnunet-service-set.c
===================================================================
--- gnunet/src/set/gnunet-service-set.c 2013-12-09 19:58:51 UTC (rev 31239)
+++ gnunet/src/set/gnunet-service-set.c 2013-12-09 20:27:32 UTC (rev 31240)
@@ -955,8 +955,8 @@
   GNUNET_CONTAINER_DLL_insert (set->ops_head, set->ops_tail, op);
 
   op->channel = GNUNET_MESH_channel_create (mesh, op, &msg->target_peer,
-                                          GNUNET_APPLICATION_TYPE_SET,
-                                          GNUNET_MESH_OPTION_RELIABLE);
+                                            GNUNET_APPLICATION_TYPE_SET,
+                                            GNUNET_MESH_OPTION_RELIABLE);
 
   op->mq = GNUNET_MESH_mq_create (op->channel);
 
@@ -1261,17 +1261,28 @@
  */
 static void
 channel_end_cb (void *cls,
-               const struct GNUNET_MESH_Channel *channel, void *channel_ctx)
+                const struct GNUNET_MESH_Channel *channel, void *channel_ctx)
 {
   struct Operation *op = channel_ctx;
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "channel end cb called\n");
   op->channel = NULL;
+  /* the vt can be null if a client already requested canceling op. */
   if (NULL != op->vt)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "calling peer disconnect due to channel end\n");
     op->vt->peer_disconnect (op);
+  }
+
+  if (GNUNET_YES == op->keep)
+    return;
+
   /* mesh will never call us with the context again! */
   GNUNET_free (channel_ctx);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "channel end cb finished\n");
 }
 
 

Modified: gnunet/src/set/gnunet-service-set.h
===================================================================
--- gnunet/src/set/gnunet-service-set.h 2013-12-09 19:58:51 UTC (rev 31239)
+++ gnunet/src/set/gnunet-service-set.h 2013-12-09 20:27:32 UTC (rev 31240)
@@ -311,8 +311,6 @@
   /**
    * GNUNET_YES if this is not a "real" set operation yet, and we still
    * need to wait for the other peer to give us more details.
-   *
-   * //TODO: replace with state-enum
    */
   int is_incoming;
 
@@ -346,6 +344,12 @@
     * a linked list.
     */
   struct Operation *prev;
+
+  /**
+   * Set to GNUNET_YES if the set service should not free
+   * the operation, as it is still needed (e.g. in some scheduled task).
+   */
+  int keep;
 };
 
 

Modified: gnunet/src/set/gnunet-service-set_union.c
===================================================================
--- gnunet/src/set/gnunet-service-set_union.c   2013-12-09 19:58:51 UTC (rev 
31239)
+++ gnunet/src/set/gnunet-service-set_union.c   2013-12-09 20:27:32 UTC (rev 
31240)
@@ -982,12 +982,15 @@
   struct Operation *op = cls;
   struct GNUNET_MQ_Envelope *ev;
   struct GNUNET_SET_ResultMessage *rm;
+  int keep = op->keep;
   ev = GNUNET_MQ_msg (rm, GNUNET_MESSAGE_TYPE_SET_RESULT);
   rm->request_id = htonl (op->spec->client_request_id);
   rm->result_status = htons (GNUNET_SET_STATUS_DONE);
   rm->element_type = htons (0);
   GNUNET_MQ_send (op->spec->set->client_mq, ev);
   _GSS_operation_destroy (op);
+  if (GNUNET_YES == keep)
+    GNUNET_free (op);
 }
 
 
@@ -1060,6 +1063,8 @@
 
   if (GNUNET_SET_RESULT_FULL == op->spec->result_mode)
   {
+    /* prevent that the op is free'd by the tunnel end handler */
+    op->keep = GNUNET_YES;
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sending full result set\n");
     GNUNET_assert (NULL == op->state->full_result_iter);
     op->state->full_result_iter =

Modified: gnunet/src/set/test_set_union_result_full.c
===================================================================
--- gnunet/src/set/test_set_union_result_full.c 2013-12-09 19:58:51 UTC (rev 
31239)
+++ gnunet/src/set/test_set_union_result_full.c 2013-12-09 20:27:32 UTC (rev 
31240)
@@ -28,6 +28,8 @@
 #include "gnunet_set_service.h"
 
 
+static int ret;
+
 static struct GNUNET_PeerIdentity local_id;
 
 static struct GNUNET_HashCode app_id;
@@ -50,6 +52,7 @@
       break;
     case GNUNET_SET_STATUS_FAILURE:
       printf ("set 1: failure\n");
+      ret = 1;
       break;
     case GNUNET_SET_STATUS_DONE:
       printf ("set 1: done\n");
@@ -72,6 +75,7 @@
       break;
     case GNUNET_SET_STATUS_FAILURE:
       printf ("set 2: failure\n");
+      ret = 1;
       break;
     case GNUNET_SET_STATUS_DONE:
       printf ("set 2: done\n");
@@ -245,11 +249,12 @@
 int
 main (int argc, char **argv)
 {
-  int ret;
-
-  ret = GNUNET_TESTING_peer_run ("test_set_api",
-                                 "test_set.conf",
-                                 &run, NULL);
+  if (0 != GNUNET_TESTING_peer_run ("test_set_api",
+                                    "test_set.conf",
+                                    &run, NULL))
+  {
+    return 0;
+  }
   return ret;
 }
 

Modified: gnunet/src/util/mq.c
===================================================================
--- gnunet/src/util/mq.c        2013-12-09 19:58:51 UTC (rev 31239)
+++ gnunet/src/util/mq.c        2013-12-09 20:27:32 UTC (rev 31240)
@@ -268,6 +268,9 @@
   struct GNUNET_MQ_Handle *mq = cls;
   struct GNUNET_MQ_Envelope *current_envelope;
 
+  if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
+    return;
+
   mq->continue_task = GNUNET_SCHEDULER_NO_TASK;
   /* call is only valid if we're actually currently sending
    * a message */
@@ -466,6 +469,12 @@
 {
   struct ServerClientSocketState *state = impl_state;
 
+  if (NULL != state->th)
+  {
+    GNUNET_SERVER_notify_transmit_ready_cancel (state->th);
+    state->th = NULL;
+  }
+
   GNUNET_assert (NULL != mq);
   GNUNET_assert (NULL != state);
   GNUNET_SERVER_client_drop (state->client);




reply via email to

[Prev in Thread] Current Thread [Next in Thread]