Thread (95 messages) 95 messages, 6 authors, 2024-02-05
STALE847d
Revisions (2)
  1. rfc [diff vs current]
  2. v3 current

[PATCH RFC v3 30/35] arm64: mte: ptrace: Handle pages with missing tag storage

From: Alexandru Elisei <hidden>
Date: 2024-01-25 16:45:41
Also in: kvmarm, linux-arch, linux-arm-kernel, linux-fsdevel, linux-mm, lkml
Subsystem: arm64 port (aarch64 architecture), the rest · Maintainers: Catalin Marinas, Will Deacon, Linus Torvalds

A page can end up mapped in a MTE enabled VMA without the corresponding tag
storage block reserved. Tag accesses made by ptrace in this case can lead
to the wrong tags being read or memory corruption for the process that is
using the tag storage memory as data.

Reserve tag storage by treating ptrace accesses like a fault.

Signed-off-by: Alexandru Elisei <redacted>
---

Changes since rfc v2:

* New patch, issue reported by Peter Collingbourne.

 arch/arm64/kernel/mte.c | 26 ++++++++++++++++++++++++--
 1 file changed, 24 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/kernel/mte.c b/arch/arm64/kernel/mte.c
index faf09da3400a..b1fa02dad4fd 100644
--- a/arch/arm64/kernel/mte.c
+++ b/arch/arm64/kernel/mte.c
@@ -412,10 +412,13 @@ static int __access_remote_tags(struct mm_struct *mm, unsigned long addr,
 	while (len) {
 		struct vm_area_struct *vma;
 		unsigned long tags, offset;
+		unsigned int fault_flags;
+		struct page *page;
+		vm_fault_t ret;
 		void *maddr;
-		struct page *page = get_user_page_vma_remote(mm, addr,
-							     gup_flags, &vma);
 
+get_page:
+		page = get_user_page_vma_remote(mm, addr, gup_flags, &vma);
 		if (IS_ERR(page)) {
 			err = PTR_ERR(page);
 			break;
@@ -433,6 +436,25 @@ static int __access_remote_tags(struct mm_struct *mm, unsigned long addr,
 			put_page(page);
 			break;
 		}
+
+		if (tag_storage_enabled() && !page_tag_storage_reserved(page)) {
+			fault_flags = FAULT_FLAG_DEFAULT | \
+				      FAULT_FLAG_USER | \
+				      FAULT_FLAG_REMOTE | \
+				      FAULT_FLAG_ALLOW_RETRY | \
+				      FAULT_FLAG_RETRY_NOWAIT;
+			if (write)
+				fault_flags |= FAULT_FLAG_WRITE;
+
+			put_page(page);
+			ret = handle_mm_fault(vma, addr, fault_flags, NULL);
+			if (ret & VM_FAULT_ERROR) {
+				err = -EFAULT;
+				break;
+			}
+			goto get_page;
+		}
+
 		WARN_ON_ONCE(!page_mte_tagged(page));
 
 		/* limit access to the end of the page */
-- 
2.43.0
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help