xref: /minix3/minix/kernel/system/do_safecopy.c (revision 433d6423c39e34ec4b79c950597bb2d236f886be)
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