qcacld-3.0: Fix OOB write in wma_unified_debug_print_event_handler
The routine wma_unified_debug_print_event_handler logs the data from debug print event handler. The param event data from firmware is copied to a destination buffer .If the maximum size of the data exceeds or equals BIG_ENDIAN_MAX_DEBUG_BUF for big endian hosts then possible OOB write will occur in wma_unified_debug_print_event_handler. For other hosts, OOB read could occur if datalen exceeds maximum firmware message size WMI_SVC_MAX_SIZE. Add check to validate datalen doesnot exceed the maximum firmware msg size WMI_SVC_MAX_SIZE. Return failure if it exceeds. Add check to ensure datalen doesnot exceed or equal the maximum buffer length value for big endian hosts BIG_ENDIAN_MAX_DEBUG_BUF. Invoke strlcpy instead of memcpy to ensure the string is null terminated before printed. Change-Id: I45943ae76d8fcf7b53e1f064c462d01cd6d00dcf CRs-Fixed: 2211133
This commit is contained in:

committed by
nshrivas

parent
c57c13aec7
commit
0008879d13
@@ -3525,31 +3525,43 @@ int wma_unified_debug_print_event_handler(void *handle, uint8_t *datap,
|
|||||||
WMI_DEBUG_PRINT_EVENTID_param_tlvs *param_buf;
|
WMI_DEBUG_PRINT_EVENTID_param_tlvs *param_buf;
|
||||||
uint8_t *data;
|
uint8_t *data;
|
||||||
uint32_t datalen;
|
uint32_t datalen;
|
||||||
|
char dbgbuf[WMI_SVC_MSG_MAX_SIZE] = { 0 };
|
||||||
|
|
||||||
param_buf = (WMI_DEBUG_PRINT_EVENTID_param_tlvs *) datap;
|
param_buf = (WMI_DEBUG_PRINT_EVENTID_param_tlvs *) datap;
|
||||||
if (!param_buf) {
|
if (!param_buf || !param_buf->data) {
|
||||||
WMA_LOGE("Get NULL point message from FW");
|
WMA_LOGE("Get NULL point message from FW");
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
data = param_buf->data;
|
data = param_buf->data;
|
||||||
datalen = param_buf->num_data;
|
datalen = param_buf->num_data;
|
||||||
|
if (datalen > WMI_SVC_MSG_MAX_SIZE) {
|
||||||
|
WMA_LOGE("Received data len %d exceeds max value %d",
|
||||||
|
datalen, WMI_SVC_MSG_MAX_SIZE);
|
||||||
|
return QDF_STATUS_E_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef BIG_ENDIAN_HOST
|
#ifdef BIG_ENDIAN_HOST
|
||||||
{
|
{
|
||||||
if (datalen > BIG_ENDIAN_MAX_DEBUG_BUF) {
|
if (datalen >= BIG_ENDIAN_MAX_DEBUG_BUF) {
|
||||||
WMA_LOGE("%s Invalid data len %d, limiting to max",
|
WMA_LOGE("%s Invalid data len %d, limiting to max",
|
||||||
__func__, datalen);
|
__func__, datalen);
|
||||||
datalen = BIG_ENDIAN_MAX_DEBUG_BUF;
|
datalen = BIG_ENDIAN_MAX_DEBUG_BUF-1;
|
||||||
}
|
}
|
||||||
char dbgbuf[BIG_ENDIAN_MAX_DEBUG_BUF] = { 0 };
|
|
||||||
|
|
||||||
memcpy(dbgbuf, data, datalen);
|
strlcpy(dbgbuf, data, datalen);
|
||||||
SWAPME(dbgbuf, datalen);
|
SWAPME(dbgbuf, datalen);
|
||||||
WMA_LOGD("FIRMWARE:%s", dbgbuf);
|
WMA_LOGD("FIRMWARE:%s", dbgbuf);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
WMA_LOGD("FIRMWARE:%s", data);
|
if (datalen == WMI_SVC_MSG_MAX_SIZE) {
|
||||||
|
WMA_LOGE("%s Invalid data len %d, limiting to max",
|
||||||
|
__func__, datalen);
|
||||||
|
datalen = WMI_SVC_MSG_MAX_SIZE -1 ;
|
||||||
|
}
|
||||||
|
|
||||||
|
strlcpy(dbgbuf, data, datalen);
|
||||||
|
WMA_LOGD("FIRMWARE:%s", dbgbuf);
|
||||||
return 0;
|
return 0;
|
||||||
#endif /* BIG_ENDIAN_HOST */
|
#endif /* BIG_ENDIAN_HOST */
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user