aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Thibault <samuel.thibault@ens-lyon.org>2023-10-01 17:35:01 +0200
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2023-10-01 19:33:20 +0200
commitb63dea5ca946c3956637a7bf85a1002866b20cd6 (patch)
tree682eb89c30f95c85a4a2b158fcdfa867c2fa56c8
parent126c0364bf7d72d4f2ecf1ad2f4ebe1d2667940d (diff)
downloadgnumach-b63dea5ca946c3956637a7bf85a1002866b20cd6.tar.gz
gnumach-b63dea5ca946c3956637a7bf85a1002866b20cd6.tar.bz2
gnumach-b63dea5ca946c3956637a7bf85a1002866b20cd6.zip
copyinmsg: Check that we have not overflown
This if of course too late in case of a failure, but better assert than get awful bugs, and it's really not supposed to happen.
-rw-r--r--i386/i386/locore.S1
-rw-r--r--i386/i386/locore.h2
-rw-r--r--ipc/ipc_kmsg.c2
-rw-r--r--ipc/mach_msg.c2
-rw-r--r--x86_64/copy_user.c3
5 files changed, 6 insertions, 4 deletions
diff --git a/i386/i386/locore.S b/i386/i386/locore.S
index d3986793..846f5567 100644
--- a/i386/i386/locore.S
+++ b/i386/i386/locore.S
@@ -1335,6 +1335,7 @@ copyin_fail:
* arg0: user address
* arg1: kernel address
* arg2: byte count - must be a multiple of four
+ * arg3: kernel byte count
*/
ENTRY(copyinmsg)
pushl %esi
diff --git a/i386/i386/locore.h b/i386/i386/locore.h
index 4388ea28..374c8cf9 100644
--- a/i386/i386/locore.h
+++ b/i386/i386/locore.h
@@ -48,7 +48,7 @@ extern int call_continuation (continuation_t continuation);
extern int discover_x86_cpu_type (void);
extern int copyin (const void *userbuf, void *kernelbuf, size_t cn);
-extern int copyinmsg (const void *userbuf, void *kernelbuf, size_t cn);
+extern int copyinmsg (const void *userbuf, void *kernelbuf, size_t cn, size_t kn);
extern int copyout (const void *kernelbuf, void *userbuf, size_t cn);
extern int copyoutmsg (const void *kernelbuf, void *userbuf, size_t cn);
diff --git a/ipc/ipc_kmsg.c b/ipc/ipc_kmsg.c
index 105e54d4..33e4d57c 100644
--- a/ipc/ipc_kmsg.c
+++ b/ipc/ipc_kmsg.c
@@ -505,7 +505,7 @@ ipc_kmsg_get(
ikm_init(kmsg, ksize);
}
- if (copyinmsg(msg, &kmsg->ikm_header, size)) {
+ if (copyinmsg(msg, &kmsg->ikm_header, size, kmsg->ikm_size)) {
ikm_free(kmsg);
return MACH_SEND_INVALID_DATA;
}
diff --git a/ipc/mach_msg.c b/ipc/mach_msg.c
index fb6e6dfc..118ce4b3 100644
--- a/ipc/mach_msg.c
+++ b/ipc/mach_msg.c
@@ -460,7 +460,7 @@ mach_msg_trap(
goto slow_get;
if (copyinmsg(msg, &kmsg->ikm_header,
- send_size)) {
+ send_size, kmsg->ikm_size)) {
ikm_free(kmsg);
goto slow_get;
}
diff --git a/x86_64/copy_user.c b/x86_64/copy_user.c
index 178a7545..0d3f301b 100644
--- a/x86_64/copy_user.c
+++ b/x86_64/copy_user.c
@@ -363,7 +363,7 @@ size_t msg_usize(const mach_msg_header_t *kmsg)
* mach_msg_header have the same size in the kernel and user variant (basically
* all fields except ports and addresses)
*/
-int copyinmsg (const void *userbuf, void *kernelbuf, const size_t usize)
+int copyinmsg (const void *userbuf, void *kernelbuf, const size_t usize, const size_t ksize)
{
const mach_msg_user_header_t *umsg = userbuf;
mach_msg_header_t *kmsg = kernelbuf;
@@ -469,6 +469,7 @@ int copyinmsg (const void *userbuf, void *kernelbuf, const size_t usize)
}
kmsg->msgh_size = sizeof(mach_msg_header_t) + ksaddr - (vm_offset_t)(kmsg + 1);
+ assert(kmsg->msgh_size <= ksize);
return 0;
}