UBIFS: use kmalloc_array() in recomp_data_node()
PATCH 1/1 UBIFS: use kmalloc_array() in recomp_data_node()
Using kmalloc_array() is a cleanup and it includes a check for integer overflows.
fs/ubifs/journal.c +1 -1
@@ -1104,7 +1104,7 @@ static int recomp_data_node(struct ubifs_data_node *dn, int *new_len)int err, len, compr_type, out_len; out_len =le32_to_cpu (dn->size); - buf =kmalloc (out_len *WORST_COMPR_FACTOR ,GFP_NOFS ); + buf =kmalloc_array (out_len,WORST_COMPR_FACTOR ,GFP_NOFS );if (!buf)return -ENOMEM ;
fs/ubifs/journal.c static int recomp_data_node(struct ubifs_data_node *dn, int *new_len) · line 1109
Quoted 5 lines · Dan Carpenter
fs/ubifs/journal.c +1
-1out_len =le32_to_cpu (dn->size); - buf =kmalloc (out_len *WORST_COMPR_FACTOR ,GFP_NOFS ); + buf =kmalloc_array (out_len,WORST_COMPR_FACTOR ,GFP_NOFS );if (!buf)return -ENOMEM ;
I think this makes the code unreadable, because we really allocate a buffer, not an array.
Signature · 2 lines
Best Regards, Artem Bityutskiy
Quoted 9 lines · Artem Bityutskiy
fs/ubifs/journal.c static int recomp_data_node(struct ubifs_data_node *dn, int *new_len) · line 1109
Quoted 5 lines · Dan Carpenter
fs/ubifs/journal.c +1
-1out_len =le32_to_cpu (dn->size); - buf =kmalloc (out_len *WORST_COMPR_FACTOR ,GFP_NOFS ); + buf =kmalloc_array (out_len,WORST_COMPR_FACTOR ,GFP_NOFS );if (!buf)return -ENOMEM ;I think this makes the code unreadable, because we really allocate a buffer, not an array.
The problem with the original code is that the multiply looks very suspect. Everyone who reads it has to backtrack to find where dn->size is capped.
I guess in one sense we never allocate an array, we always declare it on the stack. We debated the naming and there really isn't a good name. kmalloc_safe() isn't right either. But anyway, the intent is that eventually someone will right a coccinelle script which replaces all these allocations with kmalloc_array().
When I look at this code more, I still don't see a place where dn->size is capped. So I think we *need* the integer overflow check as an integer overflow fix and not just as a cleanup.
regards,
dan carpenter
Quoted 21 lines · Dan Carpenter
Quoted 9 lines · Artem Bityutskiy
fs/ubifs/journal.c static int recomp_data_node(struct ubifs_data_node *dn, int *new_len) · line 1109
Quoted 5 lines · Dan Carpenter
fs/ubifs/journal.c +1
-1out_len =le32_to_cpu (dn->size); - buf =kmalloc (out_len *WORST_COMPR_FACTOR ,GFP_NOFS ); + buf =kmalloc_array (out_len,WORST_COMPR_FACTOR ,GFP_NOFS );if (!buf)return -ENOMEM ;I think this makes the code unreadable, because we really allocate a buffer, not an array.
The problem with the original code is that the multiply looks very suspect. Everyone who reads it has to backtrack to find where
dn->sizeis capped.I guess in one sense we never allocate an array, we always declare it on the stack. We debated the naming and there really isn't a good name.
kmalloc_safe()isn't right either. But anyway, the intent is that eventually someone will right a coccinelle script which replaces all these allocations withkmalloc_array().
Quoted 3 lines
When I look at this code more, I still don't see a place where
dn->sizeis capped. So I think we *need* the integer overflow check as an integer overflow fix and not just as a cleanup.
It is validated in fs/ubifs/io.c in 'ubifs_check_node()'.
'dn' stands for 'direntry node'. We read it from the media and validate it immediately after we've read it, including 'dn->len'.
The entire code is written with the following assumption that whatever is read from the flash media is validated.
Signature · 2 lines
Best Regards, Artem Bityutskiy
Quoted 26 lines · Artem Bityutskiy
Quoted 21 lines · Dan Carpenter
Quoted 9 lines · Artem Bityutskiy
fs/ubifs/journal.c static int recomp_data_node(struct ubifs_data_node *dn, int *new_len) · line 1109
Quoted 5 lines · Dan Carpenter
fs/ubifs/journal.c +1
-1out_len =le32_to_cpu (dn->size); - buf =kmalloc (out_len *WORST_COMPR_FACTOR ,GFP_NOFS ); + buf =kmalloc_array (out_len,WORST_COMPR_FACTOR ,GFP_NOFS );if (!buf)return -ENOMEM ;I think this makes the code unreadable, because we really allocate a buffer, not an array.
The problem with the original code is that the multiply looks very suspect. Everyone who reads it has to backtrack to find where
dn->sizeis capped.I guess in one sense we never allocate an array, we always declare it on the stack. We debated the naming and there really isn't a good name.
kmalloc_safe()isn't right either. But anyway, the intent is that eventually someone will right a coccinelle script which replaces all these allocations withkmalloc_array().Quoted 3 lines
When I look at this code more, I still don't see a place where
dn->sizeis capped. So I think we *need* the integer overflow check as an integer overflow fix and not just as a cleanup.
Quoted 7 lines
It is validated in
fs/ubifs/io.cin 'ubifs_check_node()'.'dn' stands for 'direntry node'. We read it from the media and validate it immediately after we've read it, including '
dn->len'.The entire code is written with the following assumption that whatever is read from the flash media is validated.
It's actually dn->size that we care about here. That's not checked in ubifs_check_node(). :( It may be checked somewhere else, I'm still looking.
regards,
dan cparenter
Quoted 3 lines · Dan Carpenter
It's actually
dn->sizethat we care about here. That's not checked inubifs_check_node(). :( It may be checked somewhere else, I'm still looking.
Wow, despite us trying to be very careful about validating what we read from flash, it seems we indeed never validate 'size'... Let me invent a fix for this, which should also be sent to -stable.
Thanks!
Signature · 2 lines
Best Regards, Artem Bityutskiy
Quoted 9 lines · Artem Bityutskiy
Quoted 3 lines · Dan Carpenter
It's actually
dn->sizethat we care about here. That's not checked inubifs_check_node(). :( It may be checked somewhere else, I'm still looking.Wow, despite us trying to be very careful about validating what we read from flash, it seems we indeed never validate 'size'... Let me invent a fix for this, which should also be sent to -stable.
Thanks. Could you give me the Reported-by tag?
regards,
dan carpenter
Quoted 15 lines · Dan Carpenter
Quoted 9 lines · Artem Bityutskiy
fs/ubifs/journal.c static int recomp_data_node(struct ubifs_data_node *dn, int *new_len) · line 1109
Quoted 5 lines · Dan Carpenter
fs/ubifs/journal.c +1
-1out_len =le32_to_cpu (dn->size); - buf =kmalloc (out_len *WORST_COMPR_FACTOR ,GFP_NOFS ); + buf =kmalloc_array (out_len,WORST_COMPR_FACTOR ,GFP_NOFS );if (!buf)return -ENOMEM ;I think this makes the code unreadable, because we really allocate a buffer, not an array.
The problem with the original code is that the multiply looks very suspect. Everyone who reads it has to backtrack to find where
dn->sizeis capped.
Quoted 5 lines
I guess in one sense we never allocate an array, we always declare it on the stack. We debated the naming and there really isn't a good name.
kmalloc_safe()isn't right either. But anyway, the intent is that eventually someone will right a coccinelle script which replaces all these allocations withkmalloc_array().
Did you consider kcalloc() ? Just like malloc() / calloc() libc functions?
Signature · 2 lines
Best Regards, Artem Bityutskiy
Quoted 2 lines · Artem Bityutskiy
Did you consider
kcalloc()? Just likemalloc()/calloc()libc functions?
Ah, there is kcaoloc already, so I guess then we could just put the overflow check there instead?
Signature · 2 lines
Best Regards, Artem Bityutskiy
Quoted 6 lines · Artem Bityutskiy
Quoted 2 lines · Artem Bityutskiy
Did you consider
kcalloc()? Just likemalloc()/calloc()libc functions?Ah, there is kcaoloc already, so I guess then we could just put the overflow check there instead?
Yep. That's there already.
regards,
dan carpenter
Quoted 16 lines · Artem Bityutskiy
Quoted 15 lines · Dan Carpenter
Quoted 9 lines · Artem Bityutskiy
fs/ubifs/journal.c static int recomp_data_node(struct ubifs_data_node *dn, int *new_len) · line 1109
Quoted 5 lines · Dan Carpenter
fs/ubifs/journal.c +1
-1out_len =le32_to_cpu (dn->size); - buf =kmalloc (out_len *WORST_COMPR_FACTOR ,GFP_NOFS ); + buf =kmalloc_array (out_len,WORST_COMPR_FACTOR ,GFP_NOFS );if (!buf)return -ENOMEM ;I think this makes the code unreadable, because we really allocate a buffer, not an array.
The problem with the original code is that the multiply looks very suspect. Everyone who reads it has to backtrack to find where
dn->sizeis capped.
Quoted 8 lines
Quoted 5 lines
I guess in one sense we never allocate an array, we always declare it on the stack. We debated the naming and there really isn't a good name.
kmalloc_safe()isn't right either. But anyway, the intent is that eventually someone will right a coccinelle script which replaces all these allocations withkmalloc_array().Did you consider
kcalloc()? Just likemalloc()/calloc()libc functions?
We already have a kcalloc() but it zeroes out the memory.
regards,
dan carpenter