代码之家  ›  专栏  ›  技术社区  ›  Jared

强制copy\u to\u user()失败

  •  1
  • Jared  · 技术社区  · 6 年前

    我正在尝试编写一个测试,其中copy\u to\u user()失败(只复制一些数据,或者根本不复制,而不使用空指针),但没有成功。

    用户模式下的测试包含以下行:

    type to[1];
    foo(to);
    

    foo是一个包装器函数,它调用具有以下行的系统调用:

    type from[2] = {something1, something2};
    int not_copied = copy_to_user(to, from, sizeof(type) * 2);
    

    事实证明,not\u copied是0,即使我尝试将malloc用于“type to”声明。此外,“to[0]”和“to[1]”分别是“something1”和“something2”。

    我认为我的“type to”声明没有按预期限制copy\u to\u用户目标的内存,对吗?

    我怎样才能让它失败呢?

    谢谢

    2 回复  |  直到 6 年前
        1
  •  1
  •   zwol    6 年前

    据我所知,为了 copy_to_user 若要失败,范围内的某些地址实际上必须是不可写的或未映射的。你的 type to[1] 只是用户空间内存页中某个位置的地址;如果它在堆栈上,则末尾后面的地址将始终是可写的,因为堆栈会变小(除非您使用的是HPPA,而您几乎肯定不是);如果你把它放在数据段中,你必须非常小心地进行设置,以确保它在数据段的末尾是正确的,之后没有任何内容;原则上a malloc 分配 能够 之后立即没有任何内容,但除非您使用像ElectricFence这样的分配器,故意在每次分配之后立即放置未映射的保护页,否则几乎肯定不会。

    为了故意设置写入同时访问可访问和不可访问内存的情况,可以执行以下操作:

    size_t pagesize = sysconf(_SC_PAGESIZE);
    char *to_allocation = mmap(0, 2*pagesize, PROT_READ|PROT_WRITE,
                               MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
    memset(to_allocation, 0x55, 2*pagesize); // force allocation
    mprotect(to_allocation + pagesize, pagesize, PROT_NONE);
    
    foo(to_allocation + pagesize - sizeof(type));
    

    (当然是错误处理。)

        2
  •  0
  •   Jared    6 年前

    通过进行以下更改,我成功地使其可靠地失败:

    type to[SMALL_INTEGER]
    foo(to)
    

    包装器具有:

    type from[HUGE_INTEGER]
    // fill from with huge amount of data <- unsure if this part is necessary
    int not_copied = copy_to_user(to, from, sizeof(type) * HUGE_INTEGER);