All of lore.kernel.org
 help / color / mirror / Atom feed
* [bug report] vdpa_sim_blk: implement ramdisk behaviour
@ 2021-09-29 11:37 Dan Carpenter
  2021-09-29 11:46 ` Dan Carpenter
  0 siblings, 1 reply; 4+ messages in thread
From: Dan Carpenter @ 2021-09-29 11:37 UTC (permalink / raw)
  To: sgarzare; +Cc: virtualization

Hello Stefano Garzarella,

The patch 7d189f617f83: "vdpa_sim_blk: implement ramdisk behaviour"
from Mar 15, 2021, leads to the following
Smatch static checker warning:

	drivers/vdpa/vdpa_sim/vdpa_sim_blk.c:179 vdpasim_blk_handle_req()
	warn: unsigned subtraction: 'to_push - pushed' use '!='

drivers/vdpa/vdpa_sim/vdpa_sim_blk.c
    61 static bool vdpasim_blk_handle_req(struct vdpasim *vdpasim,
    62                                    struct vdpasim_virtqueue *vq)
    63 {
    64         size_t pushed = 0, to_pull, to_push;
    65         struct virtio_blk_outhdr hdr;
    66         ssize_t bytes;
    67         loff_t offset;
    68         u64 sector;
    69         u8 status;
    70         u32 type;
    71         int ret;
    72 
    73         ret = vringh_getdesc_iotlb(&vq->vring, &vq->out_iov, &vq->in_iov,
    74                                    &vq->head, GFP_ATOMIC);
    75         if (ret != 1)
    76                 return false;
    77 
    78         if (vq->out_iov.used < 1 || vq->in_iov.used < 1) {
    79                 dev_err(&vdpasim->vdpa.dev, "missing headers - out_iov: %u in_iov %u\n",
    80                         vq->out_iov.used, vq->in_iov.used);
    81                 return false;
    82         }
    83 
    84         if (vq->in_iov.iov[vq->in_iov.used - 1].iov_len < 1) {
    85                 dev_err(&vdpasim->vdpa.dev, "request in header too short\n");
    86                 return false;
    87         }
    88 
    89         /* The last byte is the status and we checked if the last iov has
    90          * enough room for it.
    91          */
    92         to_push = vringh_kiov_length(&vq->in_iov) - 1;

Are you positive that vringh_kiov_length() cannot be zero?  I looked at
the range_check() and there is no check for "if (*len == 0)".

    93 
    94         to_pull = vringh_kiov_length(&vq->out_iov);
    95 
    96         bytes = vringh_iov_pull_iotlb(&vq->vring, &vq->out_iov, &hdr,
    97                                       sizeof(hdr));
    98         if (bytes != sizeof(hdr)) {
    99                 dev_err(&vdpasim->vdpa.dev, "request out header too short\n");
    100                 return false;
    101         }
    102 
    103         to_pull -= bytes;

The same "bytes" is used for both to_pull and to_push.  In this
assignment it would only be used for the default case which prints an
error message.

    104 
    105         type = vdpasim32_to_cpu(vdpasim, hdr.type);
    106         sector = vdpasim64_to_cpu(vdpasim, hdr.sector);
    107         offset = sector << SECTOR_SHIFT;
    108         status = VIRTIO_BLK_S_OK;
    109 
    110         switch (type) {
    111         case VIRTIO_BLK_T_IN:
    112                 if (!vdpasim_blk_check_range(sector, to_push)) {
    113                         dev_err(&vdpasim->vdpa.dev,
    114                                 "reading over the capacity - offset: 0x%llx len: 0x%zx\n",
    115                                 offset, to_push);
    116                         status = VIRTIO_BLK_S_IOERR;
    117                         break;
    118                 }
    119 
    120                 bytes = vringh_iov_push_iotlb(&vq->vring, &vq->in_iov,
    121                                               vdpasim->buffer + offset,
    122                                               to_push);
    123                 if (bytes < 0) {
    124                         dev_err(&vdpasim->vdpa.dev,
    125                                 "vringh_iov_push_iotlb() error: %zd offset: 0x%llx len: 0x%zx\n",
    126                                 bytes, offset, to_push);
    127                         status = VIRTIO_BLK_S_IOERR;
    128                         break;
    129                 }
    130 
    131                 pushed += bytes;
    132                 break;
    133 
    134         case VIRTIO_BLK_T_OUT:
    135                 if (!vdpasim_blk_check_range(sector, to_pull)) {
    136                         dev_err(&vdpasim->vdpa.dev,
    137                                 "writing over the capacity - offset: 0x%llx len: 0x%zx\n",
    138                                 offset, to_pull);
    139                         status = VIRTIO_BLK_S_IOERR;
    140                         break;
    141                 }
    142 
    143                 bytes = vringh_iov_pull_iotlb(&vq->vring, &vq->out_iov,
    144                                               vdpasim->buffer + offset,
    145                                               to_pull);

Here "bytes" is to_pull again.

    146                 if (bytes < 0) {
    147                         dev_err(&vdpasim->vdpa.dev,
    148                                 "vringh_iov_pull_iotlb() error: %zd offset: 0x%llx len: 0x%zx\n",
    149                                 bytes, offset, to_pull);
    150                         status = VIRTIO_BLK_S_IOERR;
    151                         break;
    152                 }
    153                 break;
    154 
    155         case VIRTIO_BLK_T_GET_ID:
    156                 bytes = vringh_iov_push_iotlb(&vq->vring, &vq->in_iov,
    157                                               vdpasim_blk_id,
    158                                               VIRTIO_BLK_ID_BYTES);

Do we know that to_push is larger than VIRTIO_BLK_ID_BYTES?

    159                 if (bytes < 0) {
    160                         dev_err(&vdpasim->vdpa.dev,
    161                                 "vringh_iov_push_iotlb() error: %zd\n", bytes);
    162                         status = VIRTIO_BLK_S_IOERR;
    163                         break;
    164                 }
    165 
    166                 pushed += bytes;
    167                 break;
    168 
    169         default:
    170                 dev_warn(&vdpasim->vdpa.dev,
    171                          "Unsupported request type %d\n", type);
    172                 status = VIRTIO_BLK_S_IOERR;
    173                 break;
    174         }
    175 
    176         /* If some operations fail, we need to skip the remaining bytes
    177          * to put the status in the last byte
    178          */
--> 179         if (to_push - pushed > 0)

What I'm doing here is I'm looking for places where there are signedness
bugs such that "pushed > to_push" and the subtraction results in a high
positive value instead of a negative value.

I think there are potential issues here.  It's definitely not clear
without reading a lot of context whether this code is safe.

    180                 vringh_kiov_advance(&vq->in_iov, to_push - pushed);
    181 
    182         /* Last byte is the status */
    183         bytes = vringh_iov_push_iotlb(&vq->vring, &vq->in_iov, &status, 1);
    184         if (bytes != 1)
    185                 return false;
    186 
    187         pushed += bytes;
    188 
    189         /* Make sure data is wrote before advancing index */
    190         smp_wmb();
    191 
    192         vringh_complete_iotlb(&vq->vring, vq->head, pushed);
    193 
    194         return true;
    195 }

regards,
dan carpenter
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [bug report] vdpa_sim_blk: implement ramdisk behaviour
  2021-09-29 11:37 [bug report] vdpa_sim_blk: implement ramdisk behaviour Dan Carpenter
@ 2021-09-29 11:46 ` Dan Carpenter
  2021-09-29 12:07   ` Stefano Garzarella
  0 siblings, 1 reply; 4+ messages in thread
From: Dan Carpenter @ 2021-09-29 11:46 UTC (permalink / raw)
  To: sgarzare; +Cc: virtualization

On Wed, Sep 29, 2021 at 02:37:42PM +0300, Dan Carpenter wrote:
>     89         /* The last byte is the status and we checked if the last iov has
>     90          * enough room for it.
>     91          */
>     92         to_push = vringh_kiov_length(&vq->in_iov) - 1;
> 
> Are you positive that vringh_kiov_length() cannot be zero?  I looked at
> the range_check() and there is no check for "if (*len == 0)".
> 
>     93 
>     94         to_pull = vringh_kiov_length(&vq->out_iov);
>     95 
>     96         bytes = vringh_iov_pull_iotlb(&vq->vring, &vq->out_iov, &hdr,
>     97                                       sizeof(hdr));
>     98         if (bytes != sizeof(hdr)) {
>     99                 dev_err(&vdpasim->vdpa.dev, "request out header too short\n");
>     100                 return false;
>     101         }
>     102 
>     103         to_pull -= bytes;
> 
> The same "bytes" is used for both to_pull and to_push.  In this
> assignment it would only be used for the default case which prints an
> error message.
> 

Sorry, no.  This part is wrong.  "bytes" is not used for "to_push"
either here or below.  But I still am not sure "*len == 0" or how we
know that "to_push >= VIRTIO_BLK_ID_BYTES".

regards,
dan carpenter

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [bug report] vdpa_sim_blk: implement ramdisk behaviour
  2021-09-29 11:46 ` Dan Carpenter
@ 2021-09-29 12:07   ` Stefano Garzarella
  2021-09-29 13:22     ` Dan Carpenter
  0 siblings, 1 reply; 4+ messages in thread
From: Stefano Garzarella @ 2021-09-29 12:07 UTC (permalink / raw)
  To: Dan Carpenter; +Cc: virtualization

On Wed, Sep 29, 2021 at 02:46:52PM +0300, Dan Carpenter wrote:
>On Wed, Sep 29, 2021 at 02:37:42PM +0300, Dan Carpenter wrote:
>>     89         /* The last byte is the status and we checked if the last iov has
>>     90          * enough room for it.
>>     91          */
>>     92         to_push = vringh_kiov_length(&vq->in_iov) - 1;
>>
>> Are you positive that vringh_kiov_length() cannot be zero?  I looked at
>> the range_check() and there is no check for "if (*len == 0)".
>>
>>     93
>>     94         to_pull = vringh_kiov_length(&vq->out_iov);
>>     95
>>     96         bytes = vringh_iov_pull_iotlb(&vq->vring, &vq->out_iov, &hdr,
>>     97                                       sizeof(hdr));
>>     98         if (bytes != sizeof(hdr)) {
>>     99                 dev_err(&vdpasim->vdpa.dev, "request out header too short\n");
>>     100                 return false;
>>     101         }
>>     102
>>     103         to_pull -= bytes;
>>
>> The same "bytes" is used for both to_pull and to_push.  In this
>> assignment it would only be used for the default case which prints an
>> error message.
>>
>
>Sorry, no.  This part is wrong.  "bytes" is not used for "to_push"
>either here or below.  But I still am not sure "*len == 0" or how we

At line 84 we check that the last `in_iov` has at least one byte, so 
vringh_kiov_length(&vq->in_iov) cannot be zero.
It will return the sum of all lengths, so at least 1.

Maybe better to add a comment.

>know that "to_push >= VIRTIO_BLK_ID_BYTES".

vringh_iov_push_iotlb() will push at least the bytes available in 
`in_iov`, if these are less, it will copy less bytes of 
VIRTIO_BLK_ID_BYTES.

Maybe here it would be better to add a check because the driver isn't 
following the specification.

And I'd avoid the subtraction highlighted by Smatch static checker.

Thanks for reporting. I'll send patches to fix these issues.

Stefano

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [bug report] vdpa_sim_blk: implement ramdisk behaviour
  2021-09-29 12:07   ` Stefano Garzarella
@ 2021-09-29 13:22     ` Dan Carpenter
  0 siblings, 0 replies; 4+ messages in thread
From: Dan Carpenter @ 2021-09-29 13:22 UTC (permalink / raw)
  To: Stefano Garzarella; +Cc: virtualization

On Wed, Sep 29, 2021 at 02:07:12PM +0200, Stefano Garzarella wrote:
> On Wed, Sep 29, 2021 at 02:46:52PM +0300, Dan Carpenter wrote:
> > On Wed, Sep 29, 2021 at 02:37:42PM +0300, Dan Carpenter wrote:
> > >     89         /* The last byte is the status and we checked if the last iov has
> > >     90          * enough room for it.
> > >     91          */
> > >     92         to_push = vringh_kiov_length(&vq->in_iov) - 1;
> > > 
> > > Are you positive that vringh_kiov_length() cannot be zero?  I looked at
> > > the range_check() and there is no check for "if (*len == 0)".
> > > 
> > >     93
> > >     94         to_pull = vringh_kiov_length(&vq->out_iov);
> > >     95
> > >     96         bytes = vringh_iov_pull_iotlb(&vq->vring, &vq->out_iov, &hdr,
> > >     97                                       sizeof(hdr));
> > >     98         if (bytes != sizeof(hdr)) {
> > >     99                 dev_err(&vdpasim->vdpa.dev, "request out header too short\n");
> > >     100                 return false;
> > >     101         }
> > >     102
> > >     103         to_pull -= bytes;
> > > 
> > > The same "bytes" is used for both to_pull and to_push.  In this
> > > assignment it would only be used for the default case which prints an
> > > error message.
> > > 
> > 
> > Sorry, no.  This part is wrong.  "bytes" is not used for "to_push"
> > either here or below.  But I still am not sure "*len == 0" or how we
> 
> At line 84 we check that the last `in_iov` has at least one byte, so
> vringh_kiov_length(&vq->in_iov) cannot be zero.
> It will return the sum of all lengths, so at least 1.
> 
> Maybe better to add a comment.
> 
> > know that "to_push >= VIRTIO_BLK_ID_BYTES".
> 
> vringh_iov_push_iotlb() will push at least the bytes available in `in_iov`,
> if these are less, it will copy less bytes of VIRTIO_BLK_ID_BYTES.
> 
> Maybe here it would be better to add a check because the driver isn't
> following the specification.
> 
> And I'd avoid the subtraction highlighted by Smatch static checker.
> 
> Thanks for reporting. I'll send patches to fix these issues.

Nothing to fix, really.  I've looked at what you've explained and it's
all true so the code is fine as-is.  Thanks so much.

regards,
dan carpenter

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2021-09-29 13:54 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-09-29 11:37 [bug report] vdpa_sim_blk: implement ramdisk behaviour Dan Carpenter
2021-09-29 11:46 ` Dan Carpenter
2021-09-29 12:07   ` Stefano Garzarella
2021-09-29 13:22     ` Dan Carpenter

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.