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