Merge "DO NOT MERGE - Merge pie-platform-release (PPRL.190705.004) into master"
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 2ce03ed..260ec4a 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -40,6 +40,9 @@
 #include "driver_nl80211.h"
 
 
+#ifndef NETLINK_CAP_ACK
+#define NETLINK_CAP_ACK 10
+#endif /* NETLINK_CAP_ACK */
 #ifndef CONFIG_LIBNL20
 /*
  * libnl 1.1 has a bug, it tries to allocate socket numbers densely
@@ -339,6 +342,7 @@
 {
 	struct nl_cb *cb;
 	int err = -ENOMEM;
+	int opt;
 
 	if (!msg)
 		return -ENOMEM;
@@ -347,6 +351,11 @@
 	if (!cb)
 		goto out;
 
+	/* try to set NETLINK_CAP_ACK to 1, ignoring errors */
+	opt = 1;
+	setsockopt(nl_socket_get_fd(nl_handle), SOL_NETLINK,
+		   NETLINK_CAP_ACK, &opt, sizeof(opt));
+
 	err = nl_send_auto_complete(nl_handle, msg);
 	if (err < 0)
 		goto out;
@@ -5420,7 +5429,8 @@
 	if (ret)
 		goto fail;
 
-	ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+	ret = send_and_recv_msgs(drv, msg, NULL, (void *) -1);
+
 	msg = NULL;
 	if (ret) {
 		wpa_printf(MSG_DEBUG, "nl80211: MLME connect failed: ret=%d "
@@ -5431,6 +5441,7 @@
 	}
 
 fail:
+	nl80211_nlmsg_clear(msg);
 	nlmsg_free(msg);
 	return ret;
 
@@ -7576,11 +7587,12 @@
 		     params->fils_cache_id)) ||
 	    (params->pmk_len &&
 	     nla_put(msg, NL80211_ATTR_PMK, params->pmk_len, params->pmk))) {
+		nl80211_nlmsg_clear(msg);
 		nlmsg_free(msg);
 		return -ENOBUFS;
 	}
 
-	return send_and_recv_msgs(bss->drv, msg, NULL, NULL);
+	return send_and_recv_msgs(bss->drv, msg, NULL, (void *) -1);
 }
 
 
diff --git a/src/eap_peer/eap_fast.c b/src/eap_peer/eap_fast.c
index 74cec7d..94ce57d 100644
--- a/src/eap_peer/eap_fast.c
+++ b/src/eap_peer/eap_fast.c
@@ -250,8 +250,8 @@
 	os_memset(data->key_data, 0, EAP_FAST_KEY_LEN);
 	os_memset(data->emsk, 0, EAP_EMSK_LEN);
 	os_free(data->session_id);
-	wpabuf_free(data->pending_phase2_req);
-	wpabuf_free(data->pending_resp);
+	wpabuf_clear_free(data->pending_phase2_req);
+	wpabuf_clear_free(data->pending_resp);
 	os_free(data);
 }
 
@@ -486,7 +486,7 @@
 	    (config->pending_req_identity || config->pending_req_password ||
 	     config->pending_req_otp || config->pending_req_new_password ||
 	     config->pending_req_sim)) {
-		wpabuf_free(data->pending_phase2_req);
+		wpabuf_clear_free(data->pending_phase2_req);
 		data->pending_phase2_req = wpabuf_alloc_copy(hdr, len);
 	} else if (*resp == NULL)
 		return -1;
@@ -801,7 +801,7 @@
 		ret->methodState = METHOD_DONE;
 		ret->decision = DECISION_FAIL;
 		data->phase2_success = 0;
-		wpabuf_free(resp);
+		wpabuf_clear_free(resp);
 		return NULL;
 	}
 
@@ -815,7 +815,7 @@
 		} else {
 			wpa_printf(MSG_ERROR, "EAP-FAST: Failed to derive "
 				   "Session-Id");
-			wpabuf_free(resp);
+			wpabuf_clear_free(resp);
 			return NULL;
 		}
 	}
@@ -1150,7 +1150,7 @@
 		wpa_printf(MSG_INFO, "EAP-FAST: Failed to encrypt a Phase 2 "
 			   "frame");
 	}
-	wpabuf_free(resp);
+	wpabuf_clear_free(resp);
 
 	return 0;
 }
@@ -1328,14 +1328,14 @@
 		wpa_printf(MSG_INFO, "EAP-FAST: Too short Phase 2 "
 			   "TLV frame (len=%lu)",
 			   (unsigned long) wpabuf_len(in_decrypted));
-		wpabuf_free(in_decrypted);
+		wpabuf_clear_free(in_decrypted);
 		return -1;
 	}
 
 	res = eap_fast_process_decrypted(sm, data, ret, identifier,
 					 in_decrypted, out_data);
 
-	wpabuf_free(in_decrypted);
+	wpabuf_clear_free(in_decrypted);
 
 	return res;
 }
@@ -1613,7 +1613,7 @@
 		if (sm->waiting_ext_cert_check) {
 			wpa_printf(MSG_DEBUG,
 				   "EAP-FAST: Waiting external server certificate validation");
-			wpabuf_free(data->pending_resp);
+			wpabuf_clear_free(data->pending_resp);
 			data->pending_resp = resp;
 			return NULL;
 		}
@@ -1641,7 +1641,7 @@
 					   "EAP-FAST: Could not derive keys");
 				ret->methodState = METHOD_DONE;
 				ret->decision = DECISION_FAIL;
-				wpabuf_free(resp);
+				wpabuf_clear_free(resp);
 				return NULL;
 			}
 		}
@@ -1650,7 +1650,7 @@
 			/*
 			 * Application data included in the handshake message.
 			 */
-			wpabuf_free(data->pending_phase2_req);
+			wpabuf_clear_free(data->pending_phase2_req);
 			data->pending_phase2_req = resp;
 			resp = NULL;
 			res = eap_fast_decrypt(sm, data, ret, id, &msg, &resp);
@@ -1658,7 +1658,7 @@
 	}
 
 	if (res == 1) {
-		wpabuf_free(resp);
+		wpabuf_clear_free(resp);
 		return eap_peer_tls_build_ack(id, EAP_TYPE_FAST,
 					      data->fast_version);
 	}
@@ -1684,9 +1684,9 @@
 		data->phase2_method->deinit_for_reauth(sm, data->phase2_priv);
 	os_free(data->key_block_p);
 	data->key_block_p = NULL;
-	wpabuf_free(data->pending_phase2_req);
+	wpabuf_clear_free(data->pending_phase2_req);
 	data->pending_phase2_req = NULL;
-	wpabuf_free(data->pending_resp);
+	wpabuf_clear_free(data->pending_resp);
 	data->pending_resp = NULL;
 }
 
diff --git a/src/eap_peer/eap_peap.c b/src/eap_peer/eap_peap.c
index 34075b1..d2b7d92 100644
--- a/src/eap_peer/eap_peap.c
+++ b/src/eap_peer/eap_peap.c
@@ -186,9 +186,9 @@
 	eap_peer_tls_ssl_deinit(sm, &data->ssl);
 	eap_peap_free_key(data);
 	os_free(data->session_id);
-	wpabuf_free(data->pending_phase2_req);
-	wpabuf_free(data->pending_resp);
-	os_free(data);
+	wpabuf_clear_free(data->pending_phase2_req);
+	wpabuf_clear_free(data->pending_resp);
+	bin_clear_free(data, sizeof(*data));
 }
 
 
@@ -382,7 +382,7 @@
 	wpabuf_put_be16(msg, status); /* Status */
 
 	if (crypto_tlv_used && eap_tlv_add_cryptobinding(sm, data, msg)) {
-		wpabuf_free(msg);
+		wpabuf_clear_free(msg);
 		return NULL;
 	}
 
@@ -651,11 +651,11 @@
 					if (*resp == NULL) {
 						ret->methodState = METHOD_DONE;
 						ret->decision = DECISION_FAIL;
-						wpabuf_free(buf);
+						wpabuf_clear_free(buf);
 						return -1;
 					}
 					wpabuf_put_buf(*resp, buf);
-					wpabuf_free(buf);
+					wpabuf_clear_free(buf);
 					break;
 				}
 			}
@@ -728,7 +728,7 @@
 	    (config->pending_req_identity || config->pending_req_password ||
 	     config->pending_req_otp || config->pending_req_new_password ||
 	     config->pending_req_sim)) {
-		wpabuf_free(data->pending_phase2_req);
+		wpabuf_clear_free(data->pending_phase2_req);
 		data->pending_phase2_req = wpabuf_alloc_copy(hdr, len);
 	}
 
@@ -807,7 +807,7 @@
 		struct wpabuf *nmsg = wpabuf_alloc(sizeof(struct eap_hdr) +
 						   wpabuf_len(in_decrypted));
 		if (nmsg == NULL) {
-			wpabuf_free(in_decrypted);
+			wpabuf_clear_free(in_decrypted);
 			return 0;
 		}
 		nhdr = wpabuf_put(nmsg, sizeof(*nhdr));
@@ -817,7 +817,7 @@
 		nhdr->length = host_to_be16(sizeof(struct eap_hdr) +
 					    wpabuf_len(in_decrypted));
 
-		wpabuf_free(in_decrypted);
+		wpabuf_clear_free(in_decrypted);
 		in_decrypted = nmsg;
 	}
 
@@ -826,7 +826,7 @@
 		wpa_printf(MSG_INFO, "EAP-PEAP: Too short Phase 2 "
 			   "EAP frame (len=%lu)",
 			   (unsigned long) wpabuf_len(in_decrypted));
-		wpabuf_free(in_decrypted);
+		wpabuf_clear_free(in_decrypted);
 		return 0;
 	}
 	len = be_to_host16(hdr->length);
@@ -835,7 +835,7 @@
 			   "Phase 2 EAP frame (len=%lu hdr->length=%lu)",
 			   (unsigned long) wpabuf_len(in_decrypted),
 			   (unsigned long) len);
-		wpabuf_free(in_decrypted);
+		wpabuf_clear_free(in_decrypted);
 		return 0;
 	}
 	if (len < wpabuf_len(in_decrypted)) {
@@ -852,7 +852,7 @@
 	case EAP_CODE_REQUEST:
 		if (eap_peap_phase2_request(sm, data, ret, in_decrypted,
 					    &resp)) {
-			wpabuf_free(in_decrypted);
+			wpabuf_clear_free(in_decrypted);
 			wpa_printf(MSG_INFO, "EAP-PEAP: Phase2 Request "
 				   "processing failed");
 			return 0;
@@ -872,7 +872,7 @@
 					   "completed successfully");
 				ret->methodState = METHOD_DONE;
 				ret->decision = DECISION_FAIL;
-				wpabuf_free(in_decrypted);
+				wpabuf_clear_free(in_decrypted);
 				return 0;
 			}
 			wpa_printf(MSG_DEBUG, "EAP-PEAP: Version 1 - "
@@ -882,7 +882,7 @@
 			ret->methodState = METHOD_DONE;
 			data->phase2_success = 1;
 			if (data->peap_outer_success == 2) {
-				wpabuf_free(in_decrypted);
+				wpabuf_clear_free(in_decrypted);
 				wpa_printf(MSG_DEBUG, "EAP-PEAP: Use TLS ACK "
 					   "to finish authentication");
 				return 1;
@@ -928,7 +928,7 @@
 		break;
 	}
 
-	wpabuf_free(in_decrypted);
+	wpabuf_clear_free(in_decrypted);
 
 	if (resp) {
 		int skip_change2 = 0;
@@ -955,7 +955,7 @@
 			wpa_printf(MSG_INFO, "EAP-PEAP: Failed to encrypt "
 				   "a Phase 2 frame");
 		}
-		wpabuf_free(resp);
+		wpabuf_clear_free(resp);
 	}
 
 	return 0;
@@ -1056,7 +1056,7 @@
 		if (sm->waiting_ext_cert_check) {
 			wpa_printf(MSG_DEBUG,
 				   "EAP-PEAP: Waiting external server certificate validation");
-			wpabuf_free(data->pending_resp);
+			wpabuf_clear_free(data->pending_resp);
 			data->pending_resp = resp;
 			return NULL;
 		}
@@ -1131,7 +1131,7 @@
 			/*
 			 * Application data included in the handshake message.
 			 */
-			wpabuf_free(data->pending_phase2_req);
+			wpabuf_clear_free(data->pending_phase2_req);
 			data->pending_phase2_req = resp;
 			resp = NULL;
 			res = eap_peap_decrypt(sm, data, ret, req, &msg,
@@ -1144,7 +1144,7 @@
 	}
 
 	if (res == 1) {
-		wpabuf_free(resp);
+		wpabuf_clear_free(resp);
 		return eap_peer_tls_build_ack(id, EAP_TYPE_PEAP,
 					      data->peap_version);
 	}
@@ -1168,9 +1168,9 @@
 	if (data->phase2_priv && data->phase2_method &&
 	    data->phase2_method->deinit_for_reauth)
 		data->phase2_method->deinit_for_reauth(sm, data->phase2_priv);
-	wpabuf_free(data->pending_phase2_req);
+	wpabuf_clear_free(data->pending_phase2_req);
 	data->pending_phase2_req = NULL;
-	wpabuf_free(data->pending_resp);
+	wpabuf_clear_free(data->pending_resp);
 	data->pending_resp = NULL;
 	data->crypto_binding_used = 0;
 }
diff --git a/src/eap_peer/eap_ttls.c b/src/eap_peer/eap_ttls.c
index f18788c..5d26701 100644
--- a/src/eap_peer/eap_ttls.c
+++ b/src/eap_peer/eap_ttls.c
@@ -196,8 +196,8 @@
 	eap_peer_tls_ssl_deinit(sm, &data->ssl);
 	eap_ttls_free_key(data);
 	os_free(data->session_id);
-	wpabuf_free(data->pending_phase2_req);
-	wpabuf_free(data->pending_resp);
+	wpabuf_clear_free(data->pending_phase2_req);
+	wpabuf_clear_free(data->pending_resp);
 	os_free(data);
 }
 
@@ -248,7 +248,7 @@
 
 	msg = wpabuf_alloc(sizeof(struct ttls_avp) + wpabuf_len(*resp) + 4);
 	if (msg == NULL) {
-		wpabuf_free(*resp);
+		wpabuf_clear_free(*resp);
 		*resp = NULL;
 		return -1;
 	}
@@ -258,7 +258,7 @@
 	os_memcpy(pos, wpabuf_head(*resp), wpabuf_len(*resp));
 	pos += wpabuf_len(*resp);
 	AVP_PAD(avp, pos);
-	wpabuf_free(*resp);
+	wpabuf_clear_free(*resp);
 	wpabuf_put(msg, pos - avp);
 	*resp = msg;
 	return 0;
@@ -510,7 +510,7 @@
 	challenge = eap_ttls_implicit_challenge(
 		sm, data, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN + 1);
 	if (challenge == NULL) {
-		wpabuf_free(msg);
+		wpabuf_clear_free(msg);
 		wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAPV2: Failed to derive "
 			   "implicit challenge");
 		return -1;
@@ -529,7 +529,7 @@
 	*pos++ = 0; /* Flags */
 	if (os_get_random(pos, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN) < 0) {
 		os_free(challenge);
-		wpabuf_free(msg);
+		wpabuf_clear_free(msg);
 		wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAPV2: Failed to get "
 			   "random data for peer challenge");
 		return -1;
@@ -543,7 +543,7 @@
 				     peer_challenge, pos, data->auth_response,
 				     data->master_key)) {
 		os_free(challenge);
-		wpabuf_free(msg);
+		wpabuf_clear_free(msg);
 		wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAPV2: Failed to derive "
 			   "response");
 		return -1;
@@ -604,7 +604,7 @@
 	challenge = eap_ttls_implicit_challenge(
 		sm, data, EAP_TTLS_MSCHAP_CHALLENGE_LEN + 1);
 	if (challenge == NULL) {
-		wpabuf_free(msg);
+		wpabuf_clear_free(msg);
 		wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAP: Failed to derive "
 			   "implicit challenge");
 		return -1;
@@ -628,7 +628,7 @@
 		if (challenge_response(challenge, password, pos)) {
 			wpa_printf(MSG_ERROR,
 				   "EAP-TTLS/MSCHAP: Failed derive password hash");
-			wpabuf_free(msg);
+			wpabuf_clear_free(msg);
 			os_free(challenge);
 			return -1;
 		}
@@ -641,7 +641,7 @@
 					  pos)) {
 			wpa_printf(MSG_ERROR,
 				   "EAP-TTLS/MSCHAP: Failed derive password");
-			wpabuf_free(msg);
+			wpabuf_clear_free(msg);
 			os_free(challenge);
 			return -1;
 		}
@@ -760,7 +760,7 @@
 	challenge = eap_ttls_implicit_challenge(
 		sm, data, EAP_TTLS_CHAP_CHALLENGE_LEN + 1);
 	if (challenge == NULL) {
-		wpabuf_free(msg);
+		wpabuf_clear_free(msg);
 		wpa_printf(MSG_ERROR, "EAP-TTLS/CHAP: Failed to derive "
 			   "implicit challenge");
 		return -1;
@@ -1073,10 +1073,10 @@
 				 resp, out_data)) {
 		wpa_printf(MSG_INFO, "EAP-TTLS: Failed to encrypt a Phase 2 "
 			   "frame");
-		wpabuf_free(resp);
+		wpabuf_clear_free(resp);
 		return -1;
 	}
-	wpabuf_free(resp);
+	wpabuf_clear_free(resp);
 
 	return 0;
 }
@@ -1297,7 +1297,7 @@
 		   config->pending_req_otp ||
 		   config->pending_req_new_password ||
 		   config->pending_req_sim) {
-		wpabuf_free(data->pending_phase2_req);
+		wpabuf_clear_free(data->pending_phase2_req);
 		data->pending_phase2_req = wpabuf_dup(in_decrypted);
 	}
 
@@ -1340,7 +1340,7 @@
 			 * processing when EAP request is re-processed after
 			 * user input.
 			 */
-			wpabuf_free(data->pending_phase2_req);
+			wpabuf_clear_free(data->pending_phase2_req);
 			data->pending_phase2_req = wpabuf_alloc(0);
 		}
 
@@ -1413,7 +1413,7 @@
 		in_decrypted = data->pending_phase2_req;
 		data->pending_phase2_req = NULL;
 		if (wpabuf_len(in_decrypted) == 0) {
-			wpabuf_free(in_decrypted);
+			wpabuf_clear_free(in_decrypted);
 			return eap_ttls_implicit_identity_request(
 				sm, data, ret, identifier, out_data);
 		}
@@ -1449,7 +1449,7 @@
 					    &parse, in_decrypted, out_data);
 
 done:
-	wpabuf_free(in_decrypted);
+	wpabuf_clear_free(in_decrypted);
 	os_free(parse.eapdata);
 
 	if (retval < 0) {
@@ -1509,7 +1509,7 @@
 	if (sm->waiting_ext_cert_check) {
 		wpa_printf(MSG_DEBUG,
 			   "EAP-TTLS: Waiting external server certificate validation");
-		wpabuf_free(data->pending_resp);
+		wpabuf_clear_free(data->pending_resp);
 		data->pending_resp = *out_data;
 		*out_data = NULL;
 		return 0;
@@ -1543,7 +1543,7 @@
 		/*
 		 * Application data included in the handshake message.
 		 */
-		wpabuf_free(data->pending_phase2_req);
+		wpabuf_clear_free(data->pending_phase2_req);
 		data->pending_phase2_req = *out_data;
 		*out_data = NULL;
 		res = eap_ttls_decrypt(sm, data, ret, identifier, in_data,
@@ -1646,7 +1646,7 @@
 	/* FIX: what about res == -1? Could just move all error processing into
 	 * the other functions and get rid of this res==1 case here. */
 	if (res == 1) {
-		wpabuf_free(resp);
+		wpabuf_clear_free(resp);
 		return eap_peer_tls_build_ack(id, EAP_TYPE_TTLS,
 					      data->ttls_version);
 	}
@@ -1669,9 +1669,9 @@
 	if (data->phase2_priv && data->phase2_method &&
 	    data->phase2_method->deinit_for_reauth)
 		data->phase2_method->deinit_for_reauth(sm, data->phase2_priv);
-	wpabuf_free(data->pending_phase2_req);
+	wpabuf_clear_free(data->pending_phase2_req);
 	data->pending_phase2_req = NULL;
-	wpabuf_free(data->pending_resp);
+	wpabuf_clear_free(data->pending_resp);
 	data->pending_resp = NULL;
 	data->decision_succ = DECISION_FAIL;
 #ifdef EAP_TNC
diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c
index 1fd432d..25fecd6 100644
--- a/wpa_supplicant/config_file.c
+++ b/wpa_supplicant/config_file.c
@@ -482,7 +482,7 @@
 	if (value == NULL)
 		return;
 	fprintf(f, "\t%s=%s\n", field, value);
-	os_free(value);
+	str_clear_free(value);
 }