Re: [PATCH 03/16] mm: check rb_subtree_gap correctness
On Fri, Nov 9, 2012 at 6:13 AM, Sasha Levin wrote: > While fuzzing with trinity inside a KVM tools (lkvm) guest, using today's > -next > kernel, I'm getting these: > > [ 117.007714] free gap 7fba0dd1c000, correct 7fba0dcfb000 > [ 117.019773] map_count 750 rb -1 > [ 117.028362] [ cut here ] > [ 117.029813] kernel BUG at mm/mmap.c:439! > > Note that they are very easy to reproduce. Thanks for the report. I had trouble reproducing this on Friday, but after Hugh came up with an easy test case I think I have it figured out. I sent out a proposed fix as "[PATCH 0/3] fix missing rb_subtree_gap updates on vma insert/erase". Let's follow up the discussion there if necessary. Cheers, -- Michel "Walken" Lespinasse A program is never fully debugged until the last user dies. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 03/16] mm: check rb_subtree_gap correctness
On Fri, Nov 9, 2012 at 6:13 AM, Sasha Levin levinsasha...@gmail.com wrote: While fuzzing with trinity inside a KVM tools (lkvm) guest, using today's -next kernel, I'm getting these: [ 117.007714] free gap 7fba0dd1c000, correct 7fba0dcfb000 [ 117.019773] map_count 750 rb -1 [ 117.028362] [ cut here ] [ 117.029813] kernel BUG at mm/mmap.c:439! Note that they are very easy to reproduce. Thanks for the report. I had trouble reproducing this on Friday, but after Hugh came up with an easy test case I think I have it figured out. I sent out a proposed fix as [PATCH 0/3] fix missing rb_subtree_gap updates on vma insert/erase. Let's follow up the discussion there if necessary. Cheers, -- Michel Walken Lespinasse A program is never fully debugged until the last user dies. -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 03/16] mm: check rb_subtree_gap correctness
On Fri, 9 Nov 2012, Sasha Levin wrote: > On 11/05/2012 05:47 PM, Michel Lespinasse wrote: > > When CONFIG_DEBUG_VM_RB is enabled, check that rb_subtree_gap is > > correctly set for every vma and that mm->highest_vm_end is also correct. > > > > Also add an explicit 'bug' variable to track if browse_rb() detected any > > invalid condition. > > > > Signed-off-by: Michel Lespinasse > > Reviewed-by: Rik van Riel > > > > --- > > Hi all, > > While fuzzing with trinity inside a KVM tools (lkvm) guest, using today's > -next > kernel, I'm getting these: > > > [ 117.007714] free gap 7fba0dd1c000, correct 7fba0dcfb000 > [ 117.019773] map_count 750 rb -1 > [ 117.028362] [ cut here ] > [ 117.029813] kernel BUG at mm/mmap.c:439! > [ 117.031024] invalid opcode: [#1] PREEMPT SMP DEBUG_PAGEALLOC > [ 117.032933] Dumping ftrace buffer: > [ 117.033972](ftrace buffer empty) > [ 117.035085] CPU 4 > [ 117.035676] Pid: 6859, comm: trinity-child46 Tainted: GW > 3.7.0-rc4-next-20121109-sasha-00013-g9407f3c #124 > [ 117.038217] RIP: 0010:[] [] > validate_mm+0x297/0x2c0 > [ 117.041056] RSP: 0018:880016a4fdf8 EFLAGS: 00010296 > [ 117.041056] RAX: 0013 RBX: RCX: > 0006 > [ 117.041056] RDX: 5270 RSI: 880024120910 RDI: > 0286 > [ 117.052131] RBP: 880016a4fe48 R08: R09: > > [ 117.052131] R10: 0001 R11: R12: > 02ee > [ 117.052131] R13: 7fffea1fc000 R14: 88002412c000 R15: > > [ 117.052131] FS: 7fba129db700() GS:88006360() > knlGS: > [ 117.052131] CS: 0010 DS: ES: CR0: 80050033 > [ 117.052131] CR2: 03323288 CR3: 169b2000 CR4: > 000406e0 > [ 117.052131] DR0: DR1: DR2: > > [ 117.052131] DR3: DR6: 0ff0 DR7: > 0400 > [ 117.052131] Process trinity-child46 (pid: 6859, threadinfo > 880016a4e000, task 88002412) > [ 117.052131] Stack: > [ 117.052131] 8489e201 81235aa0 88000885cac8 > 0001 > [ 117.052131] 812361b9 88002412c000 88000885cac8 > 88000885cdc8 > [ 117.052131] 88000885cdd0 88002412c000 880016a4fe98 > 812367b4 > [ 117.052131] Call Trace: > [ 117.052131] [] ? vma_compute_subtree_gap+0x40/0x40 > [ 117.052131] [] ? vma_gap_update+0x19/0x30 > [ 117.052131] [] vma_link+0x94/0xe0 > [ 117.052131] [] do_brk+0x2c4/0x380 > [ 117.052131] [] ? sys_brk+0x3f/0x190 > [ 117.052131] [] sys_brk+0x14e/0x190 > [ 117.052131] [] tracesys+0xe1/0xe6 > [ 117.052131] Code: d8 41 8b 76 60 39 de 74 1b 89 da 48 c7 c7 c6 d9 89 84 31 > c0 e8 01 76 94 02 eb 10 66 0f 1f 84 00 00 00 00 00 > 8b 45 c8 85 c0 74 18 <0f> 0b 4c 8d 48 e0 48 8b 70 e0 31 db c7 45 cc 00 00 00 > 00 e9 f4 > [ 117.052131] RIP [] validate_mm+0x297/0x2c0 > [ 117.052131] RSP > [ 117.136092] ---[ end trace 5ce250e0bf6d040c ]--- > > Note that they are very easy to reproduce. > > Also, I see that lots of the code there has a local variable named 'bug' > thats tracking > whether we should BUG() later on. Why does it work that way and the BUG() > isn't immediate? 3.7.0-rc4-mm1 BUGged on mm/mmap.c:439 as soon as I tried to rebuild that kernel with Alan's tty/vt/fb patch included, no fuzzing required. free_gap 1d077000, correct 1ccd2000 in my case. It should only be affecting the minority with CONFIG_DEBUG_VM_RB=y. I've put #if 0 around the rb_subtree_gap checking block in browse_rb(), and running okay so far with that - but not yet done much with it. Hugh -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 03/16] mm: check rb_subtree_gap correctness
On 11/05/2012 05:47 PM, Michel Lespinasse wrote: > When CONFIG_DEBUG_VM_RB is enabled, check that rb_subtree_gap is > correctly set for every vma and that mm->highest_vm_end is also correct. > > Also add an explicit 'bug' variable to track if browse_rb() detected any > invalid condition. > > Signed-off-by: Michel Lespinasse > Reviewed-by: Rik van Riel > > --- Hi all, While fuzzing with trinity inside a KVM tools (lkvm) guest, using today's -next kernel, I'm getting these: [ 117.007714] free gap 7fba0dd1c000, correct 7fba0dcfb000 [ 117.019773] map_count 750 rb -1 [ 117.028362] [ cut here ] [ 117.029813] kernel BUG at mm/mmap.c:439! [ 117.031024] invalid opcode: [#1] PREEMPT SMP DEBUG_PAGEALLOC [ 117.032933] Dumping ftrace buffer: [ 117.033972](ftrace buffer empty) [ 117.035085] CPU 4 [ 117.035676] Pid: 6859, comm: trinity-child46 Tainted: GW 3.7.0-rc4-next-20121109-sasha-00013-g9407f3c #124 [ 117.038217] RIP: 0010:[] [] validate_mm+0x297/0x2c0 [ 117.041056] RSP: 0018:880016a4fdf8 EFLAGS: 00010296 [ 117.041056] RAX: 0013 RBX: RCX: 0006 [ 117.041056] RDX: 5270 RSI: 880024120910 RDI: 0286 [ 117.052131] RBP: 880016a4fe48 R08: R09: [ 117.052131] R10: 0001 R11: R12: 02ee [ 117.052131] R13: 7fffea1fc000 R14: 88002412c000 R15: [ 117.052131] FS: 7fba129db700() GS:88006360() knlGS: [ 117.052131] CS: 0010 DS: ES: CR0: 80050033 [ 117.052131] CR2: 03323288 CR3: 169b2000 CR4: 000406e0 [ 117.052131] DR0: DR1: DR2: [ 117.052131] DR3: DR6: 0ff0 DR7: 0400 [ 117.052131] Process trinity-child46 (pid: 6859, threadinfo 880016a4e000, task 88002412) [ 117.052131] Stack: [ 117.052131] 8489e201 81235aa0 88000885cac8 0001 [ 117.052131] 812361b9 88002412c000 88000885cac8 88000885cdc8 [ 117.052131] 88000885cdd0 88002412c000 880016a4fe98 812367b4 [ 117.052131] Call Trace: [ 117.052131] [] ? vma_compute_subtree_gap+0x40/0x40 [ 117.052131] [] ? vma_gap_update+0x19/0x30 [ 117.052131] [] vma_link+0x94/0xe0 [ 117.052131] [] do_brk+0x2c4/0x380 [ 117.052131] [] ? sys_brk+0x3f/0x190 [ 117.052131] [] sys_brk+0x14e/0x190 [ 117.052131] [] tracesys+0xe1/0xe6 [ 117.052131] Code: d8 41 8b 76 60 39 de 74 1b 89 da 48 c7 c7 c6 d9 89 84 31 c0 e8 01 76 94 02 eb 10 66 0f 1f 84 00 00 00 00 00 8b 45 c8 85 c0 74 18 <0f> 0b 4c 8d 48 e0 48 8b 70 e0 31 db c7 45 cc 00 00 00 00 e9 f4 [ 117.052131] RIP [] validate_mm+0x297/0x2c0 [ 117.052131] RSP [ 117.136092] ---[ end trace 5ce250e0bf6d040c ]--- Note that they are very easy to reproduce. Also, I see that lots of the code there has a local variable named 'bug' thats tracking whether we should BUG() later on. Why does it work that way and the BUG() isn't immediate? Thanks, Sasha -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 03/16] mm: check rb_subtree_gap correctness
On 11/05/2012 05:47 PM, Michel Lespinasse wrote: When CONFIG_DEBUG_VM_RB is enabled, check that rb_subtree_gap is correctly set for every vma and that mm-highest_vm_end is also correct. Also add an explicit 'bug' variable to track if browse_rb() detected any invalid condition. Signed-off-by: Michel Lespinasse wal...@google.com Reviewed-by: Rik van Riel r...@redhat.com --- Hi all, While fuzzing with trinity inside a KVM tools (lkvm) guest, using today's -next kernel, I'm getting these: [ 117.007714] free gap 7fba0dd1c000, correct 7fba0dcfb000 [ 117.019773] map_count 750 rb -1 [ 117.028362] [ cut here ] [ 117.029813] kernel BUG at mm/mmap.c:439! [ 117.031024] invalid opcode: [#1] PREEMPT SMP DEBUG_PAGEALLOC [ 117.032933] Dumping ftrace buffer: [ 117.033972](ftrace buffer empty) [ 117.035085] CPU 4 [ 117.035676] Pid: 6859, comm: trinity-child46 Tainted: GW 3.7.0-rc4-next-20121109-sasha-00013-g9407f3c #124 [ 117.038217] RIP: 0010:[81236687] [81236687] validate_mm+0x297/0x2c0 [ 117.041056] RSP: 0018:880016a4fdf8 EFLAGS: 00010296 [ 117.041056] RAX: 0013 RBX: RCX: 0006 [ 117.041056] RDX: 5270 RSI: 880024120910 RDI: 0286 [ 117.052131] RBP: 880016a4fe48 R08: R09: [ 117.052131] R10: 0001 R11: R12: 02ee [ 117.052131] R13: 7fffea1fc000 R14: 88002412c000 R15: [ 117.052131] FS: 7fba129db700() GS:88006360() knlGS: [ 117.052131] CS: 0010 DS: ES: CR0: 80050033 [ 117.052131] CR2: 03323288 CR3: 169b2000 CR4: 000406e0 [ 117.052131] DR0: DR1: DR2: [ 117.052131] DR3: DR6: 0ff0 DR7: 0400 [ 117.052131] Process trinity-child46 (pid: 6859, threadinfo 880016a4e000, task 88002412) [ 117.052131] Stack: [ 117.052131] 8489e201 81235aa0 88000885cac8 0001 [ 117.052131] 812361b9 88002412c000 88000885cac8 88000885cdc8 [ 117.052131] 88000885cdd0 88002412c000 880016a4fe98 812367b4 [ 117.052131] Call Trace: [ 117.052131] [81235aa0] ? vma_compute_subtree_gap+0x40/0x40 [ 117.052131] [812361b9] ? vma_gap_update+0x19/0x30 [ 117.052131] [812367b4] vma_link+0x94/0xe0 [ 117.052131] [812386c4] do_brk+0x2c4/0x380 [ 117.052131] [812387bf] ? sys_brk+0x3f/0x190 [ 117.052131] [812388ce] sys_brk+0x14e/0x190 [ 117.052131] [83be2618] tracesys+0xe1/0xe6 [ 117.052131] Code: d8 41 8b 76 60 39 de 74 1b 89 da 48 c7 c7 c6 d9 89 84 31 c0 e8 01 76 94 02 eb 10 66 0f 1f 84 00 00 00 00 00 8b 45 c8 85 c0 74 18 0f 0b 4c 8d 48 e0 48 8b 70 e0 31 db c7 45 cc 00 00 00 00 e9 f4 [ 117.052131] RIP [81236687] validate_mm+0x297/0x2c0 [ 117.052131] RSP 880016a4fdf8 [ 117.136092] ---[ end trace 5ce250e0bf6d040c ]--- Note that they are very easy to reproduce. Also, I see that lots of the code there has a local variable named 'bug' thats tracking whether we should BUG() later on. Why does it work that way and the BUG() isn't immediate? Thanks, Sasha -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 03/16] mm: check rb_subtree_gap correctness
On Fri, 9 Nov 2012, Sasha Levin wrote: On 11/05/2012 05:47 PM, Michel Lespinasse wrote: When CONFIG_DEBUG_VM_RB is enabled, check that rb_subtree_gap is correctly set for every vma and that mm-highest_vm_end is also correct. Also add an explicit 'bug' variable to track if browse_rb() detected any invalid condition. Signed-off-by: Michel Lespinasse wal...@google.com Reviewed-by: Rik van Riel r...@redhat.com --- Hi all, While fuzzing with trinity inside a KVM tools (lkvm) guest, using today's -next kernel, I'm getting these: [ 117.007714] free gap 7fba0dd1c000, correct 7fba0dcfb000 [ 117.019773] map_count 750 rb -1 [ 117.028362] [ cut here ] [ 117.029813] kernel BUG at mm/mmap.c:439! [ 117.031024] invalid opcode: [#1] PREEMPT SMP DEBUG_PAGEALLOC [ 117.032933] Dumping ftrace buffer: [ 117.033972](ftrace buffer empty) [ 117.035085] CPU 4 [ 117.035676] Pid: 6859, comm: trinity-child46 Tainted: GW 3.7.0-rc4-next-20121109-sasha-00013-g9407f3c #124 [ 117.038217] RIP: 0010:[81236687] [81236687] validate_mm+0x297/0x2c0 [ 117.041056] RSP: 0018:880016a4fdf8 EFLAGS: 00010296 [ 117.041056] RAX: 0013 RBX: RCX: 0006 [ 117.041056] RDX: 5270 RSI: 880024120910 RDI: 0286 [ 117.052131] RBP: 880016a4fe48 R08: R09: [ 117.052131] R10: 0001 R11: R12: 02ee [ 117.052131] R13: 7fffea1fc000 R14: 88002412c000 R15: [ 117.052131] FS: 7fba129db700() GS:88006360() knlGS: [ 117.052131] CS: 0010 DS: ES: CR0: 80050033 [ 117.052131] CR2: 03323288 CR3: 169b2000 CR4: 000406e0 [ 117.052131] DR0: DR1: DR2: [ 117.052131] DR3: DR6: 0ff0 DR7: 0400 [ 117.052131] Process trinity-child46 (pid: 6859, threadinfo 880016a4e000, task 88002412) [ 117.052131] Stack: [ 117.052131] 8489e201 81235aa0 88000885cac8 0001 [ 117.052131] 812361b9 88002412c000 88000885cac8 88000885cdc8 [ 117.052131] 88000885cdd0 88002412c000 880016a4fe98 812367b4 [ 117.052131] Call Trace: [ 117.052131] [81235aa0] ? vma_compute_subtree_gap+0x40/0x40 [ 117.052131] [812361b9] ? vma_gap_update+0x19/0x30 [ 117.052131] [812367b4] vma_link+0x94/0xe0 [ 117.052131] [812386c4] do_brk+0x2c4/0x380 [ 117.052131] [812387bf] ? sys_brk+0x3f/0x190 [ 117.052131] [812388ce] sys_brk+0x14e/0x190 [ 117.052131] [83be2618] tracesys+0xe1/0xe6 [ 117.052131] Code: d8 41 8b 76 60 39 de 74 1b 89 da 48 c7 c7 c6 d9 89 84 31 c0 e8 01 76 94 02 eb 10 66 0f 1f 84 00 00 00 00 00 8b 45 c8 85 c0 74 18 0f 0b 4c 8d 48 e0 48 8b 70 e0 31 db c7 45 cc 00 00 00 00 e9 f4 [ 117.052131] RIP [81236687] validate_mm+0x297/0x2c0 [ 117.052131] RSP 880016a4fdf8 [ 117.136092] ---[ end trace 5ce250e0bf6d040c ]--- Note that they are very easy to reproduce. Also, I see that lots of the code there has a local variable named 'bug' thats tracking whether we should BUG() later on. Why does it work that way and the BUG() isn't immediate? 3.7.0-rc4-mm1 BUGged on mm/mmap.c:439 as soon as I tried to rebuild that kernel with Alan's tty/vt/fb patch included, no fuzzing required. free_gap 1d077000, correct 1ccd2000 in my case. It should only be affecting the minority with CONFIG_DEBUG_VM_RB=y. I've put #if 0 around the rb_subtree_gap checking block in browse_rb(), and running okay so far with that - but not yet done much with it. Hugh -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 03/16] mm: check rb_subtree_gap correctness
On Mon, 5 Nov 2012 14:47:00 -0800 Michel Lespinasse wrote: > When CONFIG_DEBUG_VM_RB is enabled, check that rb_subtree_gap is > correctly set for every vma and that mm->highest_vm_end is also correct. > > Also add an explicit 'bug' variable to track if browse_rb() detected any > invalid condition. > > ... > > @@ -365,7 +365,7 @@ static void vma_rb_erase(struct vm_area_struct *vma, > struct rb_root *root) > #ifdef CONFIG_DEBUG_VM_RB > static int browse_rb(struct rb_root *root) > { > - int i = 0, j; > + int i = 0, j, bug = 0; > struct rb_node *nd, *pn = NULL; > unsigned long prev = 0, pend = 0; > > @@ -373,29 +373,33 @@ static int browse_rb(struct rb_root *root) > struct vm_area_struct *vma; > vma = rb_entry(nd, struct vm_area_struct, vm_rb); > if (vma->vm_start < prev) > - printk("vm_start %lx prev %lx\n", vma->vm_start, prev), > i = -1; > + printk("vm_start %lx prev %lx\n", vma->vm_start, prev), > bug = 1; > if (vma->vm_start < pend) > - printk("vm_start %lx pend %lx\n", vma->vm_start, pend); > + printk("vm_start %lx pend %lx\n", vma->vm_start, pend), > bug = 1; > if (vma->vm_start > vma->vm_end) > - printk("vm_end %lx < vm_start %lx\n", vma->vm_end, > vma->vm_start); > + printk("vm_end %lx < vm_start %lx\n", vma->vm_end, > vma->vm_start), bug = 1; > + if (vma->rb_subtree_gap != vma_compute_subtree_gap(vma)) > + printk("free gap %lx, correct %lx\n", > +vma->rb_subtree_gap, > +vma_compute_subtree_gap(vma)), bug = 1; OK, now who did that. Whoever it was: stop it or you'll have your kernel license revoked! --- a/mm/mmap.c~mm-check-rb_subtree_gap-correctness-fix +++ a/mm/mmap.c @@ -372,16 +372,25 @@ static int browse_rb(struct rb_root *roo for (nd = rb_first(root); nd; nd = rb_next(nd)) { struct vm_area_struct *vma; vma = rb_entry(nd, struct vm_area_struct, vm_rb); - if (vma->vm_start < prev) - printk("vm_start %lx prev %lx\n", vma->vm_start, prev), bug = 1; - if (vma->vm_start < pend) - printk("vm_start %lx pend %lx\n", vma->vm_start, pend), bug = 1; - if (vma->vm_start > vma->vm_end) - printk("vm_end %lx < vm_start %lx\n", vma->vm_end, vma->vm_start), bug = 1; - if (vma->rb_subtree_gap != vma_compute_subtree_gap(vma)) + if (vma->vm_start < prev) { + printk("vm_start %lx prev %lx\n", vma->vm_start, prev); + bug = 1; + } + if (vma->vm_start < pend) { + printk("vm_start %lx pend %lx\n", vma->vm_start, pend); + bug = 1; + } + if (vma->vm_start > vma->vm_end) { + printk("vm_end %lx < vm_start %lx\n", + vma->vm_end, vma->vm_start); + bug = 1; + } + if (vma->rb_subtree_gap != vma_compute_subtree_gap(vma)) { printk("free gap %lx, correct %lx\n", vma->rb_subtree_gap, - vma_compute_subtree_gap(vma)), bug = 1; + vma_compute_subtree_gap(vma)); + bug = 1; + } i++; pn = nd; prev = vma->vm_start; @@ -390,8 +399,10 @@ static int browse_rb(struct rb_root *roo j = 0; for (nd = pn; nd; nd = rb_prev(nd)) j++; - if (i != j) - printk("backwards %d, forwards %d\n", j, i), bug = 1; + if (i != j) { + printk("backwards %d, forwards %d\n", j, i); + bug = 1; + } return bug ? -1 : i; } @@ -411,14 +422,20 @@ void validate_mm(struct mm_struct *mm) vma = vma->vm_next; i++; } - if (i != mm->map_count) - printk("map_count %d vm_next %d\n", mm->map_count, i), bug = 1; - if (highest_address != mm->highest_vm_end) + if (i != mm->map_count) { + printk("map_count %d vm_next %d\n", mm->map_count, i); + bug = 1; + } + if (highest_address != mm->highest_vm_end) { printk("mm->highest_vm_end %lx, found %lx\n", - mm->highest_vm_end, highest_address), bug = 1; + mm->highest_vm_end, highest_address); + bug = 1; + } i = browse_rb(>mm_rb); - if (i != mm->map_count) - printk("map_count %d rb %d\n", mm->map_count, i), bug = 1; + if (i != mm->map_count) { + printk("map_count %d rb %d\n", mm->map_count,
Re: [PATCH 03/16] mm: check rb_subtree_gap correctness
On Mon, 5 Nov 2012 14:47:00 -0800 Michel Lespinasse wal...@google.com wrote: When CONFIG_DEBUG_VM_RB is enabled, check that rb_subtree_gap is correctly set for every vma and that mm-highest_vm_end is also correct. Also add an explicit 'bug' variable to track if browse_rb() detected any invalid condition. ... @@ -365,7 +365,7 @@ static void vma_rb_erase(struct vm_area_struct *vma, struct rb_root *root) #ifdef CONFIG_DEBUG_VM_RB static int browse_rb(struct rb_root *root) { - int i = 0, j; + int i = 0, j, bug = 0; struct rb_node *nd, *pn = NULL; unsigned long prev = 0, pend = 0; @@ -373,29 +373,33 @@ static int browse_rb(struct rb_root *root) struct vm_area_struct *vma; vma = rb_entry(nd, struct vm_area_struct, vm_rb); if (vma-vm_start prev) - printk(vm_start %lx prev %lx\n, vma-vm_start, prev), i = -1; + printk(vm_start %lx prev %lx\n, vma-vm_start, prev), bug = 1; if (vma-vm_start pend) - printk(vm_start %lx pend %lx\n, vma-vm_start, pend); + printk(vm_start %lx pend %lx\n, vma-vm_start, pend), bug = 1; if (vma-vm_start vma-vm_end) - printk(vm_end %lx vm_start %lx\n, vma-vm_end, vma-vm_start); + printk(vm_end %lx vm_start %lx\n, vma-vm_end, vma-vm_start), bug = 1; + if (vma-rb_subtree_gap != vma_compute_subtree_gap(vma)) + printk(free gap %lx, correct %lx\n, +vma-rb_subtree_gap, +vma_compute_subtree_gap(vma)), bug = 1; OK, now who did that. Whoever it was: stop it or you'll have your kernel license revoked! --- a/mm/mmap.c~mm-check-rb_subtree_gap-correctness-fix +++ a/mm/mmap.c @@ -372,16 +372,25 @@ static int browse_rb(struct rb_root *roo for (nd = rb_first(root); nd; nd = rb_next(nd)) { struct vm_area_struct *vma; vma = rb_entry(nd, struct vm_area_struct, vm_rb); - if (vma-vm_start prev) - printk(vm_start %lx prev %lx\n, vma-vm_start, prev), bug = 1; - if (vma-vm_start pend) - printk(vm_start %lx pend %lx\n, vma-vm_start, pend), bug = 1; - if (vma-vm_start vma-vm_end) - printk(vm_end %lx vm_start %lx\n, vma-vm_end, vma-vm_start), bug = 1; - if (vma-rb_subtree_gap != vma_compute_subtree_gap(vma)) + if (vma-vm_start prev) { + printk(vm_start %lx prev %lx\n, vma-vm_start, prev); + bug = 1; + } + if (vma-vm_start pend) { + printk(vm_start %lx pend %lx\n, vma-vm_start, pend); + bug = 1; + } + if (vma-vm_start vma-vm_end) { + printk(vm_end %lx vm_start %lx\n, + vma-vm_end, vma-vm_start); + bug = 1; + } + if (vma-rb_subtree_gap != vma_compute_subtree_gap(vma)) { printk(free gap %lx, correct %lx\n, vma-rb_subtree_gap, - vma_compute_subtree_gap(vma)), bug = 1; + vma_compute_subtree_gap(vma)); + bug = 1; + } i++; pn = nd; prev = vma-vm_start; @@ -390,8 +399,10 @@ static int browse_rb(struct rb_root *roo j = 0; for (nd = pn; nd; nd = rb_prev(nd)) j++; - if (i != j) - printk(backwards %d, forwards %d\n, j, i), bug = 1; + if (i != j) { + printk(backwards %d, forwards %d\n, j, i); + bug = 1; + } return bug ? -1 : i; } @@ -411,14 +422,20 @@ void validate_mm(struct mm_struct *mm) vma = vma-vm_next; i++; } - if (i != mm-map_count) - printk(map_count %d vm_next %d\n, mm-map_count, i), bug = 1; - if (highest_address != mm-highest_vm_end) + if (i != mm-map_count) { + printk(map_count %d vm_next %d\n, mm-map_count, i); + bug = 1; + } + if (highest_address != mm-highest_vm_end) { printk(mm-highest_vm_end %lx, found %lx\n, - mm-highest_vm_end, highest_address), bug = 1; + mm-highest_vm_end, highest_address); + bug = 1; + } i = browse_rb(mm-mm_rb); - if (i != mm-map_count) - printk(map_count %d rb %d\n, mm-map_count, i), bug = 1; + if (i != mm-map_count) { + printk(map_count %d rb %d\n, mm-map_count, i); + bug = 1; + } BUG_ON(bug); } #else -- To unsubscribe from this list: send the line
[PATCH 03/16] mm: check rb_subtree_gap correctness
When CONFIG_DEBUG_VM_RB is enabled, check that rb_subtree_gap is correctly set for every vma and that mm->highest_vm_end is also correct. Also add an explicit 'bug' variable to track if browse_rb() detected any invalid condition. Signed-off-by: Michel Lespinasse Reviewed-by: Rik van Riel --- mm/mmap.c | 24 1 files changed, 16 insertions(+), 8 deletions(-) diff --git a/mm/mmap.c b/mm/mmap.c index 2de8bcfe859d..769a09cc71af 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -365,7 +365,7 @@ static void vma_rb_erase(struct vm_area_struct *vma, struct rb_root *root) #ifdef CONFIG_DEBUG_VM_RB static int browse_rb(struct rb_root *root) { - int i = 0, j; + int i = 0, j, bug = 0; struct rb_node *nd, *pn = NULL; unsigned long prev = 0, pend = 0; @@ -373,29 +373,33 @@ static int browse_rb(struct rb_root *root) struct vm_area_struct *vma; vma = rb_entry(nd, struct vm_area_struct, vm_rb); if (vma->vm_start < prev) - printk("vm_start %lx prev %lx\n", vma->vm_start, prev), i = -1; + printk("vm_start %lx prev %lx\n", vma->vm_start, prev), bug = 1; if (vma->vm_start < pend) - printk("vm_start %lx pend %lx\n", vma->vm_start, pend); + printk("vm_start %lx pend %lx\n", vma->vm_start, pend), bug = 1; if (vma->vm_start > vma->vm_end) - printk("vm_end %lx < vm_start %lx\n", vma->vm_end, vma->vm_start); + printk("vm_end %lx < vm_start %lx\n", vma->vm_end, vma->vm_start), bug = 1; + if (vma->rb_subtree_gap != vma_compute_subtree_gap(vma)) + printk("free gap %lx, correct %lx\n", + vma->rb_subtree_gap, + vma_compute_subtree_gap(vma)), bug = 1; i++; pn = nd; prev = vma->vm_start; pend = vma->vm_end; } j = 0; - for (nd = pn; nd; nd = rb_prev(nd)) { + for (nd = pn; nd; nd = rb_prev(nd)) j++; - } if (i != j) - printk("backwards %d, forwards %d\n", j, i), i = 0; - return i; + printk("backwards %d, forwards %d\n", j, i), bug = 1; + return bug ? -1 : i; } void validate_mm(struct mm_struct *mm) { int bug = 0; int i = 0; + unsigned long highest_address = 0; struct vm_area_struct *vma = mm->mmap; while (vma) { struct anon_vma_chain *avc; @@ -403,11 +407,15 @@ void validate_mm(struct mm_struct *mm) list_for_each_entry(avc, >anon_vma_chain, same_vma) anon_vma_interval_tree_verify(avc); anon_vma_unlock(vma->anon_vma); + highest_address = vma->vm_end; vma = vma->vm_next; i++; } if (i != mm->map_count) printk("map_count %d vm_next %d\n", mm->map_count, i), bug = 1; + if (highest_address != mm->highest_vm_end) + printk("mm->highest_vm_end %lx, found %lx\n", + mm->highest_vm_end, highest_address), bug = 1; i = browse_rb(>mm_rb); if (i != mm->map_count) printk("map_count %d rb %d\n", mm->map_count, i), bug = 1; -- 1.7.7.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 03/16] mm: check rb_subtree_gap correctness
When CONFIG_DEBUG_VM_RB is enabled, check that rb_subtree_gap is correctly set for every vma and that mm-highest_vm_end is also correct. Also add an explicit 'bug' variable to track if browse_rb() detected any invalid condition. Signed-off-by: Michel Lespinasse wal...@google.com Reviewed-by: Rik van Riel r...@redhat.com --- mm/mmap.c | 24 1 files changed, 16 insertions(+), 8 deletions(-) diff --git a/mm/mmap.c b/mm/mmap.c index 2de8bcfe859d..769a09cc71af 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -365,7 +365,7 @@ static void vma_rb_erase(struct vm_area_struct *vma, struct rb_root *root) #ifdef CONFIG_DEBUG_VM_RB static int browse_rb(struct rb_root *root) { - int i = 0, j; + int i = 0, j, bug = 0; struct rb_node *nd, *pn = NULL; unsigned long prev = 0, pend = 0; @@ -373,29 +373,33 @@ static int browse_rb(struct rb_root *root) struct vm_area_struct *vma; vma = rb_entry(nd, struct vm_area_struct, vm_rb); if (vma-vm_start prev) - printk(vm_start %lx prev %lx\n, vma-vm_start, prev), i = -1; + printk(vm_start %lx prev %lx\n, vma-vm_start, prev), bug = 1; if (vma-vm_start pend) - printk(vm_start %lx pend %lx\n, vma-vm_start, pend); + printk(vm_start %lx pend %lx\n, vma-vm_start, pend), bug = 1; if (vma-vm_start vma-vm_end) - printk(vm_end %lx vm_start %lx\n, vma-vm_end, vma-vm_start); + printk(vm_end %lx vm_start %lx\n, vma-vm_end, vma-vm_start), bug = 1; + if (vma-rb_subtree_gap != vma_compute_subtree_gap(vma)) + printk(free gap %lx, correct %lx\n, + vma-rb_subtree_gap, + vma_compute_subtree_gap(vma)), bug = 1; i++; pn = nd; prev = vma-vm_start; pend = vma-vm_end; } j = 0; - for (nd = pn; nd; nd = rb_prev(nd)) { + for (nd = pn; nd; nd = rb_prev(nd)) j++; - } if (i != j) - printk(backwards %d, forwards %d\n, j, i), i = 0; - return i; + printk(backwards %d, forwards %d\n, j, i), bug = 1; + return bug ? -1 : i; } void validate_mm(struct mm_struct *mm) { int bug = 0; int i = 0; + unsigned long highest_address = 0; struct vm_area_struct *vma = mm-mmap; while (vma) { struct anon_vma_chain *avc; @@ -403,11 +407,15 @@ void validate_mm(struct mm_struct *mm) list_for_each_entry(avc, vma-anon_vma_chain, same_vma) anon_vma_interval_tree_verify(avc); anon_vma_unlock(vma-anon_vma); + highest_address = vma-vm_end; vma = vma-vm_next; i++; } if (i != mm-map_count) printk(map_count %d vm_next %d\n, mm-map_count, i), bug = 1; + if (highest_address != mm-highest_vm_end) + printk(mm-highest_vm_end %lx, found %lx\n, + mm-highest_vm_end, highest_address), bug = 1; i = browse_rb(mm-mm_rb); if (i != mm-map_count) printk(map_count %d rb %d\n, mm-map_count, i), bug = 1; -- 1.7.7.3 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/