@@ -25,25 +25,28 @@ struct FileHandle {
2525trait FileDescriptor < ' tcx > : std:: fmt:: Debug {
2626 fn as_file_handle ( & self ) -> InterpResult < ' tcx , & FileHandle > ;
2727
28- fn read ( & mut self , bytes : & mut [ u8 ] ) -> InterpResult < ' tcx , io:: Result < usize > > ;
29- fn write ( & mut self , bytes : & [ u8 ] ) -> InterpResult < ' tcx , io:: Result < usize > > ;
30- fn seek ( & mut self , offset : SeekFrom ) -> InterpResult < ' tcx , io:: Result < u64 > > ;
28+ fn read ( & mut self , communicate_allowed : bool , bytes : & mut [ u8 ] ) -> InterpResult < ' tcx , io:: Result < usize > > ;
29+ fn write ( & mut self , communicate_allowed : bool , bytes : & [ u8 ] ) -> InterpResult < ' tcx , io:: Result < usize > > ;
30+ fn seek ( & mut self , communicate_allowed : bool , offset : SeekFrom ) -> InterpResult < ' tcx , io:: Result < u64 > > ;
3131}
3232
3333impl < ' tcx > FileDescriptor < ' tcx > for FileHandle {
3434 fn as_file_handle ( & self ) -> InterpResult < ' tcx , & FileHandle > {
3535 Ok ( & self )
3636 }
3737
38- fn read ( & mut self , bytes : & mut [ u8 ] ) -> InterpResult < ' tcx , io:: Result < usize > > {
38+ fn read ( & mut self , communicate_allowed : bool , bytes : & mut [ u8 ] ) -> InterpResult < ' tcx , io:: Result < usize > > {
39+ assert ! ( communicate_allowed, "isolation should have prevented even opening a file" ) ;
3940 Ok ( self . file . read ( bytes) )
4041 }
4142
42- fn write ( & mut self , bytes : & [ u8 ] ) -> InterpResult < ' tcx , io:: Result < usize > > {
43+ fn write ( & mut self , communicate_allowed : bool , bytes : & [ u8 ] ) -> InterpResult < ' tcx , io:: Result < usize > > {
44+ assert ! ( communicate_allowed, "isolation should have prevented even opening a file" ) ;
4345 Ok ( self . file . write ( bytes) )
4446 }
4547
46- fn seek ( & mut self , offset : SeekFrom ) -> InterpResult < ' tcx , io:: Result < u64 > > {
48+ fn seek ( & mut self , communicate_allowed : bool , offset : SeekFrom ) -> InterpResult < ' tcx , io:: Result < u64 > > {
49+ assert ! ( communicate_allowed, "isolation should have prevented even opening a file" ) ;
4750 Ok ( self . file . seek ( offset) )
4851 }
4952}
@@ -53,15 +56,19 @@ impl<'tcx> FileDescriptor<'tcx> for io::Stdin {
5356 throw_unsup_format ! ( "stdin cannot be used as FileHandle" ) ;
5457 }
5558
56- fn read ( & mut self , bytes : & mut [ u8 ] ) -> InterpResult < ' tcx , io:: Result < usize > > {
59+ fn read ( & mut self , communicate_allowed : bool , bytes : & mut [ u8 ] ) -> InterpResult < ' tcx , io:: Result < usize > > {
60+ if !communicate_allowed {
61+ // We want isolation mode to be deterministic, so we have to disallow all reads, even stdin.
62+ helpers:: isolation_error ( "read" ) ?;
63+ }
5764 Ok ( Read :: read ( self , bytes) )
5865 }
5966
60- fn write ( & mut self , _bytes : & [ u8 ] ) -> InterpResult < ' tcx , io:: Result < usize > > {
67+ fn write ( & mut self , _communicate_allowed : bool , _bytes : & [ u8 ] ) -> InterpResult < ' tcx , io:: Result < usize > > {
6168 throw_unsup_format ! ( "cannot write to stdin" ) ;
6269 }
6370
64- fn seek ( & mut self , _offset : SeekFrom ) -> InterpResult < ' tcx , io:: Result < u64 > > {
71+ fn seek ( & mut self , _communicate_allowed : bool , _offset : SeekFrom ) -> InterpResult < ' tcx , io:: Result < u64 > > {
6572 throw_unsup_format ! ( "cannot seek on stdin" ) ;
6673 }
6774}
@@ -71,11 +78,12 @@ impl<'tcx> FileDescriptor<'tcx> for io::Stdout {
7178 throw_unsup_format ! ( "stdout cannot be used as FileHandle" ) ;
7279 }
7380
74- fn read ( & mut self , _bytes : & mut [ u8 ] ) -> InterpResult < ' tcx , io:: Result < usize > > {
81+ fn read ( & mut self , _communicate_allowed : bool , _bytes : & mut [ u8 ] ) -> InterpResult < ' tcx , io:: Result < usize > > {
7582 throw_unsup_format ! ( "cannot read from stdout" ) ;
7683 }
7784
78- fn write ( & mut self , bytes : & [ u8 ] ) -> InterpResult < ' tcx , io:: Result < usize > > {
85+ fn write ( & mut self , _communicate_allowed : bool , bytes : & [ u8 ] ) -> InterpResult < ' tcx , io:: Result < usize > > {
86+ // We allow writing to stderr even with isolation enabled.
7987 let result = Write :: write ( self , bytes) ;
8088 // Stdout is buffered, flush to make sure it appears on the
8189 // screen. This is the write() syscall of the interpreted
@@ -87,7 +95,7 @@ impl<'tcx> FileDescriptor<'tcx> for io::Stdout {
8795 Ok ( result)
8896 }
8997
90- fn seek ( & mut self , _offset : SeekFrom ) -> InterpResult < ' tcx , io:: Result < u64 > > {
98+ fn seek ( & mut self , _communicate_allowed : bool , _offset : SeekFrom ) -> InterpResult < ' tcx , io:: Result < u64 > > {
9199 throw_unsup_format ! ( "cannot seek on stdout" ) ;
92100 }
93101}
@@ -97,15 +105,16 @@ impl<'tcx> FileDescriptor<'tcx> for io::Stderr {
97105 throw_unsup_format ! ( "stdout cannot be used as FileHandle" ) ;
98106 }
99107
100- fn read ( & mut self , _bytes : & mut [ u8 ] ) -> InterpResult < ' tcx , io:: Result < usize > > {
108+ fn read ( & mut self , _communicate_allowed : bool , _bytes : & mut [ u8 ] ) -> InterpResult < ' tcx , io:: Result < usize > > {
101109 throw_unsup_format ! ( "cannot read from stderr" ) ;
102110 }
103111
104- fn write ( & mut self , bytes : & [ u8 ] ) -> InterpResult < ' tcx , io:: Result < usize > > {
112+ fn write ( & mut self , _communicate_allowed : bool , bytes : & [ u8 ] ) -> InterpResult < ' tcx , io:: Result < usize > > {
113+ // We allow writing to stderr even with isolation enabled.
105114 Ok ( Write :: write ( self , bytes) )
106115 }
107116
108- fn seek ( & mut self , _offset : SeekFrom ) -> InterpResult < ' tcx , io:: Result < u64 > > {
117+ fn seek ( & mut self , _communicate_allowed : bool , _offset : SeekFrom ) -> InterpResult < ' tcx , io:: Result < u64 > > {
109118 throw_unsup_format ! ( "cannot seek on stderr" ) ;
110119 }
111120}
@@ -553,7 +562,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
553562 ) -> InterpResult < ' tcx , i64 > {
554563 let this = self . eval_context_mut ( ) ;
555564
556- this . check_no_isolation ( "read" ) ? ;
565+ // Isolation check is done via `FileDescriptor` trait.
557566
558567 trace ! ( "Reading from FD {}, size {}" , fd, count) ;
559568
@@ -577,7 +586,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
577586 // `File::read` never returns a value larger than `count`,
578587 // so this cannot fail.
579588 let result = file_descriptor
580- . read ( & mut bytes) ?
589+ . read ( this . machine . communicate , & mut bytes) ?
581590 . map ( |c| i64:: try_from ( c) . unwrap ( ) ) ;
582591
583592 match result {
@@ -605,9 +614,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
605614 ) -> InterpResult < ' tcx , i64 > {
606615 let this = self . eval_context_mut ( ) ;
607616
608- if fd >= 3 {
609- this. check_no_isolation ( "write" ) ?;
610- }
617+ // Isolation check is done via `FileDescriptor` trait.
611618
612619 // Check that the *entire* buffer is actually valid memory.
613620 this. memory . check_ptr_access (
@@ -623,7 +630,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
623630 if let Some ( file_descriptor) = this. machine . file_handler . handles . get_mut ( & fd) {
624631 let bytes = this. memory . read_bytes ( buf, Size :: from_bytes ( count) ) ?;
625632 let result = file_descriptor
626- . write ( & bytes) ?
633+ . write ( this . machine . communicate , & bytes) ?
627634 . map ( |c| i64:: try_from ( c) . unwrap ( ) ) ;
628635 this. try_unwrap_io_result ( result)
629636 } else {
@@ -639,7 +646,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
639646 ) -> InterpResult < ' tcx , i64 > {
640647 let this = self . eval_context_mut ( ) ;
641648
642- this . check_no_isolation ( "lseek64" ) ? ;
649+ // Isolation check is done via `FileDescriptor` trait.
643650
644651 let fd = this. read_scalar ( fd_op) ?. to_i32 ( ) ?;
645652 let offset = this. read_scalar ( offset_op) ?. to_i64 ( ) ?;
@@ -659,7 +666,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
659666
660667 if let Some ( file_descriptor) = this. machine . file_handler . handles . get_mut ( & fd) {
661668 let result = file_descriptor
662- . seek ( seek_from) ?
669+ . seek ( this . machine . communicate , seek_from) ?
663670 . map ( |offset| i64:: try_from ( offset) . unwrap ( ) ) ;
664671 this. try_unwrap_io_result ( result)
665672 } else {
0 commit comments