summaryrefslogtreecommitdiff
path: root/ipc
diff options
context:
space:
mode:
authorSamuel Thibault <samuel.thibault@ens-lyon.org>2023-10-01 17:24:02 +0200
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2023-10-01 17:34:13 +0200
commit126c0364bf7d72d4f2ecf1ad2f4ebe1d2667940d (patch)
tree07be87498222a605dda3ea5e0ffe81d3e5b356b0 /ipc
parent513125f30a05b4ad3408d5f4efd36d2c6ba10744 (diff)
ipc: Fix allocating kernel buffer for storing user message
Otherwise ipc_kmsg_copyin_body will overflow.
Diffstat (limited to 'ipc')
-rw-r--r--ipc/ipc_kmsg.c7
-rw-r--r--ipc/ipc_kmsg.h10
-rw-r--r--ipc/mach_msg.c2
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;