Skip to main content

kernel/sched/loader/
validate.rs

1// SPDX-License-Identifier: GPL-3.0-only
2//! ELF validation logic
3//!
4//! Authors: MarioS271
5
6use super::defs::error::ElfError;
7use super::defs::header::ElfHeader;
8use super::defs::phdrs::{parse_phdrs, ElfPhdr};
9use crate::{kdebug, kerror};
10
11/// Validate a given ELF binary slice
12/// Returns a tuple of a slice of [`ElfPhdr`]s and a [`u64`] with the value of `e_entry`
13pub fn validate_elf(elf: &[u8]) -> Result<(&[ElfPhdr], u64), ElfError> {
14    let header = match validate_header(elf) {
15        Ok(h) => h,
16        Err(e) => {
17            kerror!("Failed to verify ELF header: {:?}", e);
18            return Err(e);
19        }
20    };
21
22    let phdrs = match parse_phdrs(elf, header) {
23        Ok(p) => p,
24        Err(e) => {
25            kerror!("Failed to verify ELF phdrs: {:?}", e);
26            return Err(e);
27        }
28    };
29
30    kdebug!("Validated ELF slice");
31
32    for phdr in phdrs.iter() {
33        kdebug!(
34            "- phdr type={}, vaddr={:#x}, filesz={:#x}, memsz={:#x}",
35            phdr.p_type, phdr.p_vaddr, phdr.p_filesz, phdr.p_memsz
36        );
37    }
38
39    Ok((phdrs, header.e_entry))
40}
41
42/// Validate if a byte slice contains a valid ELF header
43fn validate_header(elf: &[u8]) -> Result<&ElfHeader, ElfError> {
44    use ElfError::*;
45
46    if elf.len() < 64 {
47        return Err(TooSmall);
48    }
49
50    let header = ElfHeader::new(elf);
51
52    #[cfg(target_arch = "x86_64")] let target_arch = ElfHeader::EM_X86_64;
53
54    for (i, &byte) in ElfHeader::ELF_MAGIC.iter().enumerate() {
55        if header.e_ident[i] != byte {
56            return Err(BadMagic)
57        }
58    }
59
60    if header.e_ident[4] != 0x02 {
61        return Err(Not64Bit)
62    }
63
64    if header.e_ident[5] != 0x01 {
65        return Err(NotLittleEndian)
66    }
67
68    if header.e_type != ElfHeader::ET_EXEC && header.e_type != ElfHeader::ET_DYN {
69        return Err(NotExecutable)
70    }
71
72    if header.e_machine != target_arch {
73        return Err(WrongArch)
74    }
75
76    if header.e_phentsize != size_of::<ElfPhdr>() as u16 {
77        return Err(BadPhentsize)
78    }
79
80    Ok(header)
81}