You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by ma...@apache.org on 2016/11/22 01:17:22 UTC

[23/27] incubator-mynewt-core git commit: oic; use os_mempool for coap observers. Fix use-after-free error.

oic; use os_mempool for coap observers. Fix use-after-free error.


Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/commit/408077eb
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/408077eb
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/408077eb

Branch: refs/heads/develop
Commit: 408077eb74a8cd0a9cf5cc376e432cb4de6a2b66
Parents: f861cf8
Author: Marko Kiiskila <ma...@runtime.io>
Authored: Mon Nov 21 15:12:46 2016 -0800
Committer: Marko Kiiskila <ma...@runtime.io>
Committed: Mon Nov 21 17:15:49 2016 -0800

----------------------------------------------------------------------
 net/oic/src/messaging/coap/engine.c  |   1 +
 net/oic/src/messaging/coap/observe.c | 401 ++++++++++++++++--------------
 net/oic/src/messaging/coap/observe.h |   2 +
 3 files changed, 212 insertions(+), 192 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/408077eb/net/oic/src/messaging/coap/engine.c
----------------------------------------------------------------------
diff --git a/net/oic/src/messaging/coap/engine.c b/net/oic/src/messaging/coap/engine.c
index a17ebd6..1145447 100644
--- a/net/oic/src/messaging/coap/engine.c
+++ b/net/oic/src/messaging/coap/engine.c
@@ -306,5 +306,6 @@ coap_engine_init(void)
     coap_transaction_init();
 #ifdef OC_SERVER
     coap_separate_init();
+    coap_observe_init();
 #endif
 }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/408077eb/net/oic/src/messaging/coap/observe.c
----------------------------------------------------------------------
diff --git a/net/oic/src/messaging/coap/observe.c b/net/oic/src/messaging/coap/observe.c
index 4bd1d96..c16823a 100644
--- a/net/oic/src/messaging/coap/observe.c
+++ b/net/oic/src/messaging/coap/observe.c
@@ -35,11 +35,14 @@
 
 #ifdef OC_SERVER
 
-#include "observe.h"
-#include "util/oc_memb.h"
 #include <stdio.h>
 #include <string.h>
 
+#include <os/os_mempool.h>
+
+#include "observe.h"
+#include "util/oc_memb.h"
+
 #include "oc_coap.h"
 #include "oc_rep.h"
 #include "oc_ri.h"
@@ -47,7 +50,10 @@
 uint64_t observe_counter = 3;
 /*---------------------------------------------------------------------------*/
 OC_LIST(observers_list);
-OC_MEMB(observers_memb, coap_observer_t, COAP_MAX_OBSERVERS);
+
+static struct os_mempool coap_observers;
+static uint8_t coap_observer_area[OS_MEMPOOL_BYTES(COAP_MAX_OBSERVERS,
+      sizeof(coap_observer_t))];
 
 /*---------------------------------------------------------------------------*/
 /*- Internal API ------------------------------------------------------------*/
@@ -57,32 +63,32 @@ add_observer(oc_resource_t *resource, oc_endpoint_t *endpoint,
              const uint8_t *token, size_t token_len, const char *uri,
              int uri_len)
 {
-  /* Remove existing observe relationship, if any. */
-  int dup = coap_remove_observer_by_uri(endpoint, uri);
+    /* Remove existing observe relationship, if any. */
+    int dup = coap_remove_observer_by_uri(endpoint, uri);
 
-  coap_observer_t *o = oc_memb_alloc(&observers_memb);
+    coap_observer_t *o = os_memblock_get(&coap_observers);
 
-  if (o) {
-    int max = sizeof(o->url) - 1;
-    if (max > uri_len) {
-      max = uri_len;
+    if (o) {
+        int max = sizeof(o->url) - 1;
+        if (max > uri_len) {
+            max = uri_len;
+        }
+        memcpy(o->url, uri, max);
+        o->url[max] = 0;
+        memcpy(&o->endpoint, endpoint, sizeof(oc_endpoint_t));
+        o->token_len = token_len;
+        memcpy(o->token, token, token_len);
+        o->last_mid = 0;
+        o->obs_counter = observe_counter;
+        o->resource = resource;
+        resource->num_observers++;
+        LOG("Adding observer (%u/%u) for /%s [0x%02X%02X]\n",
+          oc_list_length(observers_list) + 1, COAP_MAX_OBSERVERS, o->url,
+          o->token[0], o->token[1]);
+        oc_list_add(observers_list, o);
+        return dup;
     }
-    memcpy(o->url, uri, max);
-    o->url[max] = 0;
-    memcpy(&o->endpoint, endpoint, sizeof(oc_endpoint_t));
-    o->token_len = token_len;
-    memcpy(o->token, token, token_len);
-    o->last_mid = 0;
-    o->obs_counter = observe_counter;
-    o->resource = resource;
-    resource->num_observers++;
-    LOG("Adding observer (%u/%u) for /%s [0x%02X%02X]\n",
-        oc_list_length(observers_list) + 1, COAP_MAX_OBSERVERS, o->url,
-        o->token[0], o->token[1]);
-    oc_list_add(observers_list, o);
-    return dup;
-  }
-  return -1;
+    return -1;
 }
 /*---------------------------------------------------------------------------*/
 /*- Removal -----------------------------------------------------------------*/
@@ -90,97 +96,99 @@ add_observer(oc_resource_t *resource, oc_endpoint_t *endpoint,
 void
 coap_remove_observer(coap_observer_t *o)
 {
-  LOG("Removing observer for /%s [0x%02X%02X]\n", o->url, o->token[0],
+    LOG("Removing observer for /%s [0x%02X%02X]\n", o->url, o->token[0],
       o->token[1]);
-  oc_memb_free(&observers_memb, o);
-  oc_list_remove(observers_list, o);
+    oc_list_remove(observers_list, o);
+    os_memblock_put(&coap_observers, o);
 }
 /*---------------------------------------------------------------------------*/
 int
 coap_remove_observer_by_client(oc_endpoint_t *endpoint)
 {
-  int removed = 0;
-  coap_observer_t *obs = (coap_observer_t *)oc_list_head(observers_list), *next;
+    int removed = 0;
+    coap_observer_t *obs = (coap_observer_t *)oc_list_head(observers_list),
+      *next;
 
-  LOG("Unregistering observers for client at: ");
-  LOGipaddr(*endpoint);
+    LOG("Unregistering observers for client at: ");
+    LOGipaddr(*endpoint);
 
-  while (obs) {
-    next = obs->next;
-    if (memcmp(&obs->endpoint, endpoint, sizeof(oc_endpoint_t)) == 0) {
-      obs->resource->num_observers--;
-      coap_remove_observer(obs);
-      removed++;
+    while (obs) {
+        next = obs->next;
+        if (memcmp(&obs->endpoint, endpoint, sizeof(oc_endpoint_t)) == 0) {
+            obs->resource->num_observers--;
+            coap_remove_observer(obs);
+            removed++;
+        }
+        obs = next;
     }
-    obs = next;
-  }
-  LOG("Removed %d observers\n", removed);
-  return removed;
+    LOG("Removed %d observers\n", removed);
+    return removed;
 }
 /*---------------------------------------------------------------------------*/
 int
 coap_remove_observer_by_token(oc_endpoint_t *endpoint, uint8_t *token,
                               size_t token_len)
 {
-  int removed = 0;
-  coap_observer_t *obs = (coap_observer_t *)oc_list_head(observers_list);
-  LOG("Unregistering observers for request token 0x%02X%02X\n", token[0],
+    int removed = 0;
+    coap_observer_t *obs = (coap_observer_t *)oc_list_head(observers_list);
+    LOG("Unregistering observers for request token 0x%02X%02X\n", token[0],
       token[1]);
-  while (obs) {
-    if (memcmp(&obs->endpoint, endpoint, sizeof(oc_endpoint_t)) == 0 &&
-        obs->token_len == token_len &&
-        memcmp(obs->token, token, token_len) == 0) {
-      obs->resource->num_observers--;
-      coap_remove_observer(obs);
-      removed++;
-      break;
+    while (obs) {
+        if (memcmp(&obs->endpoint, endpoint, sizeof(oc_endpoint_t)) == 0 &&
+          obs->token_len == token_len &&
+          memcmp(obs->token, token, token_len) == 0) {
+            obs->resource->num_observers--;
+            coap_remove_observer(obs);
+            removed++;
+            break;
+        }
+        obs = obs->next;
     }
-    obs = obs->next;
-  }
-  LOG("Removed %d observers\n", removed);
-  return removed;
+    LOG("Removed %d observers\n", removed);
+    return removed;
 }
 /*---------------------------------------------------------------------------*/
 int
 coap_remove_observer_by_uri(oc_endpoint_t *endpoint, const char *uri)
 {
-  LOG("Unregistering observers for resource uri /%s", uri);
-  int removed = 0;
-  coap_observer_t *obs = (coap_observer_t *)oc_list_head(observers_list), *next;
+    LOG("Unregistering observers for resource uri /%s", uri);
+    int removed = 0;
+    coap_observer_t *obs = (coap_observer_t *)oc_list_head(observers_list),
+      *next;
 
-  while (obs) {
-    next = obs->next;
-    if (((memcmp(&obs->endpoint, endpoint, sizeof(oc_endpoint_t)) == 0)) &&
-        (obs->url == uri || memcmp(obs->url, uri, strlen(obs->url)) == 0)) {
-      obs->resource->num_observers--;
-      coap_remove_observer(obs);
-      removed++;
+    while (obs) {
+        next = obs->next;
+        if (((memcmp(&obs->endpoint, endpoint, sizeof(oc_endpoint_t)) == 0)) &&
+          (obs->url == uri || memcmp(obs->url, uri, strlen(obs->url)) == 0)) {
+            obs->resource->num_observers--;
+            coap_remove_observer(obs);
+            removed++;
+        }
+        obs = next;
     }
-    obs = next;
-  }
-  LOG("Removed %d observers\n", removed);
-  return removed;
+    LOG("Removed %d observers\n", removed);
+    return removed;
 }
 /*---------------------------------------------------------------------------*/
 int
 coap_remove_observer_by_mid(oc_endpoint_t *endpoint, uint16_t mid)
 {
-  int removed = 0;
-  coap_observer_t *obs = NULL;
-  LOG("Unregistering observers for request MID %u\n", mid);
+    int removed = 0;
+    coap_observer_t *obs = NULL;
+    LOG("Unregistering observers for request MID %u\n", mid);
 
-  for (obs = (coap_observer_t *)oc_list_head(observers_list); obs != NULL;
-       obs = obs->next) {
-    if (memcmp(&obs->endpoint, endpoint, sizeof(*endpoint)) == 0 &&
-        obs->last_mid == mid) {
-      obs->resource->num_observers--;
-      coap_remove_observer(obs);
-      removed++;
-      break;
+    for (obs = (coap_observer_t *)oc_list_head(observers_list); obs != NULL;
+         obs = obs->next) {
+        if (memcmp(&obs->endpoint, endpoint, sizeof(*endpoint)) == 0 &&
+          obs->last_mid == mid) {
+            obs->resource->num_observers--;
+            coap_remove_observer(obs);
+            removed++;
+            break;
+        }
     }
-  }
-  LOG("Removed %d observers\n", removed);
-  return removed;
+    LOG("Removed %d observers\n", removed);
+    return removed;
 }
 /*---------------------------------------------------------------------------*/
 /*- Notification ------------------------------------------------------------*/
@@ -190,130 +198,139 @@ coap_notify_observers(oc_resource_t *resource,
                       oc_response_buffer_t *response_buf,
                       oc_endpoint_t *endpoint)
 {
-  int num_observers = 0;
-  if (resource) {
-    if (!resource->num_observers) {
-      LOG("coap_notify_observers: no observers; returning\n");
-      return 0;
+    int num_observers = 0;
+    if (resource) {
+        if (!resource->num_observers) {
+            LOG("coap_notify_observers: no observers; returning\n");
+            return 0;
+        }
+        num_observers = resource->num_observers;
     }
-    num_observers = resource->num_observers;
-  }
-  uint8_t buffer[COAP_MAX_BLOCK_SIZE];
-  oc_request_t request = {};
-  oc_response_t response = {};
-  response.separate_response = 0;
-  oc_response_buffer_t response_buffer;
-  if (!response_buf && resource && (resource->properties & OC_PERIODIC)) {
-    LOG("coap_notify_observers: Issue GET request to resource\n");
-    /* performing GET on the resource */
-    response_buffer.buffer = buffer;
-    response_buffer.buffer_size = COAP_MAX_BLOCK_SIZE;
-    response_buffer.block_offset = NULL;
-    response.response_buffer = &response_buffer;
-    request.resource = resource;
-    request.response = &response;
-    request.request_payload = NULL;
-    oc_rep_new(buffer, COAP_MAX_BLOCK_SIZE);
-    resource->get_handler(&request, resource->default_interface);
-    response_buf = &response_buffer;
-    if (response_buf->code == OC_IGNORE) {
-      LOG("coap_notify_observers: Resource ignored request\n");
-      return num_observers;
+    uint8_t buffer[COAP_MAX_BLOCK_SIZE];
+    oc_request_t request = {};
+    oc_response_t response = {};
+    response.separate_response = 0;
+    oc_response_buffer_t response_buffer;
+    if (!response_buf && resource && (resource->properties & OC_PERIODIC)) {
+        LOG("coap_notify_observers: Issue GET request to resource\n");
+        /* performing GET on the resource */
+        response_buffer.buffer = buffer;
+        response_buffer.buffer_size = COAP_MAX_BLOCK_SIZE;
+        response_buffer.block_offset = NULL;
+        response.response_buffer = &response_buffer;
+        request.resource = resource;
+        request.response = &response;
+        request.request_payload = NULL;
+        oc_rep_new(buffer, COAP_MAX_BLOCK_SIZE);
+        resource->get_handler(&request, resource->default_interface);
+        response_buf = &response_buffer;
+        if (response_buf->code == OC_IGNORE) {
+            LOG("coap_notify_observers: Resource ignored request\n");
+            return num_observers;
+        }
     }
-  }
 
-  coap_observer_t *obs = NULL;
-  /* iterate over observers */
-  for (obs = (coap_observer_t *)oc_list_head(observers_list);
-       obs && ((resource && obs->resource == resource) ||
-               (endpoint &&
-                memcmp(&obs->endpoint, endpoint, sizeof(oc_endpoint_t)) == 0));
-       obs = obs->next) {
-    num_observers = obs->resource->num_observers;
-    if (response.separate_response != NULL &&
-        response_buf->code == oc_status_code(OC_STATUS_OK)) {
-      coap_packet_t req[1];
-      /*
-  req->block1_num = 0;
-  req->block1_size = 0;
-  req->block2_num = 0;
-  req->block2_size = 0;
-      */
-      coap_init_message(req, COAP_TYPE_NON, CONTENT_2_05, 0);
-      memcpy(req->token, obs->token, obs->token_len);
-      req->token_len = obs->token_len;
-      LOG("Resource is SLOW; creating separate response\n");
-      if (coap_separate_accept(req, response.separate_response, &obs->endpoint,
-                               0) == 1)
-        response.separate_response->active = 1;
-    } else {
-      LOG("coap_notify_observers: notifying observer\n");
-      coap_transaction_t *transaction = NULL;
-      if (response_buf && (transaction = coap_new_transaction(
-                             coap_get_mid(), &obs->endpoint))) {
-        memcpy(transaction->message->data + COAP_MAX_HEADER_SIZE,
-               response_buf->buffer, response_buf->response_length);
+    coap_observer_t *obs = NULL;
+    /* iterate over observers */
+    for (obs = (coap_observer_t *)oc_list_head(observers_list);
+         obs && ((resource && obs->resource == resource) ||
+           (endpoint &&
+             memcmp(&obs->endpoint, endpoint, sizeof(oc_endpoint_t)) == 0));
+         obs = obs->next) {
+        num_observers = obs->resource->num_observers;
+        if (response.separate_response != NULL &&
+          response_buf->code == oc_status_code(OC_STATUS_OK)) {
+            coap_packet_t req[1];
+            /*
+              req->block1_num = 0;
+              req->block1_size = 0;
+              req->block2_num = 0;
+              req->block2_size = 0;
+            */
+            coap_init_message(req, COAP_TYPE_NON, CONTENT_2_05, 0);
+            memcpy(req->token, obs->token, obs->token_len);
+            req->token_len = obs->token_len;
+            LOG("Resource is SLOW; creating separate response\n");
+            if (coap_separate_accept(req, response.separate_response,
+                &obs->endpoint, 0) == 1) {
+                response.separate_response->active = 1;
+            }
+        } else {
+            LOG("coap_notify_observers: notifying observer\n");
+            coap_transaction_t *transaction = NULL;
+            if (response_buf && (transaction = coap_new_transaction(
+                  coap_get_mid(), &obs->endpoint))) {
+                memcpy(transaction->message->data + COAP_MAX_HEADER_SIZE,
+                  response_buf->buffer, response_buf->response_length);
 
-        /* update last MID for RST matching */
-        obs->last_mid = transaction->mid;
+                /* update last MID for RST matching */
+                obs->last_mid = transaction->mid;
 
-        /* prepare response */
-        /* build notification */
-        coap_packet_t notification
-          [1]; /* this way the packet can be treated as pointer as usual */
-        coap_init_message(notification, COAP_TYPE_NON, CONTENT_2_05, 0);
+                /* prepare response */
+                /* build notification */
+                coap_packet_t notification[1];
+                /* this way the packet can be treated as pointer as usual */
+                coap_init_message(notification, COAP_TYPE_NON, CONTENT_2_05, 0);
 
-        notification->mid = transaction->mid;
-        if (obs->obs_counter % COAP_OBSERVE_REFRESH_INTERVAL == 0) {
-          LOG("coap_observe_notify: forcing CON notification to check for "
-              "client liveness\n");
-          notification->type = COAP_TYPE_CON;
-        }
-        coap_set_payload(notification, response_buf->buffer,
-                         response_buf->response_length);
-        coap_set_status_code(notification, response_buf->code);
-        if (notification->code < BAD_REQUEST_4_00 &&
-            obs->resource->num_observers) {
-          coap_set_header_observe(notification, (obs->obs_counter)++);
-          observe_counter++;
-        } else {
-          coap_set_header_observe(notification, 1);
-        }
-        coap_set_token(notification, obs->token, obs->token_len);
+                notification->mid = transaction->mid;
+                if (obs->obs_counter % COAP_OBSERVE_REFRESH_INTERVAL == 0) {
+                    LOG("coap_observe_notify: forcing CON notification to "
+                      "check for client liveness\n");
+                    notification->type = COAP_TYPE_CON;
+                }
+                coap_set_payload(notification, response_buf->buffer,
+                  response_buf->response_length);
+                coap_set_status_code(notification, response_buf->code);
+                if (notification->code < BAD_REQUEST_4_00 &&
+                  obs->resource->num_observers) {
+                    coap_set_header_observe(notification, (obs->obs_counter)++);
+                    observe_counter++;
+                } else {
+                    coap_set_header_observe(notification, 1);
+                }
+                coap_set_token(notification, obs->token, obs->token_len);
 
-        transaction->message->length =
-          coap_serialize_message(notification, transaction->message->data);
+                transaction->message->length =
+                  coap_serialize_message(notification,
+                    transaction->message->data);
 
-        coap_send_transaction(transaction);
-      }
+                coap_send_transaction(transaction);
+            }
+        }
     }
-  }
-  return num_observers;
+    return num_observers;
 }
 /*---------------------------------------------------------------------------*/
 int
 coap_observe_handler(void *request, void *response, oc_resource_t *resource,
                      oc_endpoint_t *endpoint)
 {
-  coap_packet_t *const coap_req = (coap_packet_t *)request;
-  coap_packet_t *const coap_res = (coap_packet_t *)response;
-  int dup = -1;
-  if (coap_req->code == COAP_GET &&
+    coap_packet_t *const coap_req = (coap_packet_t *)request;
+    coap_packet_t *const coap_res = (coap_packet_t *)response;
+    int dup = -1;
+    if (coap_req->code == COAP_GET &&
       coap_res->code < 128) { /* GET request and response without error code */
-    if (IS_OPTION(coap_req, COAP_OPTION_OBSERVE)) {
-      if (coap_req->observe == 0) {
-        dup =
-          add_observer(resource, endpoint, coap_req->token, coap_req->token_len,
-                       coap_req->uri_path, coap_req->uri_path_len);
-      } else if (coap_req->observe == 1) {
-        /* remove client if it is currently observe */
-        dup = coap_remove_observer_by_token(endpoint, coap_req->token,
-                                            coap_req->token_len);
-      }
+        if (IS_OPTION(coap_req, COAP_OPTION_OBSERVE)) {
+            if (coap_req->observe == 0) {
+                dup =
+                  add_observer(resource, endpoint, coap_req->token,
+                    coap_req->token_len, coap_req->uri_path,
+                    coap_req->uri_path_len);
+            } else if (coap_req->observe == 1) {
+                /* remove client if it is currently observe */
+                dup = coap_remove_observer_by_token(endpoint, coap_req->token,
+                  coap_req->token_len);
+            }
+        }
     }
-  }
-  return dup;
+    return dup;
 }
 /*---------------------------------------------------------------------------*/
 
+void
+coap_observe_init(void)
+{
+    os_mempool_init(&coap_observers, COAP_MAX_OBSERVERS,
+      sizeof(coap_observer_t), coap_observer_area, "coap_obs");
+}
 #endif /* OC_SERVER */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/408077eb/net/oic/src/messaging/coap/observe.h
----------------------------------------------------------------------
diff --git a/net/oic/src/messaging/coap/observe.h b/net/oic/src/messaging/coap/observe.h
index b1eadc2..095f21e 100644
--- a/net/oic/src/messaging/coap/observe.h
+++ b/net/oic/src/messaging/coap/observe.h
@@ -80,6 +80,8 @@ int coap_notify_observers(oc_resource_t *resource,
 int coap_observe_handler(void *request, void *response, oc_resource_t *resource,
                          oc_endpoint_t *endpoint);
 
+void coap_observe_init(void);
+
 #ifdef __cplusplus
 }
 #endif