]> Zhao Yanbai Git Server - minix.git/commitdiff
Split off sys_umap_remote from sys_umap
authorErik van der Kouwe <erik@minix3.org>
Fri, 10 Jun 2011 14:28:20 +0000 (14:28 +0000)
committerErik van der Kouwe <erik@minix3.org>
Fri, 10 Jun 2011 14:28:20 +0000 (14:28 +0000)
sys_umap now supports only:
- looking up the physical address of a virtual address in the address space
  of the caller;
- looking up the physical address of a grant for which the caller is the
  grantee.

This is enough for nearly all umap users. The new sys_umap_remote supports
lookups in arbitrary address spaces and grants for arbitrary grantees.

14 files changed:
commands/service/service.c
common/include/minix/com.h
common/include/minix/syslib.h
drivers/amddev/amddev.c
etc/system.conf
kernel/config.h
kernel/system.c
kernel/system.h
kernel/system/Makefile.inc
kernel/system/do_umap.c [changed mode: 0644->0755]
kernel/system/do_umap_remote.c [new file with mode: 0644]
lib/libsys/Makefile
lib/libsys/sys_umap_remote.c [new file with mode: 0755]
servers/pm/profile.c

index 291132d82519bb7da58ee9ae1eba74a3ed1bc6cf..04b4c565d76915f8ab2894ae87933b43cd9651b5 100644 (file)
@@ -1153,6 +1153,7 @@ struct
        { "UMAP",               SYS_UMAP },
        { "VIRCOPY",            SYS_VIRCOPY },
        { "PHYSCOPY",           SYS_PHYSCOPY },
+       { "UMAP_REMOTE",        SYS_UMAP_REMOTE },
        { "IRQCTL",             SYS_IRQCTL },
        { "INT86",              SYS_INT86 },
        { "DEVIO",              SYS_DEVIO },
index ef2c1dfd625a9be078ad66dfd43a095fb2e9d87d..1ae66b6fe867b35f5fb3ac040024ad524e0b1cef 100644 (file)
 #  define SYS_UMAP       (KERNEL_CALL + 14)    /* sys_umap() */
 #  define SYS_VIRCOPY    (KERNEL_CALL + 15)    /* sys_vircopy() */
 #  define SYS_PHYSCOPY   (KERNEL_CALL + 16)    /* sys_physcopy() */
+#  define SYS_UMAP_REMOTE (KERNEL_CALL + 17)   /* sys_umap_remote() */
 
 #  define SYS_IRQCTL     (KERNEL_CALL + 19)    /* sys_irqctl() */
 #  define SYS_INT86      (KERNEL_CALL + 20)    /* sys_int86() */
index 96ce031df52cd1037945b44cf586c838edb2c8bb..c899a51acab55bd93e5604874fb947afe868c5ee 100644 (file)
@@ -175,6 +175,8 @@ _PROTOTYPE(int sys_umap, (endpoint_t proc_ep, int seg, vir_bytes vir_addr,
         vir_bytes bytes, phys_bytes *phys_addr));
 _PROTOTYPE(int sys_umap_data_fb, (endpoint_t proc_ep, vir_bytes vir_addr,
         vir_bytes bytes, phys_bytes *phys_addr));
+_PROTOTYPE(int sys_umap_remote, (endpoint_t proc_ep, endpoint_t grantee,
+       int seg, vir_bytes vir_addr, vir_bytes bytes, phys_bytes *phys_addr));
 
 /* Shorthands for sys_getinfo() system call. */
 #define sys_getkmessages(dst)  sys_getinfo(GET_KMESSAGES, dst, 0,0,0)
index 02c74dbe8b046f3cbb7e78482f03fc68f06003b8..8f9528f24938794755f12fc957c090561d11ec95 100644 (file)
@@ -357,7 +357,7 @@ static int do_add(message *m)
                        size, proc);
                return EINVAL;
        }
-       r= sys_umap(proc, VM_D, (vir_bytes)start, size, &busaddr);
+       r= sys_umap_remote(proc, SELF, VM_D, (vir_bytes)start, size, &busaddr);
        if (r != OK)
        {
                printf("amddev`do_add: umap failed for 0x%x@0x%x, proc %d\n",
@@ -405,7 +405,7 @@ static int do_add4pci(const message *m)
 
        printf("amddev`do_add4pci: should check with PCI\n");
 
-       r= sys_umap(proc, VM_D, (vir_bytes)start, size, &busaddr);
+       r= sys_umap_remote(proc, SELF, VM_D, (vir_bytes)start, size, &busaddr);
        if (r != OK)
        {
                printf(
index 622910a0cfe03e0491f71a457d82d73c3ba01cd0..996046603cceedcb19378daa19d1846e8625e95b 100644 (file)
@@ -513,7 +513,7 @@ service amddev
 {
        pci device      1022/1103;
        system
-               UMAP            # 14
+               UMAP_REMOTE     # 17
        ;
        uid     0;
 };
index d3a43dfc18d2df4bc95a46399e138c410b37bc95..29f54056f065aad7d58f4c4664742aec93f0f31e 100644 (file)
@@ -37,6 +37,7 @@
 #define USE_IRQCTL                1    /* set an interrupt policy */
 #define USE_PRIVCTL               1    /* system privileges control */
 #define USE_UMAP                  1    /* map virtual to physical address */
+#define USE_UMAP_REMOTE           1    /* sys_umap on behalf of another process */
 #define USE_VIRCOPY       1    /* copy using virtual addressing */ 
 #define USE_PHYSCOPY      1    /* copy using physical addressing */
 #define USE_MEMSET        1    /* write char to a given memory area */
index d3d83a2d9f873701caf8f46c66c0e0f4c7b82349..e74baa1f666174b6d9e044d19fe8ac0402d46210 100644 (file)
@@ -222,6 +222,7 @@ PUBLIC void system_init(void)
 
   /* Copying. */
   map(SYS_UMAP, do_umap);              /* map virtual to physical address */
+  map(SYS_UMAP_REMOTE, do_umap_remote);        /* do_umap for non-caller process */
   map(SYS_VIRCOPY, do_vircopy);        /* use pure virtual addressing */
   map(SYS_PHYSCOPY, do_copy);          /* use physical addressing */
   map(SYS_SAFECOPYFROM, do_safecopy_from);/* copy with pre-granted permission */
index 187e6d0267dfe3ad23d6a09bbb8b17fd3d43a3d1..e34106d55405a63020cd03bdc4040d575cb21791 100644 (file)
@@ -87,6 +87,11 @@ _PROTOTYPE( int do_umap, (struct proc * caller, message *m_ptr) );
 #define do_umap NULL
 #endif
 
+_PROTOTYPE( int do_umap_remote, (struct proc * caller, message *m_ptr) );
+#if ! USE_UMAP_REMOTE
+#define do_umap_remote NULL
+#endif
+
 _PROTOTYPE( int do_memset, (struct proc * caller, message *m_ptr) );
 #if ! USE_MEMSET
 #define do_memset NULL
index acde53ca126ef1a086498dfb7f63eecdf6378174..34cf87f5a3a09bee8c0207a7ea9ad170fe78f2ea 100644 (file)
@@ -20,6 +20,7 @@ SRCS+=        \
        do_vdevio.c \
        do_copy.c \
        do_umap.c \
+       do_umap_remote.c \
        do_memset.c \
        do_setgrant.c \
        do_privctl.c \
old mode 100644 (file)
new mode 100755 (executable)
index eb83db7..f36d8e7
@@ -2,11 +2,11 @@
  *   m_type:   SYS_UMAP
  *
  * The parameters for this kernel call are:
- *    m5_i1:   CP_SRC_PROC_NR  (process number)        
+ *    m5_i1:   CP_SRC_PROC_NR  (process number)
  *    m5_s1:   CP_SRC_SPACE    (segment where address is: T, D, or S)
- *    m5_l1:   CP_SRC_ADDR     (virtual address)       
- *    m5_l2:   CP_DST_ADDR     (returns physical address)      
- *    m5_l3:   CP_NR_BYTES     (size of datastructure)         
+ *    m5_l1:   CP_SRC_ADDR     (virtual address)
+ *    m5_l2:   CP_DST_ADDR     (returns physical address)
+ *    m5_l3:   CP_NR_BYTES     (size of datastructure)
  */
 
 #include "kernel/system.h"
 
 #if USE_UMAP
 
+#if ! USE_UMAP_REMOTE
+#undef do_umap_remote
+#endif
+
 /*==========================================================================*
  *                             do_umap                                     *
  *==========================================================================*/
 PUBLIC int do_umap(struct proc * caller, message * m_ptr)
 {
-/* Map virtual address to physical, for non-kernel processes. */
-  int seg_type = m_ptr->CP_SRC_SPACE & SEGMENT_TYPE;
   int seg_index = m_ptr->CP_SRC_SPACE & SEGMENT_INDEX;
-  vir_bytes offset = m_ptr->CP_SRC_ADDR;
-  int count = m_ptr->CP_NR_BYTES;
   int endpt = (int) m_ptr->CP_SRC_ENDPT;
-  int proc_nr, r;
-  int naughty = 0;
-  phys_bytes phys_addr = 0, lin_addr = 0;
-  struct proc *targetpr;
-
-  /* Verify process number. */
-  if (endpt == SELF)
-       proc_nr = _ENDPOINT_P(caller->p_endpoint);
-  else
-       if (! isokendpt(endpt, &proc_nr))
-               return(EINVAL);
-  targetpr = proc_addr(proc_nr);
-
-  /* See which mapping should be made. */
-  switch(seg_type) {
-  case LOCAL_SEG:
-      phys_addr = lin_addr = umap_local(targetpr, seg_index, offset, count); 
-      if(!lin_addr) return EFAULT;
-      naughty = 1;
-      break;
-  case LOCAL_VM_SEG:
-    if(seg_index == MEM_GRANT) {
-       vir_bytes newoffset;
-       endpoint_t newep;
-       int new_proc_nr;
-       cp_grant_id_t grant = (cp_grant_id_t) offset;
-
-        if(verify_grant(targetpr->p_endpoint, caller->p_endpoint, grant, count,
-                0, 0, &newoffset, &newep) != OK) {
-                printf("SYSTEM: do_umap: verify_grant in %s, grant %d, bytes 0x%lx, failed, caller %s\n", targetpr->p_name, offset, count, caller->p_name);
-               proc_stacktrace(caller);
-                return EFAULT;
-        }
-
-        if(!isokendpt(newep, &new_proc_nr)) {
-                printf("SYSTEM: do_umap: isokendpt failed\n");
-                return EFAULT;
-        }
-
-       /* New lookup. */
-       offset = newoffset;
-       targetpr = proc_addr(new_proc_nr);
-       seg_index = D;
-      }
-
-      if(seg_index == T || seg_index == D || seg_index == S) {
-        phys_addr = lin_addr = umap_local(targetpr, seg_index, offset, count); 
-      } else {
-       printf("SYSTEM: bogus seg type 0x%lx\n", seg_index);
-       return EFAULT;
-      }
-      if(!lin_addr) {
-       printf("SYSTEM:do_umap: umap_local failed\n");
-       return EFAULT;
-      }
-      if(vm_lookup(targetpr, lin_addr, &phys_addr, NULL) != OK) {
-       printf("SYSTEM:do_umap: vm_lookup failed\n");
-       return EFAULT;
-      }
-      if(phys_addr == 0)
-       panic("vm_lookup returned zero physical address");
-      break;
-  default:
-      if((r=arch_umap(targetpr, offset, count, seg_type, &lin_addr))
-       != OK)
-       return r;
-      phys_addr = lin_addr;
-  }
-
-  if(vm_running && !vm_contiguous(targetpr, lin_addr, count)) {
-       printf("SYSTEM:do_umap: not contiguous\n");
-       return EFAULT;
-  }
 
-  m_ptr->CP_DST_ADDR = phys_addr;
-  if(naughty || phys_addr == 0) {
-         printf("kernel: umap 0x%x done by %d / %s, pc 0x%lx, 0x%lx -> 0x%lx\n",
-               seg_type, caller->p_endpoint, caller->p_name,
-               caller->p_reg.pc, offset, phys_addr);
-       printf("caller stack: ");
-       proc_stacktrace(caller);
-  }
-  return (phys_addr == 0) ? EFAULT: OK;
+  /* This call is a subset of umap_remote, it allows mapping virtual addresses
+   * in the caller's address space and grants where the caller is specified as
+   * grantee; after the security check we simply invoke do_umap_remote
+   */
+  if (seg_index != MEM_GRANT && endpt != SELF) return EPERM;
+  m_ptr->CP_DST_ENDPT = SELF;
+  return do_umap_remote(caller, m_ptr);
 }
 
 #endif /* USE_UMAP */
diff --git a/kernel/system/do_umap_remote.c b/kernel/system/do_umap_remote.c
new file mode 100644 (file)
index 0000000..7410f6a
--- /dev/null
@@ -0,0 +1,130 @@
+/* The kernel call implemented in this file:
+ *   m_type:   SYS_UMAP_REMOTE
+ *
+ * The parameters for this kernel call are:
+ *    m5_i1:   CP_SRC_PROC_NR  (process number)
+ *    m5_s1:   CP_SRC_SPACE    (segment where address is: T, D, or S)
+ *    m5_l1:   CP_SRC_ADDR     (virtual address)
+ *    m5_i2:   CP_DST_ENDPT    (process number of grantee to check access for)
+ *    m5_l2:   CP_DST_ADDR     (returns physical address)
+ *    m5_l3:   CP_NR_BYTES     (size of datastructure)
+ */
+
+#include "kernel/system.h"
+
+#include <minix/endpoint.h>
+
+#if USE_UMAP || USE_UMAP_REMOTE
+
+#if ! USE_UMAP_REMOTE
+#undef do_umap_remote
+#endif
+
+/*==========================================================================*
+ *                             do_umap_remote                              *
+ *==========================================================================*/
+PUBLIC int do_umap_remote(struct proc * caller, message * m_ptr)
+{
+/* Map virtual address to physical, for non-kernel processes. */
+  int seg_type = m_ptr->CP_SRC_SPACE & SEGMENT_TYPE;
+  int seg_index = m_ptr->CP_SRC_SPACE & SEGMENT_INDEX;
+  vir_bytes offset = m_ptr->CP_SRC_ADDR;
+  int count = m_ptr->CP_NR_BYTES;
+  int endpt = (int) m_ptr->CP_SRC_ENDPT;
+  endpoint_t grantee = (endpoint_t) m_ptr->CP_DST_ENDPT;
+  int proc_nr, proc_nr_grantee, r;
+  int naughty = 0;
+  phys_bytes phys_addr = 0, lin_addr = 0;
+  struct proc *targetpr;
+
+  /* Verify process number. */
+  if (endpt == SELF)
+       proc_nr = _ENDPOINT_P(caller->p_endpoint);
+  else
+       if (! isokendpt(endpt, &proc_nr))
+               return(EINVAL);
+  targetpr = proc_addr(proc_nr);
+
+  /* Verify grantee endpoint */
+  if (grantee == SELF) {
+       grantee = caller->p_endpoint;
+  } else if (grantee == NONE ||
+       grantee == ANY ||
+       seg_index != MEM_GRANT ||
+       !isokendpt(grantee, &proc_nr_grantee)) {
+       return EINVAL;
+  }
+
+  /* See which mapping should be made. */
+  switch(seg_type) {
+  case LOCAL_SEG:
+      phys_addr = lin_addr = umap_local(targetpr, seg_index, offset, count);
+      if(!lin_addr) return EFAULT;
+      naughty = 1;
+      break;
+  case LOCAL_VM_SEG:
+    if(seg_index == MEM_GRANT) {
+       vir_bytes newoffset;
+       endpoint_t newep;
+       int new_proc_nr;
+       cp_grant_id_t grant = (cp_grant_id_t) offset;
+
+        if(verify_grant(targetpr->p_endpoint, grantee, grant, count,
+                0, 0, &newoffset, &newep) != OK) {
+                printf("SYSTEM: do_umap: verify_grant in %s, grant %d, bytes 0x%lx, failed, caller %s\n", targetpr->p_name, offset, count, caller->p_name);
+               proc_stacktrace(caller);
+                return EFAULT;
+        }
+
+        if(!isokendpt(newep, &new_proc_nr)) {
+                printf("SYSTEM: do_umap: isokendpt failed\n");
+                return EFAULT;
+        }
+
+       /* New lookup. */
+       offset = newoffset;
+       targetpr = proc_addr(new_proc_nr);
+       seg_index = D;
+      }
+
+      if(seg_index == T || seg_index == D || seg_index == S) {
+        phys_addr = lin_addr = umap_local(targetpr, seg_index, offset, count);
+      } else {
+       printf("SYSTEM: bogus seg type 0x%lx\n", seg_index);
+       return EFAULT;
+      }
+      if(!lin_addr) {
+       printf("SYSTEM:do_umap: umap_local failed\n");
+       return EFAULT;
+      }
+      if(vm_lookup(targetpr, lin_addr, &phys_addr, NULL) != OK) {
+       printf("SYSTEM:do_umap: vm_lookup failed\n");
+       return EFAULT;
+      }
+      if(phys_addr == 0)
+       panic("vm_lookup returned zero physical address");
+      break;
+  default:
+      if((r=arch_umap(targetpr, offset, count, seg_type, &lin_addr))
+       != OK)
+       return r;
+      phys_addr = lin_addr;
+  }
+
+  if(vm_running && !vm_contiguous(targetpr, lin_addr, count)) {
+       printf("SYSTEM:do_umap: not contiguous\n");
+       return EFAULT;
+  }
+
+  m_ptr->CP_DST_ADDR = phys_addr;
+  if(naughty || phys_addr == 0) {
+         printf("kernel: umap 0x%x done by %d / %s, pc 0x%lx, 0x%lx -> 0x%lx\n",
+               seg_type, caller->p_endpoint, caller->p_name,
+               caller->p_reg.pc, offset, phys_addr);
+       printf("caller stack: ");
+       proc_stacktrace(caller);
+  }
+  return (phys_addr == 0) ? EFAULT: OK;
+}
+
+#endif /* USE_UMAP || USE_UMAP_REMOTE */
index 94579e0edb1ab0f75f396b897f13da8a01a69bac..6e239a054ec437b494c4b6ea8dcb9a8453291cc9 100644 (file)
@@ -97,6 +97,7 @@ SRCS=  \
        sys_times.c \
        sys_trace.c \
        sys_umap.c \
+       sys_umap_remote.c \
        sys_update.c \
        sys_vinb.c \
        sys_vinl.c \
diff --git a/lib/libsys/sys_umap_remote.c b/lib/libsys/sys_umap_remote.c
new file mode 100755 (executable)
index 0000000..876f2e9
--- /dev/null
@@ -0,0 +1,35 @@
+#include "syslib.h"
+
+/*===========================================================================*
+ *                                sys_umap_remote                           *
+ *===========================================================================*/
+PUBLIC int sys_umap_remote(proc_ep, grantee, seg, vir_addr, bytes, phys_addr)
+endpoint_t proc_ep;                    /* process number to do umap for */
+endpoint_t grantee;                    /* process nr to check as grantee */
+int seg;                               /* T, D, or S segment */
+vir_bytes vir_addr;                    /* address in bytes with segment*/
+vir_bytes bytes;                       /* number of bytes to be copied */
+phys_bytes *phys_addr;                 /* placeholder for result */
+{
+    message m;
+    int result;
+
+    /* Note about the grantee parameter:
+     * - Is ignored for non-grant umap calls, but should be SELF to
+     *   pass the sanity check in that case;
+     * - May be SELF to get the same behaviour as sys_umap, namely that the
+     *   caller must be the grantee;
+     * - In all other cases, should be a valid endpoint (neither ANY nor NONE).
+     */
+
+    m.CP_SRC_ENDPT = proc_ep;
+    m.CP_DST_ENDPT = grantee;
+    m.CP_SRC_SPACE = seg;
+    m.CP_SRC_ADDR = vir_addr;
+    m.CP_NR_BYTES = bytes;
+
+    result = _kernel_call(SYS_UMAP_REMOTE, &m);
+    *phys_addr = m.CP_DST_ADDR;
+    return(result);
+}
+
index c7e2b06eaa3a27fc8a680937c38c9a4f5b3887cc..ec916ab2dfa23921bdf32086bffb78e7e3529f29 100644 (file)
@@ -97,13 +97,13 @@ int info_size;
   phys_bytes p;
 
   /* Check if supplied pointers point into user process. */
-  if ((r = sys_umap(who_e, VM_D, (vir_bytes) m_in.PROF_CTL_PTR,
+  if ((r = sys_umap_remote(who_e, SELF, VM_D, (vir_bytes) m_in.PROF_CTL_PTR,
                                                 1, &p)) != OK) {
        printf("PM: PROFILE: umap failed for process %d\n", who_e);
        return r;                                    
   }  
 
-  if ((r =sys_umap(who_e, VM_D, (vir_bytes) m_in.PROF_MEM_PTR,
+  if ((r =sys_umap_remote(who_e, SELF, VM_D, (vir_bytes) m_in.PROF_MEM_PTR,
                                         1, &p)) != OK) {
        printf("PM: PROFILE: umap failed for process %d\n", who_e);
        return r;