diff mbox series

ceph: fix overflow detection in build_snap_context()

Message ID 20241114142328.505379-1-dmantipov@yandex.ru (mailing list archive)
State New
Headers show
Series ceph: fix overflow detection in build_snap_context() | expand

Commit Message

Dmitry Antipov Nov. 14, 2024, 2:23 p.m. UTC
Since total number of snap contexts is 'u32', it can't exceed
'(SIZE_MAX - sizeof(...)) / sizeof(u64))'. And if we really
care about detecting possible overflows, it's better to use
explicit 'check_add_overflow()' instead. Compile tested only.

Found by Linux Verification Center (linuxtesting.org) with SVACE.

Signed-off-by: Dmitry Antipov <dmantipov@yandex.ru>
---
 fs/ceph/snap.c | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)
diff mbox series

Patch

diff --git a/fs/ceph/snap.c b/fs/ceph/snap.c
index c65f2b202b2b..3fa5baa73665 100644
--- a/fs/ceph/snap.c
+++ b/fs/ceph/snap.c
@@ -341,7 +341,11 @@  static int build_snap_context(struct ceph_mds_client *mdsc,
 	struct ceph_snap_realm *parent = realm->parent;
 	struct ceph_snap_context *snapc;
 	int err = 0;
-	u32 num = realm->num_prior_parent_snaps + realm->num_snaps;
+	u32 num, cnt;
+
+	if (check_add_overflow(realm->num_prior_parent_snaps,
+			       realm->num_snaps, &cnt))
+		return -EOVERFLOW;
 
 	/*
 	 * build parent context, if it hasn't been built.
@@ -354,8 +358,11 @@  static int build_snap_context(struct ceph_mds_client *mdsc,
 			list_add(&parent->rebuild_item, realm_queue);
 			return 1;
 		}
-		num += parent->cached_context->num_snaps;
-	}
+		if (check_add_overflow(parent->cached_context->num_snaps,
+				       cnt, &num))
+			return -EOVERFLOW;
+	} else
+		num = cnt;
 
 	/* do i actually need to update?  not if my context seq
 	   matches realm seq, and my parents' does to.  (this works
@@ -374,8 +381,6 @@  static int build_snap_context(struct ceph_mds_client *mdsc,
 
 	/* alloc new snap context */
 	err = -ENOMEM;
-	if (num > (SIZE_MAX - sizeof(*snapc)) / sizeof(u64))
-		goto fail;
 	snapc = ceph_create_snap_context(num, GFP_NOFS);
 	if (!snapc)
 		goto fail;