aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/drbd
diff options
context:
space:
mode:
authorLars Ellenberg <lars.ellenberg@linbit.com>2010-04-06 06:15:04 -0400
committerPhilipp Reisner <philipp.reisner@linbit.com>2010-05-17 19:09:57 -0400
commit6666032ade5a758aa05380ab92f416ab8ef25005 (patch)
treebe2ef8e83cfd52afb31fee9574baebf5b6d3866c /drivers/block/drbd
parentc3fe30b0e7cd67e0207097f5f39ce9626644879e (diff)
drbd: check for corrupt or malicous sector addresses when receiving data
Even if it should never happen if the peer does behave, we need to double check, and not even attempt access beyond end of device. It usually would be caught by lower layers, resulting in "IO error", but may also end up in the internal meta data area. Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com> Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
Diffstat (limited to 'drivers/block/drbd')
-rw-r--r--drivers/block/drbd/drbd_receiver.c10
1 files changed, 10 insertions, 0 deletions
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c
index c3504ddd59c1..3a36bc814e77 100644
--- a/drivers/block/drbd/drbd_receiver.c
+++ b/drivers/block/drbd/drbd_receiver.c
@@ -1262,6 +1262,7 @@ static int receive_Barrier(struct drbd_conf *mdev, struct p_header *h)
1262static struct drbd_epoch_entry * 1262static struct drbd_epoch_entry *
1263read_in_block(struct drbd_conf *mdev, u64 id, sector_t sector, int data_size) __must_hold(local) 1263read_in_block(struct drbd_conf *mdev, u64 id, sector_t sector, int data_size) __must_hold(local)
1264{ 1264{
1265 const sector_t capacity = drbd_get_capacity(mdev->this_bdev);
1265 struct drbd_epoch_entry *e; 1266 struct drbd_epoch_entry *e;
1266 struct bio_vec *bvec; 1267 struct bio_vec *bvec;
1267 struct page *page; 1268 struct page *page;
@@ -1287,6 +1288,15 @@ read_in_block(struct drbd_conf *mdev, u64 id, sector_t sector, int data_size) __
1287 ERR_IF(data_size & 0x1ff) return NULL; 1288 ERR_IF(data_size & 0x1ff) return NULL;
1288 ERR_IF(data_size > DRBD_MAX_SEGMENT_SIZE) return NULL; 1289 ERR_IF(data_size > DRBD_MAX_SEGMENT_SIZE) return NULL;
1289 1290
1291 /* even though we trust out peer,
1292 * we sometimes have to double check. */
1293 if (sector + (data_size>>9) > capacity) {
1294 dev_err(DEV, "capacity: %llus < sector: %llus + size: %u\n",
1295 (unsigned long long)capacity,
1296 (unsigned long long)sector, data_size);
1297 return NULL;
1298 }
1299
1290 /* GFP_NOIO, because we must not cause arbitrary write-out: in a DRBD 1300 /* GFP_NOIO, because we must not cause arbitrary write-out: in a DRBD
1291 * "criss-cross" setup, that might cause write-out on some other DRBD, 1301 * "criss-cross" setup, that might cause write-out on some other DRBD,
1292 * which in turn might block on the other node at this very place. */ 1302 * which in turn might block on the other node at this very place. */