Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

firmware: thead: Fix buffer overflow and use standard endian macros

Addresses two issues in the TH1520 AON firmware protocol driver:

1. Fix a potential buffer overflow where the code used unsafe pointer
arithmetic to access the 'mode' field through the 'resource' pointer
with an offset. This was flagged by Smatch static checker as:
"buffer overflow 'data' 2 <= 3"

2. Replace custom RPC_SET_BE* and RPC_GET_BE* macros with standard
kernel endianness conversion macros (cpu_to_be16, etc.) for better
portability and maintainability.

The functionality was re-tested with the GPU power-up sequence,
confirming the GPU powers up correctly and the driver probes
successfully.

[ 12.702370] powervr ffef400000.gpu: [drm] loaded firmware
powervr/rogue_36.52.104.182_v1.fw
[ 12.711043] powervr ffef400000.gpu: [drm] FW version v1.0 (build
6645434 OS)
[ 12.719787] [drm] Initialized powervr 1.0.0 for ffef400000.gpu on
minor 0

Fixes: e4b3cbd840e5 ("firmware: thead: Add AON firmware protocol driver")
Reported-by: Dan Carpenter <dan.carpenter@linaro.org>
Closes: https://lore.kernel.org/all/17a0ccce-060b-4b9d-a3c4-8d5d5823b1c9@stanley.mountain/
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
Reviewed-by: Dan Carpenter <dan.carpenter@linaro.org>
Acked-by: Drew Fustini <fustini@kernel.org>
Cc: stable@vger.kernel.org
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>

authored by

Michal Wilczynski and committed by
Ulf Hansson
88c4bd90 7aaa8047

+3 -78
+3 -4
drivers/firmware/thead,th1520-aon.c
··· 170 170 hdr->func = TH1520_AON_PM_FUNC_SET_RESOURCE_POWER_MODE; 171 171 hdr->size = TH1520_AON_RPC_MSG_NUM; 172 172 173 - RPC_SET_BE16(&msg.resource, 0, rsrc); 174 - RPC_SET_BE16(&msg.resource, 2, 175 - (power_on ? TH1520_AON_PM_PW_MODE_ON : 176 - TH1520_AON_PM_PW_MODE_OFF)); 173 + msg.resource = cpu_to_be16(rsrc); 174 + msg.mode = cpu_to_be16(power_on ? TH1520_AON_PM_PW_MODE_ON : 175 + TH1520_AON_PM_PW_MODE_OFF); 177 176 178 177 ret = th1520_aon_call_rpc(aon_chan, &msg); 179 178 if (ret)
-74
include/linux/firmware/thead/thead,th1520-aon.h
··· 97 97 #define RPC_GET_SVC_FLAG_ACK_TYPE(MESG) (((MESG)->svc & 0x40) >> 6) 98 98 #define RPC_SET_SVC_FLAG_ACK_TYPE(MESG, ACK) ((MESG)->svc |= (ACK) << 6) 99 99 100 - #define RPC_SET_BE64(MESG, OFFSET, SET_DATA) \ 101 - do { \ 102 - u8 *data = (u8 *)(MESG); \ 103 - u64 _offset = (OFFSET); \ 104 - u64 _set_data = (SET_DATA); \ 105 - data[_offset + 7] = _set_data & 0xFF; \ 106 - data[_offset + 6] = (_set_data & 0xFF00) >> 8; \ 107 - data[_offset + 5] = (_set_data & 0xFF0000) >> 16; \ 108 - data[_offset + 4] = (_set_data & 0xFF000000) >> 24; \ 109 - data[_offset + 3] = (_set_data & 0xFF00000000) >> 32; \ 110 - data[_offset + 2] = (_set_data & 0xFF0000000000) >> 40; \ 111 - data[_offset + 1] = (_set_data & 0xFF000000000000) >> 48; \ 112 - data[_offset + 0] = (_set_data & 0xFF00000000000000) >> 56; \ 113 - } while (0) 114 - 115 - #define RPC_SET_BE32(MESG, OFFSET, SET_DATA) \ 116 - do { \ 117 - u8 *data = (u8 *)(MESG); \ 118 - u64 _offset = (OFFSET); \ 119 - u64 _set_data = (SET_DATA); \ 120 - data[_offset + 3] = (_set_data) & 0xFF; \ 121 - data[_offset + 2] = (_set_data & 0xFF00) >> 8; \ 122 - data[_offset + 1] = (_set_data & 0xFF0000) >> 16; \ 123 - data[_offset + 0] = (_set_data & 0xFF000000) >> 24; \ 124 - } while (0) 125 - 126 - #define RPC_SET_BE16(MESG, OFFSET, SET_DATA) \ 127 - do { \ 128 - u8 *data = (u8 *)(MESG); \ 129 - u64 _offset = (OFFSET); \ 130 - u64 _set_data = (SET_DATA); \ 131 - data[_offset + 1] = (_set_data) & 0xFF; \ 132 - data[_offset + 0] = (_set_data & 0xFF00) >> 8; \ 133 - } while (0) 134 - 135 - #define RPC_SET_U8(MESG, OFFSET, SET_DATA) \ 136 - do { \ 137 - u8 *data = (u8 *)(MESG); \ 138 - data[OFFSET] = (SET_DATA) & 0xFF; \ 139 - } while (0) 140 - 141 - #define RPC_GET_BE64(MESG, OFFSET, PTR) \ 142 - do { \ 143 - u8 *data = (u8 *)(MESG); \ 144 - u64 _offset = (OFFSET); \ 145 - *(u32 *)(PTR) = \ 146 - (data[_offset + 7] | data[_offset + 6] << 8 | \ 147 - data[_offset + 5] << 16 | data[_offset + 4] << 24 | \ 148 - data[_offset + 3] << 32 | data[_offset + 2] << 40 | \ 149 - data[_offset + 1] << 48 | data[_offset + 0] << 56); \ 150 - } while (0) 151 - 152 - #define RPC_GET_BE32(MESG, OFFSET, PTR) \ 153 - do { \ 154 - u8 *data = (u8 *)(MESG); \ 155 - u64 _offset = (OFFSET); \ 156 - *(u32 *)(PTR) = \ 157 - (data[_offset + 3] | data[_offset + 2] << 8 | \ 158 - data[_offset + 1] << 16 | data[_offset + 0] << 24); \ 159 - } while (0) 160 - 161 - #define RPC_GET_BE16(MESG, OFFSET, PTR) \ 162 - do { \ 163 - u8 *data = (u8 *)(MESG); \ 164 - u64 _offset = (OFFSET); \ 165 - *(u16 *)(PTR) = (data[_offset + 1] | data[_offset + 0] << 8); \ 166 - } while (0) 167 - 168 - #define RPC_GET_U8(MESG, OFFSET, PTR) \ 169 - do { \ 170 - u8 *data = (u8 *)(MESG); \ 171 - *(u8 *)(PTR) = (data[OFFSET]); \ 172 - } while (0) 173 - 174 100 /* 175 101 * Defines for SC PM Power Mode 176 102 */