@@ -905,6 +905,9 @@ impl<V: Verifier, C: ContextObject> Executable<V, C> {
905
905
. saturating_add ( 1 )
906
906
. saturating_sub ( first_ro_section)
907
907
== n_ro_sections;
908
+ if sbpf_version. enable_elf_vaddr ( ) && !can_borrow {
909
+ return Err ( ElfError :: ValueOutOfBounds ) ;
910
+ }
908
911
let ro_section = if config. optimize_rodata && can_borrow {
909
912
// Read only sections are grouped together with no intermixed non-ro
910
913
// sections. We can borrow.
@@ -924,6 +927,9 @@ impl<V: Verifier, C: ContextObject> Executable<V, C> {
924
927
// it now.
925
928
lowest_addr. saturating_sub ( ebpf:: MM_PROGRAM_START as usize )
926
929
} else {
930
+ if sbpf_version. enable_elf_vaddr ( ) {
931
+ return Err ( ElfError :: ValueOutOfBounds ) ;
932
+ }
927
933
lowest_addr
928
934
} ;
929
935
@@ -1760,7 +1766,9 @@ mod test {
1760
1766
fn new_section ( sh_addr : u64 , sh_size : u64 ) -> Elf64Shdr {
1761
1767
Elf64Shdr {
1762
1768
sh_addr,
1763
- sh_offset : sh_addr,
1769
+ sh_offset : sh_addr
1770
+ . checked_sub ( ebpf:: MM_PROGRAM_START )
1771
+ . unwrap_or ( sh_addr) ,
1764
1772
sh_size,
1765
1773
sh_name : 0 ,
1766
1774
sh_type : 0 ,
@@ -1790,7 +1798,7 @@ mod test {
1790
1798
assert ! ( matches!(
1791
1799
ElfExecutable :: parse_ro_sections(
1792
1800
& config,
1793
- & SBPFVersion :: V2 ,
1801
+ & SBPFVersion :: V1 ,
1794
1802
sections,
1795
1803
& elf_bytes,
1796
1804
) ,
@@ -1817,7 +1825,7 @@ mod test {
1817
1825
assert ! ( matches!(
1818
1826
ElfExecutable :: parse_ro_sections(
1819
1827
& config,
1820
- & SBPFVersion :: V2 ,
1828
+ & SBPFVersion :: V1 ,
1821
1829
sections,
1822
1830
& elf_bytes,
1823
1831
) ,
@@ -1895,7 +1903,7 @@ mod test {
1895
1903
let sections: [ ( Option < & [ u8 ] > , & Elf64Shdr ) ; 2 ] =
1896
1904
[ ( Some ( b".text" ) , & s1) , ( Some ( b".rodata" ) , & s2) ] ;
1897
1905
assert_eq ! (
1898
- ElfExecutable :: parse_ro_sections( & config, & SBPFVersion :: V2 , sections, & elf_bytes, ) ,
1906
+ ElfExecutable :: parse_ro_sections( & config, & SBPFVersion :: V2 , sections, & elf_bytes) ,
1899
1907
Err ( ElfError :: ValueOutOfBounds )
1900
1908
) ;
1901
1909
}
@@ -1917,7 +1925,7 @@ mod test {
1917
1925
let sections: [ ( Option < & [ u8 ] > , & Elf64Shdr ) ; 2 ] =
1918
1926
[ ( Some ( b".text" ) , & s1) , ( Some ( b".rodata" ) , & s2) ] ;
1919
1927
assert_eq ! (
1920
- ElfExecutable :: parse_ro_sections( & config, & SBPFVersion :: V2 , sections, & elf_bytes, ) ,
1928
+ ElfExecutable :: parse_ro_sections( & config, & SBPFVersion :: V2 , sections, & elf_bytes) ,
1921
1929
Ok ( Section :: Borrowed ( 10 , 100 ..120 ) )
1922
1930
) ;
1923
1931
}
@@ -1938,7 +1946,7 @@ mod test {
1938
1946
( Some ( b".rodata" ) , & s3) ,
1939
1947
] ;
1940
1948
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)
1942
1950
. unwrap ( ) ;
1943
1951
let ro_region = get_ro_region ( & ro_section, & elf_bytes) ;
1944
1952
let owned_section = match & ro_section {
@@ -2020,7 +2028,7 @@ mod test {
2020
2028
( Some ( b".rodata" ) , & s3) ,
2021
2029
] ;
2022
2030
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)
2024
2032
. unwrap ( ) ;
2025
2033
let owned_section = match & ro_section {
2026
2034
Section :: Owned ( _offset, data) => data. as_slice ( ) ,
@@ -2091,107 +2099,117 @@ mod test {
2091
2099
fn test_borrowed_ro_sections ( ) {
2092
2100
let config = Config :: default ( ) ;
2093
2101
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
+ }
2110
2121
}
2111
2122
2112
2123
#[ test]
2113
2124
fn test_borrowed_ro_region_no_initial_gap ( ) {
2114
2125
let config = Config :: default ( ) ;
2115
2126
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
+ ) ) ;
2116
2150
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
+ }
2144
2158
}
2145
2159
2146
2160
#[ test]
2147
2161
fn test_borrowed_ro_region_initial_gap ( ) {
2148
2162
let config = Config :: default ( ) ;
2149
2163
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
+ ) ) ;
2188
2205
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
+ }
2195
2213
}
2196
2214
2197
2215
#[ test]
0 commit comments