Message ID | 20210126050248.9077-2-dmitry.fomichev@wdc.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Fix zone write validation | expand |
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 --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; }
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(-)