Re: SMC Calls in Trustzone VMM Scenario

2018-04-23 Thread Stefan Kalkowski
Hello Mauricio,

On Thu, Apr 19, 2018 at 01:09:36PM -0700, Mauricio Gutierrez wrote:
> Hello Stefan,
> 
> Thank you for your answer.
> 
> Ok, first I do not see how you can enforce the cache usage with
> > respect to the normal world. As long as the cache is enabled, how do
> > you confine memory access of the normal world when it's not asking
> > for permission (via your smc call)?
> > To me it looks like you want to close some covert channels by cache
> > data usage/displacement? In that case, maybe it is more reasonable to
> > circumvent usage of the cache by the secure world at all?
> >
> 
> It is not a side channel attack. The Cortex-A8 provides cache locking
> mechanisms for the benefit of
> real-time embedded systems. I am trying to prevent malicious users from
> exploiting these  to lock malicious
> code in the normal world cache (to avoid memory introspection from the
> Secure World) using TrustZone.
> Which is why I am working with your OS framework.

I see.

> 
> There is a designated kernel/core page-table that can be used to add
> > kernel mappings. Obviously, you are using some quite old Genode
> > version, so I'm not sure how to do that in your case. Nowadays, I
> > would add a designated static mapping to the core/kernel mappings in
> > the "bootstrap" code for the corresponding board, e.g.:
> >
> 
> As far as I know, I have a fairly recent version of Genode (17.08). But
> yes, now I am trying to
> map NONSECURE_RAM memory to the Secure World so that it can access both
> secure world and
> normal world memory such that in SW there are VA translations that map to
> PA's of NW.
> Would adding another region in
> repos/os/src/server/tz_vmm/spec/imx53/main.cc
> 
> create
> these
> mappings in SW ie:
> _m4if.set_region1(Trustzone::NON*SECURE_RAM_BASE*,
> Trustzone::NONSECURE_RAM_SIZE);

No, this region setting is about the TrustZone-affine Multi Master
Multi Memory Interface, which controls access to physical memory
dependent on the NS-bit. It has nothing to do with the MMU and cache,
but sits "behind" them.

> 
> Because attempting to have overlapping memory such as edditing
> repos/base-hw/src/bootstrap/spec/imx53_qsb/platform_trustzone.cc
> 
> early_ram_regions(Memory_region{Trustzone::*SECURE_RAM_BASE*,Trustzone::SECURE_RAM_SIZE
> + Trustzone::NONSECURE_RAM_SIZE})
> to have early ram region that encompass both secure and nonsecure is not
> allowed
> as far as I understand.

I did not wanted you to add something to the (early_)ram_regions.
Indeed, if you would do so the memory would be used by the secure
world concurrently. I advised you to add it as a region to the
core_mmio regions. In that case, a mapping is established, but no
other code implicitly uses that memory.
Anyway, I've overseen that core_mmio regions are mapped as uncached
memory anyway. So that is no good opportunity in your case.

Given your case, you might simply add a mapping within the bootstrap
process to a designated virtual memory address of core. You can add
an appropriated virtual address here: repos/base-hw/src/lib/hw/memory_map.h

The mapping can be add in the Platform constructor of bootstrap. Have
a look at existent code like: core_pd->map_insert(...). In doing so,
you should use the page_flags "PAGE_FLAGS_KERN_DATA".

> 
> However, once I do have these new virtual address translations, I am not
> sure how to get the VA from a given PA.
> VA -> PA I just use the ARM PAR register for translation, but the other way
> still eludes me.
> I know that linux provides virt_to_pys() and phys_to_virt() functions to
> convert between the two.
> In the Genode tz_vmm scenario, is there a phys_to_virt() (or equivalent
> function) I can use to get
> the virtual address that corresponds to a physical address? Or is there any
> way I could implement it?

We do not have a phys_to_virt translation function in our page-table
implementation. Although, it would be possible to add that complexity,
I do not see that you really need it. Given the physical memory
address the normal world OS likes to lock into the cache, you can
simply build the offset within the physical normal world memory and
add that offset to the virtual start address of the mapping within the
secure world kernel.

I hope that clarifies your question, best regards
Stefan

> 
> Thank you,
> 
> Mauricio
> 
> 
> On Wed, Apr 11, 2018 at 2:42 AM, Stefan Kalkowski <
> stefan.kalkow...@genode-labs.com> wrote:
> 
> > Hi Mauricio,
> >
> > thank you for sharing your intention.
> >
> > On Tue, Apr 10, 2018 at 10:51:15PM -0700, Mauricio Gutierrez wrote:
> > > Hello Stefan,
> > >
> > > Thank you for your reply.
> > >
> > > If you really need to execute code in monitor mode (I wonder why), I
> > > > think it 

Re: SMC Calls in Trustzone VMM Scenario

2018-04-19 Thread Mauricio Gutierrez
Hello Stefan,

Thank you for your answer.

Ok, first I do not see how you can enforce the cache usage with
> respect to the normal world. As long as the cache is enabled, how do
> you confine memory access of the normal world when it's not asking
> for permission (via your smc call)?
> To me it looks like you want to close some covert channels by cache
> data usage/displacement? In that case, maybe it is more reasonable to
> circumvent usage of the cache by the secure world at all?
>

It is not a side channel attack. The Cortex-A8 provides cache locking
mechanisms for the benefit of
real-time embedded systems. I am trying to prevent malicious users from
exploiting these  to lock malicious
code in the normal world cache (to avoid memory introspection from the
Secure World) using TrustZone.
Which is why I am working with your OS framework.

There is a designated kernel/core page-table that can be used to add
> kernel mappings. Obviously, you are using some quite old Genode
> version, so I'm not sure how to do that in your case. Nowadays, I
> would add a designated static mapping to the core/kernel mappings in
> the "bootstrap" code for the corresponding board, e.g.:
>

As far as I know, I have a fairly recent version of Genode (17.08). But
yes, now I am trying to
map NONSECURE_RAM memory to the Secure World so that it can access both
secure world and
normal world memory such that in SW there are VA translations that map to
PA's of NW.
Would adding another region in
repos/os/src/server/tz_vmm/spec/imx53/main.cc

create
these
mappings in SW ie:
_m4if.set_region1(Trustzone::NON*SECURE_RAM_BASE*,
Trustzone::NONSECURE_RAM_SIZE);

Because attempting to have overlapping memory such as edditing
repos/base-hw/src/bootstrap/spec/imx53_qsb/platform_trustzone.cc

early_ram_regions(Memory_region{Trustzone::*SECURE_RAM_BASE*,Trustzone::SECURE_RAM_SIZE
+ Trustzone::NONSECURE_RAM_SIZE})
to have early ram region that encompass both secure and nonsecure is not
allowed
as far as I understand.

However, once I do have these new virtual address translations, I am not
sure how to get the VA from a given PA.
VA -> PA I just use the ARM PAR register for translation, but the other way
still eludes me.
I know that linux provides virt_to_pys() and phys_to_virt() functions to
convert between the two.
In the Genode tz_vmm scenario, is there a phys_to_virt() (or equivalent
function) I can use to get
the virtual address that corresponds to a physical address? Or is there any
way I could implement it?

Thank you,

Mauricio


On Wed, Apr 11, 2018 at 2:42 AM, Stefan Kalkowski <
stefan.kalkow...@genode-labs.com> wrote:

> Hi Mauricio,
>
> thank you for sharing your intention.
>
> On Tue, Apr 10, 2018 at 10:51:15PM -0700, Mauricio Gutierrez wrote:
> > Hello Stefan,
> >
> > Thank you for your reply.
> >
> > If you really need to execute code in monitor mode (I wonder why), I
> > > think it will be best to create an explicit interface on the
> > > kernel/core level that can be called from the VMM component, maybe an
> > > extensions of the VM session interface.
> > >
> > > I think it somehow depends on what you are trying to do. If your
> > > routine has to be called every time a secure monitor call was
> > > executed, it is better to handle that directly within the
> > > Vm::exception function. If you have a very special device that needs
> > > to be accessed from secure, privileged/monitor mode you should extend
> the
> > > interface of kernel/core.
> > >
> >
> > Indeed this is what I ended up doing. I have added some exception
> handling
> > in the default case
> > of the Vm::exception function for my smc call (#4) before it switches
> over
> > to user-level privilege.
> >
> > Your are welcome. Maybe, you can give us some insights why do you need
> > > to enter monitor mode at all?
> > >
> >
> > I am trying to make it so that the secure world can lock some normal
> world
> > physical memory into the cache.
> > For security reasons, I do not want to allow the normal word to do it so
> I
> > make an smc into secure world
> > passing the virtual address to load into cache. The secure world then
> uses
> > the VA to PA registers to get the
> > physical address and load the memory into the cache. Of course, the only
> > way this would work would be for
> > the cache entry to be tagged with an NS bit = 1. In order to do this, I
> > need to enter monitor mode so that I can
> > change the NS bit to 1 while remaining is secure world. This way I
> perform
> > the cache loading and locking on
> > behalf of the normal world while being able to check for consistency. The
> > issue I am facing now is that I get a
> > cpu exception 3 (Breakpoint) when I try to write to the given 

Re: SMC Calls in Trustzone VMM Scenario

2018-04-11 Thread Stefan Kalkowski
Hi Mauricio,

thank you for sharing your intention.

On Tue, Apr 10, 2018 at 10:51:15PM -0700, Mauricio Gutierrez wrote:
> Hello Stefan,
> 
> Thank you for your reply.
> 
> If you really need to execute code in monitor mode (I wonder why), I
> > think it will be best to create an explicit interface on the
> > kernel/core level that can be called from the VMM component, maybe an
> > extensions of the VM session interface.
> >
> > I think it somehow depends on what you are trying to do. If your
> > routine has to be called every time a secure monitor call was
> > executed, it is better to handle that directly within the
> > Vm::exception function. If you have a very special device that needs
> > to be accessed from secure, privileged/monitor mode you should extend the
> > interface of kernel/core.
> >
> 
> Indeed this is what I ended up doing. I have added some exception handling
> in the default case
> of the Vm::exception function for my smc call (#4) before it switches over
> to user-level privilege.
> 
> Your are welcome. Maybe, you can give us some insights why do you need
> > to enter monitor mode at all?
> >
> 
> I am trying to make it so that the secure world can lock some normal world
> physical memory into the cache.
> For security reasons, I do not want to allow the normal word to do it so I
> make an smc into secure world
> passing the virtual address to load into cache. The secure world then uses
> the VA to PA registers to get the
> physical address and load the memory into the cache. Of course, the only
> way this would work would be for
> the cache entry to be tagged with an NS bit = 1. In order to do this, I
> need to enter monitor mode so that I can
> change the NS bit to 1 while remaining is secure world. This way I perform
> the cache loading and locking on
> behalf of the normal world while being able to check for consistency. The
> issue I am facing now is that I get a
> cpu exception 3 (Breakpoint) when I try to write to the given normal world
> memory from secure world,
> and I am not sure why.

Ok, first I do not see how you can enforce the cache usage with
respect to the normal world. As long as the cache is enabled, how do
you confine memory access of the normal world when it's not asking
for permission (via your smc call)?
To me it looks like you want to close some covert channels by cache
data usage/displacement? In that case, maybe it is more reasonable to
circumvent usage of the cache by the secure world at all?

Anyway, concerning your technical issue, I am not sure whether you
count the cpu exception from 0 or 1, but however it does not
correspond to a SMC or prefetch-abort exception. It is much more
probable that you receive a data-abort when writing to access that
memory. The first obvious reason is that you are using the wrong
virtual address to access the normal world physical memory you like to
access. Our kernel/core is not mapped one-by-one physical-to-virtual.
Moreover, the normal world memory is not mapped at all into Genode's
kernel.

> 
> Right now I am trying to access the physical address by temporarily
> disabling the mmu so PA = VA.

This should not work in recent versions of our kernel, because as I
wrote before the kernel binary is linked to a different virtual
address region than its physical memory representation. That means,
the kernel will fault immediately when disabling the MMU.

> However, another method would be to create/edit a page table entry in the
> secure world such that it
> maps to the specified physical address, essentially creating world shared
> memory. However, I am not
> sure how I would do this in Genode. For example, in the Normal World linux
> I could edit the paging global
> directory, but in the Genode OS how could I make a PTE map to a given
> physical address?

There is a designated kernel/core page-table that can be used to add
kernel mappings. Obviously, you are using some quite old Genode
version, so I'm not sure how to do that in your case. Nowadays, I
would add a designated static mapping to the core/kernel mappings in
the "bootstrap" code for the corresponding board, e.g.:

  
https://github.com/genodelabs/genode/blob/master/repos/base-hw/src/bootstrap/spec/imx53_qsb/platform_trustzone.cc#L38

as an example for the i.MX53 Quickstart board when used with
TrustZone. The "core_mmio" regions here are static mappings always
present in the kernel. When the normal world memory is to big, it
might not fit into the virtual "core_mmio" region. Have a look at this
file to check the kernel virtual memory regions:

  
https://github.com/genodelabs/genode/blob/master/repos/base-hw/src/lib/hw/spec/32bit/memory_map.cc

However, being in your position I would re-think the approach as a
whole, before digging further down the rabbit hole ;-).

Best regards
Stefan

> 
> Thank you,
> 
> Mauricio
> 
> 
> On Mon, Apr 9, 2018 at 2:36 AM, Stefan Kalkowski <
> stefan.kalkow...@genode-labs.com> wrote:
> 
> > Hi Mauricio,
> >
> > On Wed, Mar 28, 2018 

Re: SMC Calls in Trustzone VMM Scenario

2018-04-10 Thread Mauricio Gutierrez
Hello Stefan,

Thank you for your reply.

If you really need to execute code in monitor mode (I wonder why), I
> think it will be best to create an explicit interface on the
> kernel/core level that can be called from the VMM component, maybe an
> extensions of the VM session interface.
>
> I think it somehow depends on what you are trying to do. If your
> routine has to be called every time a secure monitor call was
> executed, it is better to handle that directly within the
> Vm::exception function. If you have a very special device that needs
> to be accessed from secure, privileged/monitor mode you should extend the
> interface of kernel/core.
>

Indeed this is what I ended up doing. I have added some exception handling
in the default case
of the Vm::exception function for my smc call (#4) before it switches over
to user-level privilege.

Your are welcome. Maybe, you can give us some insights why do you need
> to enter monitor mode at all?
>

I am trying to make it so that the secure world can lock some normal world
physical memory into the cache.
For security reasons, I do not want to allow the normal word to do it so I
make an smc into secure world
passing the virtual address to load into cache. The secure world then uses
the VA to PA registers to get the
physical address and load the memory into the cache. Of course, the only
way this would work would be for
the cache entry to be tagged with an NS bit = 1. In order to do this, I
need to enter monitor mode so that I can
change the NS bit to 1 while remaining is secure world. This way I perform
the cache loading and locking on
behalf of the normal world while being able to check for consistency. The
issue I am facing now is that I get a
cpu exception 3 (Breakpoint) when I try to write to the given normal world
memory from secure world,
and I am not sure why.

Right now I am trying to access the physical address by temporarily
disabling the mmu so PA = VA.
However, another method would be to create/edit a page table entry in the
secure world such that it
maps to the specified physical address, essentially creating world shared
memory. However, I am not
sure how I would do this in Genode. For example, in the Normal World linux
I could edit the paging global
directory, but in the Genode OS how could I make a PTE map to a given
physical address?

Thank you,

Mauricio


On Mon, Apr 9, 2018 at 2:36 AM, Stefan Kalkowski <
stefan.kalkow...@genode-labs.com> wrote:

> Hi Mauricio,
>
> On Wed, Mar 28, 2018 at 07:48:43PM -0700, Mauricio Gutierrez wrote:
> > Hello,
> >
> > I have been doing some work with the Genode Trustzone VMM scenario on my
> > i.MX53 development board and I am having a bit of trouble understanding
> how
> > the SMC calls work between the normal and secure world. Online you talk
> > about how you implemented 6 calls in the modified normal world linux
> kernel
> > but in the main for the tz_vmm I only found 4 different cases in the
> > _handle_smc() function. In any case, I wanted to add my own call and was
> > able to add it and check that the required arguments are passed correctly
> > and everything so that part I think I understand.
> >
> > However, I need to do some of the handling in Monitor Mode and my
> > understanding was that an SMC would throw your into monitor mode but it
> > seems the handler operates in user mode? Since it is not privileged then
> I
> > am not able to call a "cps #22" to switch to monitor mode.  In an earlier
> > thread I know you refer to the
> >
> > section "World switch between non-secure world and secure
> > > world" in http://genode.org/documentation/articles/trustzone.
> >
> > But I am still uncertain as to how I could get my case in _handle_smc()
> to
> > enter monitor mode so that I can play around with the NS bit without
> > leaving secure world.
>
> You are right, our virtual-machine monitor is an unprivileged
> user-level component. Because driving the normal world is not
> crucial to other components inside the secure world, there is no need
> to make them dependent on complex emulation/para-virtualization code inside
> the kernel. That is why the kernel contains a slim
> exception-vector-only functionality that is used to copy over the
> normal world state to the VMM user-level component. This
> exception-vector code is entered, e.g., when doing a "smc" call and
> can be found here:
>
>   repos/base-hw/src/core/spec/arm_v7/trustzone/exception_vector.s
>
> That assembly code is the only code executed in monitor mode. In the
> end it switches to secure world's supervisor mode and enters the
> normal kernel routine. However, it hits subsequently some C++ VMM
> kernel object routine here:
>
>   repos/base-hw/src/core/spec/arm_v7/trustzone/kernel/vm.cc
>
> Namely, the Vm::exception function, which informs the kernel scheduler
> to exclude the normal world for now, and signals the VMM user-level
> component that the normal world's state changed.
>
> > I have been studying what happens when I call an smc, 

Re: SMC Calls in Trustzone VMM Scenario

2018-04-09 Thread Stefan Kalkowski
Hi Mauricio,

On Wed, Mar 28, 2018 at 07:48:43PM -0700, Mauricio Gutierrez wrote:
> Hello,
> 
> I have been doing some work with the Genode Trustzone VMM scenario on my
> i.MX53 development board and I am having a bit of trouble understanding how
> the SMC calls work between the normal and secure world. Online you talk
> about how you implemented 6 calls in the modified normal world linux kernel
> but in the main for the tz_vmm I only found 4 different cases in the
> _handle_smc() function. In any case, I wanted to add my own call and was
> able to add it and check that the required arguments are passed correctly
> and everything so that part I think I understand.
> 
> However, I need to do some of the handling in Monitor Mode and my
> understanding was that an SMC would throw your into monitor mode but it
> seems the handler operates in user mode? Since it is not privileged then I
> am not able to call a "cps #22" to switch to monitor mode.  In an earlier
> thread I know you refer to the
> 
> section "World switch between non-secure world and secure
> > world" in http://genode.org/documentation/articles/trustzone.
> 
> But I am still uncertain as to how I could get my case in _handle_smc() to
> enter monitor mode so that I can play around with the NS bit without
> leaving secure world.

You are right, our virtual-machine monitor is an unprivileged
user-level component. Because driving the normal world is not
crucial to other components inside the secure world, there is no need
to make them dependent on complex emulation/para-virtualization code inside
the kernel. That is why the kernel contains a slim
exception-vector-only functionality that is used to copy over the
normal world state to the VMM user-level component. This
exception-vector code is entered, e.g., when doing a "smc" call and
can be found here:

  repos/base-hw/src/core/spec/arm_v7/trustzone/exception_vector.s

That assembly code is the only code executed in monitor mode. In the
end it switches to secure world's supervisor mode and enters the
normal kernel routine. However, it hits subsequently some C++ VMM
kernel object routine here:

  repos/base-hw/src/core/spec/arm_v7/trustzone/kernel/vm.cc

Namely, the Vm::exception function, which informs the kernel scheduler
to exclude the normal world for now, and signals the VMM user-level
component that the normal world's state changed.

> I have been studying what happens when I call an smc, say "smc #4" from
> normal world. But I have not been able to exactly pin point, where is the
> entry point for such an exception in the Genode secure world call? What
> exactly happens once I make that call to secure world and where I can I
> find/follow the code? Is this covered somewhere in your book?
> 
> I know about the mode_transitions.s file as well as the exception_vector.s
> and vm.cc files in repos/base-hw/src/core/spec/arm_v7/trustzone, it seems
> this is the entry point? But where does it go after we call the
> nonsecure_to_secure transition?
> 
> Most importantly, I need to understand where is the code operating in
> monitor mode? Where does it end and where does it start? How can I tell? If
> I needed to write at least some part of my smc handler in monitor mode
> before it switches out, what is the best approach to doing that?
> 

If you really need to execute code in monitor mode (I wonder why), I
think it will be best to create an explicit interface on the
kernel/core level that can be called from the VMM component, maybe an
extensions of the VM session interface.

I think it somehow depends on what you are trying to do. If your
routine has to be called every time a secure monitor call was
executed, it is better to handle that directly within the
Vm::exception function. If you have a very special device that needs
to be accessed from secure, privileged/monitor mode you should extend the
interface of kernel/core.

> I apologize for all the questions and would appreciate any help and
> guidance you can provide.

Your are welcome. Maybe, you can give us some insights why do you need
to enter monitor mode at all?

Best regards
Stefan

> 
> Thank you,
> 
> Mauricio

> --
> Check out the vibrant tech community on one of the world's most
> engaging tech sites, Slashdot.org! http://sdm.link/slashdot

> ___
> genode-main mailing list
> genode-main@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/genode-main


-- 
Stefan Kalkowski
Genode labs

https://github.com.skalk | https://genode.org

--
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
___
genode-main mailing list
genode-main@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/genode-main