From 126c0364bf7d72d4f2ecf1ad2f4ebe1d2667940d Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sun, 1 Oct 2023 17:24:02 +0200 Subject: ipc: Fix allocating kernel buffer for storing user message Otherwise ipc_kmsg_copyin_body will overflow. --- ipc/ipc_kmsg.c | 7 ++++--- ipc/ipc_kmsg.h | 10 ++++++++++ ipc/mach_msg.c | 2 +- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/ipc/ipc_kmsg.c b/ipc/ipc_kmsg.c index bd1b30da..105e54d4 100644 --- a/ipc/ipc_kmsg.c +++ b/ipc/ipc_kmsg.c @@ -489,19 +489,20 @@ ipc_kmsg_get( ipc_kmsg_t *kmsgp) { ipc_kmsg_t kmsg; + mach_msg_size_t ksize = size * IKM_EXPAND_FACTOR; if ((size < sizeof(mach_msg_user_header_t)) || mach_msg_user_is_misaligned(size)) return MACH_SEND_MSG_TOO_SMALL; - if (size <= IKM_SAVED_MSG_SIZE) { + if (ksize <= IKM_SAVED_MSG_SIZE) { kmsg = ikm_cache_alloc(); if (kmsg == IKM_NULL) return MACH_SEND_NO_BUFFER; } else { - kmsg = ikm_alloc(size); + kmsg = ikm_alloc(ksize); if (kmsg == IKM_NULL) return MACH_SEND_NO_BUFFER; - ikm_init(kmsg, size); + ikm_init(kmsg, ksize); } if (copyinmsg(msg, &kmsg->ikm_header, size)) { diff --git a/ipc/ipc_kmsg.h b/ipc/ipc_kmsg.h index 45e174b7..9ee1aa4a 100644 --- a/ipc/ipc_kmsg.h +++ b/ipc/ipc_kmsg.h @@ -156,6 +156,16 @@ MACRO_END #define ikm_alloc(size) \ ((ipc_kmsg_t) kalloc(ikm_plus_overhead(size))) +/* + * The conversion between userland and kernel-land has to convert from port + * names to ports. This may increase the size that needs to be allocated + * on the kernel size. At worse the message is full of port names to be + * converted. + */ +#define IKM_EXPAND_FACTOR ((sizeof(mach_port_t) + sizeof(mach_port_name_t) - 1) / sizeof(mach_port_name_t)) +/* But make sure it's not the converse. */ +_Static_assert(sizeof(mach_port_t) >= sizeof(mach_port_name_t)); + #define ikm_init(kmsg, size) \ MACRO_BEGIN \ ikm_init_special((kmsg), ikm_plus_overhead(size)); \ diff --git a/ipc/mach_msg.c b/ipc/mach_msg.c index 482c85a5..fb6e6dfc 100644 --- a/ipc/mach_msg.c +++ b/ipc/mach_msg.c @@ -450,7 +450,7 @@ mach_msg_trap( * We must clear ikm_cache before copyinmsg. */ - if ((send_size > IKM_SAVED_MSG_SIZE) || + if (((send_size * IKM_EXPAND_FACTOR) > IKM_SAVED_MSG_SIZE) || (send_size < sizeof(mach_msg_user_header_t)) || (send_size & 3)) goto slow_get; -- cgit v1.2.3