From patchwork Mon Oct 12 21:29:17 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Georgy Yakovlev X-Patchwork-Id: 1381213 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4C9Bf93p1vz9sTK for ; Tue, 13 Oct 2020 08:29:53 +1100 (AEDT) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gentoo.org Received: from bilbo.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 4C9Bf90SFszDqgk for ; Tue, 13 Oct 2020 08:29:53 +1100 (AEDT) X-Original-To: skiboot@lists.ozlabs.org Delivered-To: skiboot@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gentoo.org (client-ip=140.211.166.183; helo=smtp.gentoo.org; envelope-from=gyakovlev@gentoo.org; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=pass (p=none dis=none) header.from=gentoo.org Received: from smtp.gentoo.org (smtp.gentoo.org [140.211.166.183]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 4C9Bdt01gQzDqgC for ; Tue, 13 Oct 2020 08:29:35 +1100 (AEDT) From: Georgy Yakovlev To: skiboot@lists.ozlabs.org Date: Mon, 12 Oct 2020 14:29:17 -0700 Message-Id: <20201012212917.1297088-1-gyakovlev@gentoo.org> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201011013330.1317003-1-gyakovlev@gentoo.org> References: <20201011013330.1317003-1-gyakovlev@gentoo.org> MIME-Version: 1.0 Subject: [Skiboot] [PATCH] opal-prd: handle devtmpfs mounted with noexec X-BeenThere: skiboot@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Mailing list for skiboot development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Skiboot" On systems using recent versions of systemd /dev (devtmpfs) is mounted with noexec option. Such mount prevents mapping HBRT image code region as RWX from /dev. This commit, as suggested in github PR linked below, attempts to work around the situation by copying HBRT image to anon mmaped memory region and sets mprotect rwx on it, allowing opal-prd to sucessfully execute the code region. Having memory region set as RWX is not ideal for security, but fixing that is a separate and hard to solve problem. Original code also mmaped region as RWX, so this PR does not make things worse at least. Closes: https://github.com/open-power/skiboot/issues/258 Signed-off-by: Georgy Yakovlev Reviewed-by: Vasant Hegde --- external/opal-prd/opal-prd.c | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/external/opal-prd/opal-prd.c b/external/opal-prd/opal-prd.c index d74d8039..abf43a78 100644 --- a/external/opal-prd/opal-prd.c +++ b/external/opal-prd/opal-prd.c @@ -973,7 +973,9 @@ 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; range = find_range(name, 0); if (!range) { @@ -981,15 +983,41 @@ 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; } + buf = mmap(NULL, range->size, PROT_WRITE, + MAP_SHARED | MAP_ANONYMOUS, -1 , 0); + if (buf == MAP_FAILED) { + pr_log(LOG_ERR, "IMAGE: anon mmap(size:0x%016lx) failed: %m", + range->size); + return -1; + } + + memcpy(buf, ro_buf, range->size); + + 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); + 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;