@@ -1107,9 +1107,16 @@ struct cs_dsp_coeff_parsed_coeff {
1107
1107
int len ;
1108
1108
};
1109
1109
1110
- static int cs_dsp_coeff_parse_string (int bytes , const u8 * * pos , const u8 * * str )
1110
+ static int cs_dsp_coeff_parse_string (int bytes , const u8 * * pos , unsigned int avail ,
1111
+ const u8 * * str )
1111
1112
{
1112
- int length ;
1113
+ int length , total_field_len ;
1114
+
1115
+ /* String fields are at least one __le32 */
1116
+ if (sizeof (__le32 ) > avail ) {
1117
+ * pos = NULL ;
1118
+ return 0 ;
1119
+ }
1113
1120
1114
1121
switch (bytes ) {
1115
1122
case 1 :
@@ -1122,10 +1129,16 @@ static int cs_dsp_coeff_parse_string(int bytes, const u8 **pos, const u8 **str)
1122
1129
return 0 ;
1123
1130
}
1124
1131
1132
+ total_field_len = ((length + bytes ) + 3 ) & ~0x03 ;
1133
+ if ((unsigned int )total_field_len > avail ) {
1134
+ * pos = NULL ;
1135
+ return 0 ;
1136
+ }
1137
+
1125
1138
if (str )
1126
1139
* str = * pos + bytes ;
1127
1140
1128
- * pos += (( length + bytes ) + 3 ) & ~ 0x03 ;
1141
+ * pos += total_field_len ;
1129
1142
1130
1143
return length ;
1131
1144
}
@@ -1150,71 +1163,134 @@ static int cs_dsp_coeff_parse_int(int bytes, const u8 **pos)
1150
1163
return val ;
1151
1164
}
1152
1165
1153
- static inline void cs_dsp_coeff_parse_alg (struct cs_dsp * dsp , const u8 * * data ,
1154
- struct cs_dsp_coeff_parsed_alg * blk )
1166
+ static int cs_dsp_coeff_parse_alg (struct cs_dsp * dsp ,
1167
+ const struct wmfw_region * region ,
1168
+ struct cs_dsp_coeff_parsed_alg * blk )
1155
1169
{
1156
1170
const struct wmfw_adsp_alg_data * raw ;
1171
+ unsigned int data_len = le32_to_cpu (region -> len );
1172
+ unsigned int pos ;
1173
+ const u8 * tmp ;
1174
+
1175
+ raw = (const struct wmfw_adsp_alg_data * )region -> data ;
1157
1176
1158
1177
switch (dsp -> fw_ver ) {
1159
1178
case 0 :
1160
1179
case 1 :
1161
- raw = ( const struct wmfw_adsp_alg_data * ) * data ;
1162
- * data = raw -> data ;
1180
+ if ( sizeof ( * raw ) > data_len )
1181
+ return - EOVERFLOW ;
1163
1182
1164
1183
blk -> id = le32_to_cpu (raw -> id );
1165
1184
blk -> name = raw -> name ;
1166
1185
blk -> name_len = strlen (raw -> name );
1167
1186
blk -> ncoeff = le32_to_cpu (raw -> ncoeff );
1187
+
1188
+ pos = sizeof (* raw );
1168
1189
break ;
1169
1190
default :
1170
- blk -> id = cs_dsp_coeff_parse_int (sizeof (raw -> id ), data );
1171
- blk -> name_len = cs_dsp_coeff_parse_string (sizeof (u8 ), data ,
1191
+ if (sizeof (raw -> id ) > data_len )
1192
+ return - EOVERFLOW ;
1193
+
1194
+ tmp = region -> data ;
1195
+ blk -> id = cs_dsp_coeff_parse_int (sizeof (raw -> id ), & tmp );
1196
+ pos = tmp - region -> data ;
1197
+
1198
+ tmp = & region -> data [pos ];
1199
+ blk -> name_len = cs_dsp_coeff_parse_string (sizeof (u8 ), & tmp , data_len - pos ,
1172
1200
& blk -> name );
1173
- cs_dsp_coeff_parse_string (sizeof (u16 ), data , NULL );
1174
- blk -> ncoeff = cs_dsp_coeff_parse_int (sizeof (raw -> ncoeff ), data );
1201
+ if (!tmp )
1202
+ return - EOVERFLOW ;
1203
+
1204
+ pos = tmp - region -> data ;
1205
+ cs_dsp_coeff_parse_string (sizeof (u16 ), & tmp , data_len - pos , NULL );
1206
+ if (!tmp )
1207
+ return - EOVERFLOW ;
1208
+
1209
+ pos = tmp - region -> data ;
1210
+ if (sizeof (raw -> ncoeff ) > (data_len - pos ))
1211
+ return - EOVERFLOW ;
1212
+
1213
+ blk -> ncoeff = cs_dsp_coeff_parse_int (sizeof (raw -> ncoeff ), & tmp );
1214
+ pos += sizeof (raw -> ncoeff );
1175
1215
break ;
1176
1216
}
1177
1217
1218
+ if ((int )blk -> ncoeff < 0 )
1219
+ return - EOVERFLOW ;
1220
+
1178
1221
cs_dsp_dbg (dsp , "Algorithm ID: %#x\n" , blk -> id );
1179
1222
cs_dsp_dbg (dsp , "Algorithm name: %.*s\n" , blk -> name_len , blk -> name );
1180
1223
cs_dsp_dbg (dsp , "# of coefficient descriptors: %#x\n" , blk -> ncoeff );
1224
+
1225
+ return pos ;
1181
1226
}
1182
1227
1183
- static inline void cs_dsp_coeff_parse_coeff (struct cs_dsp * dsp , const u8 * * data ,
1184
- struct cs_dsp_coeff_parsed_coeff * blk )
1228
+ static int cs_dsp_coeff_parse_coeff (struct cs_dsp * dsp ,
1229
+ const struct wmfw_region * region ,
1230
+ unsigned int pos ,
1231
+ struct cs_dsp_coeff_parsed_coeff * blk )
1185
1232
{
1186
1233
const struct wmfw_adsp_coeff_data * raw ;
1234
+ unsigned int data_len = le32_to_cpu (region -> len );
1235
+ unsigned int blk_len , blk_end_pos ;
1187
1236
const u8 * tmp ;
1188
- int length ;
1237
+
1238
+ raw = (const struct wmfw_adsp_coeff_data * )& region -> data [pos ];
1239
+ if (sizeof (raw -> hdr ) > (data_len - pos ))
1240
+ return - EOVERFLOW ;
1241
+
1242
+ blk_len = le32_to_cpu (raw -> hdr .size );
1243
+ if (blk_len > S32_MAX )
1244
+ return - EOVERFLOW ;
1245
+
1246
+ if (blk_len > (data_len - pos - sizeof (raw -> hdr )))
1247
+ return - EOVERFLOW ;
1248
+
1249
+ blk_end_pos = pos + sizeof (raw -> hdr ) + blk_len ;
1250
+
1251
+ blk -> offset = le16_to_cpu (raw -> hdr .offset );
1252
+ blk -> mem_type = le16_to_cpu (raw -> hdr .type );
1189
1253
1190
1254
switch (dsp -> fw_ver ) {
1191
1255
case 0 :
1192
1256
case 1 :
1193
- raw = ( const struct wmfw_adsp_coeff_data * ) * data ;
1194
- * data = * data + sizeof ( raw -> hdr ) + le32_to_cpu ( raw -> hdr . size ) ;
1257
+ if ( sizeof ( * raw ) > ( data_len - pos ))
1258
+ return - EOVERFLOW ;
1195
1259
1196
- blk -> offset = le16_to_cpu (raw -> hdr .offset );
1197
- blk -> mem_type = le16_to_cpu (raw -> hdr .type );
1198
1260
blk -> name = raw -> name ;
1199
1261
blk -> name_len = strlen (raw -> name );
1200
1262
blk -> ctl_type = le16_to_cpu (raw -> ctl_type );
1201
1263
blk -> flags = le16_to_cpu (raw -> flags );
1202
1264
blk -> len = le32_to_cpu (raw -> len );
1203
1265
break ;
1204
1266
default :
1205
- tmp = * data ;
1206
- blk -> offset = cs_dsp_coeff_parse_int (sizeof (raw -> hdr .offset ), & tmp );
1207
- blk -> mem_type = cs_dsp_coeff_parse_int (sizeof (raw -> hdr .type ), & tmp );
1208
- length = cs_dsp_coeff_parse_int (sizeof (raw -> hdr .size ), & tmp );
1209
- blk -> name_len = cs_dsp_coeff_parse_string (sizeof (u8 ), & tmp ,
1267
+ pos += sizeof (raw -> hdr );
1268
+ tmp = & region -> data [pos ];
1269
+ blk -> name_len = cs_dsp_coeff_parse_string (sizeof (u8 ), & tmp , data_len - pos ,
1210
1270
& blk -> name );
1211
- cs_dsp_coeff_parse_string (sizeof (u8 ), & tmp , NULL );
1212
- cs_dsp_coeff_parse_string (sizeof (u16 ), & tmp , NULL );
1271
+ if (!tmp )
1272
+ return - EOVERFLOW ;
1273
+
1274
+ pos = tmp - region -> data ;
1275
+ cs_dsp_coeff_parse_string (sizeof (u8 ), & tmp , data_len - pos , NULL );
1276
+ if (!tmp )
1277
+ return - EOVERFLOW ;
1278
+
1279
+ pos = tmp - region -> data ;
1280
+ cs_dsp_coeff_parse_string (sizeof (u16 ), & tmp , data_len - pos , NULL );
1281
+ if (!tmp )
1282
+ return - EOVERFLOW ;
1283
+
1284
+ pos = tmp - region -> data ;
1285
+ if (sizeof (raw -> ctl_type ) + sizeof (raw -> flags ) + sizeof (raw -> len ) >
1286
+ (data_len - pos ))
1287
+ return - EOVERFLOW ;
1288
+
1213
1289
blk -> ctl_type = cs_dsp_coeff_parse_int (sizeof (raw -> ctl_type ), & tmp );
1290
+ pos += sizeof (raw -> ctl_type );
1214
1291
blk -> flags = cs_dsp_coeff_parse_int (sizeof (raw -> flags ), & tmp );
1292
+ pos += sizeof (raw -> flags );
1215
1293
blk -> len = cs_dsp_coeff_parse_int (sizeof (raw -> len ), & tmp );
1216
-
1217
- * data = * data + sizeof (raw -> hdr ) + length ;
1218
1294
break ;
1219
1295
}
1220
1296
@@ -1224,6 +1300,8 @@ static inline void cs_dsp_coeff_parse_coeff(struct cs_dsp *dsp, const u8 **data,
1224
1300
cs_dsp_dbg (dsp , "\tCoefficient flags: %#x\n" , blk -> flags );
1225
1301
cs_dsp_dbg (dsp , "\tALSA control type: %#x\n" , blk -> ctl_type );
1226
1302
cs_dsp_dbg (dsp , "\tALSA control len: %#x\n" , blk -> len );
1303
+
1304
+ return blk_end_pos ;
1227
1305
}
1228
1306
1229
1307
static int cs_dsp_check_coeff_flags (struct cs_dsp * dsp ,
@@ -1247,12 +1325,16 @@ static int cs_dsp_parse_coeff(struct cs_dsp *dsp,
1247
1325
struct cs_dsp_alg_region alg_region = {};
1248
1326
struct cs_dsp_coeff_parsed_alg alg_blk ;
1249
1327
struct cs_dsp_coeff_parsed_coeff coeff_blk ;
1250
- const u8 * data = region -> data ;
1251
- int i , ret ;
1328
+ int i , pos , ret ;
1329
+
1330
+ pos = cs_dsp_coeff_parse_alg (dsp , region , & alg_blk );
1331
+ if (pos < 0 )
1332
+ return pos ;
1252
1333
1253
- cs_dsp_coeff_parse_alg (dsp , & data , & alg_blk );
1254
1334
for (i = 0 ; i < alg_blk .ncoeff ; i ++ ) {
1255
- cs_dsp_coeff_parse_coeff (dsp , & data , & coeff_blk );
1335
+ pos = cs_dsp_coeff_parse_coeff (dsp , region , pos , & coeff_blk );
1336
+ if (pos < 0 )
1337
+ return pos ;
1256
1338
1257
1339
switch (coeff_blk .ctl_type ) {
1258
1340
case WMFW_CTL_TYPE_BYTES :
0 commit comments