Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dc66c74d authored by Philipp Reisner's avatar Philipp Reisner
Browse files

drbd: Fixed a race between disk-attach and unexpected state changes



This was a very hard to trigger race condition.

If we got a state packet from the peer, after drbd_nl_disk() has
already changed the disk state to D_NEGOTIATING but
after_state_ch() was not yet run by the worker, then receive_state()
might called drbd_sync_handshake(), which in turn crashed
when accessing p_uuid.

Signed-off-by: default avatarPhilipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: default avatarLars Ellenberg <lars.ellenberg@linbit.com>
parent 7e27d6e7
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -1236,8 +1236,6 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os,
	/* Last part of the attaching process ... */
	if (ns.conn >= C_CONNECTED &&
	    os.disk == D_ATTACHING && ns.disk == D_NEGOTIATING) {
		kfree(mdev->p_uuid); /* We expect to receive up-to-date UUIDs soon. */
		mdev->p_uuid = NULL; /* ...to not use the old ones in the mean time */
		drbd_send_sizes(mdev, 0, 0);  /* to start sync... */
		drbd_send_uuids(mdev);
		drbd_send_state(mdev);
+6 −0
Original line number Diff line number Diff line
@@ -1114,6 +1114,12 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
		mdev->new_state_tmp.i = ns.i;
		ns.i = os.i;
		ns.disk = D_NEGOTIATING;

		/* We expect to receive up-to-date UUIDs soon.
		   To avoid a race in receive_state, free p_uuid while
		   holding req_lock. I.e. atomic with the state change */
		kfree(mdev->p_uuid);
		mdev->p_uuid = NULL;
	}

	rv = _drbd_set_state(mdev, ns, CS_VERBOSE, NULL);
+1 −1
Original line number Diff line number Diff line
@@ -53,7 +53,7 @@


extern const char *drbd_buildtag(void);
#define REL_VERSION "8.3.8rc2"
#define REL_VERSION "8.3.8"
#define API_VERSION 88
#define PRO_VERSION_MIN 86
#define PRO_VERSION_MAX 94