diff mbox series

[1/3] hw/block/nvme: Check for zone boundary during append

Message ID 20210126050248.9077-2-dmitry.fomichev@wdc.com
State New
Headers show
Series Fix zone write validation | expand

Commit Message

Dmitry Fomichev Jan. 26, 2021, 5:02 a.m. UTC
It is observed that with the existing code it is possible to keep
appending to a zone indefinitely. To fix, add the missing check to
verify that the zone append is not going to write beyond zone capacity.

Reported-by: Niklas Cassel <niklas.cassel@wdc.com>
Signed-off-by: Dmitry Fomichev <dmitry.fomichev@wdc.com>
---
 hw/block/nvme.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

Comments

Klaus Jensen Jan. 26, 2021, 7:50 a.m. UTC | #1
On Jan 26 14:02, Dmitry Fomichev wrote:
> It is observed that with the existing code it is possible to keep
> appending to a zone indefinitely. To fix, add the missing check to
> verify that the zone append is not going to write beyond zone capacity.
> 
> Reported-by: Niklas Cassel <niklas.cassel@wdc.com>
> Signed-off-by: Dmitry Fomichev <dmitry.fomichev@wdc.com>
> ---
>  hw/block/nvme.c | 8 +++++---
>  1 file changed, 5 insertions(+), 3 deletions(-)
> 
> diff --git a/hw/block/nvme.c b/hw/block/nvme.c
> index f64676a930..67538010ef 100644
> --- a/hw/block/nvme.c
> +++ b/hw/block/nvme.c
> @@ -1135,9 +1135,10 @@ static uint16_t nvme_check_zone_write(NvmeCtrl *n, NvmeNamespace *ns,
>                                        NvmeZone *zone, uint64_t slba,
>                                        uint32_t nlb, bool append)
>  {
> +    uint64_t bndry = nvme_zone_wr_boundary(zone);
>      uint16_t status;
>  
> -    if (unlikely((slba + nlb) > nvme_zone_wr_boundary(zone))) {
> +    if (unlikely(slba + nlb > bndry)) {
>          status = NVME_ZONE_BOUNDARY_ERROR;
>      } else {
>          status = nvme_check_zone_state_for_write(zone);
> @@ -1151,8 +1152,9 @@ static uint16_t nvme_check_zone_write(NvmeCtrl *n, NvmeNamespace *ns,
>              if (unlikely(slba != zone->d.zslba)) {
>                  trace_pci_nvme_err_append_not_at_start(slba, zone->d.zslba);
>                  status = NVME_INVALID_FIELD;
> -            }
> -            if (nvme_l2b(ns, nlb) > (n->page_size << n->zasl)) {
> +            } else if (unlikely(zone->w_ptr + nlb > bndry)) {
> +                status = NVME_ZONE_BOUNDARY_ERROR;

Now, for appends, you are just checking the boundary condition twice.
And the first one will be moot for appends anyway.

> +            } else if (nvme_l2b(ns, nlb) > (n->page_size << n->zasl)) {
>                  trace_pci_nvme_err_append_too_large(slba, nlb, n->zasl);
>                  status = NVME_INVALID_FIELD;
>              }
> -- 
> 2.28.0
> 
>
diff mbox series

Patch

diff --git a/hw/block/nvme.c b/hw/block/nvme.c
index f64676a930..67538010ef 100644
--- a/hw/block/nvme.c
+++ b/hw/block/nvme.c
@@ -1135,9 +1135,10 @@  static uint16_t nvme_check_zone_write(NvmeCtrl *n, NvmeNamespace *ns,
                                       NvmeZone *zone, uint64_t slba,
                                       uint32_t nlb, bool append)
 {
+    uint64_t bndry = nvme_zone_wr_boundary(zone);
     uint16_t status;
 
-    if (unlikely((slba + nlb) > nvme_zone_wr_boundary(zone))) {
+    if (unlikely(slba + nlb > bndry)) {
         status = NVME_ZONE_BOUNDARY_ERROR;
     } else {
         status = nvme_check_zone_state_for_write(zone);
@@ -1151,8 +1152,9 @@  static uint16_t nvme_check_zone_write(NvmeCtrl *n, NvmeNamespace *ns,
             if (unlikely(slba != zone->d.zslba)) {
                 trace_pci_nvme_err_append_not_at_start(slba, zone->d.zslba);
                 status = NVME_INVALID_FIELD;
-            }
-            if (nvme_l2b(ns, nlb) > (n->page_size << n->zasl)) {
+            } else if (unlikely(zone->w_ptr + nlb > bndry)) {
+                status = NVME_ZONE_BOUNDARY_ERROR;
+            } else if (nvme_l2b(ns, nlb) > (n->page_size << n->zasl)) {
                 trace_pci_nvme_err_append_too_large(slba, nlb, n->zasl);
                 status = NVME_INVALID_FIELD;
             }