Message ID | 20201202092214.13520-3-parri.andrea@gmail.com |
---|---|
State | New, archived |
Headers | show |
Series |
|
Related | show |
On Wed, Dec 02, 2020 at 10:22:09AM +0100, Andrea Parri (Microsoft) wrote: > vmbus_on_msg_dpc() double fetches from msgtype. The double fetch can > lead to an out-of-bound access when accessing the channel_message_table > array. In turn, the use of the out-of-bound entry could lead to code > execution primitive (entry->message_handler()). Avoid the double fetch > by saving the value of msgtype into a local variable. > > Reported-by: Juan Vazquez <juvazq@microsoft.com> > Signed-off-by: Andrea Parri (Microsoft) <parri.andrea@gmail.com> > --- > drivers/hv/vmbus_drv.c | 18 +++++++++++++----- > 1 file changed, 13 insertions(+), 5 deletions(-) > > diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c > index 0a2711aa63a15..82b23baa446d7 100644 > --- a/drivers/hv/vmbus_drv.c > +++ b/drivers/hv/vmbus_drv.c > @@ -1057,6 +1057,7 @@ void vmbus_on_msg_dpc(unsigned long data) > struct hv_message *msg = (struct hv_message *)page_addr + > VMBUS_MESSAGE_SINT; > struct vmbus_channel_message_header *hdr; > + enum vmbus_channel_message_type msgtype; > const struct vmbus_channel_message_table_entry *entry; > struct onmessage_work_context *ctx; > u32 message_type = msg->header.message_type; > @@ -1072,12 +1073,19 @@ void vmbus_on_msg_dpc(unsigned long data) > /* no msg */ > return; > > + /* > + * The hv_message object is in memory shared with the host. The host > + * could erroneously or maliciously modify such object. Make sure to > + * validate its fields and avoid double fetches whenever feasible. > + */ > + > hdr = (struct vmbus_channel_message_header *)msg->u.payload; > + msgtype = hdr->msgtype; Should READ_ONCE be used here? Wei.
> > @@ -1072,12 +1073,19 @@ void vmbus_on_msg_dpc(unsigned long data) > > /* no msg */ > > return; > > > > + /* > > + * The hv_message object is in memory shared with the host. The host > > + * could erroneously or maliciously modify such object. Make sure to > > + * validate its fields and avoid double fetches whenever feasible. > > + */ > > + > > hdr = (struct vmbus_channel_message_header *)msg->u.payload; > > + msgtype = hdr->msgtype; > > Should READ_ONCE be used here? I think it should. Thank you for pointing this out. Andrea
On Wed, Dec 02, 2020 at 02:37:16PM +0100, Andrea Parri wrote: > > > @@ -1072,12 +1073,19 @@ void vmbus_on_msg_dpc(unsigned long data) > > > /* no msg */ > > > return; > > > > > > + /* > > > + * The hv_message object is in memory shared with the host. The host > > > + * could erroneously or maliciously modify such object. Make sure to > > > + * validate its fields and avoid double fetches whenever feasible. > > > + */ > > > + > > > hdr = (struct vmbus_channel_message_header *)msg->u.payload; > > > + msgtype = hdr->msgtype; > > > > Should READ_ONCE be used here? > > I think it should. Thank you for pointing this out. Glad I can help. The same comment applies to other patches as well, of course. Wei. > > Andrea
On Wed, Dec 02, 2020 at 01:40:04PM +0000, Wei Liu wrote: > On Wed, Dec 02, 2020 at 02:37:16PM +0100, Andrea Parri wrote: > > > > @@ -1072,12 +1073,19 @@ void vmbus_on_msg_dpc(unsigned long data) > > > > /* no msg */ > > > > return; > > > > > > > > + /* > > > > + * The hv_message object is in memory shared with the host. The host > > > > + * could erroneously or maliciously modify such object. Make sure to > > > > + * validate its fields and avoid double fetches whenever feasible. > > > > + */ > > > > + > > > > hdr = (struct vmbus_channel_message_header *)msg->u.payload; > > > > + msgtype = hdr->msgtype; > > > > > > Should READ_ONCE be used here? > > > > I think it should. Thank you for pointing this out. > > Glad I can help. > > The same comment applies to other patches as well, of course. (As discussed offline/for reference:) I can spot a similar case in patch #3; however, #4 is supposed to make that access 'non-shared'. I should probably just squash patches #3 and #4; I'll try to do so in v3... Thanks, Andrea
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index 0a2711aa63a15..82b23baa446d7 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -1057,6 +1057,7 @@ void vmbus_on_msg_dpc(unsigned long data) struct hv_message *msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT; struct vmbus_channel_message_header *hdr; + enum vmbus_channel_message_type msgtype; const struct vmbus_channel_message_table_entry *entry; struct onmessage_work_context *ctx; u32 message_type = msg->header.message_type; @@ -1072,12 +1073,19 @@ void vmbus_on_msg_dpc(unsigned long data) /* no msg */ return; + /* + * The hv_message object is in memory shared with the host. The host + * could erroneously or maliciously modify such object. Make sure to + * validate its fields and avoid double fetches whenever feasible. + */ + hdr = (struct vmbus_channel_message_header *)msg->u.payload; + msgtype = hdr->msgtype; trace_vmbus_on_msg_dpc(hdr); - if (hdr->msgtype >= CHANNELMSG_COUNT) { - WARN_ONCE(1, "unknown msgtype=%d\n", hdr->msgtype); + if (msgtype >= CHANNELMSG_COUNT) { + WARN_ONCE(1, "unknown msgtype=%d\n", msgtype); goto msg_handled; } @@ -1087,14 +1095,14 @@ void vmbus_on_msg_dpc(unsigned long data) goto msg_handled; } - entry = &channel_message_table[hdr->msgtype]; + entry = &channel_message_table[msgtype]; if (!entry->message_handler) goto msg_handled; if (msg->header.payload_size < entry->min_payload_len) { WARN_ONCE(1, "message too short: msgtype=%d len=%d\n", - hdr->msgtype, msg->header.payload_size); + msgtype, msg->header.payload_size); goto msg_handled; } @@ -1115,7 +1123,7 @@ void vmbus_on_msg_dpc(unsigned long data) * by offer_in_progress and by channel_mutex. See also the * inline comments in vmbus_onoffer_rescind(). */ - switch (hdr->msgtype) { + switch (msgtype) { case CHANNELMSG_RESCIND_CHANNELOFFER: /* * If we are handling the rescind message;
vmbus_on_msg_dpc() double fetches from msgtype. The double fetch can lead to an out-of-bound access when accessing the channel_message_table array. In turn, the use of the out-of-bound entry could lead to code execution primitive (entry->message_handler()). Avoid the double fetch by saving the value of msgtype into a local variable. Reported-by: Juan Vazquez <juvazq@microsoft.com> Signed-off-by: Andrea Parri (Microsoft) <parri.andrea@gmail.com> --- drivers/hv/vmbus_drv.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-)