On Fri, Aug 14, 2020 at 9:25 AM Utkarsh Rai <utkarsh.ra...@gmail.com> wrote:
>
> Sorry for the late reply, I somehow missed the mail notification!
>
> On Thu, Aug 13, 2020 at 9:35 PM Gedare Bloom <ged...@rtems.org> wrote:
>>
>> On Thu, Aug 13, 2020 at 9:06 AM Utkarsh Rai <utkarsh.ra...@gmail.com> wrote:
>> >
>> > -This patch provides thread-stack isolation and thread-stack sharing
>> >  mechanism for a POSIX thread.
>> >
>> Monster patch! think to yourself whether or not it makes sense to
>> split these up. The main constraint is that every patch in the series
>> should compile/run as they are applied.
>
>
> Maybe I can break this up into 3 separate patches, stack-isolation, 
> stack-sharing, and the configuration option?
>
>>
>> > -The patches are based on sebastian's build-2 branch of sebastian's repo 
>> > https://git.rtems.org/sebh
>> >
>> > -Configurations options are provided by using the new-build system. Refer 
>> > to https://ftp.rtems.org/pub/rtems/people/sebh/user.pdf,
>> >  chapter 7,for basic setup and 
>> > https://ftp.rtems.org/pub/rtems/people/sebh/eng.pdf(chapter 9) for the 
>> > internals of the build system.
>> > ---
>> >  .../realview-pbx-a9/mmu/bsp-set-mmu-attr.c    |  75 ++++++++++
>> >  bsps/shared/start/stackalloc.c                |  12 +-
>> >  .../libbsp/arm/realview-pbx-a9/Makefile.am    |   3 +
>> >  cpukit/Makefile.am                            |   1 +
>> >  cpukit/headers.am                             |   2 +
>> >  cpukit/include/rtems/score/memoryprotection.h |  91 ++++++++++++
>> >  cpukit/include/rtems/score/stack.h            |  49 +++++++
>> >  cpukit/include/rtems/score/stackprotection.h  |  80 +++++++++++
>> >  cpukit/include/rtems/score/thread.h           |   1 +
>> >  cpukit/posix/src/mmap.c                       |  41 +++++-
>> >  cpukit/posix/src/shmwkspace.c                 |  46 +++++-
>> >  cpukit/score/cpu/arm/cpu_asm.S                |  94 ++++++++++++
>> >  cpukit/score/src/stackprotection.c            | 103 +++++++++++++
>> >  cpukit/score/src/threadhandler.c              |   6 +
>> >  cpukit/score/src/threadinitialize.c           |   9 ++
>> >  .../arm/realview-pbx-a9/bsprealviewpbxa9.yml  |   1 +
>> >  spec/build/cpukit/cpuopts.yml                 |   2 +
>> >  spec/build/cpukit/librtemscpu.yml             |   3 +
>> >  .../build/cpukit/optthreadstackprotection.yml |  16 +++
>> >  spec/build/testsuites/samples/grp.yml         |   4 +
>> >  .../samples/threadstackprotection.yml         |  19 +++
>> >  .../testsuites/samples/threadstacksharing.yml |  19 +++
>> >  testsuites/samples/Makefile.am                |  16 +++
>> >  testsuites/samples/configure.ac               |   2 +
>> >  .../samples/thread_stack_protection/init.c    | 112 +++++++++++++++
>> >  .../thread_stack_protection.doc               |   2 +
>> >  .../thread_stack_protection.scn               |  20 +++
>> >  .../samples/thread_stack_sharing/init.c       | 136 ++++++++++++++++++
>> >  28 files changed, 959 insertions(+), 6 deletions(-)
>> >  create mode 100644 bsps/arm/realview-pbx-a9/mmu/bsp-set-mmu-attr.c
>> >  create mode 100644 cpukit/include/rtems/score/memoryprotection.h
>> >  create mode 100644 cpukit/include/rtems/score/stackprotection.h
>> >  create mode 100644 cpukit/score/src/stackprotection.c
>> >  create mode 100644 spec/build/cpukit/optthreadstackprotection.yml
>> >  create mode 100644 spec/build/testsuites/samples/threadstackprotection.yml
>> >  create mode 100644 spec/build/testsuites/samples/threadstacksharing.yml
>> >  create mode 100644 testsuites/samples/thread_stack_protection/init.c
>> >  create mode 100644 
>> > testsuites/samples/thread_stack_protection/thread_stack_protection.doc
>> >  create mode 100644 
>> > testsuites/samples/thread_stack_protection/thread_stack_protection.scn
>> >  create mode 100644 testsuites/samples/thread_stack_sharing/init.c
>> >
>> > diff --git a/bsps/arm/realview-pbx-a9/mmu/bsp-set-mmu-attr.c 
>> > b/bsps/arm/realview-pbx-a9/mmu/bsp-set-mmu-attr.c
>> > new file mode 100644
>> > index 0000000000..c3b469dd2a
>> > --- /dev/null
>> > +++ b/bsps/arm/realview-pbx-a9/mmu/bsp-set-mmu-attr.c
>> > @@ -0,0 +1,75 @@
>> file header block?
>>
>> > +#include <bsp/arm-cp15-start.h>
>> > +#include <rtems/score/memoryprotection.h>
>> > +#include <libcpu/arm-cp15.h>
>> > +#include <rtems.h>
>> > +
>> > +static uint32_t translate_flags(uint32_t attr_flags)
>> > +{
>> > +  uint32_t flags;
>> > +  uint32_t memory_attribute;
>> > +
>> > +  switch (attr_flags)
>> > +  {
>> > +    case RTEMS_READ_WRITE:
>> > +     flags = ARMV7_MMU_READ_WRITE;
>> > +     break;
>> > +
>> > +    case RTEMS_READ_ONLY:
>> > +     flags = ARMV7_MMU_READ_ONLY;
>> > +     break;
>> > +
>> > +    case RTEMS_NO_ACCESS:
>> > +    default:
>> > +     flags = 0;
>> > +     break;
>> > +  }
>>
>> Does this switch statement work when the attr_flags have other fields
>> defined such as RTEMS_MEMORY_CACHED?
>>
>
> Yes, I missed that.
>
>>
>> When bit flags are not mutually exclusive it makes more sense to write as...
>>
>> if ( (attr_flags & RTEMS_READ_WRITE) == RTEMS_READ_WRITE) ) {
>>    ...
>> }
>> if ( ... ) {
>>   ...
>> }
>> Maybe it makes more sense to write your helper function this way?
>>
>> > +
>> > + /*
>> > +  * Check for memory-cache operation
>> > +  */
>> > +  if( attr_flags & RTEMS_MEMORY_CACHED ) {
>> > +    flags |= ARM_MMU_SECT_TEX_0 | ARM_MMU_SECT_C | ARM_MMU_SECT_B;
>> > +  }
>> > +
>> > +  return flags;
>> > +}
>> > +
>> > +void _Memory_protection_Set_entries(uintptr_t begin, size_t size, 
>> > uint32_t flags)
>> > +{
>> > +  uintptr_t end;
>> > +  rtems_interrupt_level irq_level;
>> > +  uint32_t access_flags;
>> > +
>> > +  if(begin != NULL ) {
>> whitespace: "if ( begin ..."
>>
>> If begin is invalid, the set_entries fails. Maybe you want to return
>> an error code?
>>
>> You might want to refactor a helper to validate the memory range. That
>> will make this easier to maintain and tighten the checks.
>
>
> We can only change the memory attributes of the workspace and heap region, so 
> we need to check the memory range for only these regions right?
>

For data protection that is probably true.

>>
>>
>> > +    end = begin + size;
>> > +    access_flags = 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 _Memory_protection_Unset_entries(uintptr_t begin, size_t size)
>> > +{
>> > +  uint32_t access_flags;
>> > +  uintptr_t end;
>> > +  rtems_interrupt_level irq_level;
>> > +
>> > +  if( begin != NULL ) {
>> > +    end = begin + size;
>> > +    access_flags = translate_flags( RTEMS_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);
>> > +  }
>> > +}
>> > \ No newline at end of file
>> > diff --git a/bsps/shared/start/stackalloc.c 
>> > b/bsps/shared/start/stackalloc.c
>> > index f7cf7be0f1..6ebef4d6e5 100644
>> > --- a/bsps/shared/start/stackalloc.c
>> > +++ b/bsps/shared/start/stackalloc.c
>> > @@ -44,6 +44,15 @@ void *bsp_stack_allocate(size_t size)
>> >  {
>> >    void *stack = NULL;
>> >
>> > +#if defined (RTEMS_THREAD_STACK_PROTECTION)
>> > +/*
>> > + * This is a temporary hack, we need to use _Heap_Allocate_aligned() but 
>> > the heap
>> > + * intialization for bsp_stack_heap fails as bsp_section_stack_size is 0. 
>> > See
>> typo: initialization
>>
>> > + * bsp_stack_allocate_init().
>>
>> This is an interesting problem. You may want to explore how to solve
>> this better.
>>
>> > + */
>> > +  posix_memalign(&stack, 4096 , size);
>> > +  _Memory_protection_Set_entries( stack, size, ( RTEMS_READ_ONLY | 
>> > RTEMS_MEMORY_CACHED ) );
>> > +#else
>> >    if (bsp_stack_heap.area_begin != 0) {
>> >      stack = _Heap_Allocate(&bsp_stack_heap, size);
>> >    }
>> > @@ -51,6 +60,7 @@ void *bsp_stack_allocate(size_t size)
>> >    if (stack == NULL) {
>> >      stack = _Workspace_Allocate(size);
>> >    }
>> > +#endif
>> >
>> >    return stack;
>> >  }
>> > @@ -62,4 +72,4 @@ void bsp_stack_free(void *stack)
>> >    if (!ok) {
>> >      _Workspace_Free(stack);
>> >    }
>> > -}
>> > +}
>> > \ No newline at end of file
>> spurious change. check the settings on your text editor. It seems to
>> be truncating the end of your files.
>>
>> > diff --git a/c/src/lib/libbsp/arm/realview-pbx-a9/Makefile.am 
>> > b/c/src/lib/libbsp/arm/realview-pbx-a9/Makefile.am
>> > index d5549275be..24847c7b91 100644
>> > --- a/c/src/lib/libbsp/arm/realview-pbx-a9/Makefile.am
>> > +++ b/c/src/lib/libbsp/arm/realview-pbx-a9/Makefile.am
>> > @@ -74,6 +74,9 @@ librtemsbsp_a_SOURCES += 
>> > ../../../../../../bsps/arm/shared/clock/clock-a9mpcore.
>> >  librtemsbsp_a_SOURCES += 
>> > ../../../../../../bsps/arm/shared/cache/cache-cp15.c
>> >  librtemsbsp_a_SOURCES += 
>> > ../../../../../../bsps/arm/shared/cache/cache-v7ar-disable-data.S
>> >
>> > +#MMU
>> > +librtemsbsp_a_SOURCES += 
>> > ../../../../../../bsps/arm/realview-pbx-a9/mmu/bsp-set-mmu-attr.c
>> > +
>> >  # Start hooks
>> >  librtemsbsp_a_SOURCES += 
>> > ../../../../../../bsps/arm/realview-pbx-a9/start/bspstarthooks.c
>> >
>> > diff --git a/cpukit/Makefile.am b/cpukit/Makefile.am
>> > index 75e119ea3c..2d50d0fdce 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 0bba9674cd..211e17ddf8 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/memoryprotection.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/memoryprotection.h 
>> > b/cpukit/include/rtems/score/memoryprotection.h
>> > new file mode 100644
>> > index 0000000000..245e50313c
>> > --- /dev/null
>> > +++ b/cpukit/include/rtems/score/memoryprotection.h
>> > @@ -0,0 +1,91 @@
>> > +/* SPDX-License-Identifier: BSD-2-Clause */
>> > +
>> > +/**
>> > + * @file
>> > + *
>> > + * @ingroup RTEMSScoreMemoryprotection
>> > + *
>> > + * @brief This file provodes APIs for high-level memory protection
>> typo
>>
>> > + *
>> remove extra blank line
>>
>> > + */
>> > +
>> > +/*
>> > + * 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_MEMORYPROTECTION_H
>> > +#define _RTEMS_SCORE_MEMORYPROTECTION_H
>> > +
>> > +#if defined ( ASM )
>> > +  #include <rtems/asm.h>
>> > +#else
>> > +  #include <rtems/score/basedefs.h>
>> > +#endif
>> > +
>> > +#ifdef __cplusplus
>> > +extern "C" {
>> > +#endif
>> > +
>> > +#if !defined ( ASM )
>> > +
>> > +#define RTEMS_NO_ACCESS 0x00
>> > +#define RTEMS_READ_ONLY 0x01
>> > +#define RTEMS_WRITE_ONLY 0x02
>> > +#define RTEMS_READ_WRITE ( RTEMS_READ_ONLY | RTEMS_WRITE_ONLY )
>> > +#define RTEMS_MEMORY_CACHED 0x04
>> > +
>> > +/**
>> > + * @brief Define the memory access permission for the specified memory 
>> > region
>> > + *
>> > + * @param begin_addr Beginning of the memory region
>> > + * @param size Size of the memory region
>> > + * @param flag Memory access flag
>> > + *
>> delete extra blank
>>
>> > + */
>> > +void _Memory_protection_Set_entries(
>> > +  uintptr_t begin_addr,
>> > +  size_t size,
>> > +  uint32_t flag
>> > +);
>> > +
>> > +/**
>> > + * @brief Unset the memory access permission for the specified memory 
>> > region
>> > + * This operation implicitly sets the specified memory region with 
>> > 'NO_ACCESS'
>> > + * flag.
>> > + *
>> > + * @param begin_addr Begining of the memory region
>> typo: Beginning
>>
>> > + * @param size Size of the memory region
>> > + */
>> > +void _Memory_protection_Unset_entries(
>> > +  uintptr_t begin_addr,
>> > +  size_t size
>> > +);
>> > +
>> > +#endif  /* !defined ( ASM ) */
>> > +
>> does this get included from ASM? if so, it is not actually doing anything...
>>
>> > +#ifdef __cplusplus
>> > +}
>> > +#endif
>> > +
>> > +#endif
>> > \ No newline at end of file
>> > diff --git a/cpukit/include/rtems/score/stack.h 
>> > b/cpukit/include/rtems/score/stack.h
>> > index df1df74867..d561bf61c1 100644
>> > --- a/cpukit/include/rtems/score/stack.h
>> > +++ b/cpukit/include/rtems/score/stack.h
>> > @@ -47,6 +47,47 @@ extern "C" {
>> >   */
>> >  #define STACK_MINIMUM_SIZE  CPU_STACK_MINIMUM_SIZE
>> >
>> > +/**
>> > + * The number of stacks that can be shared with a thread.
>> > + */
>> > +#define SHARED_STACK_NUMBER 8
>> > +
>> Magic number 8?
>
>
> Will it be ok to have the shared stack number equal to 
> CONFIGURE_MAXIMUM_POSIX_THREADS -1?
>

If it is a limit of the hardware, then it needs to come through from
the CPU macros (score/cpu) or as a BSP Option.

>>
>>
>> > +#if defined ( RTEMS_THREAD_STACK_PROTECTION )
>> > +/**
>> > + * The following defines the attributes of a protected stack
>> > + */
>> > +typedef struct
>> > +{
>> > +  /** The pointer to the page table base */
>> > +  uintptr_t      page_table_base;
>> PT is an attribute of a thread, not a stack. This is a little bit misplaced.
>>
>> > +  /**Memory flag for the alllocated/shared stack */
>> typo: allocated
>>
>> > +  uint32_t  access_flags;
>> > +} Stack_Protection_attr;
>> > +
>> > +
>> > +/**
>> > + * The following defines the control block  of a shared stack. Each stack 
>> > can have
>> > + * different sharing attributes.
>> > + */
>> > +typedef struct
>> > +{
>> > +  /** This is the attribute of a shared stack*/
>> > +  Stack_Protection_attr    Base;
>> > +  /** This is the stack address of the sharing thread*/
>> > +  void* shared_stack_area;
>> > +  /** Stack size of the sharing thread*/
>> > +  size_t shared_stack_size;
>> > +  /** This is the stack address of the target stack. Maybe this area is 
>> > not
>> > +   * needed but this helps in selecting the target thread during stack 
>> > sharing.
>> > +   */
>> > +  void* target_stack_area;
>> > + /** Error checking for valid target stack address. This is also used to
>> > +  * distinguish between a normal mmap operation and a stack sharing 
>> > operation.
>> > +  */
>> > +  bool stack_shared;
>> > +} Stack_Shared_attr;
>> > +#endif
>> > +
>> I thought you were planning to integrate this better with the existing
>> Stack_Control stuff?
>>
>> Do we really need a separate structure to track 'shared' stacks (as
>> opposed to 'non-shared' ones?)
>>
>
> This is because of the design of the stack sharing mechanism. I have 
> elaborated more on this below.
>
>>
>> >  /**
>> >   *  The following defines the control block used to manage each stack.
>> >   */
>> > @@ -55,6 +96,14 @@ typedef struct {
>> >    size_t      size;
>> >    /** This is the low memory address of stack. */
>> >    void       *area;
>> > +#if defined (RTEMS_THREAD_STACK_PROTECTION)
>> > +   /** The attribute of a protected stack */
>> > +  Stack_Protection_attr    Base;
>>
>> This 'Base' stuff should only be used when the structure sits at the
>> base, to implement some kind of inheritance/polymorphism.
>>
>> > +
>> > +  Stack_Shared_attr *shared_stacks[SHARED_STACK_NUMBER];
>> I'm not sure about this design choice.
>>
>
> Yes, I now realize that we cannot do it this way. But we do have to track the 
> shared stacks as discussed here,  and for setting memory attributes of any 
> shared stack we need three properties, base address, size of the stack, and 
> the memory flag for sharing which can be different from its 'intrinsic' 
> memory flag. The stack control structure already has the size and the base 
> address but a single thread stack can be shared with multiple threads with 
> different memory flags. This is an implementation challenge I have to look 
> out for.
>

I see. Maybe it can be a pointer to the Stack_Control, plus the flags?

>>
>> > +
>> > +  uint32_t shared_stacks_count;
>> > +#endif
>> >  }   Stack_Control;
>> >
>> >  /**
>> > diff --git a/cpukit/include/rtems/score/stackprotection.h 
>> > b/cpukit/include/rtems/score/stackprotection.h
>> > new file mode 100644
>> > index 0000000000..58ab5f8673
>> > --- /dev/null
>> > +++ b/cpukit/include/rtems/score/stackprotection.h
>> > @@ -0,0 +1,80 @@
>> > +/**
>> > + * @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
>> > +
>> > +#include <rtems/score/basedefs.h>
>> > +#include <rtems/score/stack.h>
>> > +#include <rtems/score/memoryprotection.h>
>> > +
>> > +#ifdef __cplusplus
>> > +extern "C" {
>> > +#endif
>> > +
>> > +/**
>> > + * @brief Share the stack address of a given thread with the target 
>> > thread.
>> > + *
>> > + * @param target_stack Stack address of the target thread
>> > + * @param sharing_stack Stack address of the sharin thread
>> > + */
>> > +
>> > +int _Stackprotection_Share_stack(
>> _Stack_protection_
>>
>> > +  void *target_stack,
>> > +  void *sharing_stack,
>> > +  size_t size,
>> > +  uint32_t memory_flag
>> > +);
>> > +
>> > +/**
>> > + * @brief Swap the restored shared stacks  in the page table during 
>> > context
>> > + * restoration
>> > + *
>> > + * We set the entries of the restored stack and mark all the remainig 
>> > stacks as
>> typo: remaining
>>
>> > + * 'NO-ACCESS'.
>> > + *
>> > + * @param Control block of the restored stack
>> > + */
>> > +void _Stackprotection_Context_restore(
>> > +  Stack_Control *heir_stack
>> > +);
>> > +
>> > +#ifdef __cplusplus
>> > +}
>> > +#endif
>> > +
>> > +#endif
>> > \ No newline at end of file
>> > diff --git a/cpukit/include/rtems/score/thread.h 
>> > b/cpukit/include/rtems/score/thread.h
>> > index ee0aee5b79..0ad22feac4 100644
>> > --- a/cpukit/include/rtems/score/thread.h
>> > +++ b/cpukit/include/rtems/score/thread.h
>> > @@ -34,6 +34,7 @@
>> >  #include <rtems/score/priority.h>
>> >  #include <rtems/score/schedulernode.h>
>> >  #include <rtems/score/stack.h>
>> > +#include <rtems/score/stackprotection.h>
>> >  #include <rtems/score/states.h>
>> >  #include <rtems/score/threadq.h>
>> >  #include <rtems/score/timestamp.h>
>> > diff --git a/cpukit/posix/src/mmap.c b/cpukit/posix/src/mmap.c
>> > index 176c6e4fe8..6587819c0f 100644
>> > --- a/cpukit/posix/src/mmap.c
>> > +++ b/cpukit/posix/src/mmap.c
>> > @@ -28,7 +28,27 @@
>> >
>> >  #include <rtems/posix/mmanimpl.h>
>> >  #include <rtems/posix/shmimpl.h>
>> > +#include <rtems/score/stackprotection.h>
>> > +#include <rtems/score/memoryprotection.h>
>> >
>> > +static uint32_t mmap_flag_translate(int prot)
>> > +{
>> > +  int prot_read;
>> > +  int prot_write;
>> > +  int memory_flag;
>> > +
>> > +  prot_read = (prot_read & PROT_READ) == PROT_READ;
>> > +  prot_write = (prot_write & PROT_WRITE) == PROT_WRITE;
>> > +
>> > +  if(prot_read){
>> whitespace
>>
>> > +    memory_flag |= ( RTEMS_READ_ONLY| RTEMS_MEMORY_CACHED );
>> > +  }
>> > +  if(prot_write) {
>> ws
>>
>> > +    memory_flag |= ( RTEMS_READ_WRITE | RTEMS_MEMORY_CACHED );
>> > +  }
>> > +
>> > +  return memory_flag;
>> > +}
>> >
>> >  /**
>> >   * mmap chain of mappings.
>> > @@ -50,6 +70,9 @@ void *mmap(
>> >    bool            map_private;
>> >    bool            is_shared_shm;
>> >    int             err;
>> > +  uint32_t memory_flags;
>> > +  uintptr_t shared_stack_address;
>> > +  int status;
>> >
>> >    map_fixed = (flags & MAP_FIXED) == MAP_FIXED;
>> >    map_anonymous = (flags & MAP_ANON) == MAP_ANON;
>> > @@ -67,7 +90,10 @@ void *mmap(
>> >
>> >    /*
>> >     * We can provide read, write and execute because the memory in RTEMS 
>> > does
>> > -   * not normally have protections but we cannot hide access to memory.
>> > +   * not normally have protections but we cannot hide access to memory. 
>> > For
>> > +   * thread-stack protection we can provide no-access option, but stacks 
>> > are
>> > +   * implicitly isolated and it makes no sense to specify no-access 
>> > option for
>> > +   * already isolated stacks.
>> >     */
>> >    if ( prot == PROT_NONE ) {
>> >      errno = ENOTSUP;
>> > @@ -292,11 +318,18 @@ void *mmap(
>> >        free( mapping );
>> >        return MAP_FAILED;
>> >      }
>> > +  /**
>> > +    * We share thread-stacks only when we have a shared memory object and 
>> > map
>> > +    * shared flag set
>> > +    */
>> > +    memory_flags = mmap_flag_translate( prot );
>> > +    status = _Stackprotection_Share_stack( mapping->addr, addr, 
>> > len,memory_flags );
>>
>> What if someone passes an addr that is not in stack?
>>
>> Fundamentally what is the difference between sharing stacks and
>> sharing some arbitrary 'pages'?
>>
>> > +  }
>> > +  if(status == RTEMS_INVALID_ADDRESS ) {
>> ws
>>
>> what leads to this status?
>
>
>
> The _Stackprotection_Share_stack() takes the address of the target 
> thread-stack and sharing thread-stack. Now we check all the thread stack 
> addresses against the passed
> thread stack address. If we match against a valid address it returns 
> RTEMS_SUCCESSFUL otherwise we return RTEMS_INVALID_ADDRESS. Although now when 
> I relook at
> the implementation there is a glaring mistake, simply adding the pointer of 
> the Shared_stack structure that has been initialized from a  thread stack 
> that we may not be able
> to access from a certain thread. I will have to change the implementation a 
> bit, again :(.
>

I'm confused why it is only tracking the mapping for an invalid
address. that seems backward. is it to avoid breaking mmap() on
non-stack objects? if so, it should be commented.

>>
>> > +    rtems_chain_append_unprotected( &mmap_mappings, &mapping->node );
>> >    }
>> > -
>> > -  rtems_chain_append_unprotected( &mmap_mappings, &mapping->node );
>> >
>> >    mmap_mappings_lock_release( );
>> >
>> >    return mapping->addr;
>> > -}
>> > +}
>> > \ No newline at end of file
>> > diff --git a/cpukit/posix/src/shmwkspace.c b/cpukit/posix/src/shmwkspace.c
>> > index 4fa4ec4771..e4e3c594d9 100644
>> > --- a/cpukit/posix/src/shmwkspace.c
>> > +++ b/cpukit/posix/src/shmwkspace.c
>> > @@ -16,6 +16,7 @@
>> >
>> >  #include <errno.h>
>> >  #include <string.h>
>> > +#include <rtems/posix/pthread.h>
>> >  #include <rtems/score/wkspace.h>
>> >  #include <rtems/posix/shmimpl.h>
>> >
>> > @@ -24,6 +25,49 @@ int _POSIX_Shm_Object_create_from_workspace(
>> >    size_t size
>> >  )
>> >  {
>> > +#if defined(RTEMS_THREAD_STACK_PROTECTION)
>> > +  POSIX_Shm_Control *shm;
>> > +  Objects_Id id;
>> > +  Objects_Name_or_id_lookup_errors err;
>> > +  Thread_Control *Control;
>> > +  ISR_lock_Context lock_context;
>> > +  char *name;
>> > +
>> > +  shm = RTEMS_CONTAINER_OF(shm_obj, POSIX_Shm_Control, shm_object);
>> > +  name = shm->Object.name.name_p;
>> > +  /** We assign fixed pattern of naming for thread-stacks, and treat them
>> > +   *  accordingly.
>> > +   */
>> > +  if( strncmp( name, "/taskfs/", 8) == 0 ) {
>> > +    /**
>> > +     * Obtain the object id of the thread and then get the thread control 
>> > block
>> > +     * corresponding to that id.
>> > +     */
>> > +    err = _Objects_Name_to_id_u32(
>> > +            &_POSIX_Threads_Information.Objects,
>> > +           _Objects_Build_name( name[8], name[9], name[10], name[11]),
>> > +            RTEMS_LOCAL,
>> > +            &id
>> > +            );
>> > +    Control = _Thread_Get( id, &lock_context );
>> > +     if( Control != NULL ) {
>> ws
>>
>> > +       shm_obj->handle = Control->Start.Initial_stack.area;
>> > +       if( size != Control->Start.Initial_stack.size) {
>> ws
>>
>> > +         return ENOMEM;
>> > +       }
>>
>> I'm not sure this is the right place for this logic. It's not really
>> creating from the workplace in case of the tasksfs name match? should
>> this be handled before calling this function?
>>
>> > +     } else {
>> > +       return ENOMEM;
>> > +     }
>> > +  } else {
>> > +    shm_obj->handle = _Workspace_Allocate( size );
>> > +    if ( shm_obj->handle == NULL ) {
>> > +      return ENOMEM;
>> > +  }
>> > +
>> > +  shm_obj->size = size;
>> > +  return 0;
>> > +}
>> > +#else
>> >    shm_obj->handle = _Workspace_Allocate( size );
>> >    if ( shm_obj->handle == NULL ) {
>> >      return ENOMEM;
>> > @@ -32,6 +76,7 @@ int _POSIX_Shm_Object_create_from_workspace(
>> >    memset( shm_obj->handle, 0, size );
>> >    shm_obj->size = size;
>> >    return 0;
>> > +#endif
>> >  }
>> >
>> >  int _POSIX_Shm_Object_delete_from_workspace( POSIX_Shm_Object *shm_obj )
>> > @@ -97,4 +142,3 @@ void * _POSIX_Shm_Object_mmap_from_workspace(
>> >
>> >    return (char*)shm_obj->handle + off;
>> >  }
>> > -
>> stray change
>>
>> > diff --git a/cpukit/score/cpu/arm/cpu_asm.S 
>> > b/cpukit/score/cpu/arm/cpu_asm.S
>> > index 66f8ba6032..8e9a4a9f88 100644
>> > --- a/cpukit/score/cpu/arm/cpu_asm.S
>> > +++ b/cpukit/score/cpu/arm/cpu_asm.S
>> > @@ -66,6 +66,73 @@ DEFINE_FUNCTION_ARM(_CPU_Context_switch)
>> >
>> >         str     r3, [r0, #ARM_CONTEXT_CONTROL_ISR_DISPATCH_DISABLE]
>> >
>> > +#if defined ( RTEMS_THREAD_STACK_PROTECTION )
>> > +
>> > +/*
>> > + * We make a function call to set the memory attributes of the heir
>> > + * stack and unset that of the executing stack (including shared stacks ).
>> > + * This will be a simple asm code when done by switching the translation
>> > + * table base.
>> > + */
>> > +
>> > +/* Save the registers modified during function call */
>> > +       mov r8, r0
>> > +       mov r9, r1
>> > +       mov r10, r2
>> > +/* Load the parameters for function call */
>> > +       mov r0, r1
>> > +       sub r0, r0, #76
>> > +       ldr r1, [r0]
>> > +       ldr r0, [r0, #4]
>> > +       mov r2, #3
>> > +       bl _Memory_protection_Set_entries
>> > +
>> > +/* Restore the saved registers  */
>> > +       mov r0, r8
>> > +       mov r1, r9
>> > +       mov r2, r10
>> > +
>> > +/* We load the stack-pointer of the heir thread pre-maturely, this is
>> > + * done as oherwise the *_unset_entries call will execute from the stack 
>> > of the
>> > + * executing thread causing fatal exceptions.
>> > + */
>> > +       ldr sp, [r1, #32]
>> > +/* Load the parameters of the function call */
>> > +       mov r1, r0
>> > +       sub r0, r0, #76
>> > +       ldr r1, [r0]
>> > +       ldr r0, [r0, #4]
>> > +       bl  _Memory_protection_Unset_entries
>> > +/*
>> > + * Restore the saved registers
>> > + */
>> > +       mov r0, r8
>> > +       mov r1, r9
>> > +       mov r2, r10
>> > +
>> > +/* Set the memory entries of the shared stack */
>> > +    sub        r0, r0, #76
>> > +       add r6, r0, #16
>> > +
>> > +.L_shared_stack_restore:
>> > +
>> > +       ldr r1, [r6, #8]
>> > +       ldr r0, [r6, #12]
>> > +       bl _Memory_protection_Unset_entries
>> > +       add  r6, #4
>> > +       add  r11, #1
>> > +/* We compare with a hard-coded value, this is the number of shared stacks
>> > + * (SHARED_STACK_NUMBER)
>> > + */
>> > +       cmp r11, #8
>> > +       bne .L_shared_stack_restore
>> > +
>> > +/* 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
>> > @@ -95,6 +162,7 @@ DEFINE_FUNCTION_ARM(_CPU_Context_switch)
>> >
>> >  /* Start restoring context */
>> >  .L_restore:
>> > +
>> >  #if !defined(RTEMS_SMP) && defined(ARM_MULTILIB_HAS_LOAD_STORE_EXCLUSIVE)
>> >         clrex
>> >  #endif
>> > @@ -133,7 +201,33 @@ DEFINE_FUNCTION_ARM(_CPU_Context_switch)
>> >   */
>> >  DEFINE_FUNCTION_ARM(_CPU_Context_restore)
>> >          mov     r1, r0
>> > +
>> >         GET_SELF_CPU_CONTROL    r2
>> > +
>> > +#if defined ( RTEMS_THREAD_STACK_PROTECTION )
>> > +
>> > +       /* Save the registers modified during function call */
>> > +       mov r8, r0
>> > +       mov r9, r1
>> > +       mov r10, r2
>> > +
>> > +       /* Load the parameters for function call */
>> > +       mov r1, r0
>> > +       sub r0, r0, #76
>> > +       ldr r1, [r0]
>> > +       ldr r0, [r0, #4]
>> > +       mov r2, #3
>> > +       bl _Memory_protection_Set_entries
>> > +
>> > +       /* Restore the saved registers   */
>> > +       mov r0, r8
>> > +       mov r1, r9
>> > +       mov r2, r10
>> > +
>> > +       /* Set memory entries of the shared thread stacks */
>> > +
>> > +
>> > +#endif
>> >          b       .L_restore
>> >
>> >  #ifdef RTEMS_SMP
>> > diff --git a/cpukit/score/src/stackprotection.c 
>> > b/cpukit/score/src/stackprotection.c
>> > new file mode 100644
>> > index 0000000000..8427046aa0
>> > --- /dev/null
>> > +++ b/cpukit/score/src/stackprotection.c
>> > @@ -0,0 +1,103 @@
>> > +/* SPDX-License-Identifier: BSD-2-Clause */
>> > +
>> > +/**
>> > + * @file
>> > + *
>> > + * @ingroup RTEMSScoreStackprotection
>> > + *
>> > + */
>> > +
>> > +/*
>> > + * 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>
>> > +#include <rtems/score/threadimpl.h>
>> > +
>> > +void _Stackprotection_Context_restore(
>> > +Stack_Control *heir_stack
>> > +)
>> > +{
>> > +  void* stack_address;
>> > +  size_t stack_size;
>> > +  uint32_t memory_flags;
>> > +  uint32_t index;
>> > +
>> > +  for(index = 0;index < heir_stack->shared_stacks_count; index++) {
>> > +    stack_address = heir_stack->shared_stacks[index]->shared_stack_area;
>> > +    stack_size = heir_stack->shared_stacks[index]->shared_stack_size;
>> > +    _Memory_protection_Set_entries( stack_address, stack_size, 
>> > memory_flags );
>> > +  }
>> > +
>> > +}
>> > +
>> > +static bool get_target_thread( Thread_Control *Control, void *arg)
>> > +{
>> > +  Stack_Shared_attr *shared_stack;
>> > +  uint32_t count;
>> > +  shared_stack = arg;
>> > +  /**
>> > +   * Check for the target thread by comparing the stack address. Add the 
>> > shared stack
>> > +   * attribute structure to the array tracking all the shared stacks.
>> > +   */
>> > +  if( Control->Start.Initial_stack.area == 
>> > shared_stack->target_stack_area) {
>> > +     count =  Control->Start.Initial_stack.shared_stacks_count + 1;
>> > +     if(count >= SHARED_STACK_NUMBER) {
>> > +       return false;
>> > +     }
>> > +     Control->Start.Initial_stack.shared_stacks_count = count;
>> > +     Control->Start.Initial_stack.shared_stacks[count] = shared_stack;
>> > +     shared_stack->stack_shared = true;
>> > +
>> > +     return true;
>> > +  }
>> > +}
>> > +
>> > +int _Stackprotection_Share_stack(
>> > +  void* target_stack,
>> > +  void* sharing_stack,
>> > +  size_t size,
>> > +  uint32_t memory_flag
>> > +)
>> > +{
>> > + Thread_Control *target_thread;
>> > + Stack_Shared_attr shared_stack;
>> > +
>> > + shared_stack.Base.access_flags= memory_flag;
>> > + shared_stack.shared_stack_area = sharing_stack;
>> > + shared_stack.target_stack_area = target_stack;
>> > + shared_stack.shared_stack_size = size;
>> > +
>> > + _Thread_Iterate( get_target_thread, &shared_stack );
>> > + if( shared_stack.stack_shared == true ) {
>> > +   return 0;
>> > + } else {
>> > +   return -1;
>> > + }
>> > +}
>> > \ No newline at end of file
>> > diff --git a/cpukit/score/src/threadhandler.c 
>> > b/cpukit/score/src/threadhandler.c
>> > index 6742b0b391..c18e33f688 100644
>> > --- a/cpukit/score/src/threadhandler.c
>> > +++ b/cpukit/score/src/threadhandler.c
>> > @@ -22,6 +22,7 @@
>> >  #include <rtems/score/assert.h>
>> >  #include <rtems/score/interr.h>
>> >  #include <rtems/score/isrlevel.h>
>> > +#include <rtems/score/stackprotection.h>
>> >  #include <rtems/score/userextimpl.h>
>> >
>> >  /*
>> > @@ -94,6 +95,11 @@ void _Thread_Handler( void )
>> >    level = executing->Start.isr_level;
>> >    _ISR_Set_level( level );
>> >
>> > +  /*
>> > +   * Switch-out the the shared thread-stacks
>> delete the
>>
>> > +   */
>> > +  _Stackprotection_Context_restore( &executing->Start.Initial_stack );
>> > +
>> >    /*
>> >     * Initialize the floating point context because we do not come
>> >     * through _Thread_Dispatch on our first invocation. So the normal
>> > diff --git a/cpukit/score/src/threadinitialize.c 
>> > b/cpukit/score/src/threadinitialize.c
>> > index 691f56388e..96db4193bc 100644
>> > --- a/cpukit/score/src/threadinitialize.c
>> > +++ b/cpukit/score/src/threadinitialize.c
>> > @@ -114,6 +114,15 @@ bool _Thread_Initialize(
>> >       stack_size
>> >    );
>> >
>> > +#if defined ( RTEMS_THREAD_STACK_PROTECTION )
>> > +  /**
>> > +   * Initialize the protected stack attributes. Initially we initialize 
>> > the
>> > +   * thread with no access attributes, on context switch/restore action 
>> > the
>> > +   * thread stacks are assigned READ/WRITE attribute.
>> > +   */
>> > +   the_thread->Start.Initial_stack.Base.access_flags = RTEMS_NO_ACCESS | 
>> > RTEMS_MEMORY_CACHED;
>> > +#endif
>> > +
>> >    /*
>> >     *  Get thread queue heads
>> >     */
>> > diff --git a/spec/build/bsps/arm/realview-pbx-a9/bsprealviewpbxa9.yml 
>> > b/spec/build/bsps/arm/realview-pbx-a9/bsprealviewpbxa9.yml
>> > index 2721152b93..f7d2187c66 100644
>> > --- a/spec/build/bsps/arm/realview-pbx-a9/bsprealviewpbxa9.yml
>> > +++ b/spec/build/bsps/arm/realview-pbx-a9/bsprealviewpbxa9.yml
>> > @@ -57,6 +57,7 @@ links:
>> >  source:
>> >  - bsps/arm/realview-pbx-a9/console/console-config.c
>> >  - bsps/arm/realview-pbx-a9/console/console-polled.c
>> > +- bsps/arm/realview-pbx-a9/mmu/bsp-set-mmu-attr.c
>> >  - bsps/arm/realview-pbx-a9/start/bspreset.c
>> >  - bsps/arm/realview-pbx-a9/start/bspstart.c
>> >  - bsps/arm/realview-pbx-a9/start/bspstarthooks.c
>> > diff --git a/spec/build/cpukit/cpuopts.yml b/spec/build/cpukit/cpuopts.yml
>> > index 1902e543ca..f7641a5e50 100644
>> > --- a/spec/build/cpukit/cpuopts.yml
>> > +++ b/spec/build/cpukit/cpuopts.yml
>> > @@ -63,6 +63,8 @@ links:
>> >    uid: optszoff
>> >  - role: build-dependency
>> >    uid: optsztime
>> > +- role: build-dependency
>> > +  uid: optthreadstackprotection
>> >  - role: build-dependency
>> >    uid: optversion
>> >  target: cpukit/include/rtems/score/cpuopts.h
>> > diff --git a/spec/build/cpukit/librtemscpu.yml 
>> > b/spec/build/cpukit/librtemscpu.yml
>> > index 63a0b7dca5..9855401665 100644
>> > --- a/spec/build/cpukit/librtemscpu.yml
>> > +++ b/spec/build/cpukit/librtemscpu.yml
>> > @@ -353,6 +353,7 @@ install:
>> >    - cpukit/include/rtems/score/isrlevel.h
>> >    - cpukit/include/rtems/score/isrlock.h
>> >    - cpukit/include/rtems/score/memory.h
>> > +  - cpukit/include/rtems/score/memoryprotection.h
>> >    - cpukit/include/rtems/score/mpci.h
>> >    - cpukit/include/rtems/score/mpciimpl.h
>> >    - cpukit/include/rtems/score/mppkt.h
>> > @@ -405,6 +406,7 @@ install:
>> >    - cpukit/include/rtems/score/smplockstats.h
>> >    - cpukit/include/rtems/score/smplockticket.h
>> >    - cpukit/include/rtems/score/stack.h
>> > +  - cpukit/include/rtems/score/stackprotection.h
>> >    - cpukit/include/rtems/score/stackimpl.h
>> >    - cpukit/include/rtems/score/states.h
>> >    - cpukit/include/rtems/score/statesimpl.h
>> > @@ -1509,6 +1511,7 @@ source:
>> >  - cpukit/score/src/semaphore.c
>> >  - cpukit/score/src/smpbarrierwait.c
>> >  - cpukit/score/src/stackallocator.c
>> > +- cpukit/score/src/stackprotection.c
>> >  - cpukit/score/src/threadallocateunlimited.c
>> >  - cpukit/score/src/thread.c
>> >  - cpukit/score/src/threadchangepriority.c
>> > diff --git a/spec/build/cpukit/optthreadstackprotection.yml 
>> > b/spec/build/cpukit/optthreadstackprotection.yml
>> > new file mode 100644
>> > index 0000000000..4722d9f0cb
>> > --- /dev/null
>> > +++ b/spec/build/cpukit/optthreadstackprotection.yml
>> > @@ -0,0 +1,16 @@
>> > +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
>> > +actions:
>> > +- get-boolean: null
>> > +- env-enable: null
>> > +- define-condition: null
>> > +build-type: option
>> > +copyrights:
>> > +- Copyright (C) 2020 Utkarsh Rai (utkarsh.ra...@gmail.com)
>> > +default: false
>> > +default-by-variant: []
>> > +description: |
>> > +  Enable the thread stack protection support
>> > +enabled-by: true
>> > +links: []
>> > +name: RTEMS_THREAD_STACK_PROTECTION
>> > +type: build
>> > diff --git a/spec/build/testsuites/samples/grp.yml 
>> > b/spec/build/testsuites/samples/grp.yml
>> > index c7591dc551..f0367b0f9b 100644
>> > --- a/spec/build/testsuites/samples/grp.yml
>> > +++ b/spec/build/testsuites/samples/grp.yml
>> > @@ -40,6 +40,10 @@ links:
>> >    uid: pppd
>> >  - role: build-dependency
>> >    uid: ticker
>> > +- role: build-dependency
>> > +  uid: threadstackprotection
>> > +- role: build-dependency
>> > +  uid: threadstacksharing
>> >  - role: build-dependency
>> >    uid: unlimited
>> >  type: build
>> > diff --git a/spec/build/testsuites/samples/threadstackprotection.yml 
>> > b/spec/build/testsuites/samples/threadstackprotection.yml
>> > new file mode 100644
>> > index 0000000000..a33c53d392
>> > --- /dev/null
>> > +++ b/spec/build/testsuites/samples/threadstackprotection.yml
>> > @@ -0,0 +1,19 @@
>> > +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
>> > +build-type: test-program
>> > +cflags: []
>> > +copyrights:
>> > +- Copyright (C) 2020 Utkarsh Rai (utkarsh.ra...@gmail.com)
>> > +cppflags: []
>> > +cxxflags: []
>> > +enabled-by: true
>> > +features: c cprogram
>> > +includes: []
>> > +ldflags: []
>> > +links: []
>> > +source:
>> > +- testsuites/samples/thread_stack_protection/init.c
>> > +stlib: []
>> > +target: testsuites/samples/thread_stack_protection.exe
>> > +type: build
>> > +use-after: []
>> > +use-before: []
>> > diff --git a/spec/build/testsuites/samples/threadstacksharing.yml 
>> > b/spec/build/testsuites/samples/threadstacksharing.yml
>> > new file mode 100644
>> > index 0000000000..bbe99af189
>> > --- /dev/null
>> > +++ b/spec/build/testsuites/samples/threadstacksharing.yml
>> > @@ -0,0 +1,19 @@
>> > +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
>> > +build-type: test-program
>> > +cflags: []
>> > +copyrights:
>> > +- Copyright (C) 2020 Utkarsh Rai (utkarsh.ra...@gmail.com)
>> > +cppflags: []
>> > +cxxflags: []
>> > +enabled-by: true
>> > +features: c cprogram
>> > +includes: []
>> > +ldflags: []
>> > +links: []
>> > +source:
>> > +- testsuites/samples/thread_stack_sharing/init.c
>> > +stlib: []
>> > +target: testsuites/samples/thread_stack_sharing.exe
>> > +type: build
>> > +use-after: []
>> > +use-before: []
>> > diff --git a/testsuites/samples/Makefile.am 
>> > b/testsuites/samples/Makefile.am
>> > index 1944d90ccc..4d76bcb167 100644
>> > --- a/testsuites/samples/Makefile.am
>> > +++ b/testsuites/samples/Makefile.am
>> > @@ -146,6 +146,22 @@ ticker_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_FLAGS_ticker) 
>> > \
>> >         $(support_includes)
>> >  endif
>> >
>> > +if TEST_thread_stack_protection
>> > +samples += thread_stack_protection
>> > +sample_screens += thread_stack_protection/thread_stack_protection.scn
>> > +sample_docs += thread_stack_protection/thread_stack_protection.doc
>> > +thread_stack_protection_SOURCES = thread_stack_protection/init.c
>> > +thread_stack_protection_CPPFLAGS = $(AM_CPPFLAGS) 
>> > $(TEST_FLAGS_thread_stack_protection) \
>> > +       $(support_includes)
>> > +endif
>> > +
>> > +if TEST_thread_stack_sharing
>> > +samples += thread_stack_sharing
>> > +thread_stack_sharing_SOURCES = thread_stack_sharing/init.c
>> > +thread_stack_sharing_CPPFLAGS = $(AM_CPPFLAGS) 
>> > $(TEST_FLAGS_thread_stack_sharing) \
>> > +       $(support_includes)
>> > +endif
>> > +
>> >  if TEST_unlimited
>> >  samples += unlimited
>> >  sample_screens += unlimited/unlimited.scn
>> > diff --git a/testsuites/samples/configure.ac 
>> > b/testsuites/samples/configure.ac
>> > index 9721ea4f26..6460f8f2c9 100644
>> > --- a/testsuites/samples/configure.ac
>> > +++ b/testsuites/samples/configure.ac
>> > @@ -50,6 +50,8 @@ RTEMS_TEST_CHECK([nsecs])
>> >  RTEMS_TEST_CHECK([paranoia])
>> >  RTEMS_TEST_CHECK([pppd])
>> >  RTEMS_TEST_CHECK([ticker])
>> > +RTEMS_TEST_CHECK([thread_stack_protection])
>> > +RTEMS_TEST_CHECK([thread_stack_sharing])
>> >  RTEMS_TEST_CHECK([unlimited])
>> >
>> >  AC_CONFIG_FILES([Makefile])
>> > diff --git a/testsuites/samples/thread_stack_protection/init.c 
>> > b/testsuites/samples/thread_stack_protection/init.c
>> > new file mode 100644
>> > index 0000000000..a9359b459d
>> > --- /dev/null
>> > +++ b/testsuites/samples/thread_stack_protection/init.c
>> > @@ -0,0 +1,112 @@
>> > +#ifdef HAVE_CONFIG_H
>> > +#include "config.h"
>> > +#endif
>> > +
>> > +#include <rtems.h>
>> > +#include <tmacros.h>
>> > +#include <pthread.h>
>> > +#include <rtems/score/memoryprotection.h>
>> > +#include <rtems/score/thread.h>
>> > +const char rtems_test_name[] = " THREAD STACK PROTECTION ";
>> > +
>> > +static void fatal_extension(
>> > +  rtems_fatal_source source,
>> > +  bool is_internal,
>> > +  rtems_fatal_code error
>> > +)
>> > +{
>> > +  if (source == RTEMS_FATAL_SOURCE_EXCEPTION)
>> > +     {
>> > +       printk("Internal Exception Occured \n");
>> > +     }
>> > +
>> > +  exit(0);
>> > +}
>> > +
>> > +void* Test_routine( void* arg )
>> > +{
>> > +
>> > +}
>> > +
>> > +void *POSIX_Init( void *argument )
>> > +{
>> > +  void *stack_addr1;
>> > +  void *stack_addr2;
>> > +  size_t stack_size1;
>> > +  size_t stack_size2;
>> > +  pthread_t id1;
>> > +  pthread_t id2;
>> > +  pthread_attr_t attr1;
>> > +  pthread_attr_t attr2;
>> > +  Thread_Control Control;
>> > +  TEST_BEGIN();
>> > +
>> > + /*
>> > +  *  We set the stack size as 8Kb.
>> > +  */
>> > +  stack_size1 = 8192;
>> > +  stack_size2 = 8192;
>> > +  printf("%d %d \n",sizeof(Control.Post_switch_actions), 
>> > sizeof(Control.Start.tls_area));
>> > +  /*
>> > +   * We allocate page-aligned memory of the stack  from the application.
>> > +   */
>> > +  posix_memalign(&stack_addr1, sysconf( _SC_PAGESIZE ), stack_size1 );
>> > +  posix_memalign(&stack_addr2, sysconf( _SC_PAGESIZE ), stack_size2 );
>> > +
>> > +  pthread_attr_init( &attr1 );
>> > +  pthread_attr_init( &attr2 );
>> > +
>> > + /*
>> > +  * We set the stack size and address of the thread from the application 
>> > itself
>> > +  */
>> > +  pthread_attr_setstack( &attr1, stack_addr1, stack_size1 );
>> > +  pthread_attr_setstack( &attr2, stack_addr2, stack_size2 );
>> > +
>> > +  pthread_create( &id1, &attr1, Test_routine, NULL );
>> > +  pthread_create( &id2, &attr2, Test_routine, NULL );
>> > + /*
>> > +  * We set the memory attributes of the stack from the application.
>> > +  */
>> > +  _Memory_protection_Set_entries( stack_addr1, stack_size1, 
>> > RTEMS_NO_ACCESS | RTEMS_MEMORY_CACHED );
>> > +  _Memory_protection_Set_entries( stack_addr2, stack_size2, 
>> > RTEMS_NO_ACCESS | RTEMS_MEMORY_CACHED );
>> > +
>> > +  pthread_join( id1, NULL );
>> > +  /*
>> > +   * Write to the stack address of thread1 after it has been switched out.
>> > +   */
>> > +  printf("Writing to the stack of thread1 \n");
>> > +  memset(stack_addr1, 0, stack_size1);
>> > +
>> > +  pthread_join( id2, NULL );
>> > +   /*
>> > +   * Write to the stack address of thread2 after it has been switched out.
>> > +   */
>> > +
>> > +
>> > +
>> > +  TEST_END();
>> > +  rtems_test_exit( 0 );
>> > +}
>> > +
>> > +/* configuration information */
>> > +
>> > +#define CONFIGURE_INIT
>> > +
>> > +#define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
>> > +#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
>> > +
>> > +#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
>> > +
>> > +#define CONFIGURE_MAXIMUM_POSIX_THREADS        2
>> > +
>> > +#define CONFIGURE_POSIX_INIT_THREAD_TABLE
>> > +
>> > +#define CONFIGURE_INITIAL_EXTENSIONS { .fatal = fatal_extension }
>> > +
>> > +#define CONFIGURE_TASK_STACK_ALLOCATOR_INIT  bsp_stack_allocate_init
>> > +#define CONFIGURE_TASK_STACK_ALLOCATOR       bsp_stack_allocate
>> > +#define CONFIGURE_TASK_STACK_DEALLOCATOR     bsp_stack_free
>> > +
>> > +#include <bsp/stackalloc.h>
>> > +#define CONFIGURE_INIT
>> > +#include <rtems/confdefs.h>
>> > \ No newline at end of file
>> > diff --git 
>> > a/testsuites/samples/thread_stack_protection/thread_stack_protection.doc 
>> > b/testsuites/samples/thread_stack_protection/thread_stack_protection.doc
>> > new file mode 100644
>> > index 0000000000..c5c9cdfa81
>> > --- /dev/null
>> > +++ 
>> > b/testsuites/samples/thread_stack_protection/thread_stack_protection.doc
>> > @@ -0,0 +1,2 @@
>> > +This test sample demonstrates the thread stack protection functionality. 
>> > We try
>> > +to write to the stack of a switched-out thread.
>> > \ No newline at end of file
>> > diff --git 
>> > a/testsuites/samples/thread_stack_protection/thread_stack_protection.scn 
>> > b/testsuites/samples/thread_stack_protection/thread_stack_protection.scn
>> > new file mode 100644
>> > index 0000000000..1d36d0dfaf
>> > --- /dev/null
>> > +++ 
>> > b/testsuites/samples/thread_stack_protection/thread_stack_protection.scn
>> > @@ -0,0 +1,20 @@
>> > +
>> > +*** BEGIN OF TEST  THREAD STACK PROTECTION  ***
>> > +*** TEST VERSION: 5.0.0.a3b39c9e567f3f1ef5ab01de78b113e61b11853b-modified
>> > +*** TEST STATE: EXPECTED_PASS
>> > +*** TEST BUILD: RTEMS_NETWORKING RTEMS_POSIX_API
>> > +*** TEST TOOLS: 7.5.0 20191114 (RTEMS 5, RSB 5 (3bd11fd4898b), Newlib 
>> > 7947581)
>> > +Creating thread1
>> > +Creating thread2
>> > +Joining thread1
>> > +Writing to the stack of thread1
>> > +Internal Exception Occured
>> > +Internal Exception Occured
>> > +Internal Exception Occured
>> > +Internal Exception Occured
>> > +Internal Exception Occured
>> > +Internal Exception Occured
>> > +Internal Exception Occured
>> > +Internal Exception Occured
>> > +Internal Exception Occured
>> > +Internal Exception Occured
>> > \ No newline at end of file
>> > diff --git a/testsuites/samples/thread_stack_sharing/init.c 
>> > b/testsuites/samples/thread_stack_sharing/init.c
>> > new file mode 100644
>> > index 0000000000..5bb7d01418
>> > --- /dev/null
>> > +++ b/testsuites/samples/thread_stack_sharing/init.c
>> > @@ -0,0 +1,136 @@
>> > +#ifdef HAVE_CONFIG_H
>> > +#include "config.h"
>> > +#endif
>> > +
>> > +#include <rtems.h>
>> > +#include <tmacros.h>
>> > +#include <pthread.h>
>> > +#include <sys/mman.h>
>> > +#include <sys/fcntl.h>
>> > +#include <rtems/score/memoryprotection.h>
>> > +
>> > +const char rtems_test_name[] = " THREAD STACK SHARING ";
>> > +
>> > +void* Test_routine( void* arg )
>> > +{
>> > +
>> > +}
>> > +
>> > +void *POSIX_Init( void *argument )
>> > +{
>> > +  void *stack_addr1;
>> > +  void *stack_addr2;
>> > +  void* addr;
>> > +  size_t stack_size1;
>> > +  size_t stack_size2;
>> > +  pthread_t id1;
>> > +  pthread_t id2;
>> > +  pthread_attr_t attr1;
>> > +  pthread_attr_t attr2;
>> > +  int fd;
>> > +  char name[4] = "0x01";
>> > +  char thread_name[13] = "/taskfs/0x01";
>> > +
>> > +  TEST_BEGIN();
>> > +
>> > + /*
>> > +  *  We set the stack size as 8Kb.
>> > +  */
>> > +  stack_size1 = 8192;
>> > +  stack_size2 = 8192;
>> > +
>> > +  /*
>> > +   * We allocate page-aligned memory of the stack  from the application.
>> > +   */
>> > +  posix_memalign(&stack_addr1, sysconf( _SC_PAGESIZE ), stack_size1 );
>> > +  posix_memalign(&stack_addr2, sysconf( _SC_PAGESIZE ), stack_size2 );
>> > +
>> > +  pthread_attr_init( &attr1 );
>> > +  pthread_attr_init( &attr2 );
>> > +
>> > + /*
>> > +  * We set the stack size and address of the thread from the application 
>> > itself
>> > +  */
>> > +  pthread_attr_setstack( &attr1, stack_addr1, stack_size1 );
>> > +  pthread_attr_setstack( &attr2, stack_addr2, stack_size2 );
>> > +
>> > +  pthread_create( &id1, &attr1, Test_routine, NULL );
>> > +
>> > + /*
>> > +  * We set the memory attributes of the stack from the application.
>> > +  */
>> > +  _Memory_protection_Set_entries( stack_addr1, stack_size1, 
>> > RTEMS_READ_ONLY | RTEMS_MEMORY_CACHED );
>> > +
>> > +    pthread_create( &id2, &attr2, Test_routine, NULL );
>> > +  _Memory_protection_Set_entries( stack_addr2, stack_size2, 
>> > RTEMS_READ_ONLY | RTEMS_MEMORY_CACHED );
>> > +
>> > +  /*
>> > +   * Add leading "/taskfs/" to denote thread-stack name.
>> > +   */
>> > +  strlcat( thread_name, name, 4);
>> > +
>> > +  /*
>> > +  * Set the name of the thread object same as that of the shared memory 
>> > object name
>> > +  */
>> > +  rtems_object_set_name( id1, name);
>> > +
>> > +  /*
>> > +   * Create a shared memory object of the  stack we want to share with
>> > +   * appropraite permissions. We share the stack with read and write 
>> > permission
>> > +   */
>> > +  fd = shm_open( thread_name, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR );
>> > +
>> > +  /*
>> > +   * Truncate the size of the file to the size of the stack.
>> > +   */
>> > +  ftruncate( fd, stack_size1 );
>> > +
>> > +  /*
>> > +   * For sharing the stack we specify the address of the
>> > +   * thread-stack we want to share with, the size of the shared stack,
>> > +   * protection and access flags, file descriptor of the shared memory 
>> > objcet
>> > +   */
>> > +  addr = mmap( stack_addr2, stack_size1, PROT_READ | PROT_WRITE, O_RDWR, 
>> > fd, 0 );
>> > +  rtems_test_assert( addr != NULL );
>> > +
>> > +  pthread_join( id1, NULL );
>> > +  /*
>> > +   * Write to the stack address of thread1 after it has been switched out.
>> > +   */
>> > +  memset( stack_addr1, 0, stack_size1 );
>> > +
>> > +  pthread_join( id2, NULL );
>> > +   /*
>> > +   * Write to the stack address of thread2 after it has been switched out.
>> > +   */
>> > +  memset( stack_addr2, 0, stack_size2 );
>> > +
>> > +
>> > +  TEST_END();
>> > +  rtems_test_exit( 0 );
>> > +}
>> > +
>> > +/* configuration information */
>> > +
>> > +#define CONFIGURE_INIT
>> > +
>> > +#define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
>> > +#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
>> > +
>> > +#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
>> > +
>> > +#define CONFIGURE_MAXIMUM_POSIX_THREADS        4
>> > +
>> > +#define CONFIGURE_MAXIMUM_POSIX_SHMS           2
>> > +
>> > +#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 10
>> > +
>> > +#define CONFIGURE_POSIX_INIT_THREAD_TABLE
>> > +
>> > +#define CONFIGURE_TASK_STACK_ALLOCATOR_INIT  bsp_stack_allocate_init
>> > +#define CONFIGURE_TASK_STACK_ALLOCATOR       bsp_stack_allocate
>> > +#define CONFIGURE_TASK_STACK_DEALLOCATOR     bsp_stack_free
>> > +
>> > +#include <bsp/stackalloc.h>
>> > +#define CONFIGURE_INIT
>> > +#include <rtems/confdefs.h>
>> > \ No newline at end of file
>> > --
>> > 2.17.1
>> >
_______________________________________________
devel mailing list
devel@rtems.org
http://lists.rtems.org/mailman/listinfo/devel

Reply via email to