只写映射O_WRONLY打开的文件应该工作?

时间:2015-06-23 22:19:36

标签: linux mmap

mmap()是否应该能够创建O_WRONLY已打开文件的只写映射?

我问,因为Linux 4.0.4 x86-64系统(strace日志)上的跟踪失败:

mkdir("test", 0700)          = 0
open("test/foo", O_WRONLY|O_CREAT, 0666) = 3
ftruncate(3, 11)                        = 0
mmap(NULL, 11, PROT_WRITE, MAP_SHARED, 3, 0) = -1 EACCES (Permission denied)

errno等于EACCESS

O_WRONLY替换open-flag O_RDWR会产生成功的映射。

Linux mmap手册页将errno记录为:

   EACCES A  file descriptor refers to a non-regular file.  Or a file map‐
          ping was  requested,  but  fd  is  not  open  for  reading.   Or
          MAP_SHARED  was  requested  and PROT_WRITE is set, but fd is not
          open in read/write (O_RDWR) mode.  Or PROT_WRITE is set, but the
          file is append-only.

因此,第二句话记录了这种行为。

但是背后的原因是什么?

POSIX是否允许?

是内核还是库限制? (快速浏览一下,我在Linux/mm/mmap.c

中找不到任何明显的东西

2 个答案:

答案 0 :(得分:4)

修改

IEEE Std 1003.1, 2004 Edition (POSIX.1 2004)似乎禁止它。

  

实施可能允许除prot指定的访问以外的访问;但是,如果支持Memory Protection选项,则实现不允许写入在未设置PROT_WRITE的情况下成功,或者不允许任何仅在PROT_NONE设置的情况下进行访问。实现应至少支持protPROT_NONEPROT_READPROT_WRITE的以下值以及PROT_READ和{{1}的按位包含OR }}。如果不支持“内存保护”选项,则任何与指定保护冲突的访问结果都是未定义的。 无论指定的保护选项如何,都应以读取权限打开文件描述符PROT_WRITE。如果指定了fildes,则应用程序应确保已使用写入权限打开文件描述符PROT_WRITE,除非fildes参数中指定了MAP_PRIVATE,如下所述。

(强调补充)

此外,在x86上,不可能具有只写内存,这是页表条目的限制。页面可以标记为只读或读写,并且可以是可执行的或不可执行的,但不能是只写的。此外,flags的手册页说:

  

mprotect()是否具有与PROT_EXEC不同的任何效果,取决于体系结构和内核版本。在某些硬件体系结构(例如,i386)上,PROT_READ暗示PROT_WRITE

在这种情况下,您已经打开了一个没有读访问权限的文件描述符,但PROT_READ会绕过mmap(),但会授予您O_WRONLY权限。相反,它将完全拒绝PROT_READ

答案 1 :(得分:4)

我不认为x86硬件支持只写页面,因此写访问意味着读取。但它似乎是一个比x86更普遍的要求 - mm/mmap.cdo_mmap_pgoff()中包含此代码:

    case MAP_SHARED:
        if ((prot&PROT_WRITE) && !(file->f_mode&FMODE_WRITE))
            return -EACCES;
        ....
        /* fall through */
    case MAP_PRIVATE:
        if (!(file->f_mode & FMODE_READ))
            return -EACCES;

我认为这可以解释您所看到的内容。