setup_arg_pages 详解

  1 /*
  2  * Finalizes the stack vm_area_struct. The flags and permissions are updated,
  3  * the stack is optionally relocated, and some extra space is added.
  4  */
  5 
  6 /** The macro below is for platform riscv.
  7      executable_stack is the X flag of bprm.    
  8     stack_top is a value get by STACK_TOP minusing a
  9     random ul if random vm is on.
 10     STACK_TOP is 0x400 0000 0000.
 11 **/
 12 /**    bprm_mm_init set up the mm_struct of bprm
 13     vma->vm_end = 0x400 0000 0000
 14          vm_start = vm_end - 0x1000
 15     bprm->p = vm_end - sizeof(void *)
 16 **/
 17 int setup_arg_pages(struct linux_binprm *bprm,
 18             unsigned long stack_top,
 19             int executable_stack)
 20 {
 21     unsigned long ret;
 22     unsigned long stack_shift;
 23     struct mm_struct *mm = current->mm;
 24     struct vm_area_struct *vma = bprm->vma;
 25     struct vm_area_struct *prev = NULL;
 26     unsigned long vm_flags;
 27     unsigned long stack_base;
 28     unsigned long stack_size;
 29     unsigned long stack_expand;
 30     unsigned long rlim_stack;
 31 
 32 #ifdef CONFIG_STACK_GROWSUP
 33     /* Limit stack size */
 34     stack_base = rlimit_max(RLIMIT_STACK);
 35     //*    STACK_SIZE_MAX is 0x80 0000 for 8KB
 36     if (stack_base > STACK_SIZE_MAX)
 37         stack_base = STACK_SIZE_MAX;
 38 
 39     /* Add space for stack randomization. */
 40     //* For riscv, STACK_RND_MASK is 0x7ff.
 41     //* This operation makes stack_base be 0xff f000.
 42     stack_base += (STACK_RND_MASK << PAGE_SHIFT);
 43 
 44     /* Make sure we didn't let the argument array grow too large. */
 45     if (vma->vm_end - vma->vm_start > stack_base)
 46         return -ENOMEM;
 47 
 48     stack_base = PAGE_ALIGN(stack_top - stack_base);
 49     //* stack_shift = 0x3ff ff000 0000
 50     stack_shift = vma->vm_start - stack_base;
 51     //* arg_start = 0x100 0000 - sizeof(void*)
 52     mm->arg_start = bprm->p - stack_shift;
 53     //* p = 0x100 0000
 54     bprm->p = vma->vm_end - stack_shift;
 55 #else
 56     stack_top = arch_align_stack(stack_top);
 57     stack_top = PAGE_ALIGN(stack_top);
 58 
 59     if (unlikely(stack_top < mmap_min_addr) ||
 60         unlikely(vma->vm_end - vma->vm_start >= stack_top - mmap_min_addr))
 61         return -ENOMEM;
 62     //* stack_shift = 0
 63     stack_shift = vma->vm_end - stack_top;
 64     //* p = vm_end - sizeof(void*)
 65     bprm->p -= stack_shift;
 66     //* arg_start = vm_end - sizeof(void*)
 67     mm->arg_start = bprm->p;
 68 #endif
 69 
 70     if (bprm->loader)
 71         bprm->loader -= stack_shift;
 72     bprm->exec -= stack_shift;
 73 
 74     down_write(&mm->mmap_sem);
 75     vm_flags = VM_STACK_FLAGS;
 76 
 77     /*
 78      * Adjust stack execute permissions; explicitly enable for
 79      * EXSTACK_ENABLE_X, disable for EXSTACK_DISABLE_X and leave alone
 80      * (arch default) otherwise.
 81      */
 82     if (unlikely(executable_stack == EXSTACK_ENABLE_X))
 83         vm_flags |= VM_EXEC;
 84     else if (executable_stack == EXSTACK_DISABLE_X)
 85         vm_flags &= ~VM_EXEC;
 86     vm_flags |= mm->def_flags;
 87     vm_flags |= VM_STACK_INCOMPLETE_SETUP;
 88 
 89     ret = mprotect_fixup(vma, &prev, vma->vm_start, vma->vm_end,
 90             vm_flags);
 91     if (ret)
 92         goto out_unlock;
 93     BUG_ON(prev != vma);
 94 
 95     /* Move stack pages down in memory. */
 96     if (stack_shift) {
 97         ret = shift_arg_pages(vma, stack_shift);
 98         if (ret)
 99             goto out_unlock;
100     }
101 
102     /* mprotect_fixup is overkill to remove the temporary stack flags */
103     vma->vm_flags &= ~VM_STACK_INCOMPLETE_SETUP;
104 
105     stack_expand = 131072UL; /* randomly 32*4k (or 2*64k) pages */
106     //* one page: 0x1000
107     stack_size = vma->vm_end - vma->vm_start;
108     /*
109      * Align this down to a page boundary as expand_stack
110      * will align it up.
111      */
112     rlim_stack = rlimit(RLIMIT_STACK) & PAGE_MASK;
113 #ifdef CONFIG_STACK_GROWSUP
114     if (stack_size + stack_expand > rlim_stack)
115         stack_base = vma->vm_start + rlim_stack;
116     else
117         stack_base = vma->vm_end + stack_expand;
118 #else
119     if (stack_size + stack_expand > rlim_stack)
120         stack_base = vma->vm_end - rlim_stack;
121     else
122         stack_base = vma->vm_start - stack_expand;
123 #endif
124     current->mm->start_stack = bprm->p;
125     ret = expand_stack(vma, stack_base);
126     if (ret)
127         ret = -EFAULT;
128 
129 out_unlock:
130     up_write(&mm->mmap_sem);
131     return ret;
132 }
133 EXPORT_SYMBOL(setup_arg_pages);

 

posted @ 2018-01-04 09:05  glob  阅读(840)  评论(0编辑  收藏  举报