Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create ACE protection policy #215

Open
5 tasks
francois141 opened this issue Sep 27, 2024 · 0 comments
Open
5 tasks

Create ACE protection policy #215

francois141 opened this issue Sep 27, 2024 · 0 comments
Labels
enhancement New feature or request Exploration main Main functionalities question Further information is requested

Comments

@francois141
Copy link
Collaborator

francois141 commented Sep 27, 2024

ACE Integration with Miralis

Link repository: https://github.com/IBM/ACE-RISCV

High level architecture

                                                                                 
  ┌───────────────────────────┐ | ┌───────────────────────┐ | ┌───────────────────────┐        
  │  Initialisation module    │ │ │ Non Confidential Flow │ │ │ Confidential Flow     │
  └───────────────────────────┘ | └───────────────────────┘ | └───────────────────────┘                 
 

Initialisation module

Boot process of ACE. Here is the boot process in a very high level overview, where the non relevant details get abstracted.

At some point OpenSBI jumps to to the function init_security_monitor_asm which will execute mutiple steps.

  • 1 Initialise the memory layout [splitting memory between confidention and non confidential world]
  • 2 Setup security monitor state [setup page & heap allocator]
  • 3 Allocate a stack for each hart

Confidential - non confidential flow

The codes aren't too complicated to understand and don't have a heavy logic. They implement all the features the security monitor requires.

How to switch from one to the other?

In the non_confidential control flow, we have this trap handler. We have a list of HsEcall we that can alter the state of the security monitor.

    #[no_mangle]
    unsafe extern "C" fn route_trap_from_hypervisor_or_vm(hart_ptr: *mut HardwareHart) -> ! {
        // `initialization` procedure for more details.
        let flow = unsafe { Self::create(hart_ptr.as_mut().expect(Self::CTX_SWITCH_ERROR_MSG)) };
        match TrapCause::from_hart_architectural_state(flow.hypervisor_hart().hypervisor_hart_state()) {
            //
            // Classics traps you would expect (illegal instruction,....)
            // 
            HsEcall(Base(ProbeExtension)) => ProbeSbiExtension::from_hypervisor_hart(flow.hypervisor_hart()).handle(flow),
            HsEcall(Covh(TsmGetInfo)) => GetSecurityMonitorInfo::from_hypervisor_hart(flow.hypervisor_hart()).handle(flow),
            HsEcall(Covh(PromoteToTvm)) => PromoteToConfidentialVm::from_hypervisor_hart(flow.hypervisor_hart()).handle(flow),
            HsEcall(Covh(TvmVcpuRun)) => RunConfidentialHart::from_hypervisor_hart(flow.hypervisor_hart()).handle(flow),
            HsEcall(Covh(DestroyTvm)) => DestroyConfidentialVm::from_hypervisor_hart(flow.hypervisor_hart()).handle(flow),
            HsEcall(Covh(_)) => InvalidCall::from_hypervisor_hart(flow.hypervisor_hart()).handle(flow),
            HsEcall(Nacl(ProbeFeature)) => NaclProbeFeature::from_hypervisor_hart(flow.hypervisor_hart()).handle(flow),
            HsEcall(Nacl(SetupSharedMemory)) => NaclSetupSharedMemory::from_hypervisor_hart(flow.hypervisor_hart()).handle(flow),
            HsEcall(Nacl(_)) => InvalidCall::from_hypervisor_hart(flow.hypervisor_hart()).handle(flow),
            HsEcall(_) => DelegateToOpensbi::from_hypervisor_hart(flow.hypervisor_hart()).handle(flow),
            MachineEcall => DelegateToOpensbi::from_hypervisor_hart(flow.hypervisor_hart()).handle(flow),
            trap_reason => panic!("Bug: Incorrect interrupt delegation configuration: {:?}", trap_reason),
        }
    }

In the confidential control flow, we have this trap handler, which catches all VsEcalls.

    unsafe extern "C" fn route_trap_from_confidential_hart(hardware_hart_pointer: *mut HardwareHart) -> ! {
        let flow = Self { hardware_hart: unsafe { hardware_hart_pointer.as_mut().expect(Self::CTX_SWITCH_ERROR_MSG) } };
        assert!(!flow.hardware_hart.confidential_hart().is_dummy());
        match TrapCause::from_hart_architectural_state(flow.confidential_hart().confidential_hart_state()) {
            Interrupt => HandleInterrupt::from_confidential_hart(flow.confidential_hart()).handle(flow),
            VsEcall(Base(GetSpecVersion)) => SbiGetSpecVersion::from_confidential_hart(flow.confidential_hart()).handle(flow),
            VsEcall(Base(GetImplId)) => SbiGetImplId::from_confidential_hart(flow.confidential_hart()).handle(flow),
            VsEcall(Base(GetImplVersion)) => SbiGetImplVersion::from_confidential_hart(flow.confidential_hart()).handle(flow),
            VsEcall(Base(ProbeExtension)) => SbiExtensionProbe::from_confidential_hart(flow.confidential_hart()).handle(flow),
            VsEcall(Base(GetMvendorId)) => SbiGetMvendorid::from_confidential_hart(flow.confidential_hart()).handle(flow),
            VsEcall(Base(GetMarchid)) => SbiGetMarchId::from_confidential_hart(flow.confidential_hart()).handle(flow),
            VsEcall(Base(GetMimpid)) => SbiGetMimpid::from_confidential_hart(flow.confidential_hart()).handle(flow),
            VsEcall(Ipi(SendIpi)) => Ipi::from_confidential_hart(flow.confidential_hart()).handle(flow),
            VsEcall(Rfence(RemoteFenceI)) => RemoteFenceI::from_confidential_hart(flow.confidential_hart()).handle(flow),
            VsEcall(Rfence(RemoteSfenceVma)) => RemoteSfenceVma::from_confidential_hart(flow.confidential_hart()).handle(flow),
            VsEcall(Rfence(RemoteSfenceVmaAsid)) => RemoteSfenceVmaAsid::from_confidential_hart(flow.confidential_hart()).handle(flow),
            VsEcall(Rfence(RemoteHfenceGvmaVmid)) => NoOperation::from_confidential_hart(flow.confidential_hart()).handle(flow),
            VsEcall(Rfence(RemoteHfenceGvma)) => NoOperation::from_confidential_hart(flow.confidential_hart()).handle(flow),
            VsEcall(Rfence(RemoteHfenceVvmaAsid)) => NoOperation::from_confidential_hart(flow.confidential_hart()).handle(flow),
            VsEcall(Rfence(RemoteHfenceVvma)) => NoOperation::from_confidential_hart(flow.confidential_hart()).handle(flow),
            VsEcall(Hsm(HartStart)) => SbiHsmHartStart::from_confidential_hart(flow.confidential_hart()).handle(flow),
            VsEcall(Hsm(HartStop)) => SbiHsmHartStop::from_confidential_hart(flow.confidential_hart()).handle(flow),
            VsEcall(Hsm(HartSuspend)) => SbiHsmHartSuspend::from_confidential_hart(flow.confidential_hart()).handle(flow),
            VsEcall(Hsm(HartGetStatus)) => SbiHsmHartStatus::from_confidential_hart(flow.confidential_hart()).handle(flow),
            VsEcall(Srst(SystemReset)) => ShutdownRequest::from_confidential_hart(flow.confidential_hart()).handle(flow),
            VsEcall(Covg(AddMmioRegion)) => AddMmioRegion::from_confidential_hart(flow.confidential_hart()).handle(flow),
            VsEcall(Covg(RemoveMmioRegion)) => RemoveMmioRegion::from_confidential_hart(flow.confidential_hart()).handle(flow),
            VsEcall(Covg(AllowExternalInterrupt)) => AllowExternalInterrupt::from_confidential_hart(flow.confidential_hart()).handle(flow),
            VsEcall(Covg(ShareMemory)) => SharePageRequest::from_confidential_hart(flow.confidential_hart()).handle(flow),
            VsEcall(Covg(UnshareMemory)) => UnsharePageRequest::from_confidential_hart(flow.confidential_hart()).handle(flow),
            VsEcall(_) => InvalidCall::from_confidential_hart(flow.confidential_hart()).handle(flow),
            GuestLoadPageFault => MmioLoadRequest::from_confidential_hart(flow.confidential_hart()).handle(flow),
            VirtualInstruction => VirtualInstruction::from_confidential_hart(flow.confidential_hart()).handle(flow),
            GuestStorePageFault => MmioStoreRequest::from_confidential_hart(flow.confidential_hart()).handle(flow),
            trap_reason => {
                debug!("Bug: Not supported trap cause {:?}, maybe due to incorrect exception delegation?", trap_reason);
                ShutdownRequest::from_confidential_hart(flow.confidential_hart()).handle(flow)
            }
        }
    }

Concrete integration with Miralis

The security monitor can be integrated with minimal changes. In the current implementation, the initialisation process after OpenSBI is booting. At some points it jumps to the init code and then go back to OpenSBI. Then the entire code depends only on two interrupts handlers .Ideally it looks like we should use the security monitor as a library for Miralis.

Init code

In src/main.rs, we can jump to their init code, execute it and then return to Miralis.

Confidential and non confidential interrupts

Most likely : Delegate from Miralis to ACE

We don't even need to modify the trap Handler route_trap_from_hypervisor_or_vm as the classics trap will be catched by Miralis. We might want to adapt a bit the interface between the two systems. In particular two points requires a more careful consideration.

  • Policy trait: This issue requires to extend a bit the trait with a initialisation function
  • Pmp register: We probably need to modify their module to fit the Miralis Use-case
  • Context switch: Can we use the Miralis context switch to perform their heavyweight context switch?
  • How to deal with the memory allocator? Do we need it? Can we use a slab allocator instead?
  • How to deal with multiple harts?
@francois141 francois141 added enhancement New feature or request question Further information is requested draft Issue needs to be finilized main Main functionalities Exploration labels Sep 27, 2024
@francois141 francois141 changed the title Integrate ACE with Miralis [Issue in progress] Integrate ACE with Miralis Sep 27, 2024
@francois141 francois141 changed the title Integrate ACE with Miralis Create ACE protection policy Sep 30, 2024
@francois141 francois141 removed the draft Issue needs to be finilized label Sep 30, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request Exploration main Main functionalities question Further information is requested
Projects
None yet
Development

No branches or pull requests

1 participant