bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 05/17] gsync: Use copyin()/copyout() to access user memory


From: Sergey Bugaev
Subject: [PATCH 05/17] gsync: Use copyin()/copyout() to access user memory
Date: Wed, 27 Mar 2024 19:18:29 +0300

Depending on the architecture and setup, it may not be possible to
access user memory directly, for example, due to user mode mappings not
being accessible from kernel mode (x86 SMAP, AArch64 PAN). There are
dedicated machine-specific copyin()/copyout() routines that know how to
access user memory from the kernel; use them.
---
 kern/gsync.c | 38 +++++++++++++++++++++++++++++++-------
 1 file changed, 31 insertions(+), 7 deletions(-)

diff --git a/kern/gsync.c b/kern/gsync.c
index 31b564ca..656e47dd 100644
--- a/kern/gsync.c
+++ b/kern/gsync.c
@@ -23,6 +23,7 @@
 #include <kern/list.h>
 #include <vm/vm_map.h>
 #include <vm/vm_kern.h>
+#include <machine/locore.h>
 
 /* An entry in the global hash table. */
 struct gsync_hbucket
@@ -254,9 +255,28 @@ kern_return_t gsync_wait (task_t task, vm_offset_t addr,
 
   boolean_t equal;
   if (! remote)
-    equal = ((unsigned int *)addr)[0] == lo &&
-      ((flags & GSYNC_QUAD) == 0 ||
-       ((unsigned int *)addr)[1] == hi);
+    {
+      unsigned int value;
+
+      if (copyin ((const void *) addr, &value, 4))
+       {
+         vm_map_unlock_read (task->map);
+         kmutex_unlock (&hbp->lock);
+         return KERN_INVALID_ADDRESS;
+       }
+
+      equal = (value == lo);
+      if (flags & GSYNC_QUAD)
+       {
+         if (copyin ((const void *) (addr + 4), &value, 4))
+           {
+             vm_map_unlock_read (task->map);
+             kmutex_unlock (&hbp->lock);
+             return KERN_INVALID_ADDRESS;
+           }
+         equal = equal && (value == hi);
+       }
+    }
   else
     {
       vm_offset_t paddr = temp_mapping (&va, addr, VM_PROT_READ);
@@ -388,11 +408,15 @@ kern_return_t gsync_wake (task_t task,
             }
 
           addr = paddr + (addr & (PAGE_SIZE - 1));
+          *(unsigned int *)addr = val;
+          vm_map_remove (kernel_map, addr, addr + sizeof (int));
+        }
+      else if (copyout (&val, (void *) addr, 4))
+        {
+          kmutex_unlock (&hbp->lock);
+          vm_map_unlock_read (task->map);
+          return KERN_INVALID_ADDRESS;
         }
-
-      *(unsigned int *)addr = val;
-      if (task != current_task ())
-        vm_map_remove (kernel_map, addr, addr + sizeof (int));
     }
 
   vm_map_unlock_read (task->map);
-- 
2.44.0




reply via email to

[Prev in Thread] Current Thread [Next in Thread]