|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /*
26: * Copyright (c) 1997 Apple Computer, Inc. All rights reserved.
27: * Copyright (c) 1994 NeXT Computer, Inc. All rights reserved.
28: *
29: * machdep/ppc/fault_copy.c
30: *
31: * Machine dependent code for kernel user copy
32: *
33: * History :
34: * 22-Jul-1998 Umesh Vaishampayan ([email protected])
35: * Added safe_bzero().
36: *
37: * 30-Mar-1998 Umesh Vaishampayan ([email protected])
38: * Made the copy routines more robust.
39: *
40: * 22-Sep-1997 Umesh Vaishampayan ([email protected])
41: * Fixed error return from ENOENT to ENAMETOOLONG.
42: *
43: * March, 1997 Umesh Vaishampayan [[email protected]]
44: * Created from sparc.
45: *
46: */
47:
48: #include <diagnostic.h>
49: #include <mach/mach_types.h>
50: #include <sys/param.h>
51: #include <sys/errno.h>
52: #include <machine/setjmp.h>
53: #include <machine/label_t.h>
54:
55: #undef NBSEG
56: #define NBSEG 0x10000000
57: #undef SEGMASK
58: #define SEGMASK (NBSEG-1)
59: #define PGOFFSET(x) ((unsigned)x & (NBPG-1))
60: #undef SEGOFFSET
61: #define SEGOFFSET(x) ((unsigned)(x) & SEGMASK)
62:
63:
64: caddr_t cioseg(space_t space, caddr_t addr);
65:
66: int
67: safe_bcopy(caddr_t src, caddr_t dst, int len)
68: {
69: int error = 0;
70: label_t jmpbuf;
71: vm_offset_t tmpbuf = current_thread()->recover;
72:
73: #if DIAGNOSTIC
74: if(tmpbuf)
75: kprintf("safe_bcopy() ****** NESTED SETJUMP ******\n");
76: #endif /* DIAGNOSTIC */
77:
78: if (setjmp(&jmpbuf)) {
79: error = EFAULT;
80: } else {
81: current_thread()->recover = (vm_offset_t)&jmpbuf;
82: bcopy(src, dst, len);
83: }
84: current_thread()->recover = (vm_offset_t)tmpbuf;
85:
86: return(error);
87: }
88:
89: int
90: safe_bzero(void *dst, unsigned long ulen)
91: {
92: int error = 0;
93: label_t jmpbuf;
94: vm_offset_t tmpbuf = current_thread()->recover;
95:
96: #if DIAGNOSTIC
97: if (tmpbuf)
98: kprintf("safe_bzero() ****** NESTED SETJUMP ******\n");
99: #endif /* DIAGNOSTIC */
100:
101: if (setjmp(&jmpbuf)) {
102: error = EFAULT;
103: } else {
104: current_thread()->recover = (vm_offset_t)&jmpbuf;
105: bzero(dst, ulen);
106: }
107: current_thread()->recover = (vm_offset_t)tmpbuf;
108:
109: return(error);
110: }
111:
112:
113: int
114: lbcopytoz(from, to, maxlen)
115: register caddr_t from, to;
116: unsigned maxlen;
117: {
118: register unsigned l;
119:
120: for (l = 0; l < maxlen; l++) {
121: if (*from == '\0')
122: return l;
123: *to++ = *from++;
124: }
125: return maxlen;
126: }
127:
128: /*
129: * copy a null terminated string from the user address space into
130: * the kernel address space.
131: * - if the user is denied read access, return EFAULT
132: * - if the end of string isn't found before
133: * maxlen bytes are copied, return ENAMETOOLONG,
134: * indicating an incomplete copy.
135: * - otherwise, return 0, indicating success.
136: * the number of bytes copied is always returned in lencopied.
137: */
138: int
139: copyinstr(from, to, maxlen, lencopied)
140: caddr_t from, to;
141: unsigned maxlen, *lencopied;
142: {
143: unsigned segroom, room = maxlen;
144: caddr_t oto = to;
145: caddr_t mapped_from;
146: unsigned l;
147: int error = 0;
148: label_t jmpbuf;
149: vm_offset_t tmpbuf = current_thread()->recover;
150:
151: #if DIAGNOSTIC
152: if(tmpbuf)
153: kprintf("copyinstr() ****** NESTED SETJUMP ******\n");
154: #endif /* DIAGNOSTIC */
155:
156: if (setjmp(&jmpbuf)) {
157: error = EFAULT;
158: } else {
159: current_thread()->recover = (vm_offset_t)&jmpbuf;
160: do {
161: /* calc # of bytes to transfer from this seg. */
162: segroom = MIN(room, NBSEG - SEGOFFSET(from));
163:
164: mapped_from = cioseg(current_task()->map->pmap->space,from);
165: /* this *does not* copy a terminating null */
166: l = lbcopytoz(mapped_from, to, segroom);
167:
168: room -= l;
169: from += l;
170: to += l;
171: } while (l == segroom && room > 0);
172: }
173:
174: if (room == 0)
175: error = ENAMETOOLONG;
176:
177: if (error == 0)
178: *to++ = '\0'; // NULL terminate
179:
180: current_thread()->recover = (vm_offset_t)tmpbuf;
181:
182: if (lencopied)
183: *lencopied = to - oto;
184:
185: return error;
186: }
187:
188: /*
189: * Copy count bytes from (src) to (dst)
190: */
191: int
192: copywithin(src, dst, count)
193: caddr_t src,dst;
194: unsigned count;
195: {
196: int error = 0;
197: label_t jmpbuf;
198: vm_offset_t tmpbuf = current_thread()->recover;
199:
200: if (setjmp(&jmpbuf)) {
201: error = EFAULT;
202: }
203: else {
204: current_thread()->recover = (vm_offset_t)&jmpbuf;
205: bcopy(src,dst,count);
206: }
207:
208: current_thread()->recover = (vm_offset_t)tmpbuf;
209: return (error);
210: }
211:
212: caddr_t view_user_address(caddr_t addr);
213: int kdp_map_segment(unsigned int segment);
214:
215: /*
216: * Copy count bytes from (src) to (dst) where one is user space
217: */
218: int
219: copy_for_kdp_user(src, dst, count, dir)
220: caddr_t src,dst;
221: unsigned count;
222: int dir;
223: {
224: caddr_t msrc, mdst, ptr;
225: unsigned mcount;
226: int seg;
227: int rtn_value;
228:
229: #define SEG_NUM(x) ((((unsigned int)(x))>>28)&0xF)
230: #define SEG_ADDR(x, y) ((((unsigned int)(x)) << 28) | (((unsigned int)(y)) & 0x0FFFFFFF))
231:
232: rtn_value = 0;
233: while (count > 0) {
234: if (dir) {
235: ptr = dst;
236: seg = kdp_map_segment(SEG_NUM(ptr));
237: if (seg < 0) {
238: return 1;
239: }
240: mdst = view_user_address(SEG_ADDR(seg, ptr));
241: msrc = src;
242: } else {
243: ptr = src;
244: mdst = dst;
245: seg = kdp_map_segment(SEG_NUM(ptr));
246: if (seg < 0) {
247: return 1;
248: }
249: msrc = view_user_address(SEG_ADDR(seg, ptr));
250: }
251: if (SEG_NUM(ptr) != SEG_NUM(ptr+count-1)) {
252: mcount = 0x10000000 - SEG_ADDR(0, ptr);
253: count -= mcount;
254: src += mcount;
255: dst += mcount;
256: } else {
257: mcount = count;
258: count = 0;
259: }
260: rtn_value |= safe_bcopy(msrc,mdst,mcount);
261: }
262: return rtn_value;
263: }
264:
265: /*
266: * Copy count bytes from (src) to (dst)
267: */
268: int
269: copy_for_kdp(src, dst, count, dir)
270: vm_offset_t src,dst;
271: unsigned count;
272: int dir;
273: {
274: int rtn_value = 0;
275:
276: if (dir) {
277: if (dst > VM_MAX_KERNEL_ADDRESS) {
278: rtn_value = copy_for_kdp_user(src, dst, count, 1);
279: } else if (dst >= VM_MIN_KERNEL_ADDRESS) {
280: rtn_value = safe_bcopy(src, dst, count);
281: kdp_flush_icache(dst, count);
282: }
283: } else {
284: if (src > VM_MAX_KERNEL_ADDRESS) {
285: rtn_value = copy_for_kdp_user(src, dst, count, 0);
286: } else {
287: rtn_value = safe_bcopy(src, dst, count);
288: }
289: }
290: return rtn_value;
291: }
292:
293: /*
294: * copy a null terminated string from one point to another in
295: * the kernel address space.
296: * - no access checks are performed.
297: * - if the end of string isn't found before
298: * maxlen bytes are copied, return ENAMETOOLONG,
299: * indicating an incomplete copy.
300: * - otherwise, return 0, indicating success.
301: * the number of bytes copied is always returned in lencopied.
302: */
303: int
304: copystr(from, to, maxlen, lencopied)
305: register caddr_t from, to;
306: unsigned maxlen, *lencopied;
307: {
308: register unsigned l;
309: int error = 0;
310: label_t jmpbuf;
311: vm_offset_t tmpbuf = current_thread()->recover;
312:
313: #if DIAGNOSTIC
314: if(tmpbuf)
315: kprintf("copystr() ****** NESTED SETJUMP ******\n");
316: #endif /* DIAGNOSTIC */
317:
318: if (setjmp(&jmpbuf)) {
319: error = EFAULT;
320: } else {
321: current_thread()->recover = (vm_offset_t)&jmpbuf;
322: for (l = 0; l < maxlen; l++)
323: if ((*to++ = *from++) == '\0') {
324: if (lencopied)
325: *lencopied = l + 1;
326: error = 0;
327: goto out;
328: }
329: if (lencopied)
330: *lencopied = maxlen;
331: error = ENAMETOOLONG;
332: }
333: out:
334: current_thread()->recover = (vm_offset_t)tmpbuf;
335: return (error);
336: }
337:
338: /*
339: * copy a null terminated string from the kernel address space into
340: * the user address space.
341: * - if the user is denied write access, return EFAULT.
342: * - if the end of string isn't found before
343: * maxlen bytes are copied, return ENAMETOOLONG,
344: * indicating an incomplete copy.
345: * - otherwise, return 0, indicating success.
346: * the number of bytes copied is always returned in lencopied.
347: */
348: int
349: copyoutstr(from, to, maxlen, lencopied)
350: caddr_t from, to;
351: unsigned maxlen, *lencopied;
352: {
353: unsigned segroom, room = maxlen;
354: caddr_t oto = to;
355: caddr_t mapped_to;
356: unsigned l;
357: int error = 0;
358: label_t jmpbuf;
359: vm_offset_t tmpbuf = current_thread()->recover;
360:
361: #if DIAGNOSTIC
362: if(tmpbuf)
363: kprintf("copyoutstr() ****** NESTED SETJUMP ******\n");
364: #endif /* DIAGNOSTIC */
365:
366: if (setjmp(&jmpbuf)) {
367: error = EFAULT;
368: } else {
369: current_thread()->recover = (vm_offset_t)&jmpbuf;
370: do {
371: /* calc # of bytes to transfer from this seg. */
372: segroom = MIN(room, NBSEG - SEGOFFSET(to));
373:
374: mapped_to = cioseg(current_task()->map->pmap->space,to);
375:
376: /* this *does not* copy a terminating null */
377: l = lbcopytoz(from, mapped_to, segroom);
378:
379: room -= l;
380: from += l;
381: to += l;
382: mapped_to += l; // for NULL whenever
383: } while (l == segroom && room > 0);
384:
385: /* set terminating NULL */
386: *mapped_to = '\0';
387: to++;
388: }
389:
390: if (room == 0)
391: error = ENAMETOOLONG;
392:
393: if (lencopied)
394: *lencopied = to - oto;
395:
396: current_thread()->recover = (vm_offset_t)tmpbuf;
397: return error;
398: }
399:
400: #undef PGOFFSET
401:
402: int
403: copyin(void *src, void *dst, size_t len)
404: {
405: thread_t self = current_thread();
406: vm_offset_t tmpbuf = self->recover;
407: label_t jmpbuf;
408: int error = 0;
409: void *tsrc;
410: size_t tlen;
411:
412: #if DIAGNOSTIC
413: if(tmpbuf)
414: kprintf("copyin() ****** NESTED SETJUMP ******\n");
415: #endif /* DIAGNOSTIC */
416:
417: if (setjmp(&jmpbuf)) {
418: error = EFAULT;
419: }
420: else {
421: self->recover = (vm_offset_t)&jmpbuf;
422: while (len > 0) {
423: tlen = ((SEGOFFSET(src) + len) > NBSEG) ?
424: NBSEG - SEGOFFSET(src) : len;
425: tsrc = cioseg(self->task->map->pmap->space, src);
426: bcopy(tsrc, dst, tlen);
427: src += tlen;
428: dst += tlen;
429: len -= tlen;
430: }
431: }
432: self->recover = (vm_offset_t)tmpbuf;
433: return(error);
434: }
435:
436: int
437: copyout(void *src, void *dst, size_t len)
438: {
439: thread_t self = current_thread();
440: vm_offset_t tmpbuf = self->recover;
441: label_t jmpbuf;
442: int error = 0;
443: void *tdst;
444: size_t tlen;
445:
446: #if DIAGNOSTIC
447: if(tmpbuf)
448: kprintf("copyout() ****** NESTED SETJUMP ******\n");
449: #endif /* DIAGNOSTIC */
450:
451: if (setjmp(&jmpbuf)) {
452: error = EFAULT;
453: }
454: else {
455: self->recover = (vm_offset_t)&jmpbuf;
456: while (len > 0) {
457: tlen = ((SEGOFFSET(dst) + len) > NBSEG) ?
458: NBSEG - SEGOFFSET(dst) : len;
459: tdst = cioseg(self->task->map->pmap->space, dst);
460: bcopy(src, tdst, tlen);
461: src += tlen;
462: dst += tlen;
463: len -= tlen;
464: }
465: }
466: self->recover = (vm_offset_t)tmpbuf;
467: return(error);
468: }
469:
470: int
471: copyinmsg(caddr_t src, caddr_t dst, int len)
472: {
473: return(copyin(src,dst,len));
474: }
475:
476: int
477: copyoutmsg(caddr_t src, caddr_t dst, int len)
478: {
479: return(copyout(src, dst, len));
480: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.