From: Alexander Ivanov <alexander.ivanov@virtuozzo.com>
To: den@openvz.org
Cc: devel@openvz.org
Subject: [Devel] [PATCH hci-8.1 v5 01/11] dm-ploop: fix u32 overflow of the delta BAT byte size
Date: Tue, 13 Oct 2026 09:55:03 +0200 [thread overview]
Message-ID: <20261013075513.90618-2-alexander.ivanov@virtuozzo.com> (raw)
In-Reply-To: <20261013075513.90618-1-alexander.ivanov@virtuozzo.com>
The byte size of header and BAT, (PLOOP_MAP_OFFSET + m_Size) *
sizeof(map_index_t), is computed in u32 in several places. It wraps for
m_Size >= 2^30 - PLOOP_MAP_OFFSET, which a delta with small clusters
may legally have.
Compute the size in u64 and use ploop_nr_bat_clusters() for the number
of BAT clusters everywhere.
Reject a header or a resize whose hb_nr exceeds PLOOP_MAX_HB_NR,
which also keeps DIV_ROUND_UP(hb_nr, 8) and the bitmap size in bits
from wrapping.
https://virtuozzo.atlassian.net/browse/VSTOR-148171
Feature: dm-ploop: ploop target driver
Signed-off-by: Alexander Ivanov <alexander.ivanov@virtuozzo.com>
---
drivers/md/dm-ploop-bat.c | 23 ++++++++++++-----------
drivers/md/dm-ploop-cmd.c | 19 +++++++++----------
drivers/md/dm-ploop.h | 6 ++++--
3 files changed, 25 insertions(+), 23 deletions(-)
diff --git a/drivers/md/dm-ploop-bat.c b/drivers/md/dm-ploop-bat.c
index a7849de8aaa6..5ddb8ffdff07 100644
--- a/drivers/md/dm-ploop-bat.c
+++ b/drivers/md/dm-ploop-bat.c
@@ -189,7 +189,6 @@ int ploop_setup_metadata(struct ploop *ploop, struct page *page)
struct ploop_pvd_header *m_hdr = NULL;
u32 bat_clusters, offset_clusters;
struct dm_target *ti = ploop->ti;
- unsigned long size;
int ret;
m_hdr = kmap(page);
@@ -213,8 +212,11 @@ int ploop_setup_metadata(struct ploop *ploop, struct page *page)
ploop->nr_bat_entries = le32_to_cpu(m_hdr->m_Size);
/* Header and BAT-occupied clusters at start of file */
- size = (PLOOP_MAP_OFFSET + ploop->nr_bat_entries) * sizeof(map_index_t);
- bat_clusters = DIV_ROUND_UP(size, CLU_SIZE(ploop));
+ bat_clusters = ploop_nr_bat_clusters(ploop, ploop->nr_bat_entries);
+ if ((u64)bat_clusters + ploop->nr_bat_entries > PLOOP_MAX_HB_NR) {
+ PL_ERR("Too large BAT");
+ goto out;
+ }
/* Clusters from start of file to first data block */
offset_clusters = SEC_TO_CLU(ploop, le32_to_cpu(m_hdr->m_FirstBlockOffset));
@@ -242,7 +244,7 @@ static int ploop_delta_check_header(struct ploop *ploop,
struct rb_root *md_root,
u32 *delta_nr_be_ret)
{
- u32 bytes, delta_nr_be, offset_clusters, bat_clusters;
+ u32 delta_nr_be, offset_clusters, bat_clusters;
struct md_page *md0 = ploop_md_first_entry(md_root);
struct ploop_pvd_header *d_hdr;
int ret = -EPROTO;
@@ -257,8 +259,7 @@ static int ploop_delta_check_header(struct ploop *ploop,
delta_nr_be = le32_to_cpu(d_hdr->m_Size);
offset_clusters = SEC_TO_CLU(ploop, le32_to_cpu(d_hdr->m_FirstBlockOffset));
- bytes = (PLOOP_MAP_OFFSET + delta_nr_be) * sizeof(map_index_t);
- bat_clusters = DIV_ROUND_UP(bytes, CLU_SIZE(ploop));
+ bat_clusters = ploop_nr_bat_clusters(ploop, delta_nr_be);
if (delta_nr_be > ploop->nr_bat_entries ||
bat_clusters != offset_clusters)
@@ -274,13 +275,12 @@ ALLOW_ERROR_INJECTION(ploop_delta_check_header, ERRNO);
static int ploop_convert_bat_entries(struct ploop *ploop, struct rb_root *md_root,
u32 nr_be, u32 nr_pages, loff_t file_size)
{
- u32 i, end, bytes, bat_clusters, page_id, *bat_entries, max_file_clu;
+ u32 i, end, bat_clusters, page_id, *bat_entries, max_file_clu;
struct rb_node *node;
struct md_page *md;
int ret = 0;
- bytes = (PLOOP_MAP_OFFSET + nr_be) * sizeof(map_index_t);
- bat_clusters = DIV_ROUND_UP(bytes, CLU_SIZE(ploop));
+ bat_clusters = ploop_nr_bat_clusters(ploop, nr_be);
max_file_clu = file_size / CLU_SIZE(ploop) - 1;
page_id = 0;
@@ -311,12 +311,13 @@ int ploop_read_delta_metadata(struct ploop *ploop, struct file *file,
struct rb_root *md_root, u32 *delta_nr_be_ret)
{
struct bio_vec bvec_on_stack, *bvec = &bvec_on_stack;
- u32 i, size, delta_nr_be, nr_segs;
+ u32 i, delta_nr_be, nr_segs;
loff_t pos, file_size;
struct iov_iter iter;
struct rb_node *node;
struct md_page *md;
ssize_t len;
+ u64 size;
int ret;
ret = -ENOMEM;
@@ -339,7 +340,7 @@ int ploop_read_delta_metadata(struct ploop *ploop, struct file *file,
if (ret)
goto out;
- size = (PLOOP_MAP_OFFSET + delta_nr_be) * sizeof(map_index_t);
+ size = ((u64)delta_nr_be + PLOOP_MAP_OFFSET) * sizeof(map_index_t);
size = ALIGN(size, PAGE_SIZE); /* file may be open as direct */
nr_segs = size / PAGE_SIZE;
diff --git a/drivers/md/dm-ploop-cmd.c b/drivers/md/dm-ploop-cmd.c
index 5fa78e6cff9a..ab17520c2d56 100644
--- a/drivers/md/dm-ploop-cmd.c
+++ b/drivers/md/dm-ploop-cmd.c
@@ -386,7 +386,7 @@ ALLOW_ERROR_INJECTION(ploop_grow_relocate_cluster, ERRNO);
static int ploop_grow_update_header(struct ploop *ploop,
struct ploop_cmd *cmd)
{
- unsigned int size, first_block_off;
+ unsigned int first_block_off;
struct ploop_pvd_header *hdr;
struct ploop_index_wb *piwb;
u32 nr_be, offset, clus;
@@ -413,9 +413,7 @@ static int ploop_grow_update_header(struct ploop *ploop,
}
piwb = md->piwb;
- size = (PLOOP_MAP_OFFSET + cmd->resize.nr_bat_entries);
- size *= sizeof(map_index_t);
- clus = DIV_ROUND_UP(size, CLU_SIZE(ploop));
+ clus = ploop_nr_bat_clusters(ploop, cmd->resize.nr_bat_entries);
first_block_off = CLU_TO_SEC(ploop, clus);
hdr = kmap_local_page(piwb->bat_page);
@@ -597,6 +595,11 @@ static int ploop_resize(struct ploop *ploop, sector_t new_sectors)
}
nr_bat_entries = SEC_TO_CLU(ploop, new_sectors);
+ nr_bat_clusters = ploop_nr_bat_clusters(ploop, nr_bat_entries);
+ if ((u64)nr_bat_clusters + nr_bat_entries > PLOOP_MAX_HB_NR) {
+ DMWARN("resize: too large size is requested");
+ return -EINVAL;
+ }
/* Memory for new md pages */
ret = ploop_prealloc_md_pages(&cmd.resize.md_pages_root,
@@ -604,8 +607,6 @@ static int ploop_resize(struct ploop *ploop, sector_t new_sectors)
if (ret)
return ret;
- size = (PLOOP_MAP_OFFSET + nr_bat_entries) * sizeof(map_index_t);
- nr_bat_clusters = DIV_ROUND_UP(size, CLU_SIZE(ploop));
hb_nr = nr_bat_clusters + nr_bat_entries;
size = round_up(DIV_ROUND_UP(hb_nr, 8), sizeof(unsigned long));
@@ -1010,11 +1011,9 @@ static int process_flip_upper_deltas(struct ploop *ploop)
u8 level = ploop_top_level(ploop) - 1;
struct rb_node *node;
struct md_page *md;
- u64 size;
- size = (PLOOP_MAP_OFFSET + READ_ONCE(ploop->nr_bat_entries))
- * sizeof(map_index_t);
- bat_clusters = DIV_ROUND_UP(size, CLU_SIZE(ploop));
+ bat_clusters = ploop_nr_bat_clusters(ploop,
+ READ_ONCE(ploop->nr_bat_entries));
hb_nr = ploop->hb_nr;
/*
diff --git a/drivers/md/dm-ploop.h b/drivers/md/dm-ploop.h
index 23662943d56a..5041fc8f1e13 100644
--- a/drivers/md/dm-ploop.h
+++ b/drivers/md/dm-ploop.h
@@ -12,6 +12,8 @@
#include <linux/bio.h>
#define PLOOP_MAP_OFFSET 16
+/* Keeps DIV_ROUND_UP(hb_nr, 8) and clu + PLOOP_MAP_OFFSET within u32 */
+#define PLOOP_MAX_HB_NR round_down(U32_MAX - PLOOP_MAP_OFFSET, 8)
typedef u32 map_index_t;
#define BAT_ENTRIES_PER_PAGE (PAGE_SIZE / sizeof(map_index_t))
@@ -410,9 +412,9 @@ static inline unsigned int ploop_nr_pages_in_cluster(struct ploop *ploop)
static inline unsigned int ploop_nr_bat_clusters(struct ploop *ploop,
u32 nr_bat_entries)
{
- unsigned long size, bat_clusters;
+ u64 size, bat_clusters;
- size = (PLOOP_MAP_OFFSET + nr_bat_entries) * sizeof(map_index_t);
+ size = ((u64)nr_bat_entries + PLOOP_MAP_OFFSET) * sizeof(map_index_t);
bat_clusters = DIV_ROUND_UP(size, CLU_SIZE(ploop));
return bat_clusters;
--
2.53.0
_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel
next prev parent reply other threads:[~2026-10-13 7:56 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-13 7:55 [Devel] [PATCH hci-8.1 v5 00/11] dm-ploop: give back unused tail of top delta on suspend Alexander Ivanov
2026-10-13 7:55 ` Alexander Ivanov [this message]
2026-10-13 8:02 ` [Devel] [PATCH hci-8.1 v5 01/11] dm-ploop: fix u32 overflow of the delta BAT byte size no-reply
2026-10-13 9:24 ` Alexander Ivanov
2026-10-13 7:55 ` [Devel] [PATCH hci-8.1 v5 02/11] dm-ploop: fix lost wakeup in ploop_allocator() Alexander Ivanov
2026-10-13 8:00 ` no-reply
2026-10-13 7:55 ` [Devel] [PATCH hci-8.1 v5 03/11] dm-ploop: reject a delta header whose BAT does not cover the target Alexander Ivanov
2026-10-13 8:01 ` no-reply
2026-10-13 7:55 ` [Devel] [PATCH hci-8.1 v5 04/11] dm-ploop: reject empty deltas Alexander Ivanov
2026-10-13 8:02 ` no-reply
2026-10-13 7:55 ` [Devel] [PATCH hci-8.1 v5 05/11] dm-ploop: set delta is_raw before applying its mappings Alexander Ivanov
2026-10-13 8:03 ` no-reply
2026-10-13 7:55 ` [Devel] [PATCH hci-8.1 v5 06/11] dm-ploop: factor out ploop_read_delta() from ploop_add_delta() Alexander Ivanov
2026-10-13 8:04 ` no-reply
2026-10-13 7:55 ` [Devel] [PATCH hci-8.1 v5 07/11] dm-ploop: take bat_lock around md page lookup in ploop_llseek_hole() Alexander Ivanov
2026-10-13 8:06 ` no-reply
2026-10-13 7:55 ` [Devel] [PATCH hci-8.1 v5 08/11] dm-ploop: use wake_up() for inflight_md_wq and dispatcher_wq_prealloc Alexander Ivanov
2026-10-13 8:04 ` no-reply
2026-10-13 7:55 ` [Devel] [PATCH hci-8.1 v5 09/11] dm-ploop: fix use-after-free on the last inflight_md decrement Alexander Ivanov
2026-10-13 8:11 ` no-reply
2026-10-13 7:55 ` [Devel] [PATCH hci-8.1 v5 10/11] dm-ploop: reload metadata on resume Alexander Ivanov
2026-10-13 8:16 ` no-reply
2026-10-13 7:55 ` [Devel] [PATCH hci-8.1 v5 11/11] dm-ploop: truncate unused tail of top delta on suspend Alexander Ivanov
2026-10-13 8:20 ` no-reply
2026-10-13 11:00 ` Alexander Ivanov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261013075513.90618-2-alexander.ivanov@virtuozzo.com \
--to=alexander.ivanov@virtuozzo.com \
--cc=den@openvz.org \
--cc=devel@openvz.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.