bcache: fix overflow in offset_to_stripe()
[platform/kernel/linux-starfive.git] / drivers / md / bcache / writeback.h
index b029843..3f1230e 100644 (file)
@@ -52,10 +52,22 @@ static inline uint64_t bcache_dev_sectors_dirty(struct bcache_device *d)
        return ret;
 }
 
-static inline unsigned int offset_to_stripe(struct bcache_device *d,
+static inline int offset_to_stripe(struct bcache_device *d,
                                        uint64_t offset)
 {
        do_div(offset, d->stripe_size);
+
+       /* d->nr_stripes is in range [1, INT_MAX] */
+       if (unlikely(offset >= d->nr_stripes)) {
+               pr_err("Invalid stripe %llu (>= nr_stripes %d).\n",
+                       offset, d->nr_stripes);
+               return -EINVAL;
+       }
+
+       /*
+        * Here offset is definitly smaller than INT_MAX,
+        * return it as int will never overflow.
+        */
        return offset;
 }
 
@@ -63,7 +75,10 @@ static inline bool bcache_dev_stripe_dirty(struct cached_dev *dc,
                                           uint64_t offset,
                                           unsigned int nr_sectors)
 {
-       unsigned int stripe = offset_to_stripe(&dc->disk, offset);
+       int stripe = offset_to_stripe(&dc->disk, offset);
+
+       if (stripe < 0)
+               return false;
 
        while (1) {
                if (atomic_read(dc->disk.stripe_sectors_dirty + stripe))