_hurd_intr_rpc_mach_msg: handle message iteration correctly.

The `ty` pointer is only set at the end of the loop so that
`msgtl_header.msgt_inline` and `msgtl_header.msgt_deallocate` remain
valid. Also, when deallocating memory, we use the length from the
message directly rather than hard coding mach_port_t since we want to
deallocate any kind of OOL data.
Message-ID: <ZVlGVD6eEN-dXsOr@jupiter.tail36e24.ts.net>
This commit is contained in:
Flavio Cruz 2023-11-18 18:18:44 -05:00 committed by Samuel Thibault
parent dae3cf4134
commit f11a92993c

View file

@ -186,12 +186,14 @@ _hurd_intr_rpc_mach_msg (mach_msg_header_t *msg,
mach_msg_type_size_t size; mach_msg_type_size_t size;
mach_msg_type_number_t number; mach_msg_type_number_t number;
inline void clean_ports (mach_port_t *ports, int dealloc) inline void clean_ports_and_memory (char *data, const vm_size_t length,
int dealloc)
{ {
mach_msg_type_number_t i; mach_msg_type_number_t i;
switch (name) switch (name)
{ {
case MACH_MSG_TYPE_MOVE_SEND: case MACH_MSG_TYPE_MOVE_SEND:
mach_port_t *ports = (mach_port_t *) data;
for (i = 0; i < number; i++) for (i = 0; i < number; i++)
__mach_port_deallocate (__mach_task_self (), *ports++); __mach_port_deallocate (__mach_task_self (), *ports++);
if (ty->msgtl_header.msgt_longform) if (ty->msgtl_header.msgt_longform)
@ -207,40 +209,38 @@ _hurd_intr_rpc_mach_msg (mach_msg_header_t *msg,
assert (! "unexpected port type in interruptible RPC"); assert (! "unexpected port type in interruptible RPC");
} }
if (dealloc) if (dealloc)
__vm_deallocate (__mach_task_self (), __vm_deallocate (__mach_task_self (), (vm_address_t) data, length);
(vm_address_t) ports,
number * sizeof (mach_port_t));
} }
char *data;
if (ty->msgtl_header.msgt_longform) if (ty->msgtl_header.msgt_longform)
{ {
name = ty->msgtl_name; name = ty->msgtl_name;
size = ty->msgtl_size; size = ty->msgtl_size;
number = ty->msgtl_number; number = ty->msgtl_number;
ty = (void *) ty + sizeof (mach_msg_type_long_t); data = (char *) ty + sizeof (mach_msg_type_long_t);
} }
else else
{ {
name = ty->msgtl_header.msgt_name; name = ty->msgtl_header.msgt_name;
size = ty->msgtl_header.msgt_size; size = ty->msgtl_header.msgt_size;
number = ty->msgtl_header.msgt_number; number = ty->msgtl_header.msgt_number;
ty = (void *) ty + sizeof (mach_msg_type_t); data = (char *) ty + sizeof (mach_msg_type_t);
} }
const vm_size_t length = ((number * size) + 7) >> 3;
if (ty->msgtl_header.msgt_inline) if (ty->msgtl_header.msgt_inline)
{ {
/* Calculate length of data in bytes. */ /* Calculate length of data in bytes. */
const vm_size_t length = ((number * size) + 7) >> 3; clean_ports_and_memory (data, length, 0);
clean_ports ((void *) ty, 0);
/* Move to the next argument. */ /* Move to the next argument. */
ty = (void *) PTR_ALIGN_UP ((char *) ty + length, ty = (void *) PTR_ALIGN_UP (data + length, __alignof__ (uintptr_t));
__alignof__ (uintptr_t));
} }
else else
{ {
clean_ports (*(void **) ty, clean_ports_and_memory (*(void **) data, length,
ty->msgtl_header.msgt_deallocate); ty->msgtl_header.msgt_deallocate);
ty = (void *) ty + sizeof (void *); ty = (void *) data + sizeof (void *);
} }
} }
#else /* Untyped Mach IPC flavor. */ #else /* Untyped Mach IPC flavor. */