diff options
Diffstat (limited to 'ipc')
-rw-r--r-- | ipc/ipc_kmsg.c | 47 | ||||
-rw-r--r-- | ipc/ipc_mqueue.c | 5 | ||||
-rw-r--r-- | ipc/mach_msg.c | 17 |
3 files changed, 44 insertions, 25 deletions
diff --git a/ipc/ipc_kmsg.c b/ipc/ipc_kmsg.c index 55252d46..45070b7a 100644 --- a/ipc/ipc_kmsg.c +++ b/ipc/ipc_kmsg.c @@ -42,6 +42,7 @@ #include <mach/message.h> #include <mach/port.h> #include <machine/locore.h> +#include <machine/copy_user.h> #include <kern/assert.h> #include <kern/kalloc.h> #include <vm/vm_map.h> @@ -68,12 +69,6 @@ #include <ipc/ipc_print.h> #endif -/* msg body is always aligned to 4 bytes */ -typedef uint32_t msg_align_t; - -#define msg_is_misaligned(x) ( ((vm_offset_t)(x)) & (sizeof(msg_align_t)-1) ) -#define msg_align(x) \ - ( ( ((vm_offset_t)(x)) + (sizeof(msg_align_t)-1) ) & ~(sizeof(msg_align_t)-1) ) ipc_kmsg_t ipc_kmsg_cache[NCPUS]; @@ -1388,7 +1383,7 @@ ipc_kmsg_copyin_body( } else { vm_offset_t addr; - if (sizeof(msg_align_t) > sizeof(mach_msg_type_t)) + if (MACH_MSG_ALIGNMENT > sizeof(mach_msg_type_t)) saddr = msg_align(saddr); if ((eaddr - saddr) < sizeof(vm_offset_t)) { @@ -1407,14 +1402,27 @@ ipc_kmsg_copyin_body( if (data == 0) goto invalid_memory; - if (copyinmap(map, (char *) addr, - (char *) data, length) || - (dealloc && - (vm_deallocate(map, addr, length) != - KERN_SUCCESS))) { + if (sizeof(mach_port_name_t) != sizeof(mach_port_t)) + { + mach_port_name_t *src = (mach_port_name_t*)addr; + mach_port_t *dst = (mach_port_t*)data; + for (int i=0; i<number; i++) { + if (copyin_port(src + i, dst + i)) { + kfree(data, length); + goto invalid_memory; + } + } + } else if (copyinmap(map, (char *) addr, + (char *) data, length)) { + kfree(data, length); + goto invalid_memory; + } + if (dealloc && + (vm_deallocate(map, addr, length) != KERN_SUCCESS)) { kfree(data, length); goto invalid_memory; } + } else { vm_map_copy_t copy; @@ -2443,7 +2451,7 @@ ipc_kmsg_copyout_body( } else { vm_offset_t data; - if (sizeof(msg_align_t) > sizeof(mach_msg_type_t)) + if (MACH_MSG_ALIGNMENT > sizeof(mach_msg_type_t)) saddr = msg_align(saddr); data = * (vm_offset_t *) saddr; @@ -2456,8 +2464,17 @@ ipc_kmsg_copyout_body( } else if (is_port) { /* copyout to memory allocated above */ - (void) copyoutmap(map, (char *) data, - (char *) addr, length); + if (sizeof(mach_port_name_t) != sizeof(mach_port_t)) { + mach_port_t *src = (mach_port_t*)data; + mach_port_name_t *dst = (mach_port_name_t*)addr; + for (int i=0; i<number; i++) { + if (copyout_port(src + i, dst + i)) + goto vm_copyout_failure; + } + } else { + (void) copyoutmap(map, (char *) data, + (char *) addr, length); + } kfree(data, length); } else { vm_map_copy_t copy = (vm_map_copy_t) data; diff --git a/ipc/ipc_mqueue.c b/ipc/ipc_mqueue.c index ac6bed51..44e1eb98 100644 --- a/ipc/ipc_mqueue.c +++ b/ipc/ipc_mqueue.c @@ -36,6 +36,7 @@ #include <mach/port.h> #include <mach/message.h> +#include <machine/copy_user.h> #include <kern/assert.h> #include <kern/counters.h> #include <kern/debug.h> @@ -540,7 +541,7 @@ ipc_mqueue_receive( if (kmsg != IKM_NULL) { /* check space requirements */ - if (kmsg->ikm_header.msgh_size > max_size) { + if (msg_usize(&kmsg->ikm_header) > max_size) { * (mach_msg_size_t *) kmsgp = kmsg->ikm_header.msgh_size; imq_unlock(mqueue); @@ -649,7 +650,7 @@ ipc_mqueue_receive( /* we have a kmsg; unlock the msg queue */ imq_unlock(mqueue); - assert(kmsg->ikm_header.msgh_size <= max_size); + assert(msg_usize(&kmsg->ikm_header) <= max_size); } { diff --git a/ipc/mach_msg.c b/ipc/mach_msg.c index 221ea975..1a6d67d0 100644 --- a/ipc/mach_msg.c +++ b/ipc/mach_msg.c @@ -39,6 +39,7 @@ #include <mach/kern_return.h> #include <mach/port.h> #include <mach/message.h> +#include <machine/copy_user.h> #include <kern/assert.h> #include <kern/counters.h> #include <kern/debug.h> @@ -241,7 +242,7 @@ mach_msg_receive( return mr; kmsg->ikm_header.msgh_seqno = seqno; - if (kmsg->ikm_header.msgh_size > rcv_size) { + if (msg_usize(&kmsg->ikm_header) > rcv_size) { ipc_kmsg_copyout_dest(kmsg, space); (void) ipc_kmsg_put(msg, kmsg, sizeof *msg); return MACH_RCV_TOO_LARGE; @@ -321,7 +322,7 @@ mach_msg_receive_continue(void) } kmsg->ikm_header.msgh_seqno = seqno; - assert(kmsg->ikm_header.msgh_size <= rcv_size); + assert(msg_usize(&kmsg->ikm_header) <= rcv_size); } else { mr = ipc_mqueue_receive(mqueue, option & MACH_RCV_TIMEOUT, MACH_MSG_SIZE_MAX, time_out, @@ -335,7 +336,7 @@ mach_msg_receive_continue(void) } kmsg->ikm_header.msgh_seqno = seqno; - if (kmsg->ikm_header.msgh_size > rcv_size) { + if (msg_usize(&kmsg->ikm_header) > rcv_size) { ipc_kmsg_copyout_dest(kmsg, space); (void) ipc_kmsg_put(msg, kmsg, sizeof *msg); thread_syscall_return(MACH_RCV_TOO_LARGE); @@ -450,7 +451,7 @@ mach_msg_trap( */ if ((send_size > IKM_SAVED_MSG_SIZE) || - (send_size < sizeof(mach_msg_header_t)) || + (send_size < sizeof(mach_msg_user_header_t)) || (send_size & 3) || ((kmsg = ikm_cache()) == IKM_NULL)) goto slow_get; @@ -940,7 +941,7 @@ mach_msg_trap( == dest_port); reply_size = kmsg->ikm_header.msgh_size; - if (rcv_size < reply_size) + if (rcv_size < msg_usize(&kmsg->ikm_header)) goto slow_copyout; /* optimized ipc_kmsg_copyout/ipc_kmsg_copyout_header */ @@ -1450,7 +1451,7 @@ mach_msg_trap( */ reply_size = kmsg->ikm_header.msgh_size; - if (rcv_size < reply_size) { + if (rcv_size < msg_usize(&kmsg->ikm_header)) { ipc_kmsg_copyout_dest(kmsg, space); (void) ipc_kmsg_put(msg, kmsg, sizeof *msg); thread_syscall_return(MACH_RCV_TOO_LARGE); @@ -1544,7 +1545,7 @@ mach_msg_trap( return mr; kmsg->ikm_header.msgh_seqno = seqno; - if (rcv_size < kmsg->ikm_header.msgh_size) { + if (rcv_size < msg_usize(&kmsg->ikm_header)) { ipc_kmsg_copyout_dest(kmsg, space); (void) ipc_kmsg_put(msg, kmsg, sizeof *msg); return MACH_RCV_TOO_LARGE; @@ -1628,7 +1629,7 @@ mach_msg_continue(void) } kmsg->ikm_header.msgh_seqno = seqno; - if (kmsg->ikm_header.msgh_size > rcv_size) { + if (msg_usize(&kmsg->ikm_header) > rcv_size) { ipc_kmsg_copyout_dest(kmsg, space); (void) ipc_kmsg_put(msg, kmsg, sizeof *msg); thread_syscall_return(MACH_RCV_TOO_LARGE); |