summaryrefslogtreecommitdiff
path: root/ipc
diff options
context:
space:
mode:
authorLuca Dariz <luca@orpolo.org>2023-01-16 11:58:52 +0100
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2023-01-18 02:20:37 +0100
commit8ddf8e991c0d271d2681627fab08e6730ae73ae0 (patch)
tree77890e44218b0f75d1067c61f04df8cf6ad189d5 /ipc
parentcc05ed085b731232a2436efcaf03aa1e92ad20be (diff)
x86_64: expand and shrink messages in copy{in, out}msg routines
* i386/i386/copy_user.h: new file to handle 32/64 bit differences - add msg_usize() to recontruct the user-space message size - add copyin/copyout helpers for addresses and ports * include/mach/message.h: add msg alignment macros * ipc/ipc_kmsg.c: - copyin/out ports names instead of using pointer magic * ipc/ipc_mqueue.c: use msg_usize() to check if we can actually receive the message * ipc/mach_msg.c: Likewise for continuations in receive path * x86_64/Makefrag.am: add x86_64/copy_user.c * x86_64/copy_user.c: new file to handle message expansion and shrinking during copyinmsg/copyoutmsg for 64 bit kernels. - port names -> port pointers on all 64-bit builds - 32-bit pointer -> 64 bit pointer when using 32-bit userspace * x86_64/locore.S: remove copyinmsg() and copyoutmsg() Message-Id: <20230116105857.240210-3-luca@orpolo.org>
Diffstat (limited to 'ipc')
-rw-r--r--ipc/ipc_kmsg.c47
-rw-r--r--ipc/ipc_mqueue.c5
-rw-r--r--ipc/mach_msg.c17
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);