1*433d6423SLionel Sambuc /* The kernel call implemented in this file: 2*433d6423SLionel Sambuc * m_type: SYS_SAFECOPYFROM or SYS_SAFECOPYTO or SYS_VSAFECOPY 3*433d6423SLionel Sambuc * 4*433d6423SLionel Sambuc * The parameters for this kernel call are: 5*433d6423SLionel Sambuc * m_lsys_kern_safecopy.from_to other endpoint 6*433d6423SLionel Sambuc * m_lsys_kern_safecopy.gid grant id 7*433d6423SLionel Sambuc * m_lsys_kern_safecopy.offset offset within granted space 8*433d6423SLionel Sambuc * m_lsys_kern_safecopy.address address in own address space 9*433d6423SLionel Sambuc * m_lsys_kern_safecopy.bytes bytes to be copied 10*433d6423SLionel Sambuc * 11*433d6423SLionel Sambuc * For the vectored variant (do_vsafecopy): 12*433d6423SLionel Sambuc * m_lsys_kern_vsafecopy.vec_addr address of vector 13*433d6423SLionel Sambuc * m_lsys_kern_vsafecopy.vec_size number of significant elements in vector 14*433d6423SLionel Sambuc */ 15*433d6423SLionel Sambuc 16*433d6423SLionel Sambuc #include <assert.h> 17*433d6423SLionel Sambuc 18*433d6423SLionel Sambuc #include "kernel/system.h" 19*433d6423SLionel Sambuc #include "kernel/kernel.h" 20*433d6423SLionel Sambuc #include "kernel/vm.h" 21*433d6423SLionel Sambuc 22*433d6423SLionel Sambuc #define MAX_INDIRECT_DEPTH 5 /* up to how many indirect grants to follow? */ 23*433d6423SLionel Sambuc 24*433d6423SLionel Sambuc #define MEM_TOP 0xFFFFFFFFUL 25*433d6423SLionel Sambuc 26*433d6423SLionel Sambuc static int safecopy(struct proc *, endpoint_t, endpoint_t, 27*433d6423SLionel Sambuc cp_grant_id_t, size_t, vir_bytes, vir_bytes, int); 28*433d6423SLionel Sambuc 29*433d6423SLionel Sambuc #define HASGRANTTABLE(gr) \ 30*433d6423SLionel Sambuc (priv(gr) && priv(gr)->s_grant_table) 31*433d6423SLionel Sambuc 32*433d6423SLionel Sambuc /*===========================================================================* 33*433d6423SLionel Sambuc * verify_grant * 34*433d6423SLionel Sambuc *===========================================================================*/ 35*433d6423SLionel Sambuc int verify_grant(granter, grantee, grant, bytes, access, 36*433d6423SLionel Sambuc offset_in, offset_result, e_granter, flags) 37*433d6423SLionel Sambuc endpoint_t granter, grantee; /* copyee, copyer */ 38*433d6423SLionel Sambuc cp_grant_id_t grant; /* grant id */ 39*433d6423SLionel Sambuc vir_bytes bytes; /* copy size */ 40*433d6423SLionel Sambuc int access; /* direction (read/write) */ 41*433d6423SLionel Sambuc vir_bytes offset_in; /* copy offset within grant */ 42*433d6423SLionel Sambuc vir_bytes *offset_result; /* copy offset within virtual address space */ 43*433d6423SLionel Sambuc endpoint_t *e_granter; /* new granter (magic grants) */ 44*433d6423SLionel Sambuc u32_t *flags; /* CPF_* */ 45*433d6423SLionel Sambuc { 46*433d6423SLionel Sambuc static cp_grant_t g; 47*433d6423SLionel Sambuc static int proc_nr; 48*433d6423SLionel Sambuc static const struct proc *granter_proc; 49*433d6423SLionel Sambuc int depth = 0; 50*433d6423SLionel Sambuc 51*433d6423SLionel Sambuc do { 52*433d6423SLionel Sambuc /* Get granter process slot (if valid), and check range of 53*433d6423SLionel Sambuc * grant id. 54*433d6423SLionel Sambuc */ 55*433d6423SLionel Sambuc if(!isokendpt(granter, &proc_nr) ) { 56*433d6423SLionel Sambuc printf( 57*433d6423SLionel Sambuc "grant verify failed: invalid granter %d\n", (int) granter); 58*433d6423SLionel Sambuc return(EINVAL); 59*433d6423SLionel Sambuc } 60*433d6423SLionel Sambuc if(!GRANT_VALID(grant)) { 61*433d6423SLionel Sambuc printf( 62*433d6423SLionel Sambuc "grant verify failed: invalid grant %d\n", (int) grant); 63*433d6423SLionel Sambuc return(EINVAL); 64*433d6423SLionel Sambuc } 65*433d6423SLionel Sambuc granter_proc = proc_addr(proc_nr); 66*433d6423SLionel Sambuc 67*433d6423SLionel Sambuc /* If there is no priv. structure, or no grant table in the 68*433d6423SLionel Sambuc * priv. structure, or the grant table in the priv. structure 69*433d6423SLionel Sambuc * is too small for the grant, return EPERM. 70*433d6423SLionel Sambuc */ 71*433d6423SLionel Sambuc if(!HASGRANTTABLE(granter_proc)) { 72*433d6423SLionel Sambuc printf( 73*433d6423SLionel Sambuc "grant verify failed: granter %d has no grant table\n", 74*433d6423SLionel Sambuc granter); 75*433d6423SLionel Sambuc return(EPERM); 76*433d6423SLionel Sambuc } 77*433d6423SLionel Sambuc 78*433d6423SLionel Sambuc if(priv(granter_proc)->s_grant_entries <= grant) { 79*433d6423SLionel Sambuc printf( 80*433d6423SLionel Sambuc "verify_grant: grant verify failed in ep %d " 81*433d6423SLionel Sambuc "proc %d: grant %d out of range " 82*433d6423SLionel Sambuc "for table size %d\n", 83*433d6423SLionel Sambuc granter, proc_nr, grant, 84*433d6423SLionel Sambuc priv(granter_proc)->s_grant_entries); 85*433d6423SLionel Sambuc return(EPERM); 86*433d6423SLionel Sambuc } 87*433d6423SLionel Sambuc 88*433d6423SLionel Sambuc /* Copy the grant entry corresponding to this id to see what it 89*433d6423SLionel Sambuc * looks like. If it fails, hide the fact that granter has 90*433d6423SLionel Sambuc * (presumably) set an invalid grant table entry by returning 91*433d6423SLionel Sambuc * EPERM, just like with an invalid grant id. 92*433d6423SLionel Sambuc */ 93*433d6423SLionel Sambuc if(data_copy(granter, 94*433d6423SLionel Sambuc priv(granter_proc)->s_grant_table + sizeof(g)*grant, 95*433d6423SLionel Sambuc KERNEL, (vir_bytes) &g, sizeof(g)) != OK) { 96*433d6423SLionel Sambuc printf( 97*433d6423SLionel Sambuc "verify_grant: grant verify: data_copy failed\n"); 98*433d6423SLionel Sambuc return EPERM; 99*433d6423SLionel Sambuc } 100*433d6423SLionel Sambuc 101*433d6423SLionel Sambuc if(flags) *flags = g.cp_flags; 102*433d6423SLionel Sambuc 103*433d6423SLionel Sambuc /* Check validity. */ 104*433d6423SLionel Sambuc if((g.cp_flags & (CPF_USED | CPF_VALID)) != 105*433d6423SLionel Sambuc (CPF_USED | CPF_VALID)) { 106*433d6423SLionel Sambuc printf( 107*433d6423SLionel Sambuc "verify_grant: grant failed: invalid (%d flags 0x%lx)\n", 108*433d6423SLionel Sambuc grant, g.cp_flags); 109*433d6423SLionel Sambuc return EPERM; 110*433d6423SLionel Sambuc } 111*433d6423SLionel Sambuc 112*433d6423SLionel Sambuc /* The given grant may be an indirect grant, that is, a grant 113*433d6423SLionel Sambuc * that provides permission to use a grant given to the 114*433d6423SLionel Sambuc * granter (i.e., for which it is the grantee). This can lead 115*433d6423SLionel Sambuc * to a chain of indirect grants which must be followed back. 116*433d6423SLionel Sambuc */ 117*433d6423SLionel Sambuc if((g.cp_flags & CPF_INDIRECT)) { 118*433d6423SLionel Sambuc /* Stop after a few iterations. There may be a loop. */ 119*433d6423SLionel Sambuc if (depth == MAX_INDIRECT_DEPTH) { 120*433d6423SLionel Sambuc printf( 121*433d6423SLionel Sambuc "verify grant: indirect grant verify " 122*433d6423SLionel Sambuc "failed: exceeded maximum depth\n"); 123*433d6423SLionel Sambuc return ELOOP; 124*433d6423SLionel Sambuc } 125*433d6423SLionel Sambuc depth++; 126*433d6423SLionel Sambuc 127*433d6423SLionel Sambuc /* Verify actual grantee. */ 128*433d6423SLionel Sambuc if(g.cp_u.cp_indirect.cp_who_to != grantee && 129*433d6423SLionel Sambuc grantee != ANY && 130*433d6423SLionel Sambuc g.cp_u.cp_indirect.cp_who_to != ANY) { 131*433d6423SLionel Sambuc printf( 132*433d6423SLionel Sambuc "verify_grant: indirect grant verify " 133*433d6423SLionel Sambuc "failed: bad grantee\n"); 134*433d6423SLionel Sambuc return EPERM; 135*433d6423SLionel Sambuc } 136*433d6423SLionel Sambuc 137*433d6423SLionel Sambuc /* Start over with new granter, grant, and grantee. */ 138*433d6423SLionel Sambuc grantee = granter; 139*433d6423SLionel Sambuc granter = g.cp_u.cp_indirect.cp_who_from; 140*433d6423SLionel Sambuc grant = g.cp_u.cp_indirect.cp_grant; 141*433d6423SLionel Sambuc } 142*433d6423SLionel Sambuc } while(g.cp_flags & CPF_INDIRECT); 143*433d6423SLionel Sambuc 144*433d6423SLionel Sambuc /* Check access of grant. */ 145*433d6423SLionel Sambuc if(((g.cp_flags & access) != access)) { 146*433d6423SLionel Sambuc printf( 147*433d6423SLionel Sambuc "verify_grant: grant verify failed: access invalid; want 0x%x, have 0x%x\n", 148*433d6423SLionel Sambuc access, g.cp_flags); 149*433d6423SLionel Sambuc return EPERM; 150*433d6423SLionel Sambuc } 151*433d6423SLionel Sambuc 152*433d6423SLionel Sambuc if((g.cp_flags & CPF_DIRECT)) { 153*433d6423SLionel Sambuc /* Don't fiddle around with grants that wrap, arithmetic 154*433d6423SLionel Sambuc * below may be confused. 155*433d6423SLionel Sambuc */ 156*433d6423SLionel Sambuc if(MEM_TOP - g.cp_u.cp_direct.cp_len + 1 < 157*433d6423SLionel Sambuc g.cp_u.cp_direct.cp_start) { 158*433d6423SLionel Sambuc printf( 159*433d6423SLionel Sambuc "verify_grant: direct grant verify failed: len too long\n"); 160*433d6423SLionel Sambuc return EPERM; 161*433d6423SLionel Sambuc } 162*433d6423SLionel Sambuc 163*433d6423SLionel Sambuc /* Verify actual grantee. */ 164*433d6423SLionel Sambuc if(g.cp_u.cp_direct.cp_who_to != grantee && grantee != ANY 165*433d6423SLionel Sambuc && g.cp_u.cp_direct.cp_who_to != ANY) { 166*433d6423SLionel Sambuc printf( 167*433d6423SLionel Sambuc "verify_grant: direct grant verify failed: bad grantee\n"); 168*433d6423SLionel Sambuc return EPERM; 169*433d6423SLionel Sambuc } 170*433d6423SLionel Sambuc 171*433d6423SLionel Sambuc /* Verify actual copy range. */ 172*433d6423SLionel Sambuc if((offset_in+bytes < offset_in) || 173*433d6423SLionel Sambuc offset_in+bytes > g.cp_u.cp_direct.cp_len) { 174*433d6423SLionel Sambuc printf( 175*433d6423SLionel Sambuc "verify_grant: direct grant verify failed: bad size or range. " 176*433d6423SLionel Sambuc "granted %d bytes @ 0x%lx; wanted %d bytes @ 0x%lx\n", 177*433d6423SLionel Sambuc g.cp_u.cp_direct.cp_len, 178*433d6423SLionel Sambuc g.cp_u.cp_direct.cp_start, 179*433d6423SLionel Sambuc bytes, offset_in); 180*433d6423SLionel Sambuc return EPERM; 181*433d6423SLionel Sambuc } 182*433d6423SLionel Sambuc 183*433d6423SLionel Sambuc /* Verify successful - tell caller what address it is. */ 184*433d6423SLionel Sambuc *offset_result = g.cp_u.cp_direct.cp_start + offset_in; 185*433d6423SLionel Sambuc *e_granter = granter; 186*433d6423SLionel Sambuc } else if(g.cp_flags & CPF_MAGIC) { 187*433d6423SLionel Sambuc /* Currently, it is hardcoded that only FS may do 188*433d6423SLionel Sambuc * magic grants. 189*433d6423SLionel Sambuc */ 190*433d6423SLionel Sambuc if(granter != VFS_PROC_NR) { 191*433d6423SLionel Sambuc printf( 192*433d6423SLionel Sambuc "verify_grant: magic grant verify failed: granter (%d) " 193*433d6423SLionel Sambuc "is not FS (%d)\n", granter, VFS_PROC_NR); 194*433d6423SLionel Sambuc return EPERM; 195*433d6423SLionel Sambuc } 196*433d6423SLionel Sambuc 197*433d6423SLionel Sambuc /* Verify actual grantee. */ 198*433d6423SLionel Sambuc if(g.cp_u.cp_magic.cp_who_to != grantee && grantee != ANY 199*433d6423SLionel Sambuc && g.cp_u.cp_direct.cp_who_to != ANY) { 200*433d6423SLionel Sambuc printf( 201*433d6423SLionel Sambuc "verify_grant: magic grant verify failed: bad grantee\n"); 202*433d6423SLionel Sambuc return EPERM; 203*433d6423SLionel Sambuc } 204*433d6423SLionel Sambuc 205*433d6423SLionel Sambuc /* Verify actual copy range. */ 206*433d6423SLionel Sambuc if((offset_in+bytes < offset_in) || 207*433d6423SLionel Sambuc offset_in+bytes > g.cp_u.cp_magic.cp_len) { 208*433d6423SLionel Sambuc printf( 209*433d6423SLionel Sambuc "verify_grant: magic grant verify failed: bad size or range. " 210*433d6423SLionel Sambuc "granted %d bytes @ 0x%lx; wanted %d bytes @ 0x%lx\n", 211*433d6423SLionel Sambuc g.cp_u.cp_magic.cp_len, 212*433d6423SLionel Sambuc g.cp_u.cp_magic.cp_start, 213*433d6423SLionel Sambuc bytes, offset_in); 214*433d6423SLionel Sambuc return EPERM; 215*433d6423SLionel Sambuc } 216*433d6423SLionel Sambuc 217*433d6423SLionel Sambuc /* Verify successful - tell caller what address it is. */ 218*433d6423SLionel Sambuc *offset_result = g.cp_u.cp_magic.cp_start + offset_in; 219*433d6423SLionel Sambuc *e_granter = g.cp_u.cp_magic.cp_who_from; 220*433d6423SLionel Sambuc } else { 221*433d6423SLionel Sambuc printf( 222*433d6423SLionel Sambuc "verify_grant: grant verify failed: unknown grant type\n"); 223*433d6423SLionel Sambuc return EPERM; 224*433d6423SLionel Sambuc } 225*433d6423SLionel Sambuc 226*433d6423SLionel Sambuc return OK; 227*433d6423SLionel Sambuc } 228*433d6423SLionel Sambuc 229*433d6423SLionel Sambuc /*===========================================================================* 230*433d6423SLionel Sambuc * safecopy * 231*433d6423SLionel Sambuc *===========================================================================*/ 232*433d6423SLionel Sambuc static int safecopy(caller, granter, grantee, grantid, bytes, 233*433d6423SLionel Sambuc g_offset, addr, access) 234*433d6423SLionel Sambuc struct proc * caller; 235*433d6423SLionel Sambuc endpoint_t granter, grantee; 236*433d6423SLionel Sambuc cp_grant_id_t grantid; 237*433d6423SLionel Sambuc size_t bytes; 238*433d6423SLionel Sambuc vir_bytes g_offset, addr; 239*433d6423SLionel Sambuc int access; /* CPF_READ for a copy from granter to grantee, CPF_WRITE 240*433d6423SLionel Sambuc * for a copy from grantee to granter. 241*433d6423SLionel Sambuc */ 242*433d6423SLionel Sambuc { 243*433d6423SLionel Sambuc static struct vir_addr v_src, v_dst; 244*433d6423SLionel Sambuc static vir_bytes v_offset; 245*433d6423SLionel Sambuc endpoint_t new_granter, *src, *dst; 246*433d6423SLionel Sambuc struct proc *granter_p; 247*433d6423SLionel Sambuc int r; 248*433d6423SLionel Sambuc u32_t flags; 249*433d6423SLionel Sambuc #if PERF_USE_COW_SAFECOPY 250*433d6423SLionel Sambuc vir_bytes size; 251*433d6423SLionel Sambuc #endif 252*433d6423SLionel Sambuc 253*433d6423SLionel Sambuc if(granter == NONE || grantee == NONE) { 254*433d6423SLionel Sambuc printf("safecopy: nonsense processes\n"); 255*433d6423SLionel Sambuc return EFAULT; 256*433d6423SLionel Sambuc } 257*433d6423SLionel Sambuc 258*433d6423SLionel Sambuc /* See if there is a reasonable grant table. */ 259*433d6423SLionel Sambuc if(!(granter_p = endpoint_lookup(granter))) return EINVAL; 260*433d6423SLionel Sambuc if(!HASGRANTTABLE(granter_p)) { 261*433d6423SLionel Sambuc printf( 262*433d6423SLionel Sambuc "safecopy failed: granter %d has no grant table\n", granter); 263*433d6423SLionel Sambuc return(EPERM); 264*433d6423SLionel Sambuc } 265*433d6423SLionel Sambuc 266*433d6423SLionel Sambuc /* Decide who is src and who is dst. */ 267*433d6423SLionel Sambuc if(access & CPF_READ) { 268*433d6423SLionel Sambuc src = &granter; 269*433d6423SLionel Sambuc dst = &grantee; 270*433d6423SLionel Sambuc } else { 271*433d6423SLionel Sambuc src = &grantee; 272*433d6423SLionel Sambuc dst = &granter; 273*433d6423SLionel Sambuc } 274*433d6423SLionel Sambuc 275*433d6423SLionel Sambuc /* Verify permission exists. */ 276*433d6423SLionel Sambuc if((r=verify_grant(granter, grantee, grantid, bytes, access, 277*433d6423SLionel Sambuc g_offset, &v_offset, &new_granter, &flags)) != OK) { 278*433d6423SLionel Sambuc printf( 279*433d6423SLionel Sambuc "grant %d verify to copy %d->%d by %d failed: err %d\n", 280*433d6423SLionel Sambuc grantid, *src, *dst, grantee, r); 281*433d6423SLionel Sambuc return r; 282*433d6423SLionel Sambuc } 283*433d6423SLionel Sambuc 284*433d6423SLionel Sambuc /* verify_grant() can redirect the grantee to someone else, 285*433d6423SLionel Sambuc * meaning the source or destination changes. 286*433d6423SLionel Sambuc */ 287*433d6423SLionel Sambuc granter = new_granter; 288*433d6423SLionel Sambuc 289*433d6423SLionel Sambuc /* Now it's a regular copy. */ 290*433d6423SLionel Sambuc v_src.proc_nr_e = *src; 291*433d6423SLionel Sambuc v_dst.proc_nr_e = *dst; 292*433d6423SLionel Sambuc 293*433d6423SLionel Sambuc /* Now the offset in virtual addressing is known in 'offset'. 294*433d6423SLionel Sambuc * Depending on the access, this is the source or destination 295*433d6423SLionel Sambuc * address. 296*433d6423SLionel Sambuc */ 297*433d6423SLionel Sambuc if(access & CPF_READ) { 298*433d6423SLionel Sambuc v_src.offset = v_offset; 299*433d6423SLionel Sambuc v_dst.offset = (vir_bytes) addr; 300*433d6423SLionel Sambuc } else { 301*433d6423SLionel Sambuc v_src.offset = (vir_bytes) addr; 302*433d6423SLionel Sambuc v_dst.offset = v_offset; 303*433d6423SLionel Sambuc } 304*433d6423SLionel Sambuc 305*433d6423SLionel Sambuc /* Do the regular copy. */ 306*433d6423SLionel Sambuc if(flags & CPF_TRY) { 307*433d6423SLionel Sambuc int r; 308*433d6423SLionel Sambuc /* Try copy without transparently faulting in pages. */ 309*433d6423SLionel Sambuc r = virtual_copy(&v_src, &v_dst, bytes); 310*433d6423SLionel Sambuc if(r == EFAULT_SRC || r == EFAULT_DST) return EFAULT; 311*433d6423SLionel Sambuc return r; 312*433d6423SLionel Sambuc } 313*433d6423SLionel Sambuc return virtual_copy_vmcheck(caller, &v_src, &v_dst, bytes); 314*433d6423SLionel Sambuc } 315*433d6423SLionel Sambuc 316*433d6423SLionel Sambuc /*===========================================================================* 317*433d6423SLionel Sambuc * do_safecopy_to * 318*433d6423SLionel Sambuc *===========================================================================*/ 319*433d6423SLionel Sambuc int do_safecopy_to(struct proc * caller, message * m_ptr) 320*433d6423SLionel Sambuc { 321*433d6423SLionel Sambuc return safecopy(caller, m_ptr->m_lsys_kern_safecopy.from_to, caller->p_endpoint, 322*433d6423SLionel Sambuc (cp_grant_id_t) m_ptr->m_lsys_kern_safecopy.gid, 323*433d6423SLionel Sambuc m_ptr->m_lsys_kern_safecopy.bytes, m_ptr->m_lsys_kern_safecopy.offset, 324*433d6423SLionel Sambuc (vir_bytes) m_ptr->m_lsys_kern_safecopy.address, CPF_WRITE); 325*433d6423SLionel Sambuc } 326*433d6423SLionel Sambuc 327*433d6423SLionel Sambuc /*===========================================================================* 328*433d6423SLionel Sambuc * do_safecopy_from * 329*433d6423SLionel Sambuc *===========================================================================*/ 330*433d6423SLionel Sambuc int do_safecopy_from(struct proc * caller, message * m_ptr) 331*433d6423SLionel Sambuc { 332*433d6423SLionel Sambuc return safecopy(caller, m_ptr->m_lsys_kern_safecopy.from_to, caller->p_endpoint, 333*433d6423SLionel Sambuc (cp_grant_id_t) m_ptr->m_lsys_kern_safecopy.gid, 334*433d6423SLionel Sambuc m_ptr->m_lsys_kern_safecopy.bytes, m_ptr->m_lsys_kern_safecopy.offset, 335*433d6423SLionel Sambuc (vir_bytes) m_ptr->m_lsys_kern_safecopy.address, CPF_READ); 336*433d6423SLionel Sambuc } 337*433d6423SLionel Sambuc 338*433d6423SLionel Sambuc /*===========================================================================* 339*433d6423SLionel Sambuc * do_vsafecopy * 340*433d6423SLionel Sambuc *===========================================================================*/ 341*433d6423SLionel Sambuc int do_vsafecopy(struct proc * caller, message * m_ptr) 342*433d6423SLionel Sambuc { 343*433d6423SLionel Sambuc static struct vscp_vec vec[SCPVEC_NR]; 344*433d6423SLionel Sambuc static struct vir_addr src, dst; 345*433d6423SLionel Sambuc int r, i, els; 346*433d6423SLionel Sambuc size_t bytes; 347*433d6423SLionel Sambuc 348*433d6423SLionel Sambuc /* Set vector copy parameters. */ 349*433d6423SLionel Sambuc src.proc_nr_e = caller->p_endpoint; 350*433d6423SLionel Sambuc assert(src.proc_nr_e != NONE); 351*433d6423SLionel Sambuc src.offset = (vir_bytes) m_ptr->m_lsys_kern_vsafecopy.vec_addr; 352*433d6423SLionel Sambuc dst.proc_nr_e = KERNEL; 353*433d6423SLionel Sambuc dst.offset = (vir_bytes) vec; 354*433d6423SLionel Sambuc 355*433d6423SLionel Sambuc /* No. of vector elements. */ 356*433d6423SLionel Sambuc els = m_ptr->m_lsys_kern_vsafecopy.vec_size; 357*433d6423SLionel Sambuc bytes = els * sizeof(struct vscp_vec); 358*433d6423SLionel Sambuc 359*433d6423SLionel Sambuc /* Obtain vector of copies. */ 360*433d6423SLionel Sambuc if((r=virtual_copy_vmcheck(caller, &src, &dst, bytes)) != OK) 361*433d6423SLionel Sambuc return r; 362*433d6423SLionel Sambuc 363*433d6423SLionel Sambuc /* Perform safecopies. */ 364*433d6423SLionel Sambuc for(i = 0; i < els; i++) { 365*433d6423SLionel Sambuc int access; 366*433d6423SLionel Sambuc endpoint_t granter; 367*433d6423SLionel Sambuc if(vec[i].v_from == SELF) { 368*433d6423SLionel Sambuc access = CPF_WRITE; 369*433d6423SLionel Sambuc granter = vec[i].v_to; 370*433d6423SLionel Sambuc } else if(vec[i].v_to == SELF) { 371*433d6423SLionel Sambuc access = CPF_READ; 372*433d6423SLionel Sambuc granter = vec[i].v_from; 373*433d6423SLionel Sambuc } else { 374*433d6423SLionel Sambuc printf("vsafecopy: %d: element %d/%d: no SELF found\n", 375*433d6423SLionel Sambuc caller->p_endpoint, i, els); 376*433d6423SLionel Sambuc return EINVAL; 377*433d6423SLionel Sambuc } 378*433d6423SLionel Sambuc 379*433d6423SLionel Sambuc /* Do safecopy for this element. */ 380*433d6423SLionel Sambuc if((r=safecopy(caller, granter, caller->p_endpoint, 381*433d6423SLionel Sambuc vec[i].v_gid, 382*433d6423SLionel Sambuc vec[i].v_bytes, vec[i].v_offset, 383*433d6423SLionel Sambuc vec[i].v_addr, access)) != OK) { 384*433d6423SLionel Sambuc return r; 385*433d6423SLionel Sambuc } 386*433d6423SLionel Sambuc } 387*433d6423SLionel Sambuc 388*433d6423SLionel Sambuc return OK; 389*433d6423SLionel Sambuc } 390*433d6423SLionel Sambuc 391