Recognize kernel memory regions in the Linux boot path

This commit is contained in:
Zhang Junyang
2023-12-13 16:25:16 +08:00
committed by Tate, Hongliang Tian
parent d4b6eea97d
commit 487e0cdd15
11 changed files with 117 additions and 58 deletions

View File

@ -24,16 +24,14 @@ jobs:
id: boot_test_mb2
run: make run AUTO_TEST=boot ENABLE_KVM=0 BOOT_PROTOCOL=multiboot2 RELEASE_MODE=1
# FIXME: Syscall test under Linux Boot Protocol fails at JobControlTest
# We should re-enable syscall tests after fixing the bug.
- name: Boot Test (MicroVM)
id: boot_test_microvm
run: make run AUTO_TEST=boot ENABLE_KVM=0 BOOT_METHOD=microvm RELEASE_MODE=1
- name: Boot Test (Linux Boot Protocol)
id: boot_test_linux
run: make run AUTO_TEST=boot ENABLE_KVM=0 BOOT_PROTOCOL=linux RELEASE_MODE=1
- name: Regression Test (Multiboot2)
id: regression_test_linux
run: make run AUTO_TEST=regression ENABLE_KVM=0 BOOT_PROTOCOL=multiboot2 RELEASE_MODE=1
- name: Syscall Test (MicroVM)
id: syscall_test_microvm
run: make run AUTO_TEST=syscall ENABLE_KVM=0 BOOT_METHOD=microvm RELEASE_MODE=1
@ -45,3 +43,7 @@ jobs:
- name: Syscall Test at Ext2 (MicroVM)
id: syscall_test_at_ext2_microvm
run: make run AUTO_TEST=syscall SYSCALL_TEST_DIR=/ext2 ENABLE_KVM=0 BOOT_METHOD=microvm RELEASE_MODE=1
- name: Regression Test (Linux Boot Protocol)
id: regression_test_linux
run: make run AUTO_TEST=regression ENABLE_KVM=0 BOOT_PROTOCOL=linux RELEASE_MODE=1

View File

@ -5,7 +5,9 @@ use spin::Once;
use crate::{
boot::{
kcmdline::KCmdlineArg,
memory_region::{non_overlapping_regions_from, MemoryRegion, MemoryRegionType},
memory_region::{
non_overlapping_regions_from, MemoryRegion, MemoryRegionType,
},
BootloaderAcpiArg, BootloaderFramebufferArg,
},
config::PHYS_OFFSET,

View File

@ -6,7 +6,9 @@ use multiboot2::{BootInformation, BootInformationHeader, MemoryAreaType};
use crate::boot::{
kcmdline::KCmdlineArg,
memory_region::{non_overlapping_regions_from, MemoryRegion, MemoryRegionType},
memory_region::{
non_overlapping_regions_from, MemoryRegion, MemoryRegionType,
},
BootloaderAcpiArg, BootloaderFramebufferArg,
};
use spin::Once;

View File

@ -56,7 +56,7 @@ fn init_tsc_mode() {
fn determine_tsc_freq_via_pit() -> u64 {
let mut irq = IrqLine::alloc_specific(super::TIMER_IRQ_NUM.load(Ordering::Relaxed)).unwrap();
irq.on_active(pit_callback);
let mut io_apic = IO_APIC.get().unwrap().get(0).unwrap().lock();
let mut io_apic = IO_APIC.get().unwrap().first().unwrap().lock();
debug_assert_eq!(io_apic.interrupt_base(), 0);
io_apic.enable(2, irq.clone()).unwrap();
drop(io_apic);
@ -87,7 +87,7 @@ fn determine_tsc_freq_via_pit() -> u64 {
IN_TIME += 1;
return;
}
let mut io_apic = IO_APIC.get().unwrap().get(0).unwrap().lock();
let mut io_apic = IO_APIC.get().unwrap().first().unwrap().lock();
io_apic.disable(2).unwrap();
drop(io_apic);
let tsc_count = _rdtsc();

View File

@ -84,9 +84,12 @@ pub(crate) fn init(regions: &[MemoryRegion]) {
let mut allocator = FrameAllocator::<32>::new();
for region in regions.iter() {
if region.typ() == MemoryRegionType::Usable {
// Make the memory region page-aligned
// Make the memory region page-aligned, and skip if it is too small.
let start = region.base().align_up(PAGE_SIZE) / PAGE_SIZE;
let end = (region.base() + region.len()).align_down(PAGE_SIZE) / PAGE_SIZE;
if end <= start {
continue;
}
allocator.add_frame(start, end);
info!(
"Found usable region, start:{:x}, end:{:x}",

View File

@ -12,6 +12,7 @@ unsafe fn memcpy(dst: *mut u8, src: *const u8, size: usize) {
}
}
/// Load the kernel ELF payload to memory.
pub fn load_elf(file: &[u8]) {
let elf = xmas_elf::ElfFile::new(file).unwrap();

View File

@ -39,7 +39,7 @@ extern "sysv64" fn efi_handover_entry(
fn efi_phase_boot(
handle: Handle,
system_table: SystemTable<Boot>,
boot_params: *mut BootParams,
boot_params_ptr: *mut BootParams,
) -> ! {
// Safety: this init function is only called once.
unsafe { crate::console::init() };
@ -50,7 +50,7 @@ fn efi_phase_boot(
uefi_services::println!("[EFI stub] Relocations applied.");
uefi_services::println!("[EFI stub] Loading payload.");
let payload = unsafe { crate::get_payload(&*boot_params) };
let payload = unsafe { crate::get_payload(&*boot_params_ptr) };
crate::loader::load_elf(payload);
uefi_services::println!("[EFI stub] Exiting EFI boot services.");
@ -63,7 +63,7 @@ fn efi_phase_boot(
};
let (system_table, memory_map) = system_table.exit_boot_services(memory_type);
efi_phase_runtime(system_table, memory_map, boot_params);
efi_phase_runtime(system_table, memory_map, boot_params_ptr);
}
fn efi_phase_runtime(
@ -75,36 +75,10 @@ fn efi_phase_runtime(
crate::console::print_str("[EFI stub] Entered runtime services.\n");
}
let boot_params = unsafe { &mut *boot_params_ptr };
// Write memory map to e820 table in boot_params.
let e820_table = &mut boot_params.e820_table;
let mut e820_entries = 0;
for md in memory_map.entries() {
if e820_entries >= e820_table.len() || e820_entries >= 128 {
break;
}
e820_table[e820_entries] = linux_boot_params::BootE820Entry {
addr: md.phys_start as u64,
size: md.page_count as u64 * 4096,
typ: match md.ty {
uefi::table::boot::MemoryType::CONVENTIONAL => linux_boot_params::E820Type::Ram,
uefi::table::boot::MemoryType::RESERVED => linux_boot_params::E820Type::Reserved,
uefi::table::boot::MemoryType::ACPI_RECLAIM => linux_boot_params::E820Type::Acpi,
uefi::table::boot::MemoryType::ACPI_NON_VOLATILE => {
linux_boot_params::E820Type::Nvs
}
_ => linux_boot_params::E820Type::Reserved,
},
};
e820_entries += 1;
}
boot_params.e820_entries = e820_entries as u8;
#[cfg(feature = "debug_print")]
unsafe {
use crate::console::{print_hex, print_str};
print_str("[EFI stub debug] Memory map:\n");
print_str("[EFI stub debug] EFI Memory map:\n");
for md in memory_map.entries() {
// crate::println!(" [{:#x}] {:#x} ({:#x})", md.ty.0, md.phys_start, md.page_count);
print_str(" [");
@ -120,6 +94,32 @@ fn efi_phase_runtime(
}
}
let boot_params = unsafe { &mut *boot_params_ptr };
// Write memory map to e820 table in boot_params.
let e820_table = &mut boot_params.e820_table;
let mut e820_entries = 0usize;
for md in memory_map.entries() {
if e820_entries >= e820_table.len() || e820_entries >= 128 {
break;
}
e820_table[e820_entries] = linux_boot_params::BootE820Entry {
addr: md.phys_start as u64,
size: md.page_count as u64 * 4096,
typ: match md.ty {
uefi::table::boot::MemoryType::CONVENTIONAL => linux_boot_params::E820Type::Ram,
uefi::table::boot::MemoryType::RESERVED => linux_boot_params::E820Type::Reserved,
uefi::table::boot::MemoryType::ACPI_RECLAIM => linux_boot_params::E820Type::Acpi,
uefi::table::boot::MemoryType::ACPI_NON_VOLATILE => {
linux_boot_params::E820Type::Nvs
}
_ => linux_boot_params::E820Type::Unusable,
},
};
e820_entries += 1;
}
boot_params.e820_entries = e820_entries as u8;
unsafe {
use crate::console::{print_hex, print_str};
print_str("[EFI stub] Entering Jinux entrypoint at ");

View File

@ -158,16 +158,37 @@ impl Credentials_ {
return Ok(());
}
if let Some(ruid) = ruid && *ruid != self.ruid() && *ruid != self.euid() && (!ruid_may_be_old_suid || *ruid != self.suid()) {
return_errno_with_message!(Errno::EPERM, "ruid can only be one of old ruid, old euid (and old suid).");
if let Some(ruid) = ruid
&& *ruid != self.ruid()
&& *ruid != self.euid()
&& (!ruid_may_be_old_suid || *ruid != self.suid())
{
return_errno_with_message!(
Errno::EPERM,
"ruid can only be one of old ruid, old euid (and old suid)."
);
}
if let Some(euid) = euid && *euid != self.ruid() && *euid != self.euid() && *euid != self.suid() {
return_errno_with_message!(Errno::EPERM, "euid can only be one of old ruid, old euid and old suid.")
if let Some(euid) = euid
&& *euid != self.ruid()
&& *euid != self.euid()
&& *euid != self.suid()
{
return_errno_with_message!(
Errno::EPERM,
"euid can only be one of old ruid, old euid and old suid."
)
}
if let Some(suid) = suid && *suid != self.ruid() && *suid != self.euid() && *suid != self.suid() {
return_errno_with_message!(Errno::EPERM, "suid can only be one of old ruid, old euid and old suid.")
if let Some(suid) = suid
&& *suid != self.ruid()
&& *suid != self.euid()
&& *suid != self.suid()
{
return_errno_with_message!(
Errno::EPERM,
"suid can only be one of old ruid, old euid and old suid."
)
}
Ok(())
@ -291,16 +312,37 @@ impl Credentials_ {
return Ok(());
}
if let Some(rgid) = rgid && *rgid != self.rgid() && *rgid != self.egid() && (!rgid_may_be_old_sgid || *rgid != self.sgid()) {
return_errno_with_message!(Errno::EPERM, "rgid can only be one of old rgid, old egid (and old sgid).");
if let Some(rgid) = rgid
&& *rgid != self.rgid()
&& *rgid != self.egid()
&& (!rgid_may_be_old_sgid || *rgid != self.sgid())
{
return_errno_with_message!(
Errno::EPERM,
"rgid can only be one of old rgid, old egid (and old sgid)."
);
}
if let Some(egid) = egid && *egid != self.rgid() && *egid != self.egid() && *egid != self.sgid() {
return_errno_with_message!(Errno::EPERM, "egid can only be one of old rgid, old egid and old sgid.")
if let Some(egid) = egid
&& *egid != self.rgid()
&& *egid != self.egid()
&& *egid != self.sgid()
{
return_errno_with_message!(
Errno::EPERM,
"egid can only be one of old rgid, old egid and old sgid."
)
}
if let Some(sgid) = sgid && *sgid != self.rgid() && *sgid != self.egid() && *sgid != self.sgid() {
return_errno_with_message!(Errno::EPERM, "sgid can only be one of old rgid, old egid and old sgid.")
if let Some(sgid) = sgid
&& *sgid != self.rgid()
&& *sgid != self.egid()
&& *sgid != self.sgid()
{
return_errno_with_message!(
Errno::EPERM,
"sgid can only be one of old rgid, old egid and old sgid."
)
}
Ok(())

View File

@ -101,12 +101,17 @@ impl PosixThread {
return Ok(());
}
if let Some(signum) = signum && *signum == SIGCONT {
if let Some(signum) = signum
&& *signum == SIGCONT
{
let receiver_sid = self.process().session().unwrap().sid();
if receiver_sid == sender.sid() {
return Ok(())
return Ok(());
} else {
return_errno_with_message!(Errno::EPERM, "sigcont requires that sender and receiver belongs to the same session");
return_errno_with_message!(
Errno::EPERM,
"sigcont requires that sender and receiver belongs to the same session"
);
}
}

View File

@ -14,7 +14,7 @@ pub mod signals;
pub use events::{SigEvents, SigEventsFilter};
pub use pauser::Pauser;
pub use poll::{Pollee, Poller};
pub use sig_stack::{SigStack, SigStackFlags, SigStackStatus};
pub use sig_stack::{SigStack, SigStackFlags};
use align_ext::AlignExt;
use aster_frame::cpu::UserContext;

View File

@ -49,7 +49,9 @@ fn set_new_stack(sig_stack_addr: Vaddr, old_stack: Option<&SigStack>) -> Result<
return Ok(());
}
if let Some(old_stack) = old_stack && old_stack.is_active() {
if let Some(old_stack) = old_stack
&& old_stack.is_active()
{
return_errno_with_message!(Errno::EPERM, "the old stack is active now");
}