lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Mon, 11 Apr 2022 10:05:54 -0600
From:   Khalid Aziz <khalid.aziz@...cle.com>
To:     akpm@...ux-foundation.org, willy@...radead.org
Cc:     Khalid Aziz <khalid.aziz@...cle.com>, aneesh.kumar@...ux.ibm.com,
        arnd@...db.de, 21cnbao@...il.com, corbet@....net,
        dave.hansen@...ux.intel.com, david@...hat.com,
        ebiederm@...ssion.com, hagen@...u.net, jack@...e.cz,
        keescook@...omium.org, kirill@...temov.name, kucharsk@...il.com,
        linkinjeon@...nel.org, linux-fsdevel@...r.kernel.org,
        linux-kernel@...r.kernel.org, linux-mm@...ck.org,
        longpeng2@...wei.com, luto@...nel.org, markhemm@...glemail.com,
        pcc@...gle.com, rppt@...nel.org, sieberf@...zon.com,
        sjpark@...zon.de, surenb@...gle.com, tst@...oebel-theuer.de,
        yzaikin@...gle.com
Subject: [PATCH v1 10/14] mm/mshare: Check for mapped vma when mshare'ing existing mshare'd range

When a task calls mshare() to map in an existing mshare'd region,
make sure this mapping does not overlap any existing mappings in
calling task. Ensure mmap locks are taken and released in correct
order and in correct read/write mode.

Signed-off-by: Khalid Aziz <khalid.aziz@...cle.com>
---
 mm/mshare.c | 62 +++++++++++++++++++++++++++++++++++++----------------
 1 file changed, 43 insertions(+), 19 deletions(-)

diff --git a/mm/mshare.c b/mm/mshare.c
index d1896adcb00f..40c495ffc0ca 100644
--- a/mm/mshare.c
+++ b/mm/mshare.c
@@ -249,11 +249,24 @@ SYSCALL_DEFINE5(mshare, const char __user *, name, unsigned long, addr,
 	if (dentry) {
 		unsigned long mapaddr, prot = PROT_NONE;
 
+		/*
+		 * If a task is trying to map in an existing mshare'd
+		 * range, make sure there are no overlapping mappings
+		 * in calling process already
+		 */
+		mmap_read_lock(current->mm);
+		vma = find_vma_intersection(current->mm, addr, end);
+		if (vma) {
+			mmap_read_unlock(current->mm);
+			err = -EINVAL;
+			goto err_unlock_inode;
+		}
+		mmap_read_unlock(current->mm);
+
 		inode = d_inode(dentry);
 		if (inode == NULL) {
-			mmap_write_unlock(current->mm);
 			err = -EINVAL;
-			goto err_out;
+			goto err_unlock_inode;
 		}
 		info = inode->i_private;
 		dput(dentry);
@@ -272,7 +285,7 @@ SYSCALL_DEFINE5(mshare, const char __user *, name, unsigned long, addr,
 				MAP_FIXED | MAP_SHARED | MAP_ANONYMOUS, 0);
 		if (IS_ERR((void *)mapaddr)) {
 			err = -EINVAL;
-			goto err_out;
+			goto err_unlock_inode;
 		}
 
 		refcount_inc(&info->refcnt);
@@ -286,7 +299,7 @@ SYSCALL_DEFINE5(mshare, const char __user *, name, unsigned long, addr,
 		if (vma && vma->vm_start < addr) {
 			mmap_write_unlock(current->mm);
 			err = -EINVAL;
-			goto err_out;
+			goto err_unlock_inode;
 		}
 
 		while (vma && vma->vm_start < (addr + len)) {
@@ -296,6 +309,7 @@ SYSCALL_DEFINE5(mshare, const char __user *, name, unsigned long, addr,
 			next = vma->vm_next;
 			vma = next;
 		}
+		mmap_write_unlock(current->mm);
 	} else {
 		unsigned long myaddr;
 		struct mm_struct *old_mm;
@@ -325,11 +339,12 @@ SYSCALL_DEFINE5(mshare, const char __user *, name, unsigned long, addr,
 		 * over to newly created mm_struct. TODO: If VMAs do not
 		 * exist, create them and mark them as shared.
 		 */
-		mmap_write_lock(old_mm);
+		mmap_read_lock(old_mm);
 		vma = find_vma_intersection(old_mm, addr, end);
 		if (!vma) {
+			mmap_read_unlock(old_mm);
 			err = -EINVAL;
-			goto unlock;
+			goto free_info;
 		}
 		/*
 		 * TODO: If the currently allocated VMA goes beyond the
@@ -340,17 +355,21 @@ SYSCALL_DEFINE5(mshare, const char __user *, name, unsigned long, addr,
 		 */
 		vma = find_vma(old_mm, addr + len);
 		if (vma && vma->vm_start < (addr + len)) {
+			mmap_read_unlock(old_mm);
 			err = -EINVAL;
-			goto unlock;
+			goto free_info;
 		}
 
 		vma = find_vma(old_mm, addr);
 		if (vma && vma->vm_start < addr) {
+			mmap_read_unlock(old_mm);
 			err = -EINVAL;
-			goto unlock;
+			goto free_info;
 		}
+		mmap_read_unlock(old_mm);
 
 		mmap_write_lock(new_mm);
+		mmap_write_lock(old_mm);
 		while (vma && vma->vm_start < (addr + len)) {
 			/*
 			 * Copy this vma over to host mm
@@ -360,20 +379,21 @@ SYSCALL_DEFINE5(mshare, const char __user *, name, unsigned long, addr,
 			vma->vm_flags |= VM_SHARED_PT;
 			new_vma = vm_area_dup(vma);
 			if (!new_vma) {
+				mmap_write_unlock(new_mm);
+				mmap_write_unlock(old_mm);
 				err = -ENOMEM;
-				goto unlock;
+				goto free_info;
 			}
 			err = insert_vm_struct(new_mm, new_vma);
-			if (err)
-				goto unlock;
+			if (err) {
+				mmap_write_unlock(new_mm);
+				mmap_write_unlock(old_mm);
+				err = -ENOMEM;
+				goto free_info;
+			}
 
 			vma = vma->vm_next;
 		}
-		mmap_write_unlock(new_mm);
-
-		err = mshare_file_create(fname, oflag, info);
-		if (err)
-			goto unlock;
 
 		/*
 		 * Copy over current PTEs
@@ -387,15 +407,19 @@ SYSCALL_DEFINE5(mshare, const char __user *, name, unsigned long, addr,
 		 * TODO: Free the corresponding page table in calling
 		 * process
 		 */
+		mmap_write_unlock(old_mm);
+		mmap_write_unlock(new_mm);
+
+		err = mshare_file_create(fname, oflag, info);
+		if (err)
+			goto free_info;
 	}
 
-	mmap_write_unlock(current->mm);
 	inode_unlock(d_inode(msharefs_sb->s_root));
 	putname(fname);
 	return 0;
 
-unlock:
-	mmap_write_unlock(current->mm);
+free_info:
 	kfree(info);
 err_relmm:
 	mmput(new_mm);
-- 
2.32.0

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ