@@ -184,27 +184,73 @@ ext4_xattr_handler(int name_index)
184
184
}
185
185
186
186
static int
187
- ext4_xattr_check_entries (struct ext4_xattr_entry * entry , void * end ,
188
- void * value_start )
187
+ check_xattrs (struct inode * inode , struct buffer_head * bh ,
188
+ struct ext4_xattr_entry * entry , void * end , void * value_start ,
189
+ const char * function , unsigned int line )
189
190
{
190
191
struct ext4_xattr_entry * e = entry ;
192
+ int err = - EFSCORRUPTED ;
193
+ char * err_str ;
194
+
195
+ if (bh ) {
196
+ if (BHDR (bh )-> h_magic != cpu_to_le32 (EXT4_XATTR_MAGIC ) ||
197
+ BHDR (bh )-> h_blocks != cpu_to_le32 (1 )) {
198
+ err_str = "invalid header" ;
199
+ goto errout ;
200
+ }
201
+ if (buffer_verified (bh ))
202
+ return 0 ;
203
+ if (!ext4_xattr_block_csum_verify (inode , bh )) {
204
+ err = - EFSBADCRC ;
205
+ err_str = "invalid checksum" ;
206
+ goto errout ;
207
+ }
208
+ } else {
209
+ struct ext4_xattr_ibody_header * header = value_start ;
210
+
211
+ header -= 1 ;
212
+ if (end - (void * )header < sizeof (* header ) + sizeof (u32 )) {
213
+ err_str = "in-inode xattr block too small" ;
214
+ goto errout ;
215
+ }
216
+ if (header -> h_magic != cpu_to_le32 (EXT4_XATTR_MAGIC )) {
217
+ err_str = "bad magic number in in-inode xattr" ;
218
+ goto errout ;
219
+ }
220
+ }
191
221
192
222
/* Find the end of the names list */
193
223
while (!IS_LAST_ENTRY (e )) {
194
224
struct ext4_xattr_entry * next = EXT4_XATTR_NEXT (e );
195
- if ((void * )next >= end )
196
- return - EFSCORRUPTED ;
197
- if (strnlen (e -> e_name , e -> e_name_len ) != e -> e_name_len )
198
- return - EFSCORRUPTED ;
225
+ if ((void * )next >= end ) {
226
+ err_str = "e_name out of bounds" ;
227
+ goto errout ;
228
+ }
229
+ if (strnlen (e -> e_name , e -> e_name_len ) != e -> e_name_len ) {
230
+ err_str = "bad e_name length" ;
231
+ goto errout ;
232
+ }
199
233
e = next ;
200
234
}
201
235
202
236
/* Check the values */
203
237
while (!IS_LAST_ENTRY (entry )) {
204
238
u32 size = le32_to_cpu (entry -> e_value_size );
239
+ unsigned long ea_ino = le32_to_cpu (entry -> e_value_inum );
205
240
206
- if (size > EXT4_XATTR_SIZE_MAX )
207
- return - EFSCORRUPTED ;
241
+ if (!ext4_has_feature_ea_inode (inode -> i_sb ) && ea_ino ) {
242
+ err_str = "ea_inode specified without ea_inode feature enabled" ;
243
+ goto errout ;
244
+ }
245
+ if (ea_ino && ((ea_ino == EXT4_ROOT_INO ) ||
246
+ !ext4_valid_inum (inode -> i_sb , ea_ino ))) {
247
+ err_str = "invalid ea_ino" ;
248
+ goto errout ;
249
+ }
250
+ if (size > EXT4_XATTR_SIZE_MAX ) {
251
+ err_str = "e_value size too large" ;
252
+ goto errout ;
253
+ }
208
254
209
255
if (size != 0 && entry -> e_value_inum == 0 ) {
210
256
u16 offs = le16_to_cpu (entry -> e_value_offs );
@@ -216,66 +262,54 @@ ext4_xattr_check_entries(struct ext4_xattr_entry *entry, void *end,
216
262
* the padded and unpadded sizes, since the size may
217
263
* overflow to 0 when adding padding.
218
264
*/
219
- if (offs > end - value_start )
220
- return - EFSCORRUPTED ;
265
+ if (offs > end - value_start ) {
266
+ err_str = "e_value out of bounds" ;
267
+ goto errout ;
268
+ }
221
269
value = value_start + offs ;
222
270
if (value < (void * )e + sizeof (u32 ) ||
223
271
size > end - value ||
224
- EXT4_XATTR_SIZE (size ) > end - value )
225
- return - EFSCORRUPTED ;
272
+ EXT4_XATTR_SIZE (size ) > end - value ) {
273
+ err_str = "overlapping e_value " ;
274
+ goto errout ;
275
+ }
226
276
}
227
277
entry = EXT4_XATTR_NEXT (entry );
228
278
}
229
-
279
+ if (bh )
280
+ set_buffer_verified (bh );
230
281
return 0 ;
282
+
283
+ errout :
284
+ if (bh )
285
+ __ext4_error_inode (inode , function , line , 0 , - err ,
286
+ "corrupted xattr block %llu: %s" ,
287
+ (unsigned long long ) bh -> b_blocknr ,
288
+ err_str );
289
+ else
290
+ __ext4_error_inode (inode , function , line , 0 , - err ,
291
+ "corrupted in-inode xattr: %s" , err_str );
292
+ return err ;
231
293
}
232
294
233
295
static inline int
234
296
__ext4_xattr_check_block (struct inode * inode , struct buffer_head * bh ,
235
297
const char * function , unsigned int line )
236
298
{
237
- int error = - EFSCORRUPTED ;
238
-
239
- if (BHDR (bh )-> h_magic != cpu_to_le32 (EXT4_XATTR_MAGIC ) ||
240
- BHDR (bh )-> h_blocks != cpu_to_le32 (1 ))
241
- goto errout ;
242
- if (buffer_verified (bh ))
243
- return 0 ;
244
-
245
- error = - EFSBADCRC ;
246
- if (!ext4_xattr_block_csum_verify (inode , bh ))
247
- goto errout ;
248
- error = ext4_xattr_check_entries (BFIRST (bh ), bh -> b_data + bh -> b_size ,
249
- bh -> b_data );
250
- errout :
251
- if (error )
252
- __ext4_error_inode (inode , function , line , 0 , - error ,
253
- "corrupted xattr block %llu" ,
254
- (unsigned long long ) bh -> b_blocknr );
255
- else
256
- set_buffer_verified (bh );
257
- return error ;
299
+ return check_xattrs (inode , bh , BFIRST (bh ), bh -> b_data + bh -> b_size ,
300
+ bh -> b_data , function , line );
258
301
}
259
302
260
303
#define ext4_xattr_check_block (inode , bh ) \
261
304
__ext4_xattr_check_block((inode), (bh), __func__, __LINE__)
262
305
263
306
264
- static int
307
+ static inline int
265
308
__xattr_check_inode (struct inode * inode , struct ext4_xattr_ibody_header * header ,
266
309
void * end , const char * function , unsigned int line )
267
310
{
268
- int error = - EFSCORRUPTED ;
269
-
270
- if (end - (void * )header < sizeof (* header ) + sizeof (u32 ) ||
271
- (header -> h_magic != cpu_to_le32 (EXT4_XATTR_MAGIC )))
272
- goto errout ;
273
- error = ext4_xattr_check_entries (IFIRST (header ), end , IFIRST (header ));
274
- errout :
275
- if (error )
276
- __ext4_error_inode (inode , function , line , 0 , - error ,
277
- "corrupted in-inode xattr" );
278
- return error ;
311
+ return check_xattrs (inode , NULL , IFIRST (header ), end , IFIRST (header ),
312
+ function , line );
279
313
}
280
314
281
315
#define xattr_check_inode (inode , header , end ) \
0 commit comments