[PATCH v2] Strict thread-stack isolation

Utkarsh Rai utkarsh.rai60 at gmail.com
Thu Jul 16 11:29:31 UTC 2020


Kindly ignore this patch. It breaks the build.

On Thu, Jul 16, 2020 at 4:54 PM Utkarsh Rai <utkarsh.rai60 at gmail.com> wrote:

> - This is the complete set of changes for strict isolation of thread
> stacks.
> - There needs to be a confiuration operation,(#if
> defined(USE_THREAD_STACK_PROTECTION) for simple configuration can be used)
> - The stack attributes are allocated through malloc, this needs to be done
> through score unlimited objects.
>
> Mechanism for thread-stack isolation
> - Whenever a stack is allocated we assign READ_WRITE  memory attributes to
> the memory region, the stack attribute structure is appended to a chain for
> tracking
> - On each context switch, the executing stack is marked as 'not-current'
> and we unset its memory attributes. The heir stack is marked as 'current'
> - On context restore we set the memory attributes of the heir stack and
> iterate thorugh the chain to check for any other 'current' stack and unset
> its memory
>   attribute (This requires some refinement, so that we don't have to
> iterate over the chain).
> ---
>  .../include/bsp/arm-cp15-set-ttb-entries.h    |   0
>  bsps/arm/xilinx-zynq/mmu/bsp-set-mmu-attr.c   |  79 ++++++++
>  bsps/shared/start/stackalloc.c                |  16 ++
>  c/src/lib/libbsp/arm/xilinx-zynq/Makefile.am  |   5 +-
>  cpukit/Makefile.am                            |   1 +
>  cpukit/headers.am                             |   2 +
>  cpukit/include/rtems/score/memorymanagement.h |  89 +++++++++
>  cpukit/include/rtems/score/stackprotection.h  | 149 ++++++++++++++
>  cpukit/score/cpu/arm/cpu.c                    |   4 +
>  cpukit/score/cpu/arm/cpu_asm.S                |  45 ++++-
>  .../score/cpu/arm/include/rtems/score/cpu.h   |  18 ++
>  cpukit/score/src/stackprotection.c            | 188 ++++++++++++++++++
>  12 files changed, 593 insertions(+), 3 deletions(-)
>  create mode 100644 bsps/arm/include/bsp/arm-cp15-set-ttb-entries.h
>  create mode 100644 bsps/arm/xilinx-zynq/mmu/bsp-set-mmu-attr.c
>  create mode 100644 cpukit/include/rtems/score/memorymanagement.h
>  create mode 100644 cpukit/include/rtems/score/stackprotection.h
>  create mode 100644 cpukit/score/src/stackprotection.c
>
> diff --git a/bsps/arm/include/bsp/arm-cp15-set-ttb-entries.h
> b/bsps/arm/include/bsp/arm-cp15-set-ttb-entries.h
> new file mode 100644
> index 0000000000..e69de29bb2
> diff --git a/bsps/arm/xilinx-zynq/mmu/bsp-set-mmu-attr.c
> b/bsps/arm/xilinx-zynq/mmu/bsp-set-mmu-attr.c
> new file mode 100644
> index 0000000000..0c82f113a9
> --- /dev/null
> +++ b/bsps/arm/xilinx-zynq/mmu/bsp-set-mmu-attr.c
> @@ -0,0 +1,79 @@
> +#include <bsp/arm-cp15-start.h>
> +#include <rtems/score/memorymanagement.h>
> +#include <libcpu/arm-cp15.h>
> +#include <rtems.h>
> +
> +#ifdef USE_THREAD_STACK_PROTECTION
> +  #define ARM_MMU_USE_SMALL_PAGES
> +#endif
> +
> +void Memorymanagement_Set_entries(uintptr_t begin, size_t size,
> Memorymanagement_flags flags)
> +{
> +
> +    uintptr_t end;
> +    rtems_interrupt_level irq_level;
> +    uint32_t access_flags;
> +
> +    end = begin + size;
> +    access_flags = Memorymanagement_Translate_flags(flags);
> +
> +    /**
> +     *  The ARM reference manual instructs to disable all the interrupts
> before
> +     * setting up page table entries.
> +    */
> +    rtems_interrupt_disable(irq_level);
> +    arm_cp15_set_translation_table_entries(begin, end, access_flags);
> +    rtems_interrupt_enable(irq_level);
> +}
> +
> +void Memorymanagement_Unset_entries(uintptr_t begin, size_t size)
> +{
> +  uint32_t access_flags;
> +  uintptr_t end;
> +  rtems_interrupt_level irq_level;
> +
> +  end = begin + size;
> +  access_flags = Memorymanagement_Translate_flags(NO_ACCESS);
> +
> +   /**
> +     *  The ARM reference manual instructs to disable all the interrupts
> before
> +     * setting up page table entries.
> +    */
> +  rtems_interrupt_disable(irq_level);
> +  arm_cp15_set_translation_table_entries(begin, end, access_flags);
> +  rtems_interrupt_enable(irq_level);
> +}
> +
> +
> +uint32_t Memorymanagement_Translate_flags(Memorymanagement_flags
> attr_flags)
> +{
> +  uint32_t flags;
> +  switch (attr_flags)
> +  {
> +  case READ_WRITE:
> +     flags = ARMV7_MMU_READ_WRITE;
> +  break;
> +
> +  case READ_WRITE_CACHED:
> +    flags = ARMV7_MMU_DATA_READ_WRITE_CACHED;
> +  break;
> +
> +  case READ_ONLY:
> +    flags = ARMV7_MMU_READ_ONLY;
> +  break;
> +
> +  case READ_ONLY_CACHED:
> +    flags = ARMV7_MMU_READ_ONLY_CACHED;
> +  break;
> +
> +  case NO_ACCESS:
> +    flags = 0;
> +  break;
> +
> +  default:
> +     return 0;
> +  break;
> +  }
> +
> +  return flags;
> +}
> \ No newline at end of file
> diff --git a/bsps/shared/start/stackalloc.c
> b/bsps/shared/start/stackalloc.c
> index f7cf7be0f1..ea8028c8db 100644
> --- a/bsps/shared/start/stackalloc.c
> +++ b/bsps/shared/start/stackalloc.c
> @@ -25,6 +25,7 @@
>  #include <rtems.h>
>  #include <rtems/score/heapimpl.h>
>  #include <rtems/score/wkspace.h>
> +#include <rtems/score/stackprotection.h>
>
>  #include <bsp/linker-symbols.h>
>
> @@ -43,6 +44,7 @@ void bsp_stack_allocate_init(size_t stack_space_size)
>  void *bsp_stack_allocate(size_t size)
>  {
>    void *stack = NULL;
> +  uintptr_t  page_table_base;
>
>    if (bsp_stack_heap.area_begin != 0) {
>      stack = _Heap_Allocate(&bsp_stack_heap, size);
> @@ -52,6 +54,20 @@ void *bsp_stack_allocate(size_t size)
>      stack = _Workspace_Allocate(size);
>    }
>
> +#ifdef USE_THREAD_STACK_PROTECTION
> +  /**
> +   *  Although we are not performing page table switching, still we
> assign a value
> +   * to avoid compiler warniing.
> +  */
> +  page_table_base = (uintptr_t)0x1000;
> +
> +  /**
> +   * The current way to get protected stack is to assign memory attributes
> +   *  to the allocated memory.
> +  */
> +  _Stackprotection_Allocate_attr( (uintptr_t)stack, size, page_table_base
> );
> +
> +#endif
>    return stack;
>  }
>
> diff --git a/c/src/lib/libbsp/arm/xilinx-zynq/Makefile.am
> b/c/src/lib/libbsp/arm/xilinx-zynq/Makefile.am
> index cfd59475c2..490f99792e 100644
> --- a/c/src/lib/libbsp/arm/xilinx-zynq/Makefile.am
> +++ b/c/src/lib/libbsp/arm/xilinx-zynq/Makefile.am
> @@ -74,6 +74,9 @@ librtemsbsp_a_SOURCES +=
> ../../../../../../bsps/arm/xilinx-zynq/i2c/cadence-i2c.
>  # Cache
>  librtemsbsp_a_SOURCES +=
> ../../../../../../bsps/arm/shared/cache/cache-l2c-310.c
>
> +#MMU
> +librtemsbsp_a_SOURCES +=
> ../../../../../../bsps/arm/xilinx-zynq/mmu/bsp-set-mmu-attr.c
> +
>  # Start hooks
>  librtemsbsp_a_SOURCES +=
> ../../../../../../bsps/arm/xilinx-zynq/start/bspstarthooks.c
>  librtemsbsp_a_SOURCES +=
> ../../../../../../bsps/arm/xilinx-zynq/start/bspstartmmu.c
> @@ -85,4 +88,4 @@ librtemsbsp_a_SOURCES +=
> ../../../../../../bsps/arm/xilinx-zynq/start/bspstartmm
>
>  include $(srcdir)/../../../../../../bsps/shared/irq-sources.am
>  include $(srcdir)/../../../../../../bsps/shared/shared-sources.am
> -include $(srcdir)/../../../../../../bsps/arm/xilinx-zynq/headers.am
> +include $(srcdir)/../../../../../../bsps/arm/xilinx-zynq/headers.am
> \ No newline at end of file
> diff --git a/cpukit/Makefile.am b/cpukit/Makefile.am
> index 51f38c84c7..83f9bfb3ef 100644
> --- a/cpukit/Makefile.am
> +++ b/cpukit/Makefile.am
> @@ -929,6 +929,7 @@ librtemscpu_a_SOURCES +=
> score/src/schedulercbsgetserverid.c
>  librtemscpu_a_SOURCES += score/src/schedulercbssetparameters.c
>  librtemscpu_a_SOURCES += score/src/schedulercbsreleasejob.c
>  librtemscpu_a_SOURCES += score/src/schedulercbsunblock.c
> +librtemscpu_a_SOURCES += score/src/stackprotection.c
>  librtemscpu_a_SOURCES += score/src/stackallocator.c
>  librtemscpu_a_SOURCES += score/src/pheapallocate.c
>  librtemscpu_a_SOURCES += score/src/pheapextend.c
> diff --git a/cpukit/headers.am b/cpukit/headers.am
> index fcf679f09d..2f16c71d9c 100644
> --- a/cpukit/headers.am
> +++ b/cpukit/headers.am
> @@ -352,6 +352,7 @@ include_rtems_score_HEADERS +=
> include/rtems/score/isr.h
>  include_rtems_score_HEADERS += include/rtems/score/isrlevel.h
>  include_rtems_score_HEADERS += include/rtems/score/isrlock.h
>  include_rtems_score_HEADERS += include/rtems/score/memory.h
> +include_rtems_score_HEADERS += include/rtems/score/memorymanagement.h
>  include_rtems_score_HEADERS += include/rtems/score/mpci.h
>  include_rtems_score_HEADERS += include/rtems/score/mpciimpl.h
>  include_rtems_score_HEADERS += include/rtems/score/mppkt.h
> @@ -405,6 +406,7 @@ include_rtems_score_HEADERS +=
> include/rtems/score/smplockstats.h
>  include_rtems_score_HEADERS += include/rtems/score/smplockticket.h
>  include_rtems_score_HEADERS += include/rtems/score/stack.h
>  include_rtems_score_HEADERS += include/rtems/score/stackimpl.h
> +include_rtems_score_HEADERS += include/rtems/score/stackprotection.h
>  include_rtems_score_HEADERS += include/rtems/score/states.h
>  include_rtems_score_HEADERS += include/rtems/score/statesimpl.h
>  include_rtems_score_HEADERS += include/rtems/score/status.h
> diff --git a/cpukit/include/rtems/score/memorymanagement.h
> b/cpukit/include/rtems/score/memorymanagement.h
> new file mode 100644
> index 0000000000..2a5490c680
> --- /dev/null
> +++ b/cpukit/include/rtems/score/memorymanagement.h
> @@ -0,0 +1,89 @@
> +/* SPDX-License-Identifier: BSD-2-Clause */
> +
> +/**
> + * @file
> + *
> + * @ingroup RTEMSScoreMemorymanagement
> + *
> + * @brief This file provodes APIs for high-level memory management
> + *
> + */
> +
> +/*
> + * Copyright (C) 2020 Utkarsh Rai
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> "AS IS"
> + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
> THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
> PURPOSE
> + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
> BE
> + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
> + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
> + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
> BUSINESS
> + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
> + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
> + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
> THE
> + * POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +#ifndef _RTEMS_SCORE_MEMORYMANAGEMENT_H
> +#define _RTEMS_SCORE_MEMORYMANAGEMENT_H
> +
> +#include <rtems/score/basedefs.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/** This defines the various high-level memory access flags.*/
> +typedef enum
> +{
> +    READ_WRITE,
> +    READ_WRITE_CACHED,
> +    READ_ONLY,
> +    READ_ONLY_CACHED,
> +    NO_ACCESS
> +} Memorymanagement_flags;
> +
> +/**
> + * @brief Define the memory access permission for the specified memory
> region
> + *
> + * @param begin_addr Begining of the memory region
> + * @param size Size of the memory region
> + * @param flag Memory access flag
> + *
> + */
> +void Memorymanagement_Set_entries(uintptr_t begin_addr, size_t size,
> Memorymanagement_flags flag);
> +
> +/**
> + * @brief Unset the memory access permission for the specified memory
> region
> + * This operation implcitly sets the specified memory region with
> 'NO_ACCESS'
> + * flag.
> + *
> + * @param begin_addr Begining of the memory region
> + * @param size Size of the memory region
> + */
> +void Memorymanagement_Unset_entries(uintptr_t begin_addr, size_t size);
> +
> +/**
> + * @brief Translate the high-level flags to BSP-specifc MMU flags.
> + *
> + * @param attr_flags High-level memory access flags.
> + *
> + * @retval flag BSP-specifc MMU flag
> + */
> +uint32_t Memorymanagement_Translate_flags(Memorymanagement_flags
> attr_flags);
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif
> \ No newline at end of file
> diff --git a/cpukit/include/rtems/score/stackprotection.h
> b/cpukit/include/rtems/score/stackprotection.h
> new file mode 100644
> index 0000000000..91e3f6daba
> --- /dev/null
> +++ b/cpukit/include/rtems/score/stackprotection.h
> @@ -0,0 +1,149 @@
> +/**
> + * @file
> + *
> + * @ingroup RTEMSScoreStackprotection
> + *
> + * @brief Stackprotection API
> + *
> + * This include file provides the API for the management of protected
> thread-
> + * stacks
> + */
> +
> +/*
> + *  COPYRIGHT (c) 2020 Utkarsh Rai.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + * notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + * notice, this list of conditions and the following disclaimer in the
> + * documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> "AS IS"
> + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
> THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
> PURPOSE
> + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
> BE
> + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
> + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
> + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
> BUSINESS
> + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
> IN
> + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
> OTHERWISE)
> + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
> THE
> + * POSSIBILITY OF SUCH DAMAGE.
> + *
> + */
> +
> +#ifndef _RTEMS_SCORE_STACKPROTECTION_H
> +#define _RTEMS_SCORE_STACKPROTECTION_H
> +
> +#if defined ( ASM )
> +#include <rtems/asm.h>
> +#else
> +  #include <rtems/score/basedefs.h>
> +  #include <rtems/score/memorymanagement.h>
> +  #include <rtems/score/chainimpl.h>
> +#endif
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +#if !defined ( ASM )
> +
> +/**
> + * The following defines the attributes of a protected stack
> + */
> +typedef struct
> +{
> +  /** This is the node to the chain for tracking each allocated/shared
> stack */
> +  Chain_Node    node;
> +  /** This is the stack address */
> +  uintptr_t        stack_address;
> +  /** This is the stack size */
> +  size_t        size;
> +  /** This is the pointer to the page table base */
> +  uintptr_t      page_table_base;
> +  /**Memory flag for the alllocated/shared stack */
> +  Memorymanagement_flags  access_flags;
> +} Stackprotection_Attr;
> +
> +/**
> + * The following defines the control block  of a shared stack
> + */
> +typedef struct
> +{
> +  /** This is the attribute of a shared stack*/
> +  Stackprotection_Attr    Base;
> +} Stackprotection_Shared_stack;
> +
> +/**
> + * The following defines the control block of an allocated stack
> + */
> +typedef struct
> +{
> +  /** This is the attribute of an allocated stack*/
> +  Stackprotection_Attr    Base;
> +  /** This is the pointer to the attributes of a stack shared with the
> stack
> +   * in question
> +   */
> +  Stackprotection_Shared_stack  *shared_stacks;
> +  /**This marks if the stack in question belongs to an executing thread*/
> +  bool          current_stack;
> +} Stackprotection_The_stack;
> +
> +/**
> + * @brief Allocate the attributes of the stack in question.
> + *
> + * @param freechain The stack address.
> + * @param size Size of the stack.
> + * @param page_table_base Pointer to the start of a page table
> + */
> +void _Stackprotection_Allocate_attr(uintptr_t stack_address, size_t size,
> uintptr_t page_table_base);
> +
> +/**
> + * @brief Share a stack with another stack.
> + *
> + * @param shared_stack The stack to be shared
> + * @param target_stack The stack with which to share
> + */
> +void _Stackprotection_Share_stack(Stackprotection_The_stack
> *shared_stack, Stackprotection_The_stack* target_stack);
> +
> +/**
> + * @brief Initialize the context of a thread with the control block of a
> + * protected stack
> + *
> + * @retval the_stack The protected stack
> + */
> +Stackprotection_The_stack *_Stackprotection_Context_initialize(void);
> +
> +/**
> + * @brief Swap out the executing protected stack from the page table
> during
> + * context switch
> + *
> + * The current method of switching the protected stack is to mark the
> switched
> + * out stack as 'NO ACCESS'
> + *
> + * @param excuting_stack Control block of the executing stack
> + */
> +void _Stackprotection_Context_switch(Stackprotection_The_stack
> *executing_stack, Stackprotection_The_stack *heir_stack);
> +
> +/**
> + * @brief Swap the restored protected stack  in the page table during
> context
> + * restoration
> + *
> + * We set the entries of the restored stack and mark all the remainig
> stacks as
> + * 'NO-ACCESS'.
> + *
> + * @param Control block of the restored stack
> + */
> +void _Stackprotection_Context_restore(Stackprotection_The_stack
> *restored_stack);
> +
> +#endif /* !defined ( ASM ) */
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif
> diff --git a/cpukit/score/cpu/arm/cpu.c b/cpukit/score/cpu/arm/cpu.c
> index 07b9588afd..cbb62d45e5 100644
> --- a/cpukit/score/cpu/arm/cpu.c
> +++ b/cpukit/score/cpu/arm/cpu.c
> @@ -28,6 +28,7 @@
>
>  #include <rtems/score/assert.h>
>  #include <rtems/score/cpu.h>
> +#include <rtems/score/stackprotection.h>
>  #include <rtems/score/thread.h>
>  #include <rtems/score/tls.h>
>
> @@ -97,6 +98,9 @@ void _CPU_Context_Initialize(
>  {
>    (void) new_level;
>
> + #if defined (USE_THREAD_STACK_PROTECTION)
> +  the_context->the_stack = _Stackprotection_Context_initialize();
> +  #endif
>    the_context->register_sp = (uint32_t) stack_area_begin +
> stack_area_size;
>    the_context->register_lr = (uint32_t) entry_point;
>    the_context->isr_dispatch_disable = 0;
> diff --git a/cpukit/score/cpu/arm/cpu_asm.S
> b/cpukit/score/cpu/arm/cpu_asm.S
> index 66f8ba6032..7473303f02 100644
> --- a/cpukit/score/cpu/arm/cpu_asm.S
> +++ b/cpukit/score/cpu/arm/cpu_asm.S
> @@ -36,7 +36,7 @@
>  #ifdef ARM_MULTILIB_ARCH_V4
>
>          .text
> -
> +
>  /*
>   *  void _CPU_Context_switch( run_context, heir_context )
>   *  void _CPU_Context_restore( run_context, heir_context )
> @@ -66,6 +66,27 @@ DEFINE_FUNCTION_ARM(_CPU_Context_switch)
>
>         str     r3, [r0, #ARM_CONTEXT_CONTROL_ISR_DISPATCH_DISABLE]
>
> +#if defined ( USE_THREAD_STACK_PROTECTION )
> +   /*
> +    * Save the registers modifed during function call
> +    */
> +    mov r8, r0
> +       mov r9, r1
> +       mov r10, r2
> +       /*
> +        * Load the parameters to be passed
> +        */
> +       ldr r0, [r0, #ARM_CONTEXT_CONTROL_STACK_ATTR_OFFSET]
> +       ldr r1, [r1, #ARM_CONTEXT_CONTROL_STACK_ATTR_OFFSET]
> +       bl  _Stackprotection_Context_switch
> +       /*
> +       * Restore the saved registers
> +       */
> +       mov r0, r8
> +       mov r1, r9
> +       mov r2, r10
> +#endif
> +
>  #ifdef RTEMS_SMP
>         /*
>          * The executing thread no longer executes on this processor.
> Switch
> @@ -132,7 +153,27 @@ DEFINE_FUNCTION_ARM(_CPU_Context_switch)
>   *
>   */
>  DEFINE_FUNCTION_ARM(_CPU_Context_restore)
> -        mov     r1, r0
> +
> +    mov     r1, r0
> +#if defined( USE_THREAD_STACK_PROTECTION )
> +   /*
> +    * Save the registers modifed during function call
> +    */
> +       mov r8, r0
> +       mov r9, r1
> +       mov r10, r2
> +       /*
> +        * Load the parameters to be passed
> +        */
> +       ldr     r0, [r0, #ARM_CONTEXT_CONTROL_STACK_ATTR_OFFSET]
> +       bl  _Stackprotection_Context_switch
> +       /*
> +       * Restore the saved registers
> +       */
> +       mov r0, r8
> +       mov r1, r9
> +       mov r2, r10
> +#endif
>         GET_SELF_CPU_CONTROL    r2
>          b       .L_restore
>
> diff --git a/cpukit/score/cpu/arm/include/rtems/score/cpu.h
> b/cpukit/score/cpu/arm/include/rtems/score/cpu.h
> index b7b48a3ac3..df13fed258 100644
> --- a/cpukit/score/cpu/arm/include/rtems/score/cpu.h
> +++ b/cpukit/score/cpu/arm/include/rtems/score/cpu.h
> @@ -34,6 +34,7 @@
>  #include <rtems/score/paravirt.h>
>  #endif
>  #include <rtems/score/arm.h>
> +#include <rtems/score/stackprotection.h>
>
>  /**
>   * @addtogroup RTEMSScoreCPUARM
> @@ -157,6 +158,21 @@
>
>  #ifdef ARM_MULTILIB_HAS_THREAD_ID_REGISTER
>    #define ARM_CONTEXT_CONTROL_THREAD_ID_OFFSET 44
> +  #ifdef ARM_MULITLIB_VFP
> +    #define ARM_STACK_PROT_ATTR_OFFSET   112
> +  #else
> +    #define ARM_STACK_PROT_ATTR_OFFSET  48
> +  #endif
> +#endif
> +
> +#ifdef USE_THREAD_STACK_PROTECTION
> +  #if defined ARM_MULITLIB_VFP
> +    #define ARM_CONTEXT_CONTROL_STACK_ATTR_OFFSET   112
> +  #elif ARM_MULTILIB_HAS_THREAD_ID_REGISTER
> +    #define ARM_CONTEXT_CONTROL_STACK_ATTR_OFFSET 48
> +  #else
> +    #define ARM_CONTEXT_CONTROL_STACK_ATTR_OFFSET 44
> +  #endif
>  #endif
>
>  #ifdef ARM_MULTILIB_VFP
> @@ -185,6 +201,7 @@
>
>  #define ARM_VFP_CONTEXT_SIZE 264
>
> +
>  #ifndef ASM
>
>  #ifdef __cplusplus
> @@ -235,6 +252,7 @@ typedef struct {
>  #ifdef RTEMS_SMP
>    volatile bool is_executing;
>  #endif
> +Stackprotection_The_stack *the_stack;
>  } Context_Control;
>
>  static inline void _ARM_Data_memory_barrier( void )
> diff --git a/cpukit/score/src/stackprotection.c
> b/cpukit/score/src/stackprotection.c
> new file mode 100644
> index 0000000000..20c5a17b0e
> --- /dev/null
> +++ b/cpukit/score/src/stackprotection.c
> @@ -0,0 +1,188 @@
> +/* SPDX-License-Identifier: BSD-2-Clause */
> +
> +/**
> + * @file
> + *
> + * @ingroup RTEMSScoreStackprotection
> + *
> + * @brief Short "Table of Contents" Description of File Contents
> + *
> + * A short description of the purpose of this file.
> + */
> +
> +/*
> + * Copyright (C) 2020 Utkarsh Rai
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> "AS IS"
> + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
> THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
> PURPOSE
> + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
> BE
> + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
> + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
> + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
> BUSINESS
> + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
> + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
> + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
> THE
> + * POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +
> +#ifdef HAVE_CONFIG_H
> +#include "config.h"
> +#endif
> +
> +#include <rtems/score/stackprotection.h>
> +
> +Chain_Control _Stackprotection_node_control =
> CHAIN_INITIALIZER_EMPTY(_Stackprotection_node_control);
> +
> +static void _Stackprotection_Remove_prev_entry(void)
> +{
> +
> + Chain_Node *node;
> + Stackprotection_The_stack *prot_stack;
> +
> +  if( _Chain_Is_empty(&_Stackprotection_node_control) == true ) {
> +      _Chain_Initialize_empty(&_Stackprotection_node_control);
> +  }
> +     node = _Chain_First( &_Stackprotection_node_control );
> +
> +     while(_Chain_Is_tail(&_Stackprotection_node_control, node) == false)
> {
> +
> +        prot_stack = RTEMS_CONTAINER_OF(node,Stackprotection_The_stack,
> Base.node);
> +
> +        if( prot_stack->current_stack == false ) {
> +
> Memorymanagement_Unset_entries(prot_stack->Base.stack_address,
> prot_stack->Base.size);
> +        }
> +        node =  _Chain_Immutable_next( node );
> +     }
> +
> +}
> +
> +/*
> +Iterate to the end of the chain and mark all the 'currnet' stack as false
> +Append the current stack attribute to the end of the chain
> +*/
> +static void _Stackprotection_Append_chain (Chain_Control *control,
> Stackprotection_The_stack *stack_append_attr)
> +{
> +    Chain_Node *node;
> +    Stackprotection_The_stack *present_stacks_attr;
> +
> +    if(_Chain_Is_empty(&_Stackprotection_node_control) == true ) {
> +
> +    _Chain_Initialize_one(&_Stackprotection_node_control,
> &stack_append_attr->Base.node);
> +    } else {
> +        _Chain_Append_unprotected(&_Stackprotection_node_control,
> &stack_append_attr->Base.node);
> +    }
> +}
> +
> +void _Stackprotection_Allocate_attr(uintptr_t  stack_address, size_t
> size, uintptr_t  page_table_base)
> +{
> +    Stackprotection_The_stack *prot_stack;
> +
> +/*This field will be refactored and score objects will be used for
> dynamic allocation*/
> +    prot_stack = malloc(sizeof(Stackprotection_The_stack));
> +
> +    if(prot_stack != NULL) {
> +    prot_stack->Base.stack_address = stack_address;
> +    prot_stack->Base.size = size;
> +    prot_stack->Base.page_table_base = page_table_base;
> +    prot_stack->Base.access_flags = READ_WRITE_CACHED;
> +    prot_stack->current_stack = true;
> +    }
> +
> +    /*
> +    Add the attribute field to the end of the chain, remove the memory
> entries of
> +    previously allocated stack and set the memory entry of the currnet
> stack.
> +    */
> +   _Stackprotection_Append_chain(&_Stackprotection_node_control,
> prot_stack );
> +    Memorymanagement_Set_entries(stack_address, size, READ_WRITE_CACHED);
> +
> +}
> +
> +Stackprotection_The_stack *_Stackprotection_Context_initialize(void)
> +{
> +    Chain_Node *node;
> +    Stackprotection_The_stack *prot_stack;
> +
> +    if(   _Chain_Is_empty(&_Stackprotection_node_control) == false ) {
> +        node = _Chain_First( &_Stackprotection_node_control );
> +
> +        while( _Chain_Is_tail(&_Stackprotection_node_control, node ) ==
> false) {
> +            prot_stack = RTEMS_CONTAINER_OF( node,
> Stackprotection_The_stack, Base.node);
> +
> +            if(prot_stack->current_stack == true) {
> +                return prot_stack;
> +            } else {
> +                node = _Chain_Immutable_next( node );
> +            }
> +        }
> +    }
> +
> +    return prot_stack;
> +}
> +
> +void _Stackprotection_Context_switch(Stackprotection_The_stack
> *executing_stack, Stackprotection_The_stack *heir_stack)
> +{
> +    void *stack_address;
> +    size_t  size;
> +    Chain_Node *node;
> +    Chain_Control *shared_node_control;
> +
> +     /*
> +      Remove the stacks shared with the current stack by iterating the
> chain
> +     */
> +    if( executing_stack != NULL) {
> +
> +    stack_address = executing_stack->Base.stack_address;
> +    size = executing_stack->Base.size;
> +
> +        if(executing_stack->current_stack == true) {
> +            executing_stack->current_stack = false;
> +            Memorymanagement_Unset_entries(stack_address, size);
> +        }
> +    }
> +
> +    _Stackprotection_Context_restore(heir_stack);
> +
> +}
> +
> +void _Stackprotection_Context_restore(Stackprotection_The_stack
> *heir_stack)
> +{
> +    void *stack_address;
> +    size_t  size;
> +    Chain_Node *node;
> +    Memorymanagement_flags flags;
> +    Chain_Control *shared_node_control;
> +    Stackprotection_The_stack *present_stacks_attr;
> +
> +    if(heir_stack != NULL) {
> +             heir_stack->current_stack = true;
> +             stack_address = heir_stack->Base.stack_address;
> +             size = heir_stack->Base.size;
> +             flags = heir_stack->Base.access_flags;
> +             Memorymanagement_Set_entries(stack_address, size, flags);
> +    }
> +
> +      node = _Chain_First(&_Stackprotection_node_control);
> +    /** Iterate through the chain and unset memory entries of all the
> +     *  previous thread-stacks
> +    */
> +    while(_Chain_Is_tail(&_Stackprotection_node_control,node) == false) {
> +
> +            present_stacks_attr = RTEMS_CONTAINER_OF(node,
> Stackprotection_The_stack, Base.node);
> +
> +            if(present_stacks_attr->current_stack == true &&
> present_stacks_attr != heir_stack)
> +            present_stacks_attr->current_stack = false;
> +
> Memorymanagement_Unset_entries(present_stacks_attr->Base.stack_address,
> present_stacks_attr->Base.size);
> +            node = _Chain_Immutable_next( node );
> +    }
> +}
> --
> 2.17.1
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.rtems.org/pipermail/devel/attachments/20200716/dee54333/attachment-0001.html>


More information about the devel mailing list