#define BAD_ADDR(x) ((unsigned long)(x) >= TASK_SIZE)
 
-static int set_brk(unsigned long start, unsigned long end)
+static int set_brk(unsigned long start, unsigned long end, int prot)
 {
        start = ELF_PAGEALIGN(start);
        end = ELF_PAGEALIGN(end);
        if (end > start) {
-               int error = vm_brk(start, 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;
        }
        unsigned long load_addr = 0;
        int load_addr_set = 0;
        unsigned long last_bss = 0, elf_bss = 0;
+       int bss_prot = 0;
        unsigned long error = ~0UL;
        unsigned long total_size;
        int i;
                         * elf_bss and last_bss is the bss section.
                         */
                        k = load_addr + eppnt->p_vaddr + eppnt->p_memsz;
-                       if (k > last_bss)
+                       if (k > last_bss) {
                                last_bss = k;
+                               bss_prot = elf_prot;
+                       }
                }
        }
 
        /*
         * 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() below.
+        * 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(elf_bss, 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;
        }
        unsigned long error;
        struct elf_phdr *elf_ppnt, *elf_phdata, *interp_elf_phdata = NULL;
        unsigned long elf_bss, elf_brk;
+       int bss_prot = 0;
        int retval, i;
        unsigned long elf_entry;
        unsigned long interp_load_addr = 0;
                           before this one. Map anonymous pages, if needed,
                           and clear the area.  */
                        retval = set_brk(elf_bss + load_bias,
-                                        elf_brk + load_bias);
+                                        elf_brk + load_bias,
+                                        bss_prot);
                        if (retval)
                                goto out_free_dentry;
                        nbyte = ELF_PAGEOFFSET(elf_bss);
                if (end_data < k)
                        end_data = k;
                k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;
-               if (k > elf_brk)
+               if (k > elf_brk) {
+                       bss_prot = elf_prot;
                        elf_brk = k;
+               }
        }
 
        loc->elf_ex.e_entry += load_bias;
         * mapping in the interpreter, to make sure it doesn't wind
         * up getting placed where the bss needs to go.
         */
-       retval = set_brk(elf_bss, elf_brk);
+       retval = set_brk(elf_bss, elf_brk, bss_prot);
        if (retval)
                goto out_free_dentry;
        if (likely(elf_bss != elf_brk) && unlikely(padzero(elf_bss))) {
 
  *  anonymous maps.  eventually we may be able to do some
  *  brk-specific accounting here.
  */
-static int do_brk(unsigned long addr, unsigned long request)
+static int do_brk_flags(unsigned long addr, unsigned long request, unsigned long flags)
 {
        struct mm_struct *mm = current->mm;
        struct vm_area_struct *vma, *prev;
-       unsigned long flags, len;
+       unsigned long len;
        struct rb_node **rb_link, *rb_parent;
        pgoff_t pgoff = addr >> PAGE_SHIFT;
        int error;
        if (!len)
                return 0;
 
-       flags = VM_DATA_DEFAULT_FLAGS | VM_ACCOUNT | mm->def_flags;
+       /* Until we need other flags, refuse anything except VM_EXEC. */
+       if ((flags & (~VM_EXEC)) != 0)
+               return -EINVAL;
+       flags |= VM_DATA_DEFAULT_FLAGS | VM_ACCOUNT | mm->def_flags;
 
        error = get_unmapped_area(NULL, addr, len, 0, MAP_FIXED);
        if (offset_in_page(error))
        return 0;
 }
 
-int vm_brk(unsigned long addr, unsigned long len)
+static int do_brk(unsigned long addr, unsigned long len)
+{
+       return do_brk_flags(addr, len, 0);
+}
+
+int vm_brk_flags(unsigned long addr, unsigned long len, unsigned long flags)
 {
        struct mm_struct *mm = current->mm;
        int ret;
        if (down_write_killable(&mm->mmap_sem))
                return -EINTR;
 
-       ret = do_brk(addr, len);
+       ret = do_brk_flags(addr, len, flags);
        populate = ((mm->def_flags & VM_LOCKED) != 0);
        up_write(&mm->mmap_sem);
        if (populate && !ret)
                mm_populate(addr, len);
        return ret;
 }
+EXPORT_SYMBOL(vm_brk_flags);
+
+int vm_brk(unsigned long addr, unsigned long len)
+{
+       return vm_brk_flags(addr, len, 0);
+}
 EXPORT_SYMBOL(vm_brk);
 
 /* Release all mmaps. */