{ "UMAP", SYS_UMAP },
{ "VIRCOPY", SYS_VIRCOPY },
{ "PHYSCOPY", SYS_PHYSCOPY },
+ { "UMAP_REMOTE", SYS_UMAP_REMOTE },
{ "IRQCTL", SYS_IRQCTL },
{ "INT86", SYS_INT86 },
{ "DEVIO", SYS_DEVIO },
# 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() */
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)
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",
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(
{
pci device 1022/1103;
system
- UMAP # 14
+ UMAP_REMOTE # 17
;
uid 0;
};
#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 */
/* 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 */
#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
do_vdevio.c \
do_copy.c \
do_umap.c \
+ do_umap_remote.c \
do_memset.c \
do_setgrant.c \
do_privctl.c \
* 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 */
--- /dev/null
+/* 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 */
sys_times.c \
sys_trace.c \
sys_umap.c \
+ sys_umap_remote.c \
sys_update.c \
sys_vinb.c \
sys_vinl.c \
--- /dev/null
+#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);
+}
+
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;