@@ -54,6 +54,8 @@ bitflags::bitflags! {
5454 const MAY_READ = 1 << 3 ;
5555 const MAY_WRITE = 1 << 4 ;
5656 const MAY_EXEC = 1 << 5 ;
57+
58+ const SHARED = 1 << 6 ;
5759 }
5860}
5961
@@ -369,7 +371,6 @@ impl MMapFile {
369371
370372#[ derive( Clone ) ]
371373pub struct Mapping {
372- pub flags : MMapFlags ,
373374 vm_flags : VmFlag ,
374375
375376 pub start_addr : VirtAddr ,
@@ -474,7 +475,7 @@ impl Mapping {
474475 let addr = addr. align_down ( Size4KiB :: SIZE ) ;
475476 let size = Size4KiB :: SIZE . min ( file. size as u64 - ( addr - self . start_addr ) ) ;
476477
477- return if self . flags . contains ( MMapFlags :: MAP_SHARED ) {
478+ return if self . vm_flags . contains ( VmFlag :: SHARED ) {
478479 self . handle_pf_shared_file ( offset_table, reason, addr, offset as _ , size as _ )
479480 } else {
480481 self . handle_pf_private_file ( offset_table, reason, addr, offset as _ , size as _ )
@@ -545,7 +546,7 @@ impl Mapping {
545546 let frame = mmap_file
546547 . file
547548 . inode ( )
548- . mmap ( offset, size, self . flags )
549+ . mmap ( offset, size, MMapFlags :: empty ( ) )
549550 . expect ( "handle_pf_file: file does not support mmap" ) ;
550551
551552 unsafe {
@@ -764,7 +765,6 @@ impl Mapping {
764765 } ) ;
765766
766767 let new_mapping = Mapping {
767- flags : self . flags ,
768768 start_addr : end,
769769 end_addr : end + ( self . end_addr - end) ,
770770 file : new_file,
@@ -868,13 +868,10 @@ impl VmProtected {
868868 return false ;
869869 }
870870
871- let is_private = map. flags . contains ( MMapFlags :: MAP_PRIVATE ) ;
872- let is_annon = map. flags . contains ( MMapFlags :: MAP_ANONYOMUS ) ;
873-
874871 let mut address_space = AddressSpace :: this ( ) ;
875872 let mut offset_table = address_space. offset_page_table ( ) ;
876873
877- match ( is_private , is_annon ) {
874+ match ( !map . vm_flags . contains ( VmFlag :: SHARED ) , map . file . is_none ( ) ) {
878875 ( true , true ) => {
879876 map. handle_pf_private_anon ( & mut offset_table, reason, accessed_address)
880877 }
@@ -970,9 +967,6 @@ impl VmProtected {
970967 file : Option < DirCacheItem > ,
971968 vm_flags : VmFlag ,
972969 ) -> Option < VirtAddr > {
973- // TODO: Check file permissions:
974- // * Do not allow writing to an {read, append}-only file.
975-
976970 let z = file. clone ( ) ;
977971
978972 // Offset is required to be a multiple of page size.
@@ -1030,19 +1024,16 @@ impl VmProtected {
10301024 // Merge same mappings instead of creating a new one.
10311025 if let Some ( prev) = cursor. peek_prev ( ) {
10321026 if prev. end_addr == addr
1033- && prev. flags == flags
1034- && prev. protection ( ) == ( vm_flags & VM_PROT_MASK )
1027+ && prev. vm_flags == vm_flags
10351028 && prev. file . is_none ( )
1029+ && file. is_none ( )
10361030 {
10371031 prev. end_addr = addr + size_aligned;
1038-
10391032 return addr;
10401033 }
10411034 }
10421035
10431036 cursor. insert_before ( Mapping {
1044- flags,
1045-
10461037 start_addr : addr,
10471038 end_addr : addr + size_aligned,
10481039
@@ -1077,21 +1068,19 @@ impl VmProtected {
10771068 for mmap in & self . mappings {
10781069 if let Some ( file) = mmap. file . as_ref ( ) {
10791070 log:: debug!(
1080- "{:?}..{:?} => {:?}, {:?} (offset={:#x}, size={:#x})" ,
1071+ "{:?}..{:?} => {:?} (offset={:#x}, size={:#x})" ,
10811072 mmap. start_addr,
10821073 mmap. end_addr,
10831074 mmap. vm_flags,
1084- mmap. flags,
10851075 file. offset,
10861076 file. size,
10871077 ) ;
10881078 } else {
10891079 log:: debug!(
1090- "{:?}..{:?} => {:?}, {:?} " ,
1080+ "{:?}..{:?} => {:?}" ,
10911081 mmap. start_addr,
10921082 mmap. end_addr,
10931083 mmap. vm_flags,
1094- mmap. flags,
10951084 ) ;
10961085 }
10971086 }
@@ -1376,7 +1365,7 @@ impl VmProtected {
13761365
13771366 for map in self . mappings . iter ( ) . filter ( |map| {
13781367 // Do not copy page table entries where a page fault can map them correctly.
1379- !map. flags . contains ( MMapFlags :: MAP_SHARED ) && map. vm_flags . contains ( VmFlag :: MAY_WRITE )
1368+ !map. vm_flags . contains ( VmFlag :: SHARED ) && map. vm_flags . contains ( VmFlag :: MAY_WRITE )
13801369 } ) {
13811370 offset_table. copy_page_range ( & mut current, map. start_addr ..=map. end_addr ) ;
13821371 }
@@ -1406,18 +1395,31 @@ impl Vm {
14061395 offset : usize ,
14071396 file : Option < Arc < FileHandle > > ,
14081397 ) -> Option < VirtAddr > {
1409- let vm_flags =
1398+ let mut vm_flags =
14101399 VmFlag :: from ( protection) | VmFlag :: MAY_READ | VmFlag :: MAY_WRITE | VmFlag :: MAY_EXEC ;
14111400
14121401 let map_type = flags & ( MMapFlags :: MAP_SHARED | MMapFlags :: MAP_PRIVATE ) ;
14131402
14141403 match ( map_type, file. as_ref ( ) ) {
14151404 ( MMapFlags :: MAP_SHARED , Some ( file) ) => {
1416- if protection. contains ( MMapProt :: PROT_WRITE ) && !file. is_writable ( ) {
1417- return None ; // EACCES
1405+ vm_flags. insert ( VmFlag :: SHARED ) ;
1406+
1407+ if !file. is_writable ( ) {
1408+ if protection. contains ( MMapProt :: PROT_WRITE ) {
1409+ return None ; // EACCES
1410+ }
1411+
1412+ // The mapping is going to be read-only forever so, it can be converted into a
1413+ // private mapping.
1414+ vm_flags. remove ( VmFlag :: MAY_WRITE | VmFlag :: SHARED ) ;
14181415 }
14191416
1420- // TODO: check for append-only files.
1417+ if !file. is_readable ( ) {
1418+ // return None; // EACCES
1419+ }
1420+
1421+ // TODO: * check if the filsystem is noexec mounted and remove the MAY_EXEC flag.
1422+ // * error out if prot contains PROT_EXEC & filesystem is noexec.
14211423 }
14221424
14231425 ( MMapFlags :: MAP_PRIVATE , Some ( file) ) => {
@@ -1429,6 +1431,7 @@ impl Vm {
14291431 // * error out if prot contains PROT_EXEC & filesystem is noexec.
14301432 }
14311433
1434+ ( MMapFlags :: MAP_SHARED , None ) => vm_flags. insert ( VmFlag :: SHARED ) ,
14321435 _ => { }
14331436 }
14341437
0 commit comments