mmap标志MAP_UNINITIALIZED未定义

时间:2017-03-14 11:13:04

标签: linux mmap

mmap()docs提到标志MAP_UNINITIALIZED,但标志似乎没有被定义。 试图在Centos7和Xenial上,两个发行版都没有sys/mman.h中所定义的标志 令人惊讶的是,互联网似乎并没有意识到这一点。这是什么故事?

编辑:我从文档中了解到,该标志仅在嵌入式或低安全性设备上受到尊重,但这并不意味着该标志不应被定义......您如何使用它便携代码?在不支持的情况下,Google已将代码定义为0,但在我的情况下,它根本没有定义。

2 个答案:

答案 0 :(得分:1)

内核通常需要清除内存,以保护内核空间和其他进程内存的隐私。

继续阅读:

  

仅当内核配置了CONFIG_MMAP_ALLOW_UNINITIALIZED选项时,才会使用此标志。由于安全隐患,该选项通常仅在嵌入式设备上启用(即,可以完全控制用户内存内容的设备)。

答案 1 :(得分:1)

为了理解如何处理#include <sys/mman.h>未定义MAP_UNINITIALIZED这一事实,了解如何定义内核接口是有帮助的。

要构建内核模块,您将需要用于构建内核的内核头,以用于您希望为其构建模块的内核的确切版本。如果您希望在用户空间中运行,您将不再需要这些。

为用户空间定义内核API的标头主要位于/usr/include/linux/usr/include/asm(有关如何生成它们,请参阅this)。这些标头中最重要的消费者之一是C标准库,例如glibc,它必须针对这些标头的某些版本构建。由于Linux内核API是向后兼容的,因此您可能有一个glibc(或其他库实现)针对这些标头的旧版本而不是您运行的内核构建。我并不是所有各种发行版分发glibc的专家,但我的印象是定义其用户空间API的内核头文件通常是glibc构建的版本。

最后,glibc通过也安装在/usr/include下的标头(例如/usr/include/sys)来定义其API。我不确切知道为使用较旧或较新的glibc标头构建的应用程序提供了什么(如果有的话)向后或向前兼容性,但我猜测当向后可比性时,库.so版本号会受到影响碎。

现在我们可以理解您的问题是glibc标头实际上没有为您尝试过的发行版/版本定义MAP_UNINITIALIZED

然而,正如this patch所示,Linux内核API已经公开了MAP_UNINITIALIZED。如果glibc标头没有为您定义它,您可以使用linux内核API标头和#include <linux/mman.h>(如果这定义它)。请注意,为了获得mmap的原型,您仍然需要#include <sys/mman.h>

如果你的linux内核API标题没有定义MAP_UNINITIALIZED但你有一个实现它的内核版本,你可以自己定义它:

 #define MAP_UNINITIALIZED 0x4000000    

您不必担心自己有效地使用&#34;更新&#34;标头比你的glibc构建的,因为mmap的glibc实现非常薄:

#include <sys/types.h>
#include <sys/mman.h>
#include <errno.h>
#include <sysdep.h>

#ifndef MMAP_PAGE_SHIFT
#define MMAP_PAGE_SHIFT 12
#endif

__ptr_t
__mmap (__ptr_t addr, size_t len, int prot, int flags, int fd, off_t offset)
{
  if (offset & ((1 << MMAP_PAGE_SHIFT) - 1))
    {
      __set_errno (EINVAL);
      return MAP_FAILED;
    }
  return (__ptr_t) INLINE_SYSCALL (mmap2, 6, addr, len, prot, flags, fd,
                                   offset >> MMAP_PAGE_SHIFT);
}

weak_alias (__mmap, mmap)

只是将你的旗帜直接传递给内核。