Harmonyos Next 使用mmap函数报错MAP_FAILED是怎么回事?

``
mmap(NULL, len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANONYMOUS, -1, 0);
addr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_ANONYMOUS, -1, 0);
mprotect(addr, leng, PROT_READ | PROT_EXEC);

阅读 953
avatarAI BotBETA

当使用mmap函数进行内存映射时,如果返回MAP_FAILED,通常表示内存映射请求失败。MAP_FAILED是一个宏定义,通常被定义为(void *)-1,表示一个错误的状态。

在你的代码中,你首先尝试了一次带有PROT_EXEC权限的mmap调用,但随后你使用了一个不带PROT_EXECmmap调用,并且随后使用mprotect来修改内存保护标志。这里可能有几个原因导致mmap返回MAP_FAILEDEINVAL(无效参数)错误:

  1. 权限问题:不是所有的系统都允许将内存映射为可执行(PROT_EXEC)。特别是在安全敏感的系统或配置了特定安全策略的系统上,这样的请求可能会被拒绝。
  2. 长度问题len的值可能超出了系统允许的最大映射长度,或者不是页面大小的整数倍(页面大小通常是4KB、8KB、16KB等,取决于系统和硬件)。
  3. 文件描述符问题:虽然在你的例子中使用了MAP_ANONYMOUS(表示匿名映射,不需要文件描述符),但如果你不小心传入了一个无效的文件描述符,这也可能导致错误。
  4. 内存不足:系统可能没有足够的连续内存来满足你的请求。
  5. 地址问题:虽然你传递了NULLmmap作为起始地址的提示,但系统可能无法找到适合映射的地址空间。
  6. mprotect的调用:即使mmap成功,mprotect的调用也可能失败,特别是如果leng(注意这里应该是len,而不是leng)不是一个页面大小的整数倍,或者尝试设置不允许的权限组合。

为了解决这个问题,你可以:

  • 检查len的值,确保它是一个页面大小的整数倍。
  • 移除或更改PROT_EXEC权限,看看是否可以成功映射内存。
  • 确保系统配置允许内存映射为可执行。
  • 检查系统日志或errno的值以获取更详细的错误信息。
  • 逐步调试代码,先尝试简单的内存映射(例如只使用PROT_READ | PROT_WRITE),然后逐步添加其他功能。

另外,注意在你的mprotect调用中,你使用了leng而不是len,这应该是一个拼写错误。确保在调用mprotect时使用正确的变量名。

1 个回答

为了维护生态的纯净,防止恶意应用向匿名内存注入指令,实现任意代码执行,以绕过代码签名管控,达到变脸或攻击系统的目的,系统要限制应用内设置匿名内存为可执行的行为。

升级到beta2后,应用在申请内存或修改内存权限时,将匿名内存(MAP_ANONYMOUS)的权限设置为可执行(PROT_EXEC),相应行为会被系统拦截,具体如下:

  • 应用调用mmap申请包含执行权限的匿名内存将返回MAP_FAILED。
  • 应用调用mprotect更新匿名内存为可执行执行权限,调用失败,结果返回-1,errno输出为EINVAL。
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进