arch/addrenv: Change text write enable/disable to generic mprot

Implement a generic access rights modification procedure instead
of the procedures that only do one thing (enable/disable write)
to one section (text).
This commit is contained in:
Ville Juven 2022-05-12 11:55:50 +03:00 committed by Xiang Xiao
parent 072c28fe8e
commit 47e85b68fe
4 changed files with 71 additions and 88 deletions

View File

@ -25,51 +25,40 @@
#include <nuttx/config.h>
#include <nuttx/arch.h>
#include <nuttx/compiler.h>
#include <sys/mman.h>
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: up_addrenv_text_enable_write
* Name: up_addrenv_mprot
*
* Description:
* Temporarily enable write access to the .text section. This must be
* called prior to loading the process code into memory.
* Modify access rights to an address range.
*
* Input Parameters:
* addrenv - The address environment to be modified.
* addr - Base address of the region.
* len - Size of the region.
* prot - Access right flags.
*
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
*
****************************************************************************/
int up_addrenv_text_enable_write(group_addrenv_t *addrenv)
int up_addrenv_mprot(group_addrenv_t *addrenv, uintptr_t addr, size_t len,
int prot)
{
/* Nothing needs to be done */
return OK;
}
/****************************************************************************
* Name: up_addrenv_text_disable_write
*
* Description:
* Disable write access to the .text section. This must be called after the
* process code is loaded into memory.
*
* Input Parameters:
* addrenv - The address environment to be modified.
*
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
*
****************************************************************************/
int up_addrenv_text_disable_write(group_addrenv_t *addrenv)
{
/* Nothing needs to be done */
UNUSED(addrenv);
UNUSED(addr);
UNUSED(len);
UNUSED(prot);
return OK;
}

View File

@ -33,15 +33,22 @@
#include <arch/barriers.h>
#include <sys/mman.h>
#include "pgalloc.h"
#include "riscv_mmu.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define CLR_MASK (PTE_R | PTE_W | PTE_X)
/****************************************************************************
* Private Functions
****************************************************************************/
static int modify_region(uintptr_t vstart, uintptr_t vend, uintptr_t setmask,
uintptr_t clrmask)
static int modify_region(uintptr_t vstart, uintptr_t vend, uintptr_t setmask)
{
uintptr_t l1vaddr;
uintptr_t lnvaddr;
@ -78,7 +85,7 @@ static int modify_region(uintptr_t vstart, uintptr_t vend, uintptr_t setmask,
/* Get entry and modify the flags */
entry = mmu_ln_getentry(ptlevel, lnvaddr, vaddr);
entry &= ~clrmask;
entry &= ~CLR_MASK;
entry |= setmask;
/* Restore the entry */
@ -99,53 +106,49 @@ static int modify_region(uintptr_t vstart, uintptr_t vend, uintptr_t setmask,
****************************************************************************/
/****************************************************************************
* Name: up_addrenv_text_enable_write
* Name: up_addrenv_mprot
*
* Description:
* Temporarily enable write access to the .text section. This must be
* called prior to loading the process code into memory.
* Modify access rights to an address range.
*
* Input Parameters:
* addrenv - The address environment to be modified.
* addr - Base address of the region.
* len - Size of the region.
* prot - Access right flags.
*
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
*
****************************************************************************/
int up_addrenv_text_enable_write(group_addrenv_t *addrenv)
int up_addrenv_mprot(group_addrenv_t *addrenv, uintptr_t addr, size_t len,
int prot)
{
/* Sanity checks */
uintptr_t setmask;
uintptr_t vend;
DEBUGASSERT(addrenv);
DEBUGASSERT(MM_ISALIGNED(addrenv->textvbase));
DEBUGASSERT(MM_ISALIGNED(addrenv->datavbase));
/* addrenv not needed by this implementation */
return modify_region(addrenv->textvbase, addrenv->datavbase, PTE_W, 0);
}
/****************************************************************************
* Name: up_addrenv_text_disable_write
*
* Description:
* Disable write access to the .text section. This must be called after the
* process code is loaded into memory.
*
* Input Parameters:
* addrenv - The address environment to be modified.
*
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
*
****************************************************************************/
int up_addrenv_text_disable_write(group_addrenv_t *addrenv)
{
/* Sanity checks */
DEBUGASSERT(addrenv);
DEBUGASSERT(MM_ISALIGNED(addrenv->textvbase));
DEBUGASSERT(MM_ISALIGNED(addrenv->datavbase));
return modify_region(addrenv->textvbase, addrenv->datavbase, 0, PTE_W);
UNUSED(addrenv);
setmask = 0;
vend = addr + MM_PGALIGNUP(len);
if (prot & PROT_READ)
{
setmask |= PTE_R;
}
if (prot & PROT_WRITE)
{
setmask |= PTE_W;
}
if (prot & PROT_EXEC)
{
setmask |= PTE_X;
}
return modify_region(addr, vend, setmask);
}

View File

@ -30,12 +30,17 @@
#include <nuttx/arch.h>
#include <nuttx/kmalloc.h>
#include <sys/mman.h>
#include "libelf.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define ELF_TEXT_WRE (PROT_READ | PROT_WRITE | PROT_EXEC)
#define ELF_TEXT_WRD (PROT_READ | PROT_EXEC)
/****************************************************************************
* Private Constant Data
****************************************************************************/
@ -175,7 +180,8 @@ int elf_addrenv_select(FAR struct elf_loadinfo_s *loadinfo)
/* Allow write access to .text */
ret = up_addrenv_text_enable_write(&loadinfo->addrenv);
ret = up_addrenv_mprot(&loadinfo->addrenv, loadinfo->textalloc,
loadinfo->textsize, ELF_TEXT_WRE);
if (ret < 0)
{
berr("ERROR: up_addrenv_text_enable_write failed: %d\n", ret);
@ -207,7 +213,8 @@ int elf_addrenv_restore(FAR struct elf_loadinfo_s *loadinfo)
/* Remove write access to .text */
ret = up_addrenv_text_disable_write(&loadinfo->addrenv);
ret = up_addrenv_mprot(&loadinfo->addrenv, loadinfo->textalloc,
loadinfo->textsize, ELF_TEXT_WRD);
if (ret < 0)
{
berr("ERROR: up_addrenv_text_disable_write failed: %d\n", ret);

View File

@ -1186,14 +1186,16 @@ int up_addrenv_detach(FAR struct task_group_s *group, FAR struct tcb_s *tcb);
#endif
/****************************************************************************
* Name: up_addrenv_text_enable_write
* Name: up_addrenv_mprot
*
* Description:
* Temporarily enable write access to the .text section. This must be
* called prior to loading the process code into memory.
* Modify access rights to an address range.
*
* Input Parameters:
* addrenv - The address environment to be modified.
* addr - Base address of the region.
* len - Size of the region.
* prot - Access right flags.
*
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
@ -1201,26 +1203,8 @@ int up_addrenv_detach(FAR struct task_group_s *group, FAR struct tcb_s *tcb);
****************************************************************************/
#ifdef CONFIG_ARCH_ADDRENV
int up_addrenv_text_enable_write(FAR group_addrenv_t *addrenv);
#endif
/****************************************************************************
* Name: up_addrenv_text_disable_write
*
* Description:
* Disable write access to the .text section. This must be called after the
* process code is loaded into memory.
*
* Input Parameters:
* addrenv - The address environment to be modified.
*
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
*
****************************************************************************/
#ifdef CONFIG_ARCH_ADDRENV
int up_addrenv_text_disable_write(FAR group_addrenv_t *addrenv);
int up_addrenv_mprot(group_addrenv_t *addrenv, uintptr_t addr, size_t len,
int prot);
#endif
/****************************************************************************