drbd: fix access of unallocated pages and kernel panic
BUG: unable to handle kernel NULL pointer dereference at (null) ... [<d1e17561>] ? _drbd_bm_set_bits+0x151/0x240 [drbd] [<d1e236f8>] ? receive_bitmap+0x4f8/0xbc0 [drbd] This fixes an off-by-one error in the receive_bitmap() path, if run-length encoded bitmap transfer is enabled. If the bitmap is an exact multiple of PAGE_SIZE, which means the visible capacity of the drbd device is an exact multiple of 128 MiB (for 4k page size), and bitmap compression (use-rle) is enabled (which became default with 8.4), and the very last bit is dirty and reported in an rle comressed bitmap packet, we ended up trying to kmap_atomic a page pointer that does not exist (bitmap->bm_pages[last index + 1]). bug introduced by: Date: Fri Jul 24 15:33:24 2009 +0200 set bits: optimize for complete last word, fix off-by-one-word corner case made effective by: Date: Thu Dec 16 00:32:38 2010 +0100 drbd: get rid of unused debug code Long time ago, we had paranoia code in the bitmap that allocated one extra word, assigned a magic value, and checked on every occasion that the magic value was still unchanged. That debug code is unused, the extra long word complicates code a bit. Get rid of it. No-one triggered this bug in the last few years, because a large subset of our userbase is unaffected: * typically the last few blocks of a device are not modified frequently, and remain unset * use-rle was disabled by default in drbd < 8.4 * those with slightly "odd" device sizes, or * drbd internal meta data (which will skew the device size slightly, thus makes it harder to have a bug relevant device size) Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com> Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
This commit is contained in:
parent
4fd1ffaa12
commit
4eccc57979
@ -1475,10 +1475,17 @@ void _drbd_bm_set_bits(struct drbd_conf *mdev, const unsigned long s, const unsi
|
||||
first_word = 0;
|
||||
spin_lock_irq(&b->bm_lock);
|
||||
}
|
||||
|
||||
/* last page (respectively only page, for first page == last page) */
|
||||
last_word = MLPP(el >> LN2_BPL);
|
||||
bm_set_full_words_within_one_page(mdev->bitmap, last_page, first_word, last_word);
|
||||
|
||||
/* consider bitmap->bm_bits = 32768, bitmap->bm_number_of_pages = 1. (or multiples).
|
||||
* ==> e = 32767, el = 32768, last_page = 2,
|
||||
* and now last_word = 0.
|
||||
* We do not want to touch last_page in this case,
|
||||
* as we did not allocate it, it is not present in bitmap->bm_pages.
|
||||
*/
|
||||
if (last_word)
|
||||
bm_set_full_words_within_one_page(mdev->bitmap, last_page, first_word, last_word);
|
||||
|
||||
/* possibly trailing bits.
|
||||
* example: (e & 63) == 63, el will be e+1.
|
||||
|
Loading…
Reference in New Issue
Block a user