Bläddra i källkod

qcacld-3.0: Avoid OEM message overread

Currently in oem_cmd_handler() the CLD80211_ATTR_DATA is processed as
an OEM message without first verifying that the payload has a
sufficient length. This can lead to overreading the buffer. Add length
checks to make sure the payload is large enough to hold the message it
is supposed to encapsulate.

Change-Id: Ifaa7d1cce5bd427bfeca14cab5a44c4cb72ce59f
CRs-Fixed: 2054772
Jeff Johnson 8 år sedan
förälder
incheckning
1818a65523
1 ändrade filer med 17 tillägg och 3 borttagningar
  1. 17 3
      core/hdd/src/wlan_hdd_oemdata.c

+ 17 - 3
core/hdd/src/wlan_hdd_oemdata.c

@@ -1011,6 +1011,7 @@ static void oem_request_dispatcher(tAniMsgHdr *msg_hdr, int pid)
 static void oem_cmd_handler(const void *data, int data_len, void *ctx, int pid)
 {
 	tAniMsgHdr *msg_hdr;
+	int msg_len;
 	int ret;
 	struct nlattr *tb[CLD80211_ATTR_MAX + 1];
 
@@ -1020,6 +1021,10 @@ static void oem_cmd_handler(const void *data, int data_len, void *ctx, int pid)
 		return;
 	}
 
+	/*
+	 * audit note: it is ok to pass a NULL policy here since only
+	 * one attribute is parsed and it is explicitly validated
+	 */
 	if (nla_parse(tb, CLD80211_ATTR_MAX, data, data_len, NULL)) {
 		hdd_err("Invalid ATTR");
 		return;
@@ -1030,12 +1035,21 @@ static void oem_cmd_handler(const void *data, int data_len, void *ctx, int pid)
 		return;
 	}
 
-	msg_hdr = (tAniMsgHdr *)nla_data(tb[CLD80211_ATTR_DATA]);
-	if (!msg_hdr) {
-		hdd_err("msg_hdr null");
+	msg_len = nla_len(tb[CLD80211_ATTR_DATA]);
+	if (msg_len < sizeof(*msg_hdr)) {
+		hdd_err("runt ATTR_DATA size %d", msg_len);
 		send_oem_err_rsp_nlink_msg(pid, OEM_ERR_NULL_MESSAGE_HEADER);
 		return;
 	}
+
+	msg_hdr = nla_data(tb[CLD80211_ATTR_DATA]);
+	if (msg_len < (sizeof(*msg_hdr) + msg_hdr->length)) {
+		hdd_err("Invalid nl msg len %d, msg hdr len %d",
+			msg_len, msg_hdr->length);
+		send_oem_err_rsp_nlink_msg(pid, OEM_ERR_INVALID_MESSAGE_LENGTH);
+		return;
+	}
+
 	oem_request_dispatcher(msg_hdr, pid);
 }