diff --git a/arch/risc-v/src/common/riscv_addrenv_perms.c b/arch/risc-v/src/common/riscv_addrenv_perms.c new file mode 100644 index 0000000000000..dbc70e462b4a2 --- /dev/null +++ b/arch/risc-v/src/common/riscv_addrenv_perms.c @@ -0,0 +1,97 @@ +/**************************************************************************** + * arch/risc-v/src/common/riscv_addrenv_perms.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include + +#include + +#include "pgalloc.h" +#include "riscv_mmu.h" + +/**************************************************************************** + * Name: up_addrenv_text_enable_write + * + * Description: + * Temporarily enable write access to the .text section. This must be + * called prior to loading the process code 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_enable_write(FAR group_addrenv_t *addrenv) +{ +#if 0 + uintptr_t pgt; + uintptr_t pte; + int npages; + int i; + + DEBUGASSERT(addrenv); + DEBUGASSERT(MM_ISALIGNED(addrenv->textvbase)); + DEBUGASSERT(MM_ISALIGNED(addrenv->datavbase)); + + /* Size of text region is base(data) - base(text) */ + + npages = MM_NPAGES(addrenv->datavbase - addrenv->textvbase); + + for (; npages > 0; npages--) + { + + } +#endif + UNUSED(addrenv); + 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(FAR group_addrenv_t *addrenv) +{ + UNUSED(addrenv); + return OK; +} diff --git a/arch/risc-v/src/mpfs/Make.defs b/arch/risc-v/src/mpfs/Make.defs index a44a40850f40e..f34e62759cd27 100755 --- a/arch/risc-v/src/mpfs/Make.defs +++ b/arch/risc-v/src/mpfs/Make.defs @@ -102,6 +102,7 @@ endif ifeq ($(CONFIG_ARCH_ADDRENV),y) CMN_CSRCS += riscv_addrenv.c riscv_pgalloc.c riscv_addrenv_util.c +CMN_CSRCS += riscv_addrenv_perms.c endif ifeq ($(CONFIG_MM_PGALLOC),y) diff --git a/binfmt/libelf/libelf.h b/binfmt/libelf/libelf.h index e5e4a5bba6c35..d2f7b6607e040 100644 --- a/binfmt/libelf/libelf.h +++ b/binfmt/libelf/libelf.h @@ -290,7 +290,7 @@ int elf_addrenv_alloc(FAR struct elf_loadinfo_s *loadinfo, size_t textsize, ****************************************************************************/ #ifdef CONFIG_ARCH_ADDRENV -# define elf_addrenv_select(l) up_addrenv_select(&(l)->addrenv, &(l)->oldenv) +int elf_addrenv_select(FAR struct elf_loadinfo_s *loadinfo); #endif /**************************************************************************** @@ -308,7 +308,7 @@ int elf_addrenv_alloc(FAR struct elf_loadinfo_s *loadinfo, size_t textsize, ****************************************************************************/ #ifdef CONFIG_ARCH_ADDRENV -# define elf_addrenv_restore(l) up_addrenv_restore(&(l)->oldenv) +int elf_addrenv_restore(FAR struct elf_loadinfo_s *loadinfo); #endif /**************************************************************************** diff --git a/binfmt/libelf/libelf_addrenv.c b/binfmt/libelf/libelf_addrenv.c index 9ede25a383ba4..be206933eecc7 100644 --- a/binfmt/libelf/libelf_addrenv.c +++ b/binfmt/libelf/libelf_addrenv.c @@ -145,6 +145,92 @@ int elf_addrenv_alloc(FAR struct elf_loadinfo_s *loadinfo, size_t textsize, #endif } +/**************************************************************************** + * Name: elf_addrenv_restore + * + * Description: + * Restore the address environment before elf_addrenv_select() was called.. + * + * Input Parameters: + * loadinfo - Load state information + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +#ifdef CONFIG_ARCH_ADDRENV +int elf_addrenv_select(FAR struct elf_loadinfo_s *loadinfo) +{ + int ret; + + /* Instantiate the new address environment */ + + ret = up_addrenv_select(&loadinfo->addrenv, &loadinfo->oldenv); + if (ret < 0) + { + berr("ERROR: up_addrenv_select failed: %d\n", ret); + return ret; + } + + /* Allow write access to .text */ + + ret = up_addrenv_text_enable_write(&loadinfo->addrenv); + if (ret < 0) + { + berr("ERROR: up_addrenv_text_set_write failed: %d\n", ret); + return ret; + } + + return OK; +} +#endif + +/**************************************************************************** + * Name: elf_addrenv_free + * + * Description: + * Release the address environment previously created by + * elf_addrenv_alloc(). This function is called only under certain error + * conditions after the module has been loaded but not yet started. + * After the module has been started, the address environment will + * automatically be freed when the module exits. + * + * Input Parameters: + * loadinfo - Load state information + * + * Returned Value: + * None. + * + ****************************************************************************/ + +#ifdef CONFIG_ARCH_ADDRENV +int elf_addrenv_restore(FAR struct elf_loadinfo_s *loadinfo) +{ + int ret; + + /* Restore the old address environment */ + + ret = up_addrenv_restore(&loadinfo->oldenv); + if (ret < 0) + { + berr("ERROR: up_addrenv_restore failed: %d\n", ret); + return ret; + } + + /* Remove write access to .text */ + + ret = up_addrenv_text_disable_write(&loadinfo->addrenv); + if (ret < 0) + { + berr("ERROR: up_addrenv_text_clear_write failed: %d\n", ret); + return ret; + } + + return OK; +} +#endif + /**************************************************************************** * Name: elf_addrenv_free * diff --git a/include/nuttx/arch.h b/include/nuttx/arch.h index e676fd2e3ce2d..0fc8a5881e1aa 100644 --- a/include/nuttx/arch.h +++ b/include/nuttx/arch.h @@ -1185,6 +1185,44 @@ int up_addrenv_attach(FAR struct task_group_s *group, FAR struct tcb_s *tcb); int up_addrenv_detach(FAR struct task_group_s *group, FAR struct tcb_s *tcb); #endif +/**************************************************************************** + * Name: up_addrenv_text_enable_write + * + * Description: + * Temporarily enable write access to the .text section. This must be + * called prior to loading the process code 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_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); +#endif + /**************************************************************************** * Name: up_addrenv_ustackalloc *