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@xxxxxxxxx> --- fs/ceph/snap.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) 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; -- 2.47.0