In msc_data_sz(), the 'valid_dw' field of the msc block descriptor 'bdesc' is firstly checked to see whether the descriptor has a valid data width. If yes, i.e., 'bdesc->valid_dw' is not 0, the data size of this descriptor will be returned. It is worth noting that the data size is calculated from 'bdesc->valid_dw'. The problem here is that 'bdesc' actually points to a consistent DMA region, which is allocated through dma_alloc_coherent() in msc_buffer_win_alloc(). Given that the device also has the permission to access this DMA region, it is possible that a malicious device controlled by an attacker can modify the 'valid_dw' field after the if statement but before the return statement in msc_data_sz(). Through this way, the device can bypass the check and supply unexpected data width.
This patch copies the 'valid_dw' field to a local variable and then performs the check and the calculation on the local variable to avoid the above issue. Signed-off-by: Wenwen Wang <[email protected]> --- drivers/hwtracing/intel_th/msu.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/hwtracing/intel_th/msu.h b/drivers/hwtracing/intel_th/msu.h index 9cc8ace..b7d846e 100644 --- a/drivers/hwtracing/intel_th/msu.h +++ b/drivers/hwtracing/intel_th/msu.h @@ -79,10 +79,12 @@ struct msc_block_desc { static inline unsigned long msc_data_sz(struct msc_block_desc *bdesc) { - if (!bdesc->valid_dw) + u32 valid_dw = bdesc->valid_dw; + + if (!valid_dw) return 0; - return bdesc->valid_dw * 4 - MSC_BDESC; + return valid_dw * 4 - MSC_BDESC; } static inline bool msc_block_wrapped(struct msc_block_desc *bdesc) -- 2.7.4

