Chinaunix首页 | 论坛 | 博客
  • 博客访问: 429726
  • 博文数量: 99
  • 博客积分: 65
  • 博客等级: 民兵
  • 技术积分: 1012
  • 用 户 组: 普通用户
  • 注册时间: 2012-04-20 16:30
个人简介

linux kernel 工程师

文章分类

全部博文(99)

文章存档

2018年(5)

2017年(12)

2016年(27)

2015年(10)

2014年(43)

2012年(2)

我的朋友

分类: LINUX

2015-12-29 14:41:50

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) */

}



阅读(758) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~