Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

nommu: allow private mappings of read-only devices

Slightly rearrange the logic that determines capabilities and vm_flags.
Disable BDI_CAP_MAP_DIRECT in all cases if the device can't support the
protections. Allow private readonly mappings of readonly backing devices.

Signed-off-by: Bernd Schmidt <bernds_cb1@t-online.de>
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Acked-by: David McCullough <davidm@snapgear.com>
Acked-by: Greg Ungerer <gerg@uclinux.org>
Acked-by: Paul Mundt <lethal@linux-sh.org>
Acked-by: David Howells <dhowells@redhat.com>
Cc: Hugh Dickins <hughd@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Bernd Schmidt and committed by
Linus Torvalds
3c7b2045 0cae3457

+18 -14
+18 -14
mm/nommu.c
··· 918 918 if (!(capabilities & BDI_CAP_MAP_DIRECT)) 919 919 return -ENODEV; 920 920 921 - if (((prot & PROT_READ) && !(capabilities & BDI_CAP_READ_MAP)) || 922 - ((prot & PROT_WRITE) && !(capabilities & BDI_CAP_WRITE_MAP)) || 923 - ((prot & PROT_EXEC) && !(capabilities & BDI_CAP_EXEC_MAP)) 924 - ) { 925 - printk("MAP_SHARED not completely supported on !MMU\n"); 926 - return -EINVAL; 927 - } 928 - 929 921 /* we mustn't privatise shared mappings */ 930 922 capabilities &= ~BDI_CAP_MAP_COPY; 931 923 } ··· 931 939 * shared with the backing device */ 932 940 if (prot & PROT_WRITE) 933 941 capabilities &= ~BDI_CAP_MAP_DIRECT; 942 + } 943 + 944 + if (capabilities & BDI_CAP_MAP_DIRECT) { 945 + if (((prot & PROT_READ) && !(capabilities & BDI_CAP_READ_MAP)) || 946 + ((prot & PROT_WRITE) && !(capabilities & BDI_CAP_WRITE_MAP)) || 947 + ((prot & PROT_EXEC) && !(capabilities & BDI_CAP_EXEC_MAP)) 948 + ) { 949 + capabilities &= ~BDI_CAP_MAP_DIRECT; 950 + if (flags & MAP_SHARED) { 951 + printk(KERN_WARNING 952 + "MAP_SHARED not completely supported on !MMU\n"); 953 + return -EINVAL; 954 + } 955 + } 934 956 } 935 957 936 958 /* handle executable mappings and implied executable ··· 1002 996 unsigned long vm_flags; 1003 997 1004 998 vm_flags = calc_vm_prot_bits(prot) | calc_vm_flag_bits(flags); 1005 - vm_flags |= VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC; 1006 999 /* vm_flags |= mm->def_flags; */ 1007 1000 1008 1001 if (!(capabilities & BDI_CAP_MAP_DIRECT)) { 1009 1002 /* attempt to share read-only copies of mapped file chunks */ 1003 + vm_flags |= VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC; 1010 1004 if (file && !(prot & PROT_WRITE)) 1011 1005 vm_flags |= VM_MAYSHARE; 1012 - } 1013 - else { 1006 + } else { 1014 1007 /* overlay a shareable mapping on the backing device or inode 1015 1008 * if possible - used for chardevs, ramfs/tmpfs/shmfs and 1016 1009 * romfs/cramfs */ 1010 + vm_flags |= VM_MAYSHARE | (capabilities & BDI_CAP_VMFLAGS); 1017 1011 if (flags & MAP_SHARED) 1018 - vm_flags |= VM_MAYSHARE | VM_SHARED; 1019 - else if ((((vm_flags & capabilities) ^ vm_flags) & BDI_CAP_VMFLAGS) == 0) 1020 - vm_flags |= VM_MAYSHARE; 1012 + vm_flags |= VM_SHARED; 1021 1013 } 1022 1014 1023 1015 /* refuse to let anyone share private mappings with this process if