paxtest里面对于stack和Arg/env的测试结果:
Stack randomisation test (SEGMEXEC) : 35 quality bits (guessed)
Stack randomisation test (PAGEEXEC) : 35 quality bits (guessed)
Arg/env randomisation test (SEGMEXEC) : 39 quality bits (guessed)
Arg/env randomisation test (PAGEEXEC) : 39 quality bits (guessed)
-------------------------------------------------------------------------------
--------------------------------------------------------------------------------
1. load_elf_binary->setup_arg_pages
setup_arg_pages怎样实现stack的基地址39bits随机,分为两部分
a. randomize_stack_top 实现12~38 bit随机
b. __bprm_mm_init实现bprm->p的0~11bit随机
arg_start 与栈紧密相关,实现了39bits随机
2. load_elf_binary->create_elf_tables
掩掉栈的低4bit,使得栈只有5~38bit随机。这样栈的基地址就有35bit随机了
-------------------------------------------------------------------------------
--------------------------------------------------------------------------------
1. setup_arg_pages
--------------------------------------------------------------------------------
/* STACK_TOP = (1<<42 - 0x1000), 其中 randomize_stack_top(STACK_TOP)含有27bit随机数 */
retval = setup_arg_pages(bprm, randomize_stack_top(STACK_TOP),
executable_stack);
{
#ifdef CONFIG_STACK_GROWSUP
/* Limit stack size to 1GB */
stack_base = rlimit_max(RLIMIT_STACK);
if (stack_base > (1 << 30))
stack_base = 1 << 30;
/* Make sure we didn't let the argument array grow too large. */
if (vma->vm_end - vma->vm_start > stack_base)
return -ENOMEM;
stack_base = PAGE_ALIGN(stack_top - stack_base);
stack_shift = vma->vm_start - stack_base;
mm->arg_start = bprm->p - stack_shift;
bprm->p = vma->vm_end - stack_shift;
#else
stack_top = arch_align_stack(stack_top);
stack_top = PAGE_ALIGN(stack_top);
stack_shift = vma->vm_end - stack_top; /* stacktop含有27bit随机数, stack_shift将含有27bit随机数 */
bprm->p -= stack_shift; /* bprm->p 的0~11 bit 为随机数,stack_shift的12~38 bit为随机数,这样相减叠加产生一个39bits的随机数 */
mm->arg_start = bprm->p; /* 所以arg_start将是一个39bit的随机数,对应的测试用例Arg/env randomisation test 产生39bit的随机数 */
#endif
}
setup_arg_pages
1.a 下面是对 randomize_stack_top 的随机注释
-------------------------------------------------------------
static unsigned long randomize_stack_top(unsigned long stack_top)
{
unsigned int random_variable = 0;
#ifdef CONFIG_PAX_RANDUSTACK
/* stack_top = (1 << 42 - 0x1000) */
/* delta_stack= (pax_get_random_long() & ((1UL << PAX_DELTA_STACK_LEN)-1)) << PAGE_SHIFT */
对于delta_stack的值, 其bit12~bit38 的27bits随机。
这是由于pax_get_random_long() 产生64bit的随机数,PAX_DELTA_STACK_LEN=27
pax_get_random_long() & ((1UL << PAX_DELTA_STACK_LEN)-1)) 使这个64bit数的低27bit(0~26)有效,
(pax_get_random_long() & ((1UL << PAX_DELTA_STACK_LEN)-1)) << PAGE_SHIFT 仍然只有27bits有效,即12~38bit
63 42 41 39| 38 32|31 12 | 11 0
|---------------------|--------|-------------|----------------|--------------------------|
| |
|----------------------------------------------------------------------------------------|
if (current->mm->pax_flags & MF_PAX_RANDMMAP)
return stack_top - current->mm->delta_stack; /* 返回值有27bits随机数,*/
#endif
if ((current->flags & PF_RANDOMIZE) &&
!(current->personality & ADDR_NO_RANDOMIZE)) {
random_variable = get_random_int() & STACK_RND_MASK;
random_variable <<= PAGE_SHIFT;
}
#ifdef CONFIG_STACK_GROWSUP
return PAGE_ALIGN(stack_top) + random_variable;
#else
return PAGE_ALIGN(stack_top) - random_variable;
#endif
}
1.b 我们再看do_execve_common->bprm_mm_init->__bprm_mm_init,在该函数中bprm->p是一个低12bits随机的数
注意:
do_execve_common在调用bprm_mm_init之后还会调用search_binary_handler,在search_binary_handler会调用load_elf_binary
即do_execve_common->search_binary_handler->load_binary
其中可执行程序为elf格式时,load_binary就是load_elf_binary
static int __bprm_mm_init(struct linux_binprm *bprm)
{
int err;
struct vm_area_struct *vma = NULL;
struct mm_struct *mm = bprm->mm;
bprm->vma = vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
if (!vma)
return -ENOMEM;
down_write(&mm->mmap_sem);
vma->vm_mm = mm;
/*
* Place the stack at the largest stack address the architecture
* supports. Later, we'll move this to an appropriate place. We don't
* use STACK_TOP because that can depend on attributes which aren't
* configured yet.
*/
BUILD_BUG_ON(VM_STACK_FLAGS & VM_STACK_INCOMPLETE_SETUP);
vma->vm_end = STACK_TOP_MAX;
vma->vm_start = vma->vm_end - PAGE_SIZE;
vma->vm_flags = VM_STACK_FLAGS | VM_STACK_INCOMPLETE_SETUP;
#ifdef CONFIG_PAX_SEGMEXEC
vma->vm_flags &= ~(VM_EXEC | VM_MAYEXEC);
#endif
vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
INIT_LIST_HEAD(&vma->anon_vma_chain);
err = security_file_mmap(NULL, 0, 0, 0, vma->vm_start, 1);
if (err)
goto err;
err = insert_vm_struct(mm, vma);
if (err)
goto err;
mm->stack_vm = mm->total_vm = 1;
up_write(&mm->mmap_sem);
bprm->p = vma->vm_end - sizeof(void *);
#ifdef CONFIG_PAX_RANDUSTACK
/* random32() 产生32bit的随机数,~PAGE_MASK=1<<12 - 1 */
/* random32() & ~PAGE_MASK; 就是取32bit数的低12bits, 相当于, 产生一个12bits的随机数, bit 0~11 随机*/
if (randomize_va_space)
bprm->p ^= random32() & ~PAGE_MASK;
#endif
return 0;
err:
up_write(&mm->mmap_sem);
bprm->vma = NULL;
kmem_cache_free(vm_area_cachep, vma);
return err;
}
2. create_elf_tables 函数里实现了掩掉栈的低4bits,这样就使39bits的随机数变成35bits
--------------------------------------------------------------------------------
{
p = arch_align_stack(p); /* #define arch_align_stack(x) ((x) & ~0xfUL) */
}
阅读(771) | 评论(0) | 转发(0) |