Fix corruption error in rh_alloc_fixed()
PATCH 1/1 Fix corruption error in rh_alloc_fixed()
There is an error in rh_alloc_fixed() of the Remote Heap code:
If there is at least one free block blk won't be NULL at the end of the search loop, so -ENOMEM won't be returned and the else branch of "if (bs == s || be == e)" will be taken, corrupting the management structures.
---
Fix an error in rh_alloc_fixed() that made allocations succeed when they should fail, and corrupted management structures.
arch/powerpc/lib/rheap.c +1 -0
@@ -556,6 +556,7 @@ unsigned long rh_alloc_fixed(rh_info_t * info, unsigned long start, int size, co be = blk->start + blk->size;if (s >= bs && e <= be)break ; + blk =NULL ; }if (blk ==NULL )
Quoted 16 lines · Guillaume Knispel
There is an error in
rh_alloc_fixed()of the Remote Heap code:
If there is at least one free block blk won't be NULL at the end of the search loop, so-ENOMEMwon't be returned and the else branch of "if (bs == s || be == e)" will be taken, corrupting the management structures.Signed-off-by Guillaume Knispel <[email protected]>---
Fix an error inrh_alloc_fixed()that made allocations succeed when they should fail, and corrupted management structures.arch/powerpc/lib/rheap.c +0
-0
arch/powerpc/lib/rheap.c unsigned long rh_alloc_fixed(rh_info_t * info, unsigned long start, int size, co · line 562
Quoted 7 lines
arch/powerpc/lib/rheap.c +1
-0@@ -556,6 +556,7 @@ unsigned long rh_alloc_fixed(rh_info_t * info, unsigned long start, int size, co be = blk->start + blk->size;if (s >= bs && e <= be)break ; + blk =NULL ; }if (blk ==NULL )
This is a good catch, however, wouldn't it be better to do this:
list_for_each(l, &info->free_list) {
blk = list_entry(l, rh_block_t, list);
/* The range must lie entirely inside one free block */
bs = blk->start;
be = blk->start + blk->size;
if (s >= bs && e <= be)
break;
}- if (blk == NULL)
+ if (blk == &info->free_list)
return (unsigned long) -ENOMEM;
I haven't tested this, but the if-statement at the end of the loop is meant to check whether the list_for_each() loop got to the end or not.
What do you think?
Signature · 2 lines
Timur Tabi Linux kernel developer at Freescale
Quoted 40 lines · On Tue, 09 Dec 2008 09:03:19 -0600 Timur Tabi <[email protected]> wrote:
Quoted 16 lines · Guillaume Knispel
There is an error in
rh_alloc_fixed()of the Remote Heap code:
If there is at least one free block blk won't be NULL at the end of the search loop, so-ENOMEMwon't be returned and the else branch of "if (bs == s || be == e)" will be taken, corrupting the management structures.Signed-off-by Guillaume Knispel <[email protected]>---
Fix an error inrh_alloc_fixed()that made allocations succeed when they should fail, and corrupted management structures.arch/powerpc/lib/rheap.c +0
-0arch/powerpc/lib/rheap.c unsigned long rh_alloc_fixed(rh_info_t * info, unsigned long start, int size, co · line 562
Quoted 7 lines
arch/powerpc/lib/rheap.c +1
-0@@ -556,6 +556,7 @@ unsigned long rh_alloc_fixed(rh_info_t * info, unsigned long start, int size, co be = blk->start + blk->size;if (s >= bs && e <= be)break ; + blk =NULL ; }if (blk ==NULL )This is a good catch, however, wouldn't it be better to do this:
list_for_each(l, &info->free_list) { blk = list_entry(l, rh_block_t, list); /* The range must lie entirely inside one free block */ bs = blk->start; be = blk->start + blk->size; if (s >= bs && e <= be) break; }(quoted diff) +1
-1- if (blk == NULL) + if (blk == &info->free_list)return (unsigned long) -ENOMEM;
Quoted 4 lines
I haven't tested this, but the if-statement at the end of the loop is meant to check whether the
list_for_each()loop got to the end or not.What do you think?
blk = NULL; at the end of the loop is what is done in the more used rh_alloc_align(), so for consistency either we change both or we use the same construction here.
I also think that testing for &info->free_list is harder to understand because you must have the linked list implementation in your head (which a kernel developer should anyway so this is not so important)
Guillaume Knispel
Timur Tabi
Acked-byQuoted 6 lines · Guillaume Knispel
blk = NULL; at the end of the loop is what is done in the more used
rh_alloc_align(), so for consistency either we change both or we use the same construction here.
I also think that testing for&info->free_listis harder to understand because you must have the linked list implementation in your head (which a kernel developer should anyway so this is not so important)
Fair enough.
Signature · 2 lines
Timur Tabi Linux kernel developer at Freescale
Quoted 9 lines · On Tue, 09 Dec 2008 09:16:50 -0600 Timur Tabi <[email protected]> wrote:
Quoted 6 lines · Guillaume Knispel
blk = NULL; at the end of the loop is what is done in the more used
rh_alloc_align(), so for consistency either we change both or we use the same construction here.
I also think that testing for&info->free_listis harder to understand because you must have the linked list implementation in your head (which a kernel developer should anyway so this is not so important)
Quoted 4 lines
Fair enough.
Acked-by Timur Tabi <[email protected]>
Kumar, can this go into your tree ?
(copying the patch under so you have it at hand)
There is an error in rh_alloc_fixed() of the Remote Heap code:
If there is at least one free block blk won't be NULL at the end of the search loop, so -ENOMEM won't be returned and the else branch of "if (bs == s || be == e)" will be taken, corrupting the management structures.
---
Fix an error in rh_alloc_fixed() that made allocations succeed when they should fail, and corrupted management structures.
arch/powerpc/lib/rheap.c +1 -0
@@ -556,6 +556,7 @@ unsigned long rh_alloc_fixed(rh_info_t * info, unsigned long start, int size, co be = blk->start + blk->size;if (s >= bs && e <= be)break ; + blk =NULL ; }if (blk ==NULL )
Signature · 1 line
Guillaume KNISPEL
Quoted 26 lines · Guillaume Knispel
Quoted 9 lines · On Tue, 09 Dec 2008 09:16:50 -0600 Timur Tabi <[email protected]> wrote:
Quoted 6 lines · Guillaume Knispel
blk = NULL; at the end of the loop is what is done in the more used
rh_alloc_align(), so for consistency either we change both or we use the same construction here.
I also think that testing for&info->free_listis harder to understand because you must have the linked list implementation in your head (which a kernel developer should anyway so this is not so important)Quoted 4 lines
Fair enough.
Acked-by Timur Tabi <[email protected]>Kumar, can this go into your tree ?
(copying the patch under so you have it at hand)There is an error in
rh_alloc_fixed()of the Remote Heap code:
If there is at least one free block blk won't be NULL at the end of the search loop, so-ENOMEMwon't be returned and the else branch of "if (bs == s || be == e)" will be taken, corrupting the management structures.
Quoted 4 lines
Signed-off-by Guillaume Knispel <[email protected]>---
Fix an error inrh_alloc_fixed()that made allocations succeed when they should fail, and corrupted management structures.
What's the impact of this? Can it cause an oops?
Is it a regression from 2.6.27? Should we be putting it in 2.6.28?
Paul.
Quoted 33 lines · On Mon, 15 Dec 2008 08:21:05 +1100 Paul Mackerras <[email protected]> wrote:
Quoted 26 lines · Guillaume Knispel
Quoted 9 lines · On Tue, 09 Dec 2008 09:16:50 -0600 Timur Tabi <[email protected]> wrote:
Quoted 6 lines · Guillaume Knispel
blk = NULL; at the end of the loop is what is done in the more used
rh_alloc_align(), so for consistency either we change both or we use the same construction here.
I also think that testing for&info->free_listis harder to understand because you must have the linked list implementation in your head (which a kernel developer should anyway so this is not so important)Quoted 4 lines
Fair enough.
Acked-by Timur Tabi <[email protected]>Kumar, can this go into your tree ?
(copying the patch under so you have it at hand)There is an error in
rh_alloc_fixed()of the Remote Heap code:
If there is at least one free block blk won't be NULL at the end of the search loop, so-ENOMEMwon't be returned and the else branch of "if (bs == s || be == e)" will be taken, corrupting the management structures.Quoted 4 lines
Signed-off-by Guillaume Knispel <[email protected]>---
Fix an error inrh_alloc_fixed()that made allocations succeed when they should fail, and corrupted management structures.
Quoted 5 lines
What's the impact of this? Can it cause an oops?
Is it a regression from 2.6.27? Should we be putting it in 2.6.28?
Paul.
The problem obviously only affect people that make use of rh_alloc_fixed(), which is the case when you program an MCC or a QMC controller of the CPM. Without the patch cpm_muram_alloc_fixed() succeed when it should not, for example when trying to allocate out of range areas or already allocated areas, so it is possible that buffer descriptors or other control structures used by other controllers get corrupted.
Digging into ooooold Linux (like 2.6.9, I haven't checked before), the problem seems to always have been present.
Without this patch I experienced oops (sometimes panic, sometimes not) in various unrelated part (probably an indirect result of either corruption of rheap management structures or corruption caused by the CPM using crazy overwritten data) and also initialization of multi-channel control structures putting other communication controllers out-of-order.
The only risk I can think off is that it could break some out of tree kernel space code which worked because of luck and a double error - for example when doing a single DPRam allocation from offset 0 while leaving an area reserved at the base of the DPRam. So I think it should be put in 2.6.28.
Guillaume Knispel
Quoted 19 lines
The problem obviously only affect people that make use of
rh_alloc_fixed(), which is the case when you program an MCC or a QMC controller of the CPM. Without the patchcpm_muram_alloc_fixed()succeed when it should not, for example when trying to allocate out of range areas or already allocated areas, so it is possible that buffer descriptors or other control structures used by other controllers get corrupted.Digging into ooooold Linux (like 2.6.9, I haven't checked before), the problem seems to always have been present.
Without this patch I experienced oops (sometimes panic, sometimes not) in various unrelated part (probably an indirect result of either corruption of rheap management structures or corruption caused by the CPM using crazy overwritten data) and also initialization of multi-channel control structures putting other communication controllers out-of-order.
Quoted 5 lines
The only risk I can think off is that it could break some out of tree kernel space code which worked because of luck and a double error - for example when doing a single DPRam allocation from offset 0 while leaving an area reserved at the base of the DPRam. So I think it should be put in 2.6.28.
Paul are you planning on picking this up for .28 if not I'll pick it up for .29
- k
Quoted 2 lines · Kumar Gala
Paul are you planning on picking this up for .28 if not I'll pick it up for .29
I was waiting for you to say if it needed to go in .28. Sounds like you don't think it's that urgent then?
Paul.
Quoted 7 lines · Paul Mackerras
Quoted 2 lines · Kumar Gala
Paul are you planning on picking this up for .28 if not I'll pick it up for .29
I was waiting for you to say if it needed to go in .28. Sounds like you don't think it's that urgent then?
Since I have another patch for .28 I'll include in my merge tree.
- k
Kumar Gala
AppliedQuoted 21 lines · Guillaume Knispel
There is an error in
rh_alloc_fixed()of the Remote Heap code:
If there is at least one free block blk won't be NULL at the end of the search loop, so-ENOMEMwon't be returned and the else branch of "if (bs == s || be == e)" will be taken, corrupting the management structures.Signed-off-by Guillaume Knispel <[email protected]>---
Fix an error inrh_alloc_fixed()that made allocations succeed when they should fail, and corrupted management structures.arch/powerpc/lib/rheap.c +0
-0@@ -556,6 +556,7 @@ unsigned long rh_alloc_fixed(rh_info_t * info,unsigned long start, int size, co
be = blk->start + blk->size; if (s >= bs && e <= be) break;arch/powerpc/lib/rheap.c +1
-0+ blk =NULL ;
Quoted 3 lines
} if (blk == NULL)
applied
- k