Re: kernel BUG at mm/gup.c:LINE!

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Oscar Salvador wrote:
> Anyway, I just gave it a try, and making sure that bss gets page aligned seems to
> "fix" the issue (at the process doesn't hang anymore):
> 
> -       bss = eppnt->p_memsz + eppnt->p_vaddr;
> +       bss = ELF_PAGESTART(eppnt->p_memsz + eppnt->p_vaddr);
> 	if (bss > len) {
>                 error = vm_brk(len, bss - len);
> 
> Although I'm not sure about the correctness of this.

static int set_brk(unsigned long start, unsigned long end, int prot)
{
        start = ELF_PAGEALIGN(start);
        end = ELF_PAGEALIGN(end);
        if (end > start) {
                /*
                 * Map the last of the bss segment.
                 * If the header is requesting these pages to be
                 * executable, honour that (ppc32 needs this).
                 */
                int error = vm_brk_flags(start, end - start,
                                prot & PROT_EXEC ? VM_EXEC : 0);
                if (error)
                        return error;
        }
        current->mm->start_brk = current->mm->brk = end;
        return 0;
}

static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex,
                struct file *interpreter, unsigned long *interp_map_addr,
                unsigned long no_base, struct elf_phdr *interp_elf_phdata)
{
(...snipped...)
        /*
         * Next, align both the file and mem bss up to the page size,
         * since this is where elf_bss was just zeroed up to, and where
         * last_bss will end after the vm_brk_flags() below.
         */
        elf_bss = ELF_PAGEALIGN(elf_bss);
        last_bss = ELF_PAGEALIGN(last_bss);
        /* Finally, if there is still more bss to allocate, do it. */
        if (last_bss > elf_bss) {
                error = vm_brk_flags(elf_bss, last_bss - elf_bss,
                                bss_prot & PROT_EXEC ? VM_EXEC : 0);
                if (error)
                        goto out;
        }
(...snipped...)
}

static int load_elf_library(struct file *file)
{
(...snipped...)
        len = ELF_PAGESTART(eppnt->p_filesz + eppnt->p_vaddr +
                            ELF_MIN_ALIGN - 1);
        bss = eppnt->p_memsz + eppnt->p_vaddr;
        if (bss > len) {
                error = vm_brk(len, bss - len);
                if (error)
                        goto out_free_ph;
        }
(...snipped...)
}

So, indeed "bss" needs to be aligned.
But ELF_PAGESTART() or ELF_PAGEALIGN(), which one to use?

#define ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(ELF_MIN_ALIGN-1))
#define ELF_PAGEALIGN(_v) (((_v) + ELF_MIN_ALIGN - 1) & ~(ELF_MIN_ALIGN - 1))

Is

-	len = ELF_PAGESTART(eppnt->p_filesz + eppnt->p_vaddr +
-			    ELF_MIN_ALIGN - 1);
+	len = ELF_PAGEALIGN(eppnt->p_filesz + eppnt->p_vaddr);

suggesting that

-	bss = eppnt->p_memsz + eppnt->p_vaddr;
+	bss = ELF_PAGEALIGN(eppnt->p_memsz + eppnt->p_vaddr);

is the right choice? I don't know...




[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Bugtraq]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux