【问题标题】:Calling mprotect on the main thread's stack always fails在主线程的堆栈上调用 mprotect 总是失败
【发布时间】:2016-02-09 17:55:54
【问题描述】:

我尝试在主线程的堆栈上调用mprotect,但它总是失败。每次我尝试时,都会产生ENOMEM 错误。我已经签入 /proc/[pid]/maps 整个堆栈都映射到地址空间中。但是,我可以在主堆栈的子线程堆栈上成功调用mprotect。主线程的堆栈一定有一些特殊的东西可以防止自己被mprotect 改变。但我找不到任何文件。有人有想法吗?

#define _GNU_SOURCE
#include <unistd.h>
#include <sys/mman.h>
#include <assert.h>
#include <pthread.h>
#include <stdio.h>

void * addr;
size_t size;

void * thread(void * tls) {
    sleep(1);
    if (mprotect(addr, size, PROT_NONE) == -1) perror(NULL);
    return NULL;
}

int main(int argc, const char *argv[]) {
    pthread_attr_t attr;
    pthread_getattr_np(pthread_self(), &attr);
    pthread_attr_getstack(&attr, &addr, &size);

    pthread_t th;
    pthread_create(&th, NULL, thread, NULL);
    sleep(2);
    pthread_join(th, NULL);
    return 0;
}

【问题讨论】:

  • 当我尝试执行上述代码时,得到输出“无法分配内存”
  • @Startup 这是ENOMEM的错误信息。

标签: c multithreading mprotect


【解决方案1】:

您试图保护未映射的页面。如果查看pthread_attr_getstack的来源,会发现没有mmap.Stack页面是按需映射的。 this might help you

【讨论】:

  • 但是,我检查了 /proc/[pid]/maps 中列出的映射。整个堆栈 [addr, addr + size) 被列为映射。
  • 我发布了一个新答案,因为我可以提供一个重要的评论。请帮我理解。
【解决方案2】:

我用这个code 来保护记忆。它适用于您的代码。 像这样调用方法->

39     pthread_attr_getstack(&attr, &addr, &size);
40     __enable_execute_stack(&addr);

并编译:gcc your_code.c __enable_execute_stack_code.h -lpthread -fbuilding-libgcc

【讨论】:

  • 您的意思是__enable_execute_stack(addr);,在addr 前面没有&amp;?它不起作用,仍然返回ENOMEM
  • 使用&amp;addr保护了存储addr的内存页,这不是我想要的。我想保护addr指向的主线程的栈。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多