Whamcloud - gitweb
LU-1923 lov: verify stripe is on given device
authorAndreas Dilger <adilger@whamcloud.com>
Thu, 13 Sep 2012 02:35:55 +0000 (20:35 -0600)
committerOleg Drokin <green@whamcloud.com>
Thu, 13 Sep 2012 17:34:08 +0000 (13:34 -0400)
When restarting FIEMAP from a file with many extents, the first
supplied fiemap extent contains the offset of the previous last
extent found.  If this data is invalid, it may cause the LOV code
to acccess out-of-bounds array indices.

Verify data passed from userspace is within bounds.

Signed-off-by: Andreas Dilger <adilger@whamcloud.com>
Change-Id: I8e70e891b9f23c8f72aa78a4807369584ac2b04f
Reviewed-on: http://review.whamcloud.com/3962
Tested-by: Hudson
Tested-by: Maloo <whamcloud.maloo@gmail.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
Reviewed-by: wangdi <di.wang@whamcloud.com>
lustre/lov/lov_obd.c

index ea72c2e..c0ee782 100644 (file)
@@ -2250,6 +2250,8 @@ obd_size fiemap_calc_fm_end_offset(struct ll_user_fiemap *fiemap,
                         break;
                 }
         }
+       if (stripe_no == -1)
+               return -EINVAL;
 
         /* If we have finished mapping on previous device, shift logical
          * offset to start of next device */
@@ -2353,7 +2355,7 @@ static int lov_fiemap(struct lov_obd *lov, __u32 keylen, void *key,
         int count_local;
         unsigned int get_num_extents = 0;
         int ost_index = 0, actual_start_stripe, start_stripe;
-        obd_size fm_start, fm_end, fm_length, fm_end_offset = 0;
+       obd_size fm_start, fm_end, fm_length, fm_end_offset;
         obd_size curr_loc;
         int current_extent = 0, rc = 0, i;
         int ost_eof = 0; /* EOF for object */
@@ -2389,8 +2391,10 @@ static int lov_fiemap(struct lov_obd *lov, __u32 keylen, void *key,
         last_stripe = fiemap_calc_last_stripe(lsm, fm_start, fm_end,
                                             actual_start_stripe, &stripe_count);
 
-        fm_end_offset = fiemap_calc_fm_end_offset(fiemap, lsm, fm_start, fm_end,
-                                                  &start_stripe);
+       fm_end_offset = fiemap_calc_fm_end_offset(fiemap, lsm, fm_start,
+                                                 fm_end, &start_stripe);
+       if (fm_end_offset == -EINVAL)
+               return -EINVAL;
 
         if (fiemap->fm_extent_count == 0) {
                 get_num_extents = 1;