On Thu, Sep 19, 2024 at 05:32:00PM +0100, Mate Kukri wrote: > For NX, we need to set write and executable permissions on the sections > of grub modules when we load them. > > On sections with SHF_ALLOC set, which is typically everything except > .modname and the symbol and string tables, this patch clears the Read > Only flag on sections that have the ELF flag SHF_WRITE set, and clears > the No eXecute flag on sections with SHF_EXECINSTR set. In all other
This part of commit message does not (exactly) reflect what the code does. Especially in the SHF_EXECINSTR case. Additionally, I would suggest to split this long sentence to a few shorter ones. Or use bullets to make things clear... > cases it sets both flags. > > Signed-off-by: Peter Jones <pjo...@redhat.com> > Signed-off-by: Robbie Harwood <rharw...@redhat.com> > Signed-off-by: Laszlo Ersek <ler...@redhat.com> > Signed-off-by: Jan Setje-Eilers <jan.setjeeil...@oracle.com> > Signed-off-by: Mate Kukri <mate.ku...@canonical.com> > --- > grub-core/kern/dl.c | 85 ++++++++++++++++++++++++++++++++++++++++++++- > 1 file changed, 84 insertions(+), 1 deletion(-) > > diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c > index 47705f5af..54daa7f30 100644 > --- a/grub-core/kern/dl.c > +++ b/grub-core/kern/dl.c > @@ -634,6 +634,84 @@ grub_dl_relocate_symbols (grub_dl_t mod, void *ehdr) > return GRUB_ERR_NONE; > } > > +/* Only define this on EFI to save space in core */ > +#ifdef GRUB_MACHINE_EFI > +static grub_err_t > +grub_dl_set_mem_attrs (grub_dl_t mod, void *ehdr) > +{ > + unsigned i; > + const Elf_Shdr *s; > + const Elf_Ehdr *e = ehdr; > + grub_err_t err; > +#if !defined (__i386__) && !defined (__x86_64__) && !defined (__riscv) What about ARM and loongarch64 architectures? Anything else? > + grub_size_t arch_addralign = GRUB_DL_ALIGN; > + grub_addr_t tgaddr; > + grub_size_t tgsz; > +#endif > + > + for (i = 0, s = (const Elf_Shdr *) ((const char *) e + e->e_shoff); > + i < e->e_shnum; > + i++, s = (const Elf_Shdr *) ((const char *) s + e->e_shentsize)) > + { > + grub_dl_segment_t seg; > + grub_uint64_t set_attrs = GRUB_MEM_ATTR_R; > + grub_uint64_t clear_attrs = GRUB_MEM_ATTR_W | GRUB_MEM_ATTR_X; > + > + for (seg = mod->segment; seg; seg = seg->next) > + if (seg->section == s->sh_info) > + break; > + > + if (!seg) > + continue; > + > + if (seg->size == 0 || !(s->sh_flags & SHF_ALLOC)) > + continue; > + > + if (s->sh_flags & SHF_WRITE) > + { > + set_attrs |= GRUB_MEM_ATTR_W; > + clear_attrs &= ~GRUB_MEM_ATTR_W; > + } > + > + if (s->sh_flags & SHF_EXECINSTR) > + { > + set_attrs |= GRUB_MEM_ATTR_X; > + clear_attrs &= ~GRUB_MEM_ATTR_X; > + } > + > + err = grub_update_mem_attrs ((grub_addr_t) seg->addr, seg->size, > + set_attrs, clear_attrs); > + if (err != GRUB_ERR_NONE) > + return err; > + } > + > +#if !defined (__i386__) && !defined (__x86_64__) && !defined (__riscv) What about other archs? I can see this second time in this short code. This is error prone. Would not it be easier to introduce a constant, e.g., ARCH_NX (probably not good example)? And first of all why this code is arch specific? I think it requires at least a comment... > + tgaddr = grub_min ((grub_addr_t) mod->tramp, (grub_addr_t) mod->got); > + tgsz = grub_max ((grub_addr_t) mod->trampptr, (grub_addr_t) mod->gotptr) - > tgaddr; > + > + if (tgsz) > + { > + tgsz = ALIGN_UP (tgsz, arch_addralign); > + > + if (tgaddr < (grub_addr_t) mod->base || > + tgsz > (grub_addr_t) -1 - tgaddr || > + tgaddr + tgsz > (grub_addr_t) mod->base + mod->sz) > + return grub_error (GRUB_ERR_BUG, > + "BUG: trying to protect pages outside of module " > + "allocation (\"%s\"): module base %p, size 0x%" > + PRIxGRUB_SIZE "; tramp/GOT base 0x%" PRIxGRUB_ADDR > + ", size 0x%" PRIxGRUB_SIZE, > + mod->name, mod->base, mod->sz, tgaddr, tgsz); > + err = grub_update_mem_attrs (tgaddr, tgsz, GRUB_MEM_ATTR_R | > GRUB_MEM_ATTR_X, GRUB_MEM_ATTR_W); > + if (err != GRUB_ERR_NONE) > + return err; > + } > +#endif > + > + return GRUB_ERR_NONE; > +} > +#endif > + > /* Load a module from core memory. */ > grub_dl_t > grub_dl_load_core_noinit (void *addr, grub_size_t size) > @@ -680,7 +758,12 @@ grub_dl_load_core_noinit (void *addr, grub_size_t size) > || grub_dl_resolve_dependencies (mod, e) > || grub_dl_load_segments (mod, e) > || grub_dl_resolve_symbols (mod, e) > - || grub_dl_relocate_symbols (mod, e)) > + || grub_dl_relocate_symbols (mod, e) > +#ifdef GRUB_MACHINE_EFI > + || grub_dl_set_mem_attrs (mod, e)) Again, if you define an empty grub_dl_set_mem_attrs() counterpart for non-EFI case this part of code will be simplified. > +#else > + ) > +#endif Daniel _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel