aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlavio Cruz <flaviocruz@gmail.com>2023-02-12 13:11:13 -0500
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2023-02-12 19:43:00 +0100
commite09f2d9584375a0d9e06bbcadec1910b042df620 (patch)
treed777fb64dcaac3893bced15ccfa5d946984a58bb
parent6a46db9fe035c26ab549bc0b681469fc650141d6 (diff)
downloadgnumach-e09f2d9584375a0d9e06bbcadec1910b042df620.tar.gz
gnumach-e09f2d9584375a0d9e06bbcadec1910b042df620.tar.bz2
gnumach-e09f2d9584375a0d9e06bbcadec1910b042df620.zip
Consider protected payloads in mach_msg_header_t when resizing messages.
Protected payloads will be 8-byte longs which are the same size as kernel ports. Also aligned all the structures to be 4-byte aligned since it makes it easier to parse them as padding won't be added to mach_msg_user_header_t before the protected payload. Message-Id: <Y+krwRFIUeyRszl9@jupiter.tail36e24.ts.net>
-rw-r--r--include/mach/message.h9
-rw-r--r--x86_64/copy_user.c22
2 files changed, 30 insertions, 1 deletions
diff --git a/include/mach/message.h b/include/mach/message.h
index 21c551c2..63341e6f 100644
--- a/include/mach/message.h
+++ b/include/mach/message.h
@@ -132,6 +132,9 @@ typedef unsigned int mach_msg_size_t;
typedef natural_t mach_msg_seqno_t;
typedef integer_t mach_msg_id_t;
+/* Force 4-byte alignment to simplify how the kernel parses the messages */
+#pragma pack(push, 4)
+
/* full header structure, may have different size in user/kernel spaces */
typedef struct mach_msg_header {
mach_msg_bits_t msgh_bits;
@@ -151,7 +154,10 @@ typedef struct {
mach_msg_bits_t msgh_bits;
mach_msg_size_t msgh_size;
mach_port_name_t msgh_remote_port;
- mach_port_name_t msgh_local_port;
+ union {
+ mach_port_name_t msgh_local_port;
+ rpc_uintptr_t msgh_protected_payload;
+ };
mach_port_seqno_t msgh_seqno;
mach_msg_id_t msgh_id;
} mach_msg_user_header_t;
@@ -224,6 +230,7 @@ typedef struct {
natural_t msgtl_number;
} mach_msg_type_long_t;
+#pragma pack(pop)
/*
* Known values for the msgt_name field.
diff --git a/x86_64/copy_user.c b/x86_64/copy_user.c
index b340d6f0..ae062645 100644
--- a/x86_64/copy_user.c
+++ b/x86_64/copy_user.c
@@ -16,6 +16,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include <stddef.h>
#include <string.h>
#include <kern/debug.h>
@@ -181,8 +182,21 @@ int copyinmsg (const void *userbuf, void *kernelbuf, const size_t usize)
/* kmsg->msgh_size is filled in later */
if (copyin_port(&umsg->msgh_remote_port, &kmsg->msgh_remote_port))
return 1;
+#ifdef USER32
+ /* This could contain a payload, but for 32 bits it will be the same size as a mach_port_name_t */
+ _Static_assert(sizeof(rpc_uintptr_t) == sizeof(mach_port_name_t),
+ "rpc_uintptr_t and mach_port_name_t expected to have the same size");
if (copyin_port(&umsg->msgh_local_port, &kmsg->msgh_local_port))
return 1;
+#else
+ /* For pure 64 bits, the protected payload is as large as a port pointer. */
+ _Static_assert(sizeof(rpc_uintptr_t) == sizeof(mach_port_t),
+ "rpc_uintptr_t and mach_port_t expected to have the same size");
+ if (copyin((char*)umsg + offsetof(mach_msg_user_header_t, msgh_local_port),
+ (char*)kmsg + offsetof(mach_msg_header_t, msgh_local_port),
+ sizeof(rpc_uintptr_t)))
+ return 1;
+#endif
if (copyin(&umsg->msgh_seqno, &kmsg->msgh_seqno,
sizeof(kmsg->msgh_seqno) + sizeof(kmsg->msgh_id)))
return 1;
@@ -275,8 +289,16 @@ int copyoutmsg (const void *kernelbuf, void *userbuf, const size_t ksize)
/* umsg->msgh_size is filled in later */
if (copyout_port(&kmsg->msgh_remote_port, &umsg->msgh_remote_port))
return 1;
+#ifdef USER32
if (copyout_port(&kmsg->msgh_local_port, &umsg->msgh_local_port))
return 1;
+#else
+ /* Handle protected payloads correctly, same as copyinmsg. */
+ if (copyout((char*)kmsg + offsetof(mach_msg_header_t, msgh_local_port),
+ (char*)umsg + offsetof(mach_msg_user_header_t, msgh_local_port),
+ sizeof(rpc_uintptr_t)))
+ return 1;
+#endif
if (copyout(&kmsg->msgh_seqno, &umsg->msgh_seqno,
sizeof(kmsg->msgh_seqno) + sizeof(kmsg->msgh_id)))
return 1;