Hi,
There is a bug in copy_page_range in current 2.6.11-rc1 with 4 level
page table change. copy_page_range do a continue without adding pgds and
addr when pgd_none(*src_pgd) or pgd_bad(*src_pgd).
I think it's wrong in logic, copy_page_range will run into infinite loop
when when pgd_none(*src_pgd) or pgd_bad(*src_pgd).
Although maybe this bug does not break anything currently...,
Signed-off-by: Zou Nan hai <[email protected]>
--- a/mm/memory.c 2005-01-21 01:21:18.000000000 +0800
+++ b/mm/memory.c 2005-01-21 04:49:13.000000000 +0800
@@ -442,17 +442,18 @@ int copy_page_range(struct mm_struct *ds
if (next > end || next <= addr)
next = end;
if (pgd_none(*src_pgd))
- continue;
+ goto next_pgd;
if (pgd_bad(*src_pgd)) {
pgd_ERROR(*src_pgd);
pgd_clear(src_pgd);
- continue;
+ goto next_pgd;
}
err = copy_pud_range(dst, src, dst_pgd, src_pgd,
vma, addr, next);
if (err)
break;
+next_pgd:
src_pgd++;
dst_pgd++;
addr = next;
Zou Nan hai wrote:
> Hi,
>
> There is a bug in copy_page_range in current 2.6.11-rc1 with 4 level
> page table change. copy_page_range do a continue without adding pgds and
> addr when pgd_none(*src_pgd) or pgd_bad(*src_pgd).
>
> I think it's wrong in logic, copy_page_range will run into infinite loop
> when when pgd_none(*src_pgd) or pgd_bad(*src_pgd).
>
> Although maybe this bug does not break anything currently...,
>
>
> Signed-off-by: Zou Nan hai <[email protected]>
>
> --- a/mm/memory.c 2005-01-21 01:21:18.000000000 +0800
> +++ b/mm/memory.c 2005-01-21 04:49:13.000000000 +0800
> @@ -442,17 +442,18 @@ int copy_page_range(struct mm_struct *ds
> if (next > end || next <= addr)
> next = end;
> if (pgd_none(*src_pgd))
> - continue;
> + goto next_pgd;
> if (pgd_bad(*src_pgd)) {
> pgd_ERROR(*src_pgd);
> pgd_clear(src_pgd);
> - continue;
> + goto next_pgd;
> }
> err = copy_pud_range(dst, src, dst_pgd, src_pgd,
> vma, addr, next);
> if (err)
> break;
>
> +next_pgd:
> src_pgd++;
> dst_pgd++;
> addr = next;
>
>
>
This looks right to me. Andrew and/or Linus, did this get picked up?