OOB read preventive checks and fixing nan dp end request, event data parse issue

Bug:269055469
Test: Verified comms

Change-Id: I54fc76e3eadbfdb08766ee3b9b0d63ecf78806a6
Signed-off-by: Ajay Davanageri <ajay.davanageri@broadcom.corp-partner.google.com>
diff --git a/bcmdhd/wifi_hal/common.h b/bcmdhd/wifi_hal/common.h
index b54fbb1..29e0e97 100644
--- a/bcmdhd/wifi_hal/common.h
+++ b/bcmdhd/wifi_hal/common.h
@@ -56,6 +56,8 @@
 #define NMRSTR "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x"
 #define NAN_MASTER_RANK_LEN 8
 #define NAN_SCID_INFO_LEN   16
+#define NAN_MAX_NDP_PEER 8u
+#define NAN_MAX_NDP_COUNT_SIZE NAN_MAX_NDP_PEER * sizeof(NanDataPathId)
 
 #define SAR_CONFIG_SCENARIO_COUNT      100
 #define MAX_NUM_RADIOS 3
diff --git a/bcmdhd/wifi_hal/nan.cpp b/bcmdhd/wifi_hal/nan.cpp
index 4dd4dd9..0a696b2 100755
--- a/bcmdhd/wifi_hal/nan.cpp
+++ b/bcmdhd/wifi_hal/nan.cpp
@@ -1634,19 +1634,19 @@
                         ALOGI("svc length %d", it.get_u16());
                         subscribe_event.service_specific_info_len = it.get_u16();
                     } else if (attr_type == NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO) {
-                        memcpy(subscribe_event.service_specific_info, it.get_data(),
-                                subscribe_event.service_specific_info_len);
-                        subscribe_event.service_specific_info
-                            [subscribe_event.service_specific_info_len] = '\0';
+                        u16 len = min(subscribe_event.service_specific_info_len,
+                                      sizeof(subscribe_event.service_specific_info) - 1);
+                        memcpy(subscribe_event.service_specific_info, it.get_data(), len);
+                        subscribe_event.service_specific_info[len] = '\0';
                         ALOGI("service info: %s", subscribe_event.service_specific_info);
                     } else if (attr_type == NAN_ATTRIBUTE_TX_MATCH_FILTER_LEN) {
                         ALOGI("sdf match filter length: %d", subscribe_event.sdf_match_filter_len);
                         subscribe_event.sdf_match_filter_len = it.get_u16();
                     } else if (attr_type == NAN_ATTRIBUTE_TX_MATCH_FILTER) {
-                        memcpy(subscribe_event.sdf_match_filter, it.get_data(),
-                                subscribe_event.sdf_match_filter_len);
-                        subscribe_event.sdf_match_filter
-                            [subscribe_event.sdf_match_filter_len] = '\0';
+                        u16 len = min(subscribe_event.sdf_match_filter_len,
+                                      sizeof(subscribe_event.sdf_match_filter) - 1);
+                        memcpy(subscribe_event.sdf_match_filter, it.get_data(), len);
+                        subscribe_event.sdf_match_filter[len] = '\0';
                         ALOGI("sdf match filter: %s", subscribe_event.sdf_match_filter);
                     } else if (attr_type == NAN_ATTRIBUTE_CIPHER_SUITE_TYPE) {
                         ALOGI("Peer Cipher suite type: %u", it.get_u8());
@@ -1655,11 +1655,10 @@
                         ALOGI("scid length %d", it.get_u32());
                         subscribe_event.scid_len= it.get_u32();
                     } else if (attr_type == NAN_ATTRIBUTE_SCID) {
-                        memcpy(subscribe_event.scid, it.get_data(),
-                                subscribe_event.scid_len);
-                        subscribe_event.scid
-                            [subscribe_event.scid_len] = '\0';
-                        ALOGI("scid: %s", subscribe_event.scid);
+                        u16 len = min(subscribe_event.scid_len,
+                                      sizeof(subscribe_event.scid) - 1);
+                        memcpy(subscribe_event.scid, it.get_data(), len);
+                        subscribe_event.scid[len] = '\0';
                     } else if (attr_type == NAN_ATTRIBUTE_RANGING_INDICATION) {
                         subscribe_event.range_info.ranging_event_type = it.get_u32();
                         ALOGI("ranging indication %d", it.get_u32());
@@ -1673,10 +1672,10 @@
                         ALOGI("sdea svc length %d", it.get_u16());
                         subscribe_event.sdea_service_specific_info_len = it.get_u16();
                     } else if (attr_type == NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO) {
-                        memcpy(subscribe_event.sdea_service_specific_info, it.get_data(),
-                                subscribe_event.sdea_service_specific_info_len);
-                        subscribe_event.sdea_service_specific_info
-                            [subscribe_event.sdea_service_specific_info_len] = '\0';
+                        u16 len = min(subscribe_event.sdea_service_specific_info_len,
+                                      sizeof(subscribe_event.sdea_service_specific_info) - 1);
+                        memcpy(subscribe_event.sdea_service_specific_info, it.get_data(), len);
+                        subscribe_event.sdea_service_specific_info[len] = '\0';
                         ALOGI("sdea service info: %s", subscribe_event.sdea_service_specific_info);
                     } else if (attr_type == NAN_ATTRIBUTE_MATCH_OCCURRED_FLAG) {
                         ALOGI("match occurred flag: %u", it.get_u8());
@@ -1752,11 +1751,15 @@
                     } else if (attr_type == NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN) {
                         followup_event.service_specific_info_len = it.get_u16();
                     } else if (attr_type == NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO) {
-                        memcpy(followup_event.service_specific_info, it.get_data(),
-                                followup_event.service_specific_info_len);
+                        u16 len = min(followup_event.service_specific_info_len,
+                                      sizeof(followup_event.service_specific_info) - 1);
+                        memcpy(followup_event.service_specific_info, it.get_data(), len);
+                        followup_event.service_specific_info[len] = '\0';
                     } else if (attr_type == NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO) {
-                        memcpy(followup_event.sdea_service_specific_info, it.get_data(),
-                                followup_event.sdea_service_specific_info_len);
+                        u16 len = min(followup_event.sdea_service_specific_info_len,
+                                      sizeof(followup_event.sdea_service_specific_info) - 1);
+                        memcpy(followup_event.sdea_service_specific_info, it.get_data(), len);
+                        followup_event.sdea_service_specific_info[len] = '\0';
                     }
                 }
                 counters.transmit_recv++;
@@ -2326,17 +2329,19 @@
             return result;
         }
 
-        while (count) {
-            result = request.put_u32(NAN_ATTRIBUTE_NDP_ID, mParams->ndp_instance_id[count-1]);
-            if (result < 0) {
-                ALOGE("%s: Failed to fill ndp id = %d, result = %d\n",
-                        __func__, mParams->ndp_instance_id[count-1], result);
-                return result;
-            }
-            ALOGE("%s:NDP ID = %d\n", __func__, mParams->ndp_instance_id[count-1]);
-            count -= 1;
+        if (!count || count != 1) {
+            ALOGE("Unsupported more than 1 ndp id in single end request!");
+            return WIFI_ERROR_NOT_SUPPORTED;
         }
 
+        result = request.put_u32(NAN_ATTRIBUTE_NDP_ID, mParams->ndp_instance_id[count-1]);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill ndp id = %d, result = %d\n",
+                    __func__, mParams->ndp_instance_id[count-1], result);
+            return result;
+        }
+        ALOGE("%s:NDP ID = %d\n", __func__, mParams->ndp_instance_id[count-1]);
+
         request.attr_end(data);
         return WIFI_SUCCESS;
     }
@@ -2459,6 +2464,7 @@
     int handleEvent(WifiEvent& event)
     {
         int cmd = event.get_vendor_subcmd();
+        NanDataPathEndInd *ndp_end_event = NULL;
         u16 attr_type;
 
         nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
@@ -2503,10 +2509,10 @@
                         ndp_ind_app_info_len = ndp_request_event.app_info.ndp_app_info_len;
 
                     } else if (attr_type == NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO) {
-                        memcpy(ndp_request_event.app_info.ndp_app_info, it.get_data(),
-                                ndp_ind_app_info_len);
-                        ndp_request_event.app_info.ndp_app_info
-                            [ndp_ind_app_info_len] = '\0';
+                        u16 len = min(ndp_ind_app_info_len,
+                                      sizeof(ndp_request_event.app_info.ndp_app_info) - 1);
+                        memcpy(ndp_request_event.app_info.ndp_app_info, it.get_data(), len);
+                        ndp_request_event.app_info.ndp_app_info[len] = '\0';
                         ALOGI("service info: %s\n", ndp_request_event.app_info.ndp_app_info);
 
                     } else if (attr_type == NAN_ATTRIBUTE_SCID_LEN) {
@@ -2514,9 +2520,10 @@
                         ndp_request_event.scid_len = it.get_u32();
 
                     } else if (attr_type == NAN_ATTRIBUTE_SCID) {
-                        memcpy(ndp_request_event.scid, it.get_data(),
-                                ndp_request_event.scid_len);
-                        ndp_request_event.scid[ndp_request_event.scid_len] = '\0';
+                        u16 len = min(ndp_request_event.scid_len,
+                                      sizeof(ndp_request_event.scid) - 1);
+                        memcpy(ndp_request_event.scid, it.get_data(), len);
+                        ndp_request_event.scid[len] = '\0';
                         ALOGI("scid : %s\n", ndp_request_event.scid);
 
                     }
@@ -2549,11 +2556,14 @@
                     } else if (attr_type == NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN) {
                         ALOGI("service info len: %d", it.get_u16());
                         ndp_create_confirmation_event.app_info.ndp_app_info_len = it.get_u16();
-                        ndp_conf_app_info_len = ndp_create_confirmation_event.app_info.ndp_app_info_len;
+                        ndp_conf_app_info_len =
+                            ndp_create_confirmation_event.app_info.ndp_app_info_len;
                     } else if (attr_type == NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO) {
+                        u16 len = min(ndp_conf_app_info_len,
+                                 sizeof(ndp_create_confirmation_event.app_info.ndp_app_info) - 1);
                         memcpy(ndp_create_confirmation_event.app_info.ndp_app_info,
-                                it.get_data(), ndp_conf_app_info_len);
-                        ndp_create_confirmation_event.app_info.ndp_app_info[ndp_conf_app_info_len]
+                                it.get_data(), len);
+                        ndp_create_confirmation_event.app_info.ndp_app_info[len]
                             = '\0';
                         ALOGI("service info: %s",
                                 ndp_create_confirmation_event.app_info.ndp_app_info);
@@ -2578,8 +2588,11 @@
                         }
                     } else if (attr_type == NAN_ATTRIBUTE_CHANNEL_INFO) {
                         ALOGI("Channel info \n");
-                        memcpy((u8 *)ndp_create_confirmation_event.channel_info, it.get_data(),
-                            ndp_create_confirmation_event.num_channels * sizeof(NanChannelInfo));
+                        u16 len = min(
+                            ndp_create_confirmation_event.num_channels * sizeof(NanChannelInfo),
+                            it.get_len());
+                        memcpy((u8 *)ndp_create_confirmation_event.channel_info,
+                            it.get_data(), len);
                         while (chan_idx < ndp_create_confirmation_event.num_channels) {
                             ALOGI("channel: %u, Bandwidth: %u, nss: %u\n",
                                 ndp_create_confirmation_event.channel_info[chan_idx].channel,
@@ -2593,9 +2606,19 @@
                 break;
             }
             case NAN_EVENT_DATA_END: {
-                NanDataPathEndInd ndp_end_event;
-                memset(&ndp_end_event, 0, sizeof(NanDataPathEndInd));
+                u8 i = 0;
                 u16 attr_type;
+
+                ndp_end_event =
+                    (NanDataPathEndInd *)malloc(NAN_MAX_NDP_COUNT_SIZE +
+                    sizeof(ndp_end_event->num_ndp_instances));
+                if (!ndp_end_event) {
+                    ALOGE("Failed to alloc for end request event\n");
+                    break;
+                }
+
+                memset(ndp_end_event, 0, (NAN_MAX_NDP_COUNT_SIZE +
+                    sizeof(ndp_end_event->num_ndp_instances)));
                 ALOGI("Received NAN_EVENT_DATA_END\n");
 
                 for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
@@ -2603,23 +2626,33 @@
 
                     if (attr_type == NAN_ATTRIBUTE_INST_COUNT) {
                         ALOGI("ndp count: %u\n", it.get_u8());
-                        ndp_end_event.num_ndp_instances = it.get_u8();
                         count = it.get_u8();
-                    } else if (attr_type == NAN_ATTRIBUTE_NDP_ID) {
-                        while (count) {
-                            ndp_end_event.ndp_instance_id[count-1] = it.get_u32();
-                            ALOGI("NDP Id from the Event = %u\n", ndp_end_event.ndp_instance_id[count-1]);
-                            count -= 1;
+                        if (!count || (count != 1)) {
+                            ALOGE("%s:Invalid inst_count value.\n", __FUNCTION__);
+                            break;
                         }
+                        ndp_end_event->num_ndp_instances = count;
+                    } else if (attr_type == NAN_ATTRIBUTE_NDP_ID) {
+                        if (!ndp_end_event->num_ndp_instances ||
+                            (i > ndp_end_event->num_ndp_instances)) {
+                            ALOGE("num of ndp instances need to be minimum 1\n");
+                            break;
+                        }
+                        ndp_end_event->ndp_instance_id[i++] = it.get_u32();
+                        ALOGI("NDP Id from the Event = %u\n", it.get_u32());
                     } else {
                         ALOGI("Unknown attr_type: %s\n", NanAttrToString(attr_type));
                     }
                 }
 
-                GET_NAN_HANDLE(info)->mHandlers.EventDataEnd(&ndp_end_event);
+                GET_NAN_HANDLE(info)->mHandlers.EventDataEnd(ndp_end_event);
                 break;
             }
         } // end-of-switch
+
+        if (ndp_end_event) {
+            free(ndp_end_event);
+        }
         return NL_SKIP;
     }
 };
@@ -3263,7 +3296,6 @@
                 }
                 mParams->fam_val.numchans -= 1;
             }
-
         }
 
         if (mParams->config_dw.config_2dot4g_dw_band) {
@@ -3558,17 +3590,17 @@
                 ALOGE("%s: dp_primitive is no more available\n", __func__);
             }
             return NL_SKIP;
-	} else {
-		if (is_cmd_response(event_id)) {
-			ALOGE("Handling cmd response asynchronously\n");
-			if (rsp_vndr_data != NULL) {
-				handleAsyncResponse(rsp_vndr_data);
-			} else {
-				ALOGE("Wrong response data, rsp_vndr_data is NULL\n");
-				return NL_SKIP;
-			}
-		}
-	}
+        } else {
+            if (is_cmd_response(event_id)) {
+                ALOGE("Handling cmd response asynchronously\n");
+                if (rsp_vndr_data != NULL) {
+                    handleAsyncResponse(rsp_vndr_data);
+                } else {
+                    ALOGE("Wrong response data, rsp_vndr_data is NULL\n");
+                    return NL_SKIP;
+                }
+            }
+        }
 
         switch(event_id) {
             case NAN_EVENT_DE_EVENT:
@@ -3673,9 +3705,11 @@
 
                     } else if (attr_type == NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO) {
                         ALOGI("Received NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO\n");
-                        memcpy(&sdfInd.data.frame_data, it.get_data(), sdfInd.data.frame_len);
+                        u16 len = min(sdfInd.data.frame_len, sizeof(sdfInd.data.frame_data) - 1);
+                        memcpy(&sdfInd.data.frame_data, it.get_data(), len);
                         prhex("sdfInd.data.frame_data: ", (u8*)sdfInd.data.frame_data,
                                 sdfInd.data.frame_len);
+                        sdfInd.data.frame_data[len] = '\0';
                     }
                 }
                 GET_NAN_HANDLE(info)->mHandlers.EventBeaconSdfPayload(&sdfInd);
@@ -4896,6 +4930,7 @@
         }
 
         int handleEvent(WifiEvent& event) {
+            NanDataPathEndInd *ndp_end_event = NULL;
             int cmd = event.get_vendor_subcmd();
             u16 attr_type;
             nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
@@ -5024,10 +5059,10 @@
                             subscribe_event.service_specific_info_len = it.get_u16();
 
                         } else if (attr_type == NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO) {
-                            memcpy(subscribe_event.service_specific_info, it.get_data(),
-                                    subscribe_event.service_specific_info_len);
-                            subscribe_event.service_specific_info
-                                [subscribe_event.service_specific_info_len] = '\0';
+                            u16 len = min(subscribe_event.service_specific_info_len,
+                                          sizeof(subscribe_event.service_specific_info) - 1);
+                            memcpy(subscribe_event.service_specific_info, it.get_data(), len);
+                            subscribe_event.service_specific_info[len] = '\0';
                             ALOGI("service info: %s", subscribe_event.service_specific_info);
 
                         } else if (attr_type == NAN_ATTRIBUTE_TX_MATCH_FILTER_LEN) {
@@ -5065,10 +5100,10 @@
                             ALOGI("sdea svc length %d", it.get_u16());
                             subscribe_event.sdea_service_specific_info_len = it.get_u16();
                         } else if (attr_type == NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO) {
-                            memcpy(subscribe_event.sdea_service_specific_info, it.get_data(),
-                                    subscribe_event.sdea_service_specific_info_len);
-                            subscribe_event.sdea_service_specific_info
-                                [subscribe_event.sdea_service_specific_info_len] = '\0';
+                            u16 len = min(subscribe_event.sdea_service_specific_info_len,
+                                          sizeof(subscribe_event.sdea_service_specific_info) - 1);
+                            memcpy(subscribe_event.sdea_service_specific_info, it.get_data(), len);
+                            subscribe_event.sdea_service_specific_info[len] = '\0';
                             ALOGI("sdea service info: %s", subscribe_event.sdea_service_specific_info);
                         } else if (attr_type == NAN_ATTRIBUTE_MATCH_OCCURRED_FLAG) {
                             ALOGI("match occurred flag: %u", it.get_u8());
@@ -5152,17 +5187,18 @@
                             followup_event.service_specific_info_len = it.get_u16();
 
                         } else if (attr_type == NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO) {
-                            memcpy(followup_event.service_specific_info, it.get_data(),
-                                    followup_event.service_specific_info_len);
-                            followup_event.service_specific_info[followup_event.service_specific_info_len] =
-                                '\0';
+                            u16 len = min(followup_event.service_specific_info_len,
+                                          sizeof(followup_event.service_specific_info) - 1);
+                            memcpy(followup_event.service_specific_info, it.get_data(), len);
+                            followup_event.service_specific_info[len] = '\0';
                         } else if (attr_type == NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO_LEN) {
                             ALOGI("sdea svc length %d", it.get_u16());
                             followup_event.sdea_service_specific_info_len = it.get_u16();
                         } else if (attr_type == NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO) {
-                            memcpy(followup_event.sdea_service_specific_info, it.get_data(),
-                                    followup_event.sdea_service_specific_info_len);
-                            followup_event.sdea_service_specific_info[followup_event.sdea_service_specific_info_len] = '\0';
+                            u16 len = min(followup_event.sdea_service_specific_info_len,
+                                          sizeof(followup_event.sdea_service_specific_info) - 1);
+                            memcpy(followup_event.sdea_service_specific_info, it.get_data(), len);
+                            followup_event.sdea_service_specific_info[len] = '\0';
                             ALOGI("sdea service info: %s", followup_event.sdea_service_specific_info);
                         }
                     }
@@ -5328,29 +5364,43 @@
                 }
                 case NAN_EVENT_DATA_END: {
                     ALOGI("Received NAN_EVENT_DATA_END\n");
-                    NanDataPathEndInd ndp_end_event;
-                    memset(&ndp_end_event, 0, sizeof(NanDataPathEndInd));
-                    u8 count = 0;
+                    u8 i = 0, count = 0;
+                    u16 attr_type;
+
+                    ndp_end_event =
+                        (NanDataPathEndInd *)malloc(NAN_MAX_NDP_COUNT_SIZE +
+                        sizeof(ndp_end_event->num_ndp_instances));
+                    if (!ndp_end_event) {
+                        ALOGE("Failed to alloc for end request event\n");
+                        break;
+                    }
+                    memset(ndp_end_event, 0, (NAN_MAX_NDP_COUNT_SIZE +
+                        sizeof(ndp_end_event->num_ndp_instances)));
 
                     for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
                         attr_type = it.get_type();
+
                         if (attr_type == NAN_ATTRIBUTE_INST_COUNT) {
                             ALOGI("ndp count: %u\n", it.get_u8());
-                            ndp_end_event.num_ndp_instances = it.get_u8();
                             count = it.get_u8();
-                        } else if (attr_type == NAN_ATTRIBUTE_NDP_ID) {
-                            ALOGI("count: %u\n", count);
-                            while (count) {
-                                ndp_end_event.ndp_instance_id[count-1] = it.get_u32();
-                                ALOGI("ndp id: %u\n", ndp_end_event.ndp_instance_id[count-1]);
-                                count -= 1;
+                            if (!count || (count != 1)) {
+                                ALOGE("%s:Invalid inst_count value.\n", __FUNCTION__);
+                                break;
                             }
+                            ndp_end_event->num_ndp_instances = count;
+                        } else if (attr_type == NAN_ATTRIBUTE_NDP_ID) {
+                            if (!ndp_end_event->num_ndp_instances ||
+                                (i > ndp_end_event->num_ndp_instances)) {
+                                ALOGE("num of ndp instances need to be minimum 1\n");
+                                break;
+                            }
+                            ndp_end_event->ndp_instance_id[i++] = it.get_u32();
+                            ALOGI("NDP Id from the Event = %u\n", it.get_u32());
                         } else {
                             ALOGI("Unknown attr_type: %s\n", NanAttrToString(attr_type));
                         }
                     }
-
-                    GET_NAN_HANDLE(info)->mHandlers.EventDataEnd(&ndp_end_event);
+                    GET_NAN_HANDLE(info)->mHandlers.EventDataEnd(ndp_end_event);
                     break;
                 }
                 case NAN_EVENT_TRANSMIT_FOLLOWUP_IND: {
@@ -5380,6 +5430,10 @@
                     ALOGI("Received NAN_EVENT_UNKNOWN\n");
                     break;
             } // end-of-switch
+
+            if (ndp_end_event) {
+                free(ndp_end_event);
+            }
             return NL_SKIP;
         }
 };