Skip to content

Commit 5cfc912

Browse files
Jiansong Chenalexdeucher
authored andcommitted
drm/amdgpu: refine amdgpu_fru_get_product_info
1. eliminate potential array index out of bounds. 2. return meaningful value for failure. Signed-off-by: Jiansong Chen <[email protected]> Reviewed-by: Jack Gui <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
1 parent 147feb0 commit 5cfc912

File tree

1 file changed

+23
-19
lines changed

1 file changed

+23
-19
lines changed

drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -101,15 +101,16 @@ static int amdgpu_fru_read_eeprom(struct amdgpu_device *adev, uint32_t addrptr,
101101
int amdgpu_fru_get_product_info(struct amdgpu_device *adev)
102102
{
103103
unsigned char buff[34];
104-
int addrptr = 0, size = 0;
104+
int addrptr, size;
105+
int len;
105106

106107
if (!is_fru_eeprom_supported(adev))
107108
return 0;
108109

109110
/* If algo exists, it means that the i2c_adapter's initialized */
110111
if (!adev->pm.smu_i2c.algo) {
111112
DRM_WARN("Cannot access FRU, EEPROM accessor not initialized");
112-
return 0;
113+
return -ENODEV;
113114
}
114115

115116
/* There's a lot of repetition here. This is due to the FRU having
@@ -128,7 +129,7 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev)
128129
size = amdgpu_fru_read_eeprom(adev, addrptr, buff);
129130
if (size < 1) {
130131
DRM_ERROR("Failed to read FRU Manufacturer, ret:%d", size);
131-
return size;
132+
return -EINVAL;
132133
}
133134

134135
/* Increment the addrptr by the size of the field, and 1 due to the
@@ -138,62 +139,65 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev)
138139
size = amdgpu_fru_read_eeprom(adev, addrptr, buff);
139140
if (size < 1) {
140141
DRM_ERROR("Failed to read FRU product name, ret:%d", size);
141-
return size;
142+
return -EINVAL;
142143
}
143144

145+
len = size;
144146
/* Product name should only be 32 characters. Any more,
145147
* and something could be wrong. Cap it at 32 to be safe
146148
*/
147-
if (size > 32) {
149+
if (len >= sizeof(adev->product_name)) {
148150
DRM_WARN("FRU Product Number is larger than 32 characters. This is likely a mistake");
149-
size = 32;
151+
len = sizeof(adev->product_name) - 1;
150152
}
151153
/* Start at 2 due to buff using fields 0 and 1 for the address */
152-
memcpy(adev->product_name, &buff[2], size);
153-
adev->product_name[size] = '\0';
154+
memcpy(adev->product_name, &buff[2], len);
155+
adev->product_name[len] = '\0';
154156

155157
addrptr += size + 1;
156158
size = amdgpu_fru_read_eeprom(adev, addrptr, buff);
157159
if (size < 1) {
158160
DRM_ERROR("Failed to read FRU product number, ret:%d", size);
159-
return size;
161+
return -EINVAL;
160162
}
161163

164+
len = size;
162165
/* Product number should only be 16 characters. Any more,
163166
* and something could be wrong. Cap it at 16 to be safe
164167
*/
165-
if (size > 16) {
168+
if (len >= sizeof(adev->product_number)) {
166169
DRM_WARN("FRU Product Number is larger than 16 characters. This is likely a mistake");
167-
size = 16;
170+
len = sizeof(adev->product_number) - 1;
168171
}
169-
memcpy(adev->product_number, &buff[2], size);
170-
adev->product_number[size] = '\0';
172+
memcpy(adev->product_number, &buff[2], len);
173+
adev->product_number[len] = '\0';
171174

172175
addrptr += size + 1;
173176
size = amdgpu_fru_read_eeprom(adev, addrptr, buff);
174177

175178
if (size < 1) {
176179
DRM_ERROR("Failed to read FRU product version, ret:%d", size);
177-
return size;
180+
return -EINVAL;
178181
}
179182

180183
addrptr += size + 1;
181184
size = amdgpu_fru_read_eeprom(adev, addrptr, buff);
182185

183186
if (size < 1) {
184187
DRM_ERROR("Failed to read FRU serial number, ret:%d", size);
185-
return size;
188+
return -EINVAL;
186189
}
187190

191+
len = size;
188192
/* Serial number should only be 16 characters. Any more,
189193
* and something could be wrong. Cap it at 16 to be safe
190194
*/
191-
if (size > 16) {
195+
if (len >= sizeof(adev->serial)) {
192196
DRM_WARN("FRU Serial Number is larger than 16 characters. This is likely a mistake");
193-
size = 16;
197+
len = sizeof(adev->serial) - 1;
194198
}
195-
memcpy(adev->serial, &buff[2], size);
196-
adev->serial[size] = '\0';
199+
memcpy(adev->serial, &buff[2], len);
200+
adev->serial[len] = '\0';
197201

198202
return 0;
199203
}

0 commit comments

Comments
 (0)