From: Bandan Das <bsd@redhat.com>
CID 1390578: In usb_mtp_write_metadata, parent can never be NULL but
just in case, add an assert
CID 1390592: Check for o->format only if o !=NULL
CID 1390604: Check s->data_out != NULL in usb_mtp_handle_data
Signed-off-by: Bandan Das <bsd@redhat.com>
Message-id: 20180503192028.14353-2-bsd@redhat.com
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/usb/dev-mtp.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/hw/usb/dev-mtp.c b/hw/usb/dev-mtp.c
index 6ecf70a79b..24cff640c0 100644
--- a/hw/usb/dev-mtp.c
+++ b/hw/usb/dev-mtp.c
@@ -1446,8 +1446,7 @@ static void usb_mtp_command(MTPState *s, MTPControl *c)
if (o == NULL) {
usb_mtp_queue_result(s, RES_INVALID_OBJECT_HANDLE, c->trans,
0, 0, 0, 0);
- }
- if (o->format != FMT_ASSOCIATION) {
+ } else if (o->format != FMT_ASSOCIATION) {
usb_mtp_queue_result(s, RES_INVALID_PARENT_OBJECT, c->trans,
0, 0, 0, 0);
}
@@ -1660,6 +1659,7 @@ static void usb_mtp_write_metadata(MTPState *s)
uint32_t next_handle = s->next_handle;
assert(!s->write_pending);
+ assert(p != NULL);
utf16_to_str(dataset->length, dataset->filename, filename);
@@ -1838,7 +1838,7 @@ static void usb_mtp_handle_data(USBDevice *dev, USBPacket *p)
p->status = USB_RET_STALL;
return;
}
- if (s->data_out && !s->data_out->first) {
+ if ((s->data_out != NULL) && !s->data_out->first) {
container_type = TYPE_DATA;
} else {
usb_packet_copy(p, &container, sizeof(container));
--
2.9.3
On 7 May 2018 at 10:44, Gerd Hoffmann <kraxel@redhat.com> wrote:
> From: Bandan Das <bsd@redhat.com>
>
> CID 1390578: In usb_mtp_write_metadata, parent can never be NULL but
> just in case, add an assert
> CID 1390592: Check for o->format only if o !=NULL
> CID 1390604: Check s->data_out != NULL in usb_mtp_handle_data
> @@ -1838,7 +1838,7 @@ static void usb_mtp_handle_data(USBDevice *dev, USBPacket *p)
> p->status = USB_RET_STALL;
> return;
> }
> - if (s->data_out && !s->data_out->first) {
> + if ((s->data_out != NULL) && !s->data_out->first) {
> container_type = TYPE_DATA;
> } else {
> usb_packet_copy(p, &container, sizeof(container));
> --
I just noticed this, but this isn't actually changing the logic
in this function: "s->data_out" and "s->data_out != NULL" are
exactly the same test. So this won't change CID 1390604.
Looking back at my previous email on this, it looks like I
managed to completely misinterpret the code and/or what
coverity is talking about, which is probably the source of
the confusion. Let me try again...
In the function usb_mtp_handle_data() EP_DATA_OUT case, we have:
(1) a check for whether s->data_out is NULL, which implies
that it might be NULL sometimes
(2) some time later, a call to usb_mtp_get_data() which is
not protected by a test for whether s->data_out is NULL
and if s->data_out is NULL at point (2) then usb_mtp_get_data()
will crash.
Obviously the code path that goes through "containe_type = TYPE_DATA"
must have s->data_out being non-NULL. But in the else branch of
that, can the container_type we get via usb_packet_copy() ever
be TYPE_DATA ? (It's not clear to me whether that comes from
a trusted or untrusted source.)
If this is a "can't happen" situation we can mark it as a false
positive in coverity.
thanks
-- PMM
Peter Maydell <peter.maydell@linaro.org> writes:
> On 7 May 2018 at 10:44, Gerd Hoffmann <kraxel@redhat.com> wrote:
>> From: Bandan Das <bsd@redhat.com>
>>
>> CID 1390578: In usb_mtp_write_metadata, parent can never be NULL but
>> just in case, add an assert
>> CID 1390592: Check for o->format only if o !=NULL
>> CID 1390604: Check s->data_out != NULL in usb_mtp_handle_data
>
>> @@ -1838,7 +1838,7 @@ static void usb_mtp_handle_data(USBDevice *dev, USBPacket *p)
>> p->status = USB_RET_STALL;
>> return;
>> }
>> - if (s->data_out && !s->data_out->first) {
>> + if ((s->data_out != NULL) && !s->data_out->first) {
>> container_type = TYPE_DATA;
>> } else {
>> usb_packet_copy(p, &container, sizeof(container));
>> --
>
> I just noticed this, but this isn't actually changing the logic
> in this function: "s->data_out" and "s->data_out != NULL" are
> exactly the same test. So this won't change CID 1390604.
Right, indeed they are. I am unfamiliar with coverity and just
incorrectly assumed that somehow it's assuming the test for NULL
can return false.
> Looking back at my previous email on this, it looks like I
> managed to completely misinterpret the code and/or what
> coverity is talking about, which is probably the source of
> the confusion. Let me try again...
>
> In the function usb_mtp_handle_data() EP_DATA_OUT case, we have:
> (1) a check for whether s->data_out is NULL, which implies
> that it might be NULL sometimes
> (2) some time later, a call to usb_mtp_get_data() which is
> not protected by a test for whether s->data_out is NULL
>
> and if s->data_out is NULL at point (2) then usb_mtp_get_data()
> will crash.
>
> Obviously the code path that goes through "containe_type = TYPE_DATA"
> must have s->data_out being non-NULL. But in the else branch of
> that, can the container_type we get via usb_packet_copy() ever
> be TYPE_DATA ? (It's not clear to me whether that comes from
> a trusted or untrusted source.)
>
> If this is a "can't happen" situation we can mark it as a false
> positive in coverity.
The protocol ofcourse won't let this happen but the guest can't be
trusted. It can easily send a packet with TYPE_DATA without sending
OBJECT_INFO first that allocates memory for data_out. I will submit a
fix.
Thanks for clearing out the confusion.
Bandan
> thanks
> -- PMM
Bandan Das <bsd@redhat.com> writes: >> If this is a "can't happen" situation we can mark it as a false >> positive in coverity. I posted a patch with an assert added in usb_mtp_get_data. I believe CID 1390604 can be marked as a false positive. Thanks, Bandan > The protocol ofcourse won't let this happen but the guest can't be > trusted. It can easily send a packet with TYPE_DATA without sending > OBJECT_INFO first that allocates memory for data_out. I will submit a > fix. > > Thanks for clearing out the confusion. > > Bandan > >> thanks >> -- PMM
CID 1390604
If the initiator sends a packet with TYPE_DATA set without
initiating a CMD_GET_OBJECT_INFO first, then usb_mtp_get_data
can trip on a null s->data_out.
Signed-off-by: Bandan Das <bsd@redhat.com>
---
hw/usb/dev-mtp.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/hw/usb/dev-mtp.c b/hw/usb/dev-mtp.c
index 3d59fe4944..905e025d7f 100644
--- a/hw/usb/dev-mtp.c
+++ b/hw/usb/dev-mtp.c
@@ -1696,6 +1696,7 @@ static void usb_mtp_get_data(MTPState *s, mtp_container *container,
uint64_t dlen;
uint32_t data_len = p->iov.size;
+ assert(d != NULL);
if (d->first) {
/* Total length of incoming data */
d->length = cpu_to_le32(container->length) - sizeof(mtp_container);
--
2.14.3
On 18 May 2018 at 19:22, Bandan Das <bsd@redhat.com> wrote:
>
> CID 1390604
> If the initiator sends a packet with TYPE_DATA set without
> initiating a CMD_GET_OBJECT_INFO first, then usb_mtp_get_data
> can trip on a null s->data_out.
>
> Signed-off-by: Bandan Das <bsd@redhat.com>
I think you said this can be provoked by the guest?
Misbehaving or malicious guests should never be able
to provoke assertions.
> ---
> hw/usb/dev-mtp.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/hw/usb/dev-mtp.c b/hw/usb/dev-mtp.c
> index 3d59fe4944..905e025d7f 100644
> --- a/hw/usb/dev-mtp.c
> +++ b/hw/usb/dev-mtp.c
> @@ -1696,6 +1696,7 @@ static void usb_mtp_get_data(MTPState *s, mtp_container *container,
> uint64_t dlen;
> uint32_t data_len = p->iov.size;
>
> + assert(d != NULL);
> if (d->first) {
> /* Total length of incoming data */
> d->length = cpu_to_le32(container->length) - sizeof(mtp_container);
> --
> 2.14.3
thanks
-- PMM
Peter Maydell <peter.maydell@linaro.org> writes:
> On 18 May 2018 at 19:22, Bandan Das <bsd@redhat.com> wrote:
>>
>> CID 1390604
>> If the initiator sends a packet with TYPE_DATA set without
>> initiating a CMD_GET_OBJECT_INFO first, then usb_mtp_get_data
>> can trip on a null s->data_out.
>>
>> Signed-off-by: Bandan Das <bsd@redhat.com>
>
> I think you said this can be provoked by the guest?
Yes, this can only be initated by the guest as far as I
understand.
> Misbehaving or malicious guests should never be able
> to provoke assertions.
I am not sure, I thought it's better to kill a misbehaving guest rather
than silently letting it run. Anyway, it's possible to send a
No_Valid_ObjectInfo as well and we wouldn't have to mark it as a
false positive either.
Bandan
>> ---
>> hw/usb/dev-mtp.c | 1 +
>> 1 file changed, 1 insertion(+)
>>
>> diff --git a/hw/usb/dev-mtp.c b/hw/usb/dev-mtp.c
>> index 3d59fe4944..905e025d7f 100644
>> --- a/hw/usb/dev-mtp.c
>> +++ b/hw/usb/dev-mtp.c
>> @@ -1696,6 +1696,7 @@ static void usb_mtp_get_data(MTPState *s, mtp_container *container,
>> uint64_t dlen;
>> uint32_t data_len = p->iov.size;
>>
>> + assert(d != NULL);
>> if (d->first) {
>> /* Total length of incoming data */
>> d->length = cpu_to_le32(container->length) - sizeof(mtp_container);
>> --
>> 2.14.3
>
> thanks
> -- PMM
On 18 May 2018 at 19:38, Bandan Das <bsd@redhat.com> wrote: > Peter Maydell <peter.maydell@linaro.org> writes: > >> On 18 May 2018 at 19:22, Bandan Das <bsd@redhat.com> wrote: >>> >>> CID 1390604 >>> If the initiator sends a packet with TYPE_DATA set without >>> initiating a CMD_GET_OBJECT_INFO first, then usb_mtp_get_data >>> can trip on a null s->data_out. >>> >>> Signed-off-by: Bandan Das <bsd@redhat.com> >> >> I think you said this can be provoked by the guest? > > Yes, this can only be initated by the guest as far as I > understand. > >> Misbehaving or malicious guests should never be able >> to provoke assertions. > > I am not sure, I thought it's better to kill a misbehaving guest rather > than silently letting it run. Anyway, it's possible to send a > No_Valid_ObjectInfo as well and we wouldn't have to mark it as a > false positive either. Broadly speaking, where we're emulating hardware we should do what the hardware does when the guest does wrong things to it. A real server doesn't suddenly vanish leaving behind a message saying "assertion failed" :-) thanks -- PMM
Peter Maydell <peter.maydell@linaro.org> writes: > On 18 May 2018 at 19:38, Bandan Das <bsd@redhat.com> wrote: >> Peter Maydell <peter.maydell@linaro.org> writes: >> >>> On 18 May 2018 at 19:22, Bandan Das <bsd@redhat.com> wrote: >>>> >>>> CID 1390604 >>>> If the initiator sends a packet with TYPE_DATA set without >>>> initiating a CMD_GET_OBJECT_INFO first, then usb_mtp_get_data >>>> can trip on a null s->data_out. >>>> >>>> Signed-off-by: Bandan Das <bsd@redhat.com> >>> >>> I think you said this can be provoked by the guest? >> >> Yes, this can only be initated by the guest as far as I >> understand. >> >>> Misbehaving or malicious guests should never be able >>> to provoke assertions. >> >> I am not sure, I thought it's better to kill a misbehaving guest rather >> than silently letting it run. Anyway, it's possible to send a >> No_Valid_ObjectInfo as well and we wouldn't have to mark it as a >> false positive either. > > Broadly speaking, where we're emulating hardware we should do > what the hardware does when the guest does wrong things to it. > A real server doesn't suddenly vanish leaving behind a > message saying "assertion failed" :-) Posted v2 and agree with you! Especially, since the protocol does specify the case where something like this can happen. Thanks for reviewing, Bandan > thanks > -- PMM
CID 1390604
If the initiator sends a packet with TYPE_DATA set without
initiating a CMD_GET_OBJECT_INFO first, then usb_mtp_get_data
can trip on a null s->data_out.
Signed-off-by: Bandan Das <bsd@redhat.com>
---
hw/usb/dev-mtp.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/hw/usb/dev-mtp.c b/hw/usb/dev-mtp.c
index 3d59fe4944..28384ea3b0 100644
--- a/hw/usb/dev-mtp.c
+++ b/hw/usb/dev-mtp.c
@@ -1696,6 +1696,11 @@ static void usb_mtp_get_data(MTPState *s, mtp_container *container,
uint64_t dlen;
uint32_t data_len = p->iov.size;
+ if (!d) {
+ usb_mtp_queue_result(s, RES_INVALID_OBJECTINFO, 0,
+ 0, 0, 0, 0);
+ return;
+ }
if (d->first) {
/* Total length of incoming data */
d->length = cpu_to_le32(container->length) - sizeof(mtp_container);
--
2.14.3
© 2016 - 2026 Red Hat, Inc.