@@ -905,6 +905,9 @@ impl<V: Verifier, C: ContextObject> Executable<V, C> {
905905 . saturating_add ( 1 )
906906 . saturating_sub ( first_ro_section)
907907 == n_ro_sections;
908+ if sbpf_version. enable_elf_vaddr ( ) && !can_borrow {
909+ return Err ( ElfError :: ValueOutOfBounds ) ;
910+ }
908911 let ro_section = if config. optimize_rodata && can_borrow {
909912 // Read only sections are grouped together with no intermixed non-ro
910913 // sections. We can borrow.
@@ -924,6 +927,9 @@ impl<V: Verifier, C: ContextObject> Executable<V, C> {
924927 // it now.
925928 lowest_addr. saturating_sub ( ebpf:: MM_PROGRAM_START as usize )
926929 } else {
930+ if sbpf_version. enable_elf_vaddr ( ) {
931+ return Err ( ElfError :: ValueOutOfBounds ) ;
932+ }
927933 lowest_addr
928934 } ;
929935
@@ -1760,7 +1766,9 @@ mod test {
17601766 fn new_section ( sh_addr : u64 , sh_size : u64 ) -> Elf64Shdr {
17611767 Elf64Shdr {
17621768 sh_addr,
1763- sh_offset : sh_addr,
1769+ sh_offset : sh_addr
1770+ . checked_sub ( ebpf:: MM_PROGRAM_START )
1771+ . unwrap_or ( sh_addr) ,
17641772 sh_size,
17651773 sh_name : 0 ,
17661774 sh_type : 0 ,
@@ -1790,7 +1798,7 @@ mod test {
17901798 assert ! ( matches!(
17911799 ElfExecutable :: parse_ro_sections(
17921800 & config,
1793- & SBPFVersion :: V2 ,
1801+ & SBPFVersion :: V1 ,
17941802 sections,
17951803 & elf_bytes,
17961804 ) ,
@@ -1817,7 +1825,7 @@ mod test {
18171825 assert ! ( matches!(
18181826 ElfExecutable :: parse_ro_sections(
18191827 & config,
1820- & SBPFVersion :: V2 ,
1828+ & SBPFVersion :: V1 ,
18211829 sections,
18221830 & elf_bytes,
18231831 ) ,
@@ -1895,7 +1903,7 @@ mod test {
18951903 let sections: [ ( Option < & [ u8 ] > , & Elf64Shdr ) ; 2 ] =
18961904 [ ( Some ( b".text" ) , & s1) , ( Some ( b".rodata" ) , & s2) ] ;
18971905 assert_eq ! (
1898- ElfExecutable :: parse_ro_sections( & config, & SBPFVersion :: V2 , sections, & elf_bytes, ) ,
1906+ ElfExecutable :: parse_ro_sections( & config, & SBPFVersion :: V2 , sections, & elf_bytes) ,
18991907 Err ( ElfError :: ValueOutOfBounds )
19001908 ) ;
19011909 }
@@ -1917,7 +1925,7 @@ mod test {
19171925 let sections: [ ( Option < & [ u8 ] > , & Elf64Shdr ) ; 2 ] =
19181926 [ ( Some ( b".text" ) , & s1) , ( Some ( b".rodata" ) , & s2) ] ;
19191927 assert_eq ! (
1920- ElfExecutable :: parse_ro_sections( & config, & SBPFVersion :: V2 , sections, & elf_bytes, ) ,
1928+ ElfExecutable :: parse_ro_sections( & config, & SBPFVersion :: V2 , sections, & elf_bytes) ,
19211929 Ok ( Section :: Borrowed ( 10 , 100 ..120 ) )
19221930 ) ;
19231931 }
@@ -1938,7 +1946,7 @@ mod test {
19381946 ( Some ( b".rodata" ) , & s3) ,
19391947 ] ;
19401948 let ro_section =
1941- ElfExecutable :: parse_ro_sections ( & config, & SBPFVersion :: V2 , sections, & elf_bytes)
1949+ ElfExecutable :: parse_ro_sections ( & config, & SBPFVersion :: V1 , sections, & elf_bytes)
19421950 . unwrap ( ) ;
19431951 let ro_region = get_ro_region ( & ro_section, & elf_bytes) ;
19441952 let owned_section = match & ro_section {
@@ -2020,7 +2028,7 @@ mod test {
20202028 ( Some ( b".rodata" ) , & s3) ,
20212029 ] ;
20222030 let ro_section =
2023- ElfExecutable :: parse_ro_sections ( & config, & SBPFVersion :: V2 , sections, & elf_bytes)
2031+ ElfExecutable :: parse_ro_sections ( & config, & SBPFVersion :: V1 , sections, & elf_bytes)
20242032 . unwrap ( ) ;
20252033 let owned_section = match & ro_section {
20262034 Section :: Owned ( _offset, data) => data. as_slice ( ) ,
@@ -2091,107 +2099,117 @@ mod test {
20912099 fn test_borrowed_ro_sections ( ) {
20922100 let config = Config :: default ( ) ;
20932101 let elf_bytes = [ 0u8 ; 512 ] ;
2094-
2095- let s1 = new_section ( 0 , 10 ) ;
2096- let s2 = new_section ( 20 , 10 ) ;
2097- let s3 = new_section ( 40 , 10 ) ;
2098- let s4 = new_section ( 50 , 10 ) ;
2099-
2100- let sections: [ ( Option < & [ u8 ] > , & Elf64Shdr ) ; 4 ] = [
2101- ( Some ( b".dynsym" ) , & s1) ,
2102- ( Some ( b".text" ) , & s2) ,
2103- ( Some ( b".rodata" ) , & s3) ,
2104- ( Some ( b".dynamic" ) , & s4) ,
2105- ] ;
2106- assert_eq ! (
2107- ElfExecutable :: parse_ro_sections( & config, & SBPFVersion :: V2 , sections, & elf_bytes, ) ,
2108- Ok ( Section :: Borrowed ( 20 , 20 ..50 ) )
2109- ) ;
2102+ for ( vaddr_base, sbpf_version) in [
2103+ ( 0 , SBPFVersion :: V1 ) ,
2104+ ( ebpf:: MM_PROGRAM_START , SBPFVersion :: V2 ) ,
2105+ ] {
2106+ let s1 = new_section ( vaddr_base, 10 ) ;
2107+ let s2 = new_section ( vaddr_base + 20 , 10 ) ;
2108+ let s3 = new_section ( vaddr_base + 40 , 10 ) ;
2109+ let s4 = new_section ( vaddr_base + 50 , 10 ) ;
2110+ let sections: [ ( Option < & [ u8 ] > , & Elf64Shdr ) ; 4 ] = [
2111+ ( Some ( b".dynsym" ) , & s1) ,
2112+ ( Some ( b".text" ) , & s2) ,
2113+ ( Some ( b".rodata" ) , & s3) ,
2114+ ( Some ( b".dynamic" ) , & s4) ,
2115+ ] ;
2116+ assert_eq ! (
2117+ ElfExecutable :: parse_ro_sections( & config, & sbpf_version, sections, & elf_bytes) ,
2118+ Ok ( Section :: Borrowed ( 20 , 20 ..50 ) )
2119+ ) ;
2120+ }
21102121 }
21112122
21122123 #[ test]
21132124 fn test_borrowed_ro_region_no_initial_gap ( ) {
21142125 let config = Config :: default ( ) ;
21152126 let elf_bytes = [ 0u8 ; 512 ] ;
2127+ for ( vaddr_base, sbpf_version) in [
2128+ ( 0 , SBPFVersion :: V1 ) ,
2129+ ( ebpf:: MM_PROGRAM_START , SBPFVersion :: V2 ) ,
2130+ ] {
2131+ let s1 = new_section ( vaddr_base, 10 ) ;
2132+ let s2 = new_section ( vaddr_base + 10 , 10 ) ;
2133+ let s3 = new_section ( vaddr_base + 20 , 10 ) ;
2134+ let sections: [ ( Option < & [ u8 ] > , & Elf64Shdr ) ; 3 ] = [
2135+ ( Some ( b".text" ) , & s1) ,
2136+ ( Some ( b".rodata" ) , & s2) ,
2137+ ( Some ( b".dynamic" ) , & s3) ,
2138+ ] ;
2139+ let ro_section =
2140+ ElfExecutable :: parse_ro_sections ( & config, & sbpf_version, sections, & elf_bytes)
2141+ . unwrap ( ) ;
2142+ let ro_region = get_ro_region ( & ro_section, & elf_bytes) ;
2143+
2144+ // s1 starts at sh_offset=0 so [0..s2.sh_offset + s2.sh_size]
2145+ // is the valid ro memory area
2146+ assert ! ( matches!(
2147+ ro_region. vm_to_host( ebpf:: MM_PROGRAM_START + s1. sh_offset, s2. sh_offset + s2. sh_size) ,
2148+ ProgramResult :: Ok ( ptr) if ptr == elf_bytes. as_ptr( ) as u64 ,
2149+ ) ) ;
21162150
2117- let s1 = new_section ( 0 , 10 ) ;
2118- let s2 = new_section ( 10 , 10 ) ;
2119- let s3 = new_section ( 10 , 10 ) ;
2120-
2121- let sections: [ ( Option < & [ u8 ] > , & Elf64Shdr ) ; 3 ] = [
2122- ( Some ( b".text" ) , & s1) ,
2123- ( Some ( b".rodata" ) , & s2) ,
2124- ( Some ( b".dynamic" ) , & s3) ,
2125- ] ;
2126- let ro_section =
2127- ElfExecutable :: parse_ro_sections ( & config, & SBPFVersion :: V2 , sections, & elf_bytes)
2128- . unwrap ( ) ;
2129- let ro_region = get_ro_region ( & ro_section, & elf_bytes) ;
2130-
2131- // s1 starts at sh_addr=0 so [0..s2.sh_addr + s2.sh_size] is the valid
2132- // ro memory area
2133- assert ! ( matches!(
2134- ro_region. vm_to_host( ebpf:: MM_PROGRAM_START , s2. sh_addr + s2. sh_size) ,
2135- ProgramResult :: Ok ( ptr) if ptr == elf_bytes. as_ptr( ) as u64 ,
2136- ) ) ;
2137-
2138- // one byte past the ro section is not mappable
2139- assert_error ! (
2140- ro_region. vm_to_host( ebpf:: MM_PROGRAM_START + s2. sh_addr + s2. sh_size, 1 ) ,
2141- "InvalidVirtualAddress({})" ,
2142- ebpf:: MM_PROGRAM_START + s2. sh_addr + s2. sh_size
2143- ) ;
2151+ // one byte past the ro section is not mappable
2152+ assert_error ! (
2153+ ro_region. vm_to_host( ebpf:: MM_PROGRAM_START + s3. sh_offset, 1 ) ,
2154+ "InvalidVirtualAddress({})" ,
2155+ ebpf:: MM_PROGRAM_START + s3. sh_offset
2156+ ) ;
2157+ }
21442158 }
21452159
21462160 #[ test]
21472161 fn test_borrowed_ro_region_initial_gap ( ) {
21482162 let config = Config :: default ( ) ;
21492163 let elf_bytes = [ 0u8 ; 512 ] ;
2150- let s1 = new_section ( 0 , 10 ) ;
2151- let s2 = new_section ( 10 , 10 ) ;
2152- let s3 = new_section ( 20 , 10 ) ;
2153-
2154- let sections: [ ( Option < & [ u8 ] > , & Elf64Shdr ) ; 3 ] = [
2155- ( Some ( b".dynamic" ) , & s1) ,
2156- ( Some ( b".text" ) , & s2) ,
2157- ( Some ( b".rodata" ) , & s3) ,
2158- ] ;
2159- let ro_section =
2160- ElfExecutable :: parse_ro_sections ( & config, & SBPFVersion :: V2 , sections, & elf_bytes)
2161- . unwrap ( ) ;
2162- let ro_region = get_ro_region ( & ro_section, & elf_bytes) ;
2163-
2164- // s2 starts at sh_addr=10 so [0..10] is not mappable
2165-
2166- // the low bound of the initial gap is not mappable
2167- assert_error ! (
2168- ro_region. vm_to_host( ebpf:: MM_PROGRAM_START , 1 ) ,
2169- "InvalidVirtualAddress({})" ,
2170- ebpf:: MM_PROGRAM_START
2171- ) ;
2172-
2173- // the hi bound of the initial gap is not mappable
2174- assert_error ! (
2175- ro_region. vm_to_host( ebpf:: MM_PROGRAM_START + s2. sh_addr - 1 , 1 ) ,
2176- "InvalidVirtualAddress({})" ,
2177- ebpf:: MM_PROGRAM_START + 9
2178- ) ;
2179-
2180- // [s2.sh_addr..s3.sh_addr + s3.sh_size] is the valid ro memory area
2181- assert ! ( matches!(
2182- ro_region. vm_to_host(
2183- ebpf:: MM_PROGRAM_START + s2. sh_addr,
2184- s3. sh_addr + s3. sh_size - s2. sh_addr
2185- ) ,
2186- ProgramResult :: Ok ( ptr) if ptr == elf_bytes[ s2. sh_addr as usize ..] . as_ptr( ) as u64 ,
2187- ) ) ;
2164+ for ( vaddr_base, sbpf_version) in [
2165+ ( 0 , SBPFVersion :: V1 ) ,
2166+ ( ebpf:: MM_PROGRAM_START , SBPFVersion :: V2 ) ,
2167+ ] {
2168+ let s1 = new_section ( vaddr_base, 10 ) ;
2169+ let s2 = new_section ( vaddr_base + 10 , 10 ) ;
2170+ let s3 = new_section ( vaddr_base + 20 , 10 ) ;
2171+ let sections: [ ( Option < & [ u8 ] > , & Elf64Shdr ) ; 3 ] = [
2172+ ( Some ( b".dynamic" ) , & s1) ,
2173+ ( Some ( b".text" ) , & s2) ,
2174+ ( Some ( b".rodata" ) , & s3) ,
2175+ ] ;
2176+ let ro_section =
2177+ ElfExecutable :: parse_ro_sections ( & config, & sbpf_version, sections, & elf_bytes)
2178+ . unwrap ( ) ;
2179+ let ro_region = get_ro_region ( & ro_section, & elf_bytes) ;
2180+
2181+ // s2 starts at sh_addr=10 so [0..10] is not mappable
2182+
2183+ // the low bound of the initial gap is not mappable
2184+ assert_error ! (
2185+ ro_region. vm_to_host( ebpf:: MM_PROGRAM_START + s1. sh_offset, 1 ) ,
2186+ "InvalidVirtualAddress({})" ,
2187+ ebpf:: MM_PROGRAM_START + s1. sh_offset
2188+ ) ;
2189+
2190+ // the hi bound of the initial gap is not mappable
2191+ assert_error ! (
2192+ ro_region. vm_to_host( ebpf:: MM_PROGRAM_START + s2. sh_offset - 1 , 1 ) ,
2193+ "InvalidVirtualAddress({})" ,
2194+ ebpf:: MM_PROGRAM_START + s2. sh_offset - 1
2195+ ) ;
2196+
2197+ // [s2.sh_offset..s3.sh_offset + s3.sh_size] is the valid ro memory area
2198+ assert ! ( matches!(
2199+ ro_region. vm_to_host(
2200+ ebpf:: MM_PROGRAM_START + s2. sh_offset,
2201+ s3. sh_offset + s3. sh_size - s2. sh_offset
2202+ ) ,
2203+ ProgramResult :: Ok ( ptr) if ptr == elf_bytes[ s2. sh_offset as usize ..] . as_ptr( ) as u64 ,
2204+ ) ) ;
21882205
2189- // one byte past the ro section is not mappable
2190- assert_error ! (
2191- ro_region. vm_to_host( ebpf:: MM_PROGRAM_START + s3. sh_addr + s3. sh_size, 1 ) ,
2192- "InvalidVirtualAddress({})" ,
2193- ebpf:: MM_PROGRAM_START + s3. sh_addr + s3. sh_size
2194- ) ;
2206+ // one byte past the ro section is not mappable
2207+ assert_error ! (
2208+ ro_region. vm_to_host( ebpf:: MM_PROGRAM_START + s3. sh_offset + s3. sh_size, 1 ) ,
2209+ "InvalidVirtualAddress({})" ,
2210+ ebpf:: MM_PROGRAM_START + s3. sh_offset + s3. sh_size
2211+ ) ;
2212+ }
21952213 }
21962214
21972215 #[ test]
0 commit comments