@@ -1380,7 +1380,7 @@ mod test {
13801380 elf_parser:: {
13811381 // FIXME consts::{ELFCLASS32, ELFDATA2MSB, ET_REL},
13821382 consts:: { ELFCLASS32 , ELFDATA2MSB , ET_REL } ,
1383- types:: { Elf64Ehdr , Elf64Shdr } ,
1383+ types:: { Elf64Ehdr , Elf64Shdr , Elf64Sym } ,
13841384 SECTION_NAME_LENGTH_MAXIMUM ,
13851385 } ,
13861386 error:: ProgramResult ,
@@ -1409,6 +1409,137 @@ mod test {
14091409 ) )
14101410 }
14111411
1412+ #[ test]
1413+ fn test_strict_header ( ) {
1414+ let elf_bytes =
1415+ std:: fs:: read ( "tests/elfs/strict_header.so" ) . expect ( "failed to read elf file" ) ;
1416+ let loader = loader ( ) ;
1417+
1418+ // Check that the unmodified file can be parsed
1419+ {
1420+ let loader = Arc :: new ( BuiltinProgram :: new_loader (
1421+ Config {
1422+ enable_symbol_and_section_labels : true ,
1423+ ..Config :: default ( )
1424+ } ,
1425+ FunctionRegistry :: < BuiltinFunction < TestContextObject > > :: default ( ) ,
1426+ ) ) ;
1427+ let executable = ElfExecutable :: load ( & elf_bytes, loader. clone ( ) ) . unwrap ( ) ;
1428+ let ( name, _pc) = executable. get_function_registry ( ) . lookup_by_key ( 4 ) . unwrap ( ) ;
1429+ assert_eq ! ( name, b"entrypoint" ) ;
1430+ }
1431+
1432+ // Check that using a reserved SBPF version fails
1433+ {
1434+ let mut elf_bytes = elf_bytes. clone ( ) ;
1435+ elf_bytes[ 0x0030 ] = 0xFF ;
1436+ let err = ElfExecutable :: load ( & elf_bytes, loader. clone ( ) ) . unwrap_err ( ) ;
1437+ assert_eq ! ( err, ElfError :: UnsupportedSBPFVersion ) ;
1438+ }
1439+
1440+ // Check that an empty file fails
1441+ let err = ElfExecutable :: load_with_strict_parser ( & [ ] , loader. clone ( ) ) . unwrap_err ( ) ;
1442+ assert_eq ! ( err, ElfParserError :: OutOfBounds ) ;
1443+
1444+ // Break the file header one byte at a time
1445+ let expected_results = std:: iter:: repeat ( & Err ( ElfParserError :: InvalidFileHeader ) )
1446+ . take ( 40 )
1447+ . chain ( std:: iter:: repeat ( & Ok ( ( ) ) ) . take ( 12 ) )
1448+ . chain ( std:: iter:: repeat ( & Err ( ElfParserError :: InvalidFileHeader ) ) . take ( 4 ) )
1449+ . chain ( std:: iter:: repeat ( & Err ( ElfParserError :: InvalidProgramHeader ) ) . take ( 1 ) )
1450+ . chain ( std:: iter:: repeat ( & Err ( ElfParserError :: InvalidFileHeader ) ) . take ( 3 ) )
1451+ . chain ( std:: iter:: repeat ( & Ok ( ( ) ) ) . take ( 2 ) )
1452+ . chain ( std:: iter:: repeat ( & Err ( ElfParserError :: InvalidFileHeader ) ) . take ( 2 ) ) ;
1453+ for ( offset, expected) in ( 0 ..std:: mem:: size_of :: < Elf64Ehdr > ( ) ) . zip ( expected_results) {
1454+ let mut elf_bytes = elf_bytes. clone ( ) ;
1455+ elf_bytes[ offset] = 0xAF ;
1456+ let result =
1457+ ElfExecutable :: load_with_strict_parser ( & elf_bytes, loader. clone ( ) ) . map ( |_| ( ) ) ;
1458+ assert_eq ! ( & result, expected) ;
1459+ }
1460+
1461+ // Break the program header table one byte at a time
1462+ let expected_results_readonly =
1463+ std:: iter:: repeat ( & Err ( ElfParserError :: InvalidProgramHeader ) )
1464+ . take ( 48 )
1465+ . chain ( std:: iter:: repeat ( & Ok ( ( ) ) ) . take ( 8 ) )
1466+ . collect :: < Vec < _ > > ( ) ;
1467+ let expected_results_writable =
1468+ std:: iter:: repeat ( & Err ( ElfParserError :: InvalidProgramHeader ) )
1469+ . take ( 40 )
1470+ . chain ( std:: iter:: repeat ( & Ok ( ( ) ) ) . take ( 4 ) )
1471+ . chain ( std:: iter:: repeat ( & Err ( ElfParserError :: InvalidProgramHeader ) ) . take ( 4 ) )
1472+ . chain ( std:: iter:: repeat ( & Ok ( ( ) ) ) . take ( 8 ) )
1473+ . collect :: < Vec < _ > > ( ) ;
1474+ let expected_results = vec ! [
1475+ expected_results_readonly. iter( ) ,
1476+ expected_results_readonly. iter( ) ,
1477+ expected_results_writable. iter( ) ,
1478+ expected_results_writable. iter( ) ,
1479+ expected_results_readonly. iter( ) ,
1480+ ] ;
1481+ for ( header_index, expected_results) in expected_results. into_iter ( ) . enumerate ( ) {
1482+ for ( offset, expected) in ( std:: mem:: size_of :: < Elf64Ehdr > ( )
1483+ + std:: mem:: size_of :: < Elf64Phdr > ( ) * header_index
1484+ ..std:: mem:: size_of :: < Elf64Ehdr > ( )
1485+ + std:: mem:: size_of :: < Elf64Phdr > ( ) * ( header_index + 1 ) )
1486+ . zip ( expected_results)
1487+ {
1488+ let mut elf_bytes = elf_bytes. clone ( ) ;
1489+ elf_bytes[ offset] = 0xAF ;
1490+ let result =
1491+ ElfExecutable :: load_with_strict_parser ( & elf_bytes, loader. clone ( ) ) . map ( |_| ( ) ) ;
1492+ assert_eq ! ( &&result, expected) ;
1493+ }
1494+ }
1495+
1496+ // Break the dynamic symbol table one byte at a time
1497+ for index in 1 ..3 {
1498+ let expected_results = std:: iter:: repeat ( & Ok ( ( ) ) )
1499+ . take ( 8 )
1500+ . chain ( std:: iter:: repeat ( & Err ( ElfParserError :: OutOfBounds ) ) . take ( 8 ) )
1501+ . chain ( std:: iter:: repeat ( & Err ( ElfParserError :: InvalidSize ) ) . take ( 1 ) )
1502+ . chain ( std:: iter:: repeat ( & Err ( ElfParserError :: OutOfBounds ) ) . take ( 7 ) ) ;
1503+ for ( offset, expected) in ( 0x3000 + std:: mem:: size_of :: < Elf64Sym > ( ) * index
1504+ ..0x3000 + std:: mem:: size_of :: < Elf64Sym > ( ) * ( index + 1 ) )
1505+ . zip ( expected_results)
1506+ {
1507+ let mut elf_bytes = elf_bytes. clone ( ) ;
1508+ elf_bytes[ offset] = 0xAF ;
1509+ let result =
1510+ ElfExecutable :: load_with_strict_parser ( & elf_bytes, loader. clone ( ) ) . map ( |_| ( ) ) ;
1511+ assert_eq ! ( & result, expected) ;
1512+ }
1513+ }
1514+
1515+ // Check that an empty function symbol fails
1516+ {
1517+ let mut elf_bytes = elf_bytes. clone ( ) ;
1518+ elf_bytes[ 0x3040 ] = 0x00 ;
1519+ let err =
1520+ ElfExecutable :: load_with_strict_parser ( & elf_bytes, loader. clone ( ) ) . unwrap_err ( ) ;
1521+ assert_eq ! ( err, ElfParserError :: InvalidSize ) ;
1522+ }
1523+
1524+ // Check that bytecode not covered by function symbols fails
1525+ {
1526+ let mut elf_bytes = elf_bytes. clone ( ) ;
1527+ elf_bytes[ 0x3040 ] = 0x08 ;
1528+ let err =
1529+ ElfExecutable :: load_with_strict_parser ( & elf_bytes, loader. clone ( ) ) . unwrap_err ( ) ;
1530+ assert_eq ! ( err, ElfParserError :: OutOfBounds ) ;
1531+ }
1532+
1533+ // Check that an entrypoint not covered by function symbols fails
1534+ {
1535+ let mut elf_bytes = elf_bytes. clone ( ) ;
1536+ elf_bytes[ 0x0018 ] = 0x10 ;
1537+ let err =
1538+ ElfExecutable :: load_with_strict_parser ( & elf_bytes, loader. clone ( ) ) . unwrap_err ( ) ;
1539+ assert_eq ! ( err, ElfParserError :: InvalidFileHeader ) ;
1540+ }
1541+ }
1542+
14121543 #[ test]
14131544 fn test_validate ( ) {
14141545 let elf_bytes = std:: fs:: read ( "tests/elfs/relative_call_sbpfv1.so" ) . unwrap ( ) ;
0 commit comments