public inbox for linux-scsi@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] libfc: fix potential timer list corruption
@ 2017-05-30 15:14 Hannes Reinecke
  2017-05-30 15:14 ` [PATCH 1/3] libfc: move 'pending' and 'requested' setting Hannes Reinecke
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Hannes Reinecke @ 2017-05-30 15:14 UTC (permalink / raw)
  To: Martin K. Petersen
  Cc: Christoph Hellwig, James Bottomley, Johannes Thumshirn,
	linux-scsi, Hannes Reinecke

Hi all,

we've seen reports for a crash with an invalid timer_list->function,
which turned out to be an unsafe usage of libfc discovery callbacks.
This patchset fixes up the problem

As usual, comments and reviews are welcome.

Hannes Reinecke (3):
  libfc: move 'pending' and 'requested' setting
  libfc: only restart discovery after timeout if not already running
  libfc: fixup locking in fc_disc_stop()

 drivers/scsi/libfc/fc_disc.c | 26 +++++++++++++++++++-------
 1 file changed, 19 insertions(+), 7 deletions(-)

-- 
1.8.5.6

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 1/3] libfc: move 'pending' and 'requested' setting
  2017-05-30 15:14 [PATCH 0/3] libfc: fix potential timer list corruption Hannes Reinecke
@ 2017-05-30 15:14 ` Hannes Reinecke
  2017-05-30 15:14 ` [PATCH 2/3] libfc: only restart discovery after timeout if not already running Hannes Reinecke
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Hannes Reinecke @ 2017-05-30 15:14 UTC (permalink / raw)
  To: Martin K. Petersen
  Cc: Christoph Hellwig, James Bottomley, Johannes Thumshirn,
	linux-scsi, Hannes Reinecke, Hannes Reinecke

Move 'pending' and 'requested' setting out of fc_disc_gpn_fc_req()
into the calling function.

No functional change.

Signed-off-by: Hannes Reinecke <hare@suse.com>
---
 drivers/scsi/libfc/fc_disc.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c
index fd501f8..913beb5 100644
--- a/drivers/scsi/libfc/fc_disc.c
+++ b/drivers/scsi/libfc/fc_disc.c
@@ -242,6 +242,9 @@ static void fc_disc_restart(struct fc_disc *disc)
 	 */
 	disc->disc_id = (disc->disc_id + 2) | 1;
 	disc->retry_count = 0;
+	disc->pending = 1;
+	disc->requested = 0;
+
 	fc_disc_gpn_ft_req(disc);
 }
 
@@ -371,9 +374,6 @@ static void fc_disc_gpn_ft_req(struct fc_disc *disc)
 
 	WARN_ON(!fc_lport_test_ready(lport));
 
-	disc->pending = 1;
-	disc->requested = 0;
-
 	disc->buf_len = 0;
 	disc->seq_count = 0;
 	fp = fc_frame_alloc(lport,
@@ -503,6 +503,9 @@ static void fc_disc_timeout(struct work_struct *work)
 					    struct fc_disc,
 					    disc_work.work);
 	mutex_lock(&disc->disc_mutex);
+	disc->pending = 1;
+	disc->requested = 0;
+
 	fc_disc_gpn_ft_req(disc);
 	mutex_unlock(&disc->disc_mutex);
 }
-- 
1.8.5.6

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/3] libfc: only restart discovery after timeout if not already running
  2017-05-30 15:14 [PATCH 0/3] libfc: fix potential timer list corruption Hannes Reinecke
  2017-05-30 15:14 ` [PATCH 1/3] libfc: move 'pending' and 'requested' setting Hannes Reinecke
@ 2017-05-30 15:14 ` Hannes Reinecke
  2017-05-30 15:14 ` [PATCH 3/3] libfc: fixup locking in fc_disc_stop() Hannes Reinecke
  2017-05-31  9:27 ` [PATCH 0/3] libfc: fix potential timer list corruption Johannes Thumshirn
  3 siblings, 0 replies; 5+ messages in thread
From: Hannes Reinecke @ 2017-05-30 15:14 UTC (permalink / raw)
  To: Martin K. Petersen
  Cc: Christoph Hellwig, James Bottomley, Johannes Thumshirn,
	linux-scsi, Hannes Reinecke, Hannes Reinecke

If a discovery is already running (ie if the 'pending' flags is set)
there is no need to restart discovery from the timeout handler.

Signed-off-by: Hannes Reinecke <hare@suse.com>
---
 drivers/scsi/libfc/fc_disc.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c
index 913beb5..82b1c97 100644
--- a/drivers/scsi/libfc/fc_disc.c
+++ b/drivers/scsi/libfc/fc_disc.c
@@ -503,10 +503,12 @@ static void fc_disc_timeout(struct work_struct *work)
 					    struct fc_disc,
 					    disc_work.work);
 	mutex_lock(&disc->disc_mutex);
-	disc->pending = 1;
-	disc->requested = 0;
+	if (!disc->pending) {
+		disc->pending = 1;
+		disc->requested = 0;
 
-	fc_disc_gpn_ft_req(disc);
+		fc_disc_gpn_ft_req(disc);
+	}
 	mutex_unlock(&disc->disc_mutex);
 }
 
-- 
1.8.5.6

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 3/3] libfc: fixup locking in fc_disc_stop()
  2017-05-30 15:14 [PATCH 0/3] libfc: fix potential timer list corruption Hannes Reinecke
  2017-05-30 15:14 ` [PATCH 1/3] libfc: move 'pending' and 'requested' setting Hannes Reinecke
  2017-05-30 15:14 ` [PATCH 2/3] libfc: only restart discovery after timeout if not already running Hannes Reinecke
@ 2017-05-30 15:14 ` Hannes Reinecke
  2017-05-31  9:27 ` [PATCH 0/3] libfc: fix potential timer list corruption Johannes Thumshirn
  3 siblings, 0 replies; 5+ messages in thread
From: Hannes Reinecke @ 2017-05-30 15:14 UTC (permalink / raw)
  To: Martin K. Petersen
  Cc: Christoph Hellwig, James Bottomley, Johannes Thumshirn,
	linux-scsi, Hannes Reinecke, Hannes Reinecke

fc_disc_stop() calls fc_disc_stop_rports(), which requires the
disc_mutex to be held.
And we need to ensure that no fc_disc_timeout functions are queued
after this function, so set the callback to NULL and ensure that
all functions terminate early when the callback is not set.

Signed-off-by: Hannes Reinecke <hare@suse.com>
---
 drivers/scsi/libfc/fc_disc.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c
index 82b1c97..109174f 100644
--- a/drivers/scsi/libfc/fc_disc.c
+++ b/drivers/scsi/libfc/fc_disc.c
@@ -283,6 +283,7 @@ static void fc_disc_done(struct fc_disc *disc, enum fc_disc_event event)
 {
 	struct fc_lport *lport = fc_disc_lport(disc);
 	struct fc_rport_priv *rdata;
+	void (*callback)(struct fc_lport *, enum fc_disc_event);
 
 	FC_DISC_DBG(disc, "Discovery complete\n");
 
@@ -311,8 +312,10 @@ static void fc_disc_done(struct fc_disc *disc, enum fc_disc_event event)
 		kref_put(&rdata->kref, fc_rport_destroy);
 	}
 	rcu_read_unlock();
+	callback = disc->disc_callback;
 	mutex_unlock(&disc->disc_mutex);
-	disc->disc_callback(lport, event);
+	if (callback)
+		callback(lport, event);
 	mutex_lock(&disc->disc_mutex);
 }
 
@@ -711,9 +714,13 @@ static void fc_disc_stop(struct fc_lport *lport)
 {
 	struct fc_disc *disc = &lport->disc;
 
-	if (disc->pending)
-		cancel_delayed_work_sync(&disc->disc_work);
+	mutex_lock(&disc->disc_mutex);
+	disc->disc_callback = NULL;
+	mutex_unlock(&disc->disc_mutex);
+	cancel_delayed_work_sync(&disc->disc_work);
+	mutex_lock(&disc->disc_mutex);
 	fc_disc_stop_rports(disc);
+	mutex_unlock(&disc->disc_mutex);
 }
 
 /**
-- 
1.8.5.6

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH 0/3] libfc: fix potential timer list corruption
  2017-05-30 15:14 [PATCH 0/3] libfc: fix potential timer list corruption Hannes Reinecke
                   ` (2 preceding siblings ...)
  2017-05-30 15:14 ` [PATCH 3/3] libfc: fixup locking in fc_disc_stop() Hannes Reinecke
@ 2017-05-31  9:27 ` Johannes Thumshirn
  3 siblings, 0 replies; 5+ messages in thread
From: Johannes Thumshirn @ 2017-05-31  9:27 UTC (permalink / raw)
  To: Hannes Reinecke, Martin K. Petersen
  Cc: Christoph Hellwig, James Bottomley, Johannes Thumshirn,
	linux-scsi

On 05/30/2017 05:14 PM, Hannes Reinecke wrote:
> Hi all,
> 
> we've seen reports for a crash with an invalid timer_list->function,
> which turned out to be an unsafe usage of libfc discovery callbacks.
> This patchset fixes up the problem
> 
> As usual, comments and reviews are welcome.

The patches look good themselves, but I'd prefer a *why* in the commit
message. For instance in patch 1 you have:

"Move 'pending' and 'requested' setting out of fc_disc_gpn_fc_req()
into the calling function.

No functional change."

But why do you need to move the 'pending' and 'requested' settings?

With an a bit more verbose changelog

Acked-by: Johannes Thumshirn <jth@kernel.org>

for the whole series

-- 
Johannes Thumshirn                                          Storage
jthumshirn@suse.de                                +49 911 74053 689
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: Felix Imendörffer, Jane Smithard, Graham Norton
HRB 21284 (AG Nürnberg)
Key fingerprint = EC38 9CAB C2C4 F25D 8600 D0D0 0393 969D 2D76 0850

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2017-05-31  9:27 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-05-30 15:14 [PATCH 0/3] libfc: fix potential timer list corruption Hannes Reinecke
2017-05-30 15:14 ` [PATCH 1/3] libfc: move 'pending' and 'requested' setting Hannes Reinecke
2017-05-30 15:14 ` [PATCH 2/3] libfc: only restart discovery after timeout if not already running Hannes Reinecke
2017-05-30 15:14 ` [PATCH 3/3] libfc: fixup locking in fc_disc_stop() Hannes Reinecke
2017-05-31  9:27 ` [PATCH 0/3] libfc: fix potential timer list corruption Johannes Thumshirn

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox