qcacmn: Use panic in qdf_mem_copy/move/set/zero/cmp()
It has been observed at that several issues have crept into mainline due to qdf_mem_copy() gracefully returning when the source or destination pointers are NULL. In order to prevent such regressions in the future, change calls to qdf_mem_copy/move/set/zero/cmp() with NULL pointer parameters so they panic in debug builds. Change-Id: I6df4c42245ed1d0d8a85477f59552f8243488924 CRs-Fixed: 2408266
This commit is contained in:
@@ -318,41 +318,87 @@ void qdf_mem_set_io(void *ptr, uint32_t num_bytes, uint32_t value);
|
|||||||
void qdf_mem_copy_toio(void *dst_addr, const void *src_addr,
|
void qdf_mem_copy_toio(void *dst_addr, const void *src_addr,
|
||||||
uint32_t num_bytes);
|
uint32_t num_bytes);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* qdf_mem_set() - set (fill) memory with a specified byte value.
|
||||||
|
* @ptr: Pointer to memory that will be set
|
||||||
|
* @num_bytes: Number of bytes to be set
|
||||||
|
* @value: Byte set in memory
|
||||||
|
*
|
||||||
|
* WARNING: parameter @num_bytes and @value are swapped comparing with
|
||||||
|
* standard C function "memset", please ensure correct usage of this function!
|
||||||
|
*
|
||||||
|
* Return: None
|
||||||
|
*/
|
||||||
void qdf_mem_set(void *ptr, uint32_t num_bytes, uint32_t value);
|
void qdf_mem_set(void *ptr, uint32_t num_bytes, uint32_t value);
|
||||||
|
|
||||||
void qdf_mem_zero(void *ptr, uint32_t num_bytes);
|
/**
|
||||||
|
* qdf_mem_zero() - zero out memory
|
||||||
|
* @ptr: pointer to memory that will be set to zero
|
||||||
|
* @num_bytes: number of bytes zero
|
||||||
|
*
|
||||||
|
* This function sets the memory location to all zeros, essentially clearing
|
||||||
|
* the memory.
|
||||||
|
*
|
||||||
|
* Return: None
|
||||||
|
*/
|
||||||
|
static inline void qdf_mem_zero(void *ptr, uint32_t num_bytes)
|
||||||
|
{
|
||||||
|
qdf_mem_set(ptr, num_bytes, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* qdf_mem_copy() - copy memory
|
||||||
|
* @dst_addr: Pointer to destination memory location (to copy to)
|
||||||
|
* @src_addr: Pointer to source memory location (to copy from)
|
||||||
|
* @num_bytes: Number of bytes to copy.
|
||||||
|
*
|
||||||
|
* Copy host memory from one location to another, similar to memcpy in
|
||||||
|
* standard C. Note this function does not specifically handle overlapping
|
||||||
|
* source and destination memory locations. Calling this function with
|
||||||
|
* overlapping source and destination memory locations will result in
|
||||||
|
* unpredictable results. Use qdf_mem_move() if the memory locations
|
||||||
|
* for the source and destination are overlapping (or could be overlapping!)
|
||||||
|
*
|
||||||
|
* Return: none
|
||||||
|
*/
|
||||||
void qdf_mem_copy(void *dst_addr, const void *src_addr, uint32_t num_bytes);
|
void qdf_mem_copy(void *dst_addr, const void *src_addr, uint32_t num_bytes);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* qdf_mem_move() - move memory
|
||||||
|
* @dst_addr: pointer to destination memory location (to move to)
|
||||||
|
* @src_addr: pointer to source memory location (to move from)
|
||||||
|
* @num_bytes: number of bytes to move.
|
||||||
|
*
|
||||||
|
* Move host memory from one location to another, similar to memmove in
|
||||||
|
* standard C. Note this function *does* handle overlapping
|
||||||
|
* source and destination memory locations.
|
||||||
|
|
||||||
|
* Return: None
|
||||||
|
*/
|
||||||
void qdf_mem_move(void *dst_addr, const void *src_addr, uint32_t num_bytes);
|
void qdf_mem_move(void *dst_addr, const void *src_addr, uint32_t num_bytes);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* qdf_mem_cmp() - memory compare
|
||||||
|
* @left: pointer to one location in memory to compare
|
||||||
|
* @right: pointer to second location in memory to compare
|
||||||
|
* @size: the number of bytes to compare
|
||||||
|
*
|
||||||
|
* Function to compare two pieces of memory, similar to memcmp function
|
||||||
|
* in standard C.
|
||||||
|
*
|
||||||
|
* Return:
|
||||||
|
* 0 -- equal
|
||||||
|
* < 0 -- *memory1 is less than *memory2
|
||||||
|
* > 0 -- *memory1 is bigger than *memory2
|
||||||
|
*/
|
||||||
|
int qdf_mem_cmp(const void *left, const void *right, size_t size);
|
||||||
|
|
||||||
void qdf_mem_free_outline(void *buf);
|
void qdf_mem_free_outline(void *buf);
|
||||||
|
|
||||||
void qdf_mem_zero_outline(void *buf, qdf_size_t size);
|
void qdf_mem_zero_outline(void *buf, qdf_size_t size);
|
||||||
|
|
||||||
void qdf_ether_addr_copy(void *dst_addr, const void *src_addr);
|
void qdf_ether_addr_copy(void *dst_addr, const void *src_addr);
|
||||||
|
|
||||||
/**
|
|
||||||
* qdf_mem_cmp() - memory compare
|
|
||||||
* @memory1: pointer to one location in memory to compare.
|
|
||||||
* @memory2: pointer to second location in memory to compare.
|
|
||||||
* @num_bytes: the number of bytes to compare.
|
|
||||||
*
|
|
||||||
* Function to compare two pieces of memory, similar to memcmp function
|
|
||||||
* in standard C.
|
|
||||||
* Return:
|
|
||||||
* int32_t - returns an int value that tells if the memory
|
|
||||||
* locations are equal or not equal.
|
|
||||||
* 0 -- equal
|
|
||||||
* < 0 -- *memory1 is less than *memory2
|
|
||||||
* > 0 -- *memory1 is bigger than *memory2
|
|
||||||
*/
|
|
||||||
static inline int32_t qdf_mem_cmp(const void *memory1, const void *memory2,
|
|
||||||
uint32_t num_bytes)
|
|
||||||
{
|
|
||||||
return __qdf_mem_cmp(memory1, memory2, num_bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* qdf_mem_map_nbytes_single - Map memory for DMA
|
* qdf_mem_map_nbytes_single - Map memory for DMA
|
||||||
* @osdev: pomter OS device context
|
* @osdev: pomter OS device context
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2018 The Linux Foundation. All rights reserved.
|
* Copyright (c) 2014-2019 The Linux Foundation. All rights reserved.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and/or distribute this software for
|
* Permission to use, copy, modify, and/or distribute this software for
|
||||||
* any purpose with or without fee is hereby granted, provided that the
|
* any purpose with or without fee is hereby granted, provided that the
|
||||||
@@ -180,27 +180,6 @@ void __qdf_mempool_free(qdf_device_t osdev, __qdf_mempool_t pool, void *buf);
|
|||||||
#define __qdf_mempool_elem_size(_pool) ((_pool)->elem_size)
|
#define __qdf_mempool_elem_size(_pool) ((_pool)->elem_size)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
|
||||||
* __qdf_mem_cmp() - memory compare
|
|
||||||
* @memory1: pointer to one location in memory to compare.
|
|
||||||
* @memory2: pointer to second location in memory to compare.
|
|
||||||
* @num_bytes: the number of bytes to compare.
|
|
||||||
*
|
|
||||||
* Function to compare two pieces of memory, similar to memcmp function
|
|
||||||
* in standard C.
|
|
||||||
* Return:
|
|
||||||
* int32_t - returns an int value that tells if the memory
|
|
||||||
* locations are equal or not equal.
|
|
||||||
* 0 -- equal
|
|
||||||
* < 0 -- *memory1 is less than *memory2
|
|
||||||
* > 0 -- *memory1 is bigger than *memory2
|
|
||||||
*/
|
|
||||||
static inline int32_t __qdf_mem_cmp(const void *memory1, const void *memory2,
|
|
||||||
uint32_t num_bytes)
|
|
||||||
{
|
|
||||||
return (int32_t) memcmp(memory1, memory2, num_bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* __qdf_mem_smmu_s1_enabled() - Return SMMU stage 1 translation enable status
|
* __qdf_mem_smmu_s1_enabled() - Return SMMU stage 1 translation enable status
|
||||||
* @osdev parent device instance
|
* @osdev parent device instance
|
||||||
|
@@ -1423,35 +1423,17 @@ int qdf_mem_multi_page_link(qdf_device_t osdev,
|
|||||||
}
|
}
|
||||||
qdf_export_symbol(qdf_mem_multi_page_link);
|
qdf_export_symbol(qdf_mem_multi_page_link);
|
||||||
|
|
||||||
/**
|
|
||||||
* qdf_mem_copy() - copy memory
|
|
||||||
* @dst_addr: Pointer to destination memory location (to copy to)
|
|
||||||
* @src_addr: Pointer to source memory location (to copy from)
|
|
||||||
* @num_bytes: Number of bytes to copy.
|
|
||||||
*
|
|
||||||
* Copy host memory from one location to another, similar to memcpy in
|
|
||||||
* standard C. Note this function does not specifically handle overlapping
|
|
||||||
* source and destination memory locations. Calling this function with
|
|
||||||
* overlapping source and destination memory locations will result in
|
|
||||||
* unpredictable results. Use qdf_mem_move() if the memory locations
|
|
||||||
* for the source and destination are overlapping (or could be overlapping!)
|
|
||||||
*
|
|
||||||
* Return: none
|
|
||||||
*/
|
|
||||||
void qdf_mem_copy(void *dst_addr, const void *src_addr, uint32_t num_bytes)
|
void qdf_mem_copy(void *dst_addr, const void *src_addr, uint32_t num_bytes)
|
||||||
{
|
{
|
||||||
if (0 == num_bytes) {
|
/* special case where dst_addr or src_addr can be NULL */
|
||||||
/* special case where dst_addr or src_addr can be NULL */
|
if (!num_bytes)
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
if ((dst_addr == NULL) || (src_addr == NULL)) {
|
QDF_BUG(dst_addr);
|
||||||
QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
|
QDF_BUG(src_addr);
|
||||||
"%s called with NULL parameter, source:%pK destination:%pK",
|
if (!dst_addr || !src_addr)
|
||||||
__func__, src_addr, dst_addr);
|
|
||||||
QDF_ASSERT(0);
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
memcpy(dst_addr, src_addr, num_bytes);
|
memcpy(dst_addr, src_addr, num_bytes);
|
||||||
}
|
}
|
||||||
qdf_export_symbol(qdf_mem_copy);
|
qdf_export_symbol(qdf_mem_copy);
|
||||||
@@ -1504,32 +1486,6 @@ qdf_shared_mem_t *qdf_mem_shared_mem_alloc(qdf_device_t osdev, uint32_t size)
|
|||||||
|
|
||||||
qdf_export_symbol(qdf_mem_shared_mem_alloc);
|
qdf_export_symbol(qdf_mem_shared_mem_alloc);
|
||||||
|
|
||||||
/**
|
|
||||||
* qdf_mem_zero() - zero out memory
|
|
||||||
* @ptr: pointer to memory that will be set to zero
|
|
||||||
* @num_bytes: number of bytes zero
|
|
||||||
*
|
|
||||||
* This function sets the memory location to all zeros, essentially clearing
|
|
||||||
* the memory.
|
|
||||||
*
|
|
||||||
* Return: None
|
|
||||||
*/
|
|
||||||
void qdf_mem_zero(void *ptr, uint32_t num_bytes)
|
|
||||||
{
|
|
||||||
if (0 == num_bytes) {
|
|
||||||
/* special case where ptr can be NULL */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ptr == NULL) {
|
|
||||||
QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
|
|
||||||
"%s called with NULL parameter ptr", __func__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
memset(ptr, 0, num_bytes);
|
|
||||||
}
|
|
||||||
qdf_export_symbol(qdf_mem_zero);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* qdf_mem_copy_toio() - copy memory
|
* qdf_mem_copy_toio() - copy memory
|
||||||
* @dst_addr: Pointer to destination memory location (to copy to)
|
* @dst_addr: Pointer to destination memory location (to copy to)
|
||||||
@@ -1576,57 +1532,40 @@ void qdf_mem_set_io(void *ptr, uint32_t num_bytes, uint32_t value)
|
|||||||
|
|
||||||
qdf_export_symbol(qdf_mem_set_io);
|
qdf_export_symbol(qdf_mem_set_io);
|
||||||
|
|
||||||
/**
|
|
||||||
* qdf_mem_set() - set (fill) memory with a specified byte value.
|
|
||||||
* @ptr: Pointer to memory that will be set
|
|
||||||
* @num_bytes: Number of bytes to be set
|
|
||||||
* @value: Byte set in memory
|
|
||||||
*
|
|
||||||
* WARNING: parameter @num_bytes and @value are swapped comparing with
|
|
||||||
* standard C function "memset", please ensure correct usage of this function!
|
|
||||||
*
|
|
||||||
* Return: None
|
|
||||||
*/
|
|
||||||
void qdf_mem_set(void *ptr, uint32_t num_bytes, uint32_t value)
|
void qdf_mem_set(void *ptr, uint32_t num_bytes, uint32_t value)
|
||||||
{
|
{
|
||||||
if (ptr == NULL) {
|
QDF_BUG(ptr);
|
||||||
qdf_print("%s called with NULL parameter ptr", __func__);
|
if (!ptr)
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
memset(ptr, value, num_bytes);
|
memset(ptr, value, num_bytes);
|
||||||
}
|
}
|
||||||
qdf_export_symbol(qdf_mem_set);
|
qdf_export_symbol(qdf_mem_set);
|
||||||
|
|
||||||
/**
|
|
||||||
* qdf_mem_move() - move memory
|
|
||||||
* @dst_addr: pointer to destination memory location (to move to)
|
|
||||||
* @src_addr: pointer to source memory location (to move from)
|
|
||||||
* @num_bytes: number of bytes to move.
|
|
||||||
*
|
|
||||||
* Move host memory from one location to another, similar to memmove in
|
|
||||||
* standard C. Note this function *does* handle overlapping
|
|
||||||
* source and destination memory locations.
|
|
||||||
|
|
||||||
* Return: None
|
|
||||||
*/
|
|
||||||
void qdf_mem_move(void *dst_addr, const void *src_addr, uint32_t num_bytes)
|
void qdf_mem_move(void *dst_addr, const void *src_addr, uint32_t num_bytes)
|
||||||
{
|
{
|
||||||
if (0 == num_bytes) {
|
/* special case where dst_addr or src_addr can be NULL */
|
||||||
/* special case where dst_addr or src_addr can be NULL */
|
if (!num_bytes)
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
if ((dst_addr == NULL) || (src_addr == NULL)) {
|
QDF_BUG(dst_addr);
|
||||||
QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
|
QDF_BUG(src_addr);
|
||||||
"%s called with NULL parameter, source:%pK destination:%pK",
|
if (!dst_addr || !src_addr)
|
||||||
__func__, src_addr, dst_addr);
|
|
||||||
QDF_ASSERT(0);
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
memmove(dst_addr, src_addr, num_bytes);
|
memmove(dst_addr, src_addr, num_bytes);
|
||||||
}
|
}
|
||||||
qdf_export_symbol(qdf_mem_move);
|
qdf_export_symbol(qdf_mem_move);
|
||||||
|
|
||||||
|
int qdf_mem_cmp(const void *left, const void *right, size_t size)
|
||||||
|
{
|
||||||
|
QDF_BUG(left);
|
||||||
|
QDF_BUG(right);
|
||||||
|
|
||||||
|
return memcmp(left, right, size);
|
||||||
|
}
|
||||||
|
qdf_export_symbol(qdf_mem_cmp);
|
||||||
|
|
||||||
#if defined(A_SIMOS_DEVHOST) || defined(HIF_SDIO) || defined(HIF_USB)
|
#if defined(A_SIMOS_DEVHOST) || defined(HIF_SDIO) || defined(HIF_USB)
|
||||||
/**
|
/**
|
||||||
* qdf_mem_dma_alloc() - allocates memory for dma
|
* qdf_mem_dma_alloc() - allocates memory for dma
|
||||||
|
Reference in New Issue
Block a user