Home | History | Annotate | Line # | Download | only in rumpkern
rumpcopy.c revision 1.17.16.2
      1  1.17.16.1       tls /*	$NetBSD: rumpcopy.c,v 1.17.16.2 2017/12/03 11:39:16 jdolecek Exp $	*/
      2        1.1     pooka 
      3        1.1     pooka /*
      4        1.1     pooka  * Copyright (c) 2009 Antti Kantee.  All Rights Reserved.
      5        1.1     pooka  *
      6        1.1     pooka  * Redistribution and use in source and binary forms, with or without
      7        1.1     pooka  * modification, are permitted provided that the following conditions
      8        1.1     pooka  * are met:
      9        1.1     pooka  * 1. Redistributions of source code must retain the above copyright
     10        1.1     pooka  *    notice, this list of conditions and the following disclaimer.
     11        1.1     pooka  * 2. Redistributions in binary form must reproduce the above copyright
     12        1.1     pooka  *    notice, this list of conditions and the following disclaimer in the
     13        1.1     pooka  *    documentation and/or other materials provided with the distribution.
     14        1.1     pooka  *
     15        1.1     pooka  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
     16        1.1     pooka  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     17        1.1     pooka  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     18        1.1     pooka  * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     19        1.1     pooka  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     20        1.1     pooka  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     21        1.1     pooka  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     22        1.1     pooka  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     23        1.1     pooka  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     24        1.1     pooka  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     25        1.1     pooka  * SUCH DAMAGE.
     26        1.1     pooka  */
     27        1.1     pooka 
     28        1.1     pooka #include <sys/cdefs.h>
     29  1.17.16.1       tls __KERNEL_RCSID(0, "$NetBSD: rumpcopy.c,v 1.17.16.2 2017/12/03 11:39:16 jdolecek Exp $");
     30        1.1     pooka 
     31        1.1     pooka #include <sys/param.h>
     32        1.1     pooka #include <sys/lwp.h>
     33        1.1     pooka #include <sys/systm.h>
     34       1.11     pooka #include <sys/uio.h>
     35        1.1     pooka 
     36  1.17.16.2  jdolecek #include <rump-sys/kern.h>
     37        1.1     pooka 
     38  1.17.16.2  jdolecek #include <rump/rumpuser.h>
     39        1.1     pooka 
     40        1.1     pooka int
     41        1.1     pooka copyin(const void *uaddr, void *kaddr, size_t len)
     42        1.1     pooka {
     43       1.11     pooka 	int error = 0;
     44        1.7     pooka 
     45        1.6     pooka 	if (__predict_false(uaddr == NULL && len)) {
     46        1.6     pooka 		return EFAULT;
     47        1.6     pooka 	}
     48        1.1     pooka 
     49       1.16     pooka 	if (RUMP_LOCALPROC_P(curproc)) {
     50        1.1     pooka 		memcpy(kaddr, uaddr, len);
     51       1.15     pooka 	} else if (len) {
     52  1.17.16.2  jdolecek 		error = rump_sysproxy_copyin(RUMP_SPVM2CTL(curproc->p_vmspace),
     53       1.11     pooka 		    uaddr, kaddr, len);
     54        1.4     pooka 	}
     55       1.11     pooka 
     56       1.11     pooka 	return error;
     57        1.1     pooka }
     58        1.1     pooka 
     59        1.1     pooka int
     60        1.1     pooka copyout(const void *kaddr, void *uaddr, size_t len)
     61        1.1     pooka {
     62       1.11     pooka 	int error = 0;
     63        1.7     pooka 
     64        1.6     pooka 	if (__predict_false(uaddr == NULL && len)) {
     65        1.6     pooka 		return EFAULT;
     66        1.6     pooka 	}
     67        1.1     pooka 
     68       1.16     pooka 	if (RUMP_LOCALPROC_P(curproc)) {
     69        1.1     pooka 		memcpy(uaddr, kaddr, len);
     70       1.15     pooka 	} else if (len) {
     71  1.17.16.2  jdolecek 		error = rump_sysproxy_copyout(RUMP_SPVM2CTL(curproc->p_vmspace),
     72       1.11     pooka 		    kaddr, uaddr, len);
     73        1.4     pooka 	}
     74       1.11     pooka 	return error;
     75        1.1     pooka }
     76        1.1     pooka 
     77        1.1     pooka int
     78        1.1     pooka subyte(void *uaddr, int byte)
     79        1.1     pooka {
     80       1.11     pooka 	int error = 0;
     81        1.1     pooka 
     82       1.16     pooka 	if (RUMP_LOCALPROC_P(curproc))
     83        1.1     pooka 		*(char *)uaddr = byte;
     84        1.1     pooka 	else
     85  1.17.16.2  jdolecek 		error = rump_sysproxy_copyout(RUMP_SPVM2CTL(curproc->p_vmspace),
     86       1.11     pooka 		    &byte, uaddr, 1);
     87       1.11     pooka 
     88       1.11     pooka 	return error;
     89        1.1     pooka }
     90        1.1     pooka 
     91        1.1     pooka int
     92        1.1     pooka copystr(const void *kfaddr, void *kdaddr, size_t len, size_t *done)
     93        1.1     pooka {
     94        1.8     pooka 	uint8_t *to = kdaddr;
     95        1.8     pooka 	const uint8_t *from = kfaddr;
     96        1.8     pooka 	size_t actlen = 0;
     97        1.8     pooka 
     98        1.8     pooka 	while (len-- > 0 && (*to++ = *from++) != 0)
     99        1.8     pooka 		actlen++;
    100        1.8     pooka 
    101        1.8     pooka 	if (len+1 == 0 && *(to-1) != 0)
    102        1.8     pooka 		return ENAMETOOLONG;
    103        1.1     pooka 
    104        1.6     pooka 	if (done)
    105        1.8     pooka 		*done = actlen+1; /* + '\0' */
    106        1.6     pooka 	return 0;
    107        1.1     pooka }
    108        1.1     pooka 
    109        1.1     pooka int
    110        1.1     pooka copyinstr(const void *uaddr, void *kaddr, size_t len, size_t *done)
    111        1.1     pooka {
    112        1.8     pooka 	uint8_t *to;
    113        1.8     pooka 	int rv;
    114        1.1     pooka 
    115        1.9     pooka 	if (len == 0)
    116        1.9     pooka 		return 0;
    117        1.9     pooka 
    118  1.17.16.1       tls 	if (__predict_false(uaddr == NULL)) {
    119  1.17.16.1       tls 		return EFAULT;
    120  1.17.16.1       tls 	}
    121  1.17.16.1       tls 
    122       1.16     pooka 	if (RUMP_LOCALPROC_P(curproc))
    123        1.8     pooka 		return copystr(uaddr, kaddr, len, done);
    124        1.8     pooka 
    125  1.17.16.2  jdolecek 	if ((rv = rump_sysproxy_copyinstr(RUMP_SPVM2CTL(curproc->p_vmspace),
    126       1.13     pooka 	    uaddr, kaddr, &len)) != 0)
    127        1.8     pooka 		return rv;
    128        1.8     pooka 
    129        1.9     pooka 	/* figure out if we got a terminated string or not */
    130        1.9     pooka 	to = (uint8_t *)kaddr + (len-1);
    131       1.14     pooka 	while (to >= (uint8_t *)kaddr) {
    132        1.8     pooka 		if (*to == 0)
    133        1.8     pooka 			goto found;
    134        1.8     pooka 		to--;
    135        1.8     pooka 	}
    136        1.8     pooka 	return ENAMETOOLONG;
    137        1.8     pooka 
    138        1.8     pooka  found:
    139        1.1     pooka 	if (done)
    140        1.1     pooka 		*done = strlen(kaddr)+1; /* includes termination */
    141        1.8     pooka 
    142        1.1     pooka 	return 0;
    143        1.1     pooka }
    144        1.1     pooka 
    145        1.1     pooka int
    146        1.1     pooka copyoutstr(const void *kaddr, void *uaddr, size_t len, size_t *done)
    147        1.1     pooka {
    148        1.8     pooka 	size_t slen;
    149       1.11     pooka 	int error;
    150        1.1     pooka 
    151  1.17.16.1       tls 	if (__predict_false(uaddr == NULL && len)) {
    152  1.17.16.1       tls 		return EFAULT;
    153  1.17.16.1       tls 	}
    154  1.17.16.1       tls 
    155       1.16     pooka 	if (RUMP_LOCALPROC_P(curproc))
    156        1.8     pooka 		return copystr(kaddr, uaddr, len, done);
    157        1.8     pooka 
    158        1.8     pooka 	slen = strlen(kaddr)+1;
    159        1.8     pooka 	if (slen > len)
    160        1.8     pooka 		return ENAMETOOLONG;
    161        1.8     pooka 
    162  1.17.16.2  jdolecek 	error = rump_sysproxy_copyoutstr(RUMP_SPVM2CTL(curproc->p_vmspace),
    163       1.13     pooka 	    kaddr, uaddr, &slen);
    164        1.1     pooka 	if (done)
    165        1.8     pooka 		*done = slen;
    166        1.8     pooka 
    167       1.11     pooka 	return error;
    168        1.1     pooka }
    169        1.1     pooka 
    170        1.1     pooka int
    171        1.1     pooka kcopy(const void *src, void *dst, size_t len)
    172        1.1     pooka {
    173        1.1     pooka 
    174        1.1     pooka 	memcpy(dst, src, len);
    175        1.1     pooka 	return 0;
    176        1.1     pooka }
    177       1.11     pooka 
    178       1.11     pooka /*
    179       1.11     pooka  * Low-level I/O routine.  This is used only when "all else fails",
    180       1.11     pooka  * i.e. the current thread does not have an appropriate vm context.
    181       1.11     pooka  */
    182       1.11     pooka int
    183  1.17.16.2  jdolecek uvm_io(struct vm_map *vm, struct uio *uio, int flag)
    184       1.11     pooka {
    185       1.12     pooka 	int error = 0;
    186       1.11     pooka 
    187       1.11     pooka 	/* loop over iovecs one-by-one and copyout */
    188       1.11     pooka 	for (; uio->uio_resid && uio->uio_iovcnt;
    189       1.11     pooka 	    uio->uio_iovcnt--, uio->uio_iov++) {
    190       1.11     pooka 		struct iovec *iov = uio->uio_iov;
    191       1.11     pooka 		size_t curlen = MIN(uio->uio_resid, iov->iov_len);
    192       1.11     pooka 
    193       1.11     pooka 		if (__predict_false(curlen == 0))
    194       1.11     pooka 			continue;
    195       1.11     pooka 
    196       1.11     pooka 		if (uio->uio_rw == UIO_READ) {
    197  1.17.16.2  jdolecek 			error = rump_sysproxy_copyin(RUMP_SPVM2CTL(vm),
    198       1.11     pooka 			    (void *)(vaddr_t)uio->uio_offset, iov->iov_base,
    199       1.11     pooka 			    curlen);
    200       1.11     pooka 		} else {
    201  1.17.16.2  jdolecek 			error = rump_sysproxy_copyout(RUMP_SPVM2CTL(vm),
    202       1.11     pooka 			    iov->iov_base, (void *)(vaddr_t)uio->uio_offset,
    203       1.11     pooka 			    curlen);
    204       1.11     pooka 		}
    205       1.11     pooka 		if (error)
    206       1.11     pooka 			break;
    207       1.11     pooka 
    208       1.11     pooka 		iov->iov_base = (uint8_t *)iov->iov_base + curlen;
    209       1.11     pooka 		iov->iov_len -= curlen;
    210       1.11     pooka 
    211       1.11     pooka 		uio->uio_resid -= curlen;
    212       1.11     pooka 		uio->uio_offset += curlen;
    213       1.11     pooka 	}
    214       1.11     pooka 
    215       1.11     pooka 	return error;
    216       1.11     pooka }
    217       1.17      haad 
    218       1.17      haad /*
    219       1.17      haad  * Copy one byte from userspace to kernel.
    220       1.17      haad  */
    221       1.17      haad int
    222       1.17      haad fubyte(const void *base)
    223       1.17      haad {
    224       1.17      haad 	unsigned char val;
    225       1.17      haad 	int error;
    226       1.17      haad 
    227       1.17      haad 	error = copyin(base, &val, sizeof(char));
    228       1.17      haad 	if (error != 0)
    229       1.17      haad 		return -1;
    230       1.17      haad 
    231       1.17      haad 	return (int)val;
    232       1.17      haad }
    233