Skip to content

Commit

Permalink
drbd: fix unlikely access after free and list corruption
Browse files Browse the repository at this point in the history
Various cleanup paths have been incomplete, for the very unlikely case
that we cannot allocate enough bios from process context when submitting
on behalf of the peer or resync process.

Never observed.

Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
  • Loading branch information
Lars Ellenberg authored and Philipp Reisner committed Oct 14, 2010
1 parent af85e8e commit 22cc37a
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 2 deletions.
25 changes: 25 additions & 0 deletions drivers/block/drbd/drbd_receiver.c
Original file line number Diff line number Diff line change
Expand Up @@ -1573,6 +1573,13 @@ static int recv_resync_read(struct drbd_conf *mdev, sector_t sector, int data_si
if (drbd_submit_ee(mdev, e, WRITE, DRBD_FAULT_RS_WR) == 0)
return TRUE;

/* drbd_submit_ee currently fails for one reason only:
* not being able to allocate enough bios.
* Is dropping the connection going to help? */
spin_lock_irq(&mdev->req_lock);
list_del(&e->w.list);
spin_unlock_irq(&mdev->req_lock);

drbd_free_ee(mdev, e);
fail:
put_ldev(mdev);
Expand Down Expand Up @@ -1998,6 +2005,16 @@ static int receive_Data(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned
if (drbd_submit_ee(mdev, e, rw, DRBD_FAULT_DT_WR) == 0)
return TRUE;

/* drbd_submit_ee currently fails for one reason only:
* not being able to allocate enough bios.
* Is dropping the connection going to help? */
spin_lock_irq(&mdev->req_lock);
list_del(&e->w.list);
hlist_del_init(&e->colision);
spin_unlock_irq(&mdev->req_lock);
if (e->flags & EE_CALL_AL_COMPLETE_IO)
drbd_al_complete_io(mdev, e->sector);

out_interrupted:
/* yes, the epoch_size now is imbalanced.
* but we drop the connection anyways, so we don't have a chance to
Expand Down Expand Up @@ -2202,6 +2219,14 @@ static int receive_DataRequest(struct drbd_conf *mdev, enum drbd_packets cmd, un
if (drbd_submit_ee(mdev, e, READ, fault_type) == 0)
return TRUE;

/* drbd_submit_ee currently fails for one reason only:
* not being able to allocate enough bios.
* Is dropping the connection going to help? */
spin_lock_irq(&mdev->req_lock);
list_del(&e->w.list);
spin_unlock_irq(&mdev->req_lock);
/* no drbd_rs_complete_io(), we are dropping the connection anyways */

out_free_e:
put_ldev(mdev);
drbd_free_ee(mdev, e);
Expand Down
7 changes: 7 additions & 0 deletions drivers/block/drbd/drbd_worker.c
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,13 @@ static int read_for_csum(struct drbd_conf *mdev, sector_t sector, int size)
if (drbd_submit_ee(mdev, e, READ, DRBD_FAULT_RS_RD) == 0)
return 0;

/* drbd_submit_ee currently fails for one reason only:
* not being able to allocate enough bios.
* Is dropping the connection going to help? */
spin_lock_irq(&mdev->req_lock);
list_del(&e->w.list);
spin_unlock_irq(&mdev->req_lock);

drbd_free_ee(mdev, e);
defer:
put_ldev(mdev);
Expand Down
4 changes: 2 additions & 2 deletions include/linux/drbd.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,10 @@


extern const char *drbd_buildtag(void);
#define REL_VERSION "8.3.8.1"
#define REL_VERSION "8.3.9rc1"
#define API_VERSION 88
#define PRO_VERSION_MIN 86
#define PRO_VERSION_MAX 94
#define PRO_VERSION_MAX 95


enum drbd_io_error_p {
Expand Down

0 comments on commit 22cc37a

Please sign in to comment.