[Skiboot] [PATCH] opal-prd: handle devtmpfs mounted with noexec
Oliver O'Halloran
oohall at gmail.com
Mon Oct 12 08:59:52 AEDT 2020
On Sun, Oct 11, 2020 at 12:34 PM Georgy Yakovlev <gyakovlev at gentoo.org> wrote:
>
> Closes: https://github.com/open-power/skiboot/issues/258
Github / bugzilla links aren't a substitute for a commit message.
> Signed-off-by: Georgy Yakovlev <gyakovlev at gentoo.org>
> ---
> external/opal-prd/opal-prd.c | 39 ++++++++++++++++++++++++++++++++++--
> 1 file changed, 37 insertions(+), 2 deletions(-)
>
> diff --git a/external/opal-prd/opal-prd.c b/external/opal-prd/opal-prd.c
> index d74d8039..eb9a0b38 100644
> --- a/external/opal-prd/opal-prd.c
> +++ b/external/opal-prd/opal-prd.c
> @@ -973,7 +973,10 @@ static int map_hbrt_file(struct opal_prd_ctx *ctx, const char *name)
> static int map_hbrt_physmem(struct opal_prd_ctx *ctx, const char *name)
> {
> struct prd_range *range;
> + int rc;
> void *buf;
> + void *ro_buf;
> + void *rwx_buf;
>
> range = find_range(name, 0);
> if (!range) {
> @@ -981,15 +984,47 @@ static int map_hbrt_physmem(struct opal_prd_ctx *ctx, const char *name)
> return -1;
> }
>
> - buf = mmap(NULL, range->size, PROT_READ | PROT_WRITE | PROT_EXEC,
> + ro_buf = mmap(NULL, range->size, PROT_READ,
> MAP_PRIVATE, ctx->fd, range->physaddr);
> - if (buf == MAP_FAILED) {
> + if (ro_buf == MAP_FAILED) {
> pr_log(LOG_ERR, "IMAGE: mmap(range:%s, "
> "phys:0x%016lx, size:0x%016lx) failed: %m",
> name, range->physaddr, range->size);
> return -1;
> }
>
> + rwx_buf = mmap(NULL, range->size, PROT_WRITE,
> + MAP_SHARED | MAP_ANONYMOUS, -1 , 0);
> + if (rwx_buf == MAP_FAILED) {
> + pr_log(LOG_ERR, "IMAGE: anon mmap(size:0x%016lx) failed: %m",
> + range->size);
> + return -1;
> + }
> +
> + buf = memcpy(rwx_buf, ro_buf, range->size);
> + if (!buf) {
memcpy() just returns the dest pointer so the condition will never be
hit unless rwx_buf is NULL to begin with.
> + pr_log(LOG_ERR, "IMAGE: memcpy(dest:%p, "
> + "src: %p, size:0x%016lx) failed: %m",
> + rwx_buf, ro_buf, range->size);
> + return -1;
> + }
> +
> + rc = munmap(ro_buf, range->size);
> + if (rc < 0) {
> + pr_log(LOG_ERR, "IMAGE: munmap("
> + "phys:0x%016lx, size:0x%016lx) failed: %m",
> + range->physaddr, range->size);
> + return -1;
> + }
> +
> + rc = mprotect(buf, range->size, PROT_READ | PROT_WRITE | PROT_EXEC);
This should be PROT_READ | PROT_EXEC. You almost never want memory to
be writable and executable at the same time. There's some legitimate
uses for W+X memory (mainly JITs), but for the most part it just gives
people writing exploits a convenient place to drop shellcode.
> + if (rc < 0) {
> + pr_log(LOG_ERR, "IMAGE: mprotect(phys:%p, "
> + "size:0x%016lx, rwx) failed: %m",
> + buf, range->size);
> + return -1;
> + }
> +
> ctx->code_addr = buf;
> ctx->code_size = range->size;
> return 0;
> --
> 2.28.0
>
> _______________________________________________
> Skiboot mailing list
> Skiboot at lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/skiboot
More information about the Skiboot
mailing list