All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/3] floppy: use a statically allocated error counter
@ 2022-05-08  9:37 Willy Tarreau
  2022-05-08  9:37 ` [PATCH 2/3] ataflop: use a statically allocated error counters Willy Tarreau
                   ` (7 more replies)
  0 siblings, 8 replies; 11+ messages in thread
From: Willy Tarreau @ 2022-05-08  9:37 UTC (permalink / raw)
  To: linux-block, linux-kernel
  Cc: Denis Efremov, Geert Uytterhoeven, Christoph Hellwig, Minh Yuan,
	Linus Torvalds, Willy Tarreau

Interrupt handler bad_flp_intr() may cause a UAF on the recently freed
request just to increment the error count. There's no point keeping
that one in the request anyway, and since the interrupt handler uses
a static pointer to the error which cannot be kept in sync with the
pending request, better make it use a static error counter that's
reset for each new request. This reset now happens when entering
redo_fd_request() for a new request via set_next_request().

One initial concern about a single error counter was that errors on
one floppy drive could be reported on another one, but this problem
is not real given that the driver uses a single drive at a time, as
that PC-compatible controllers also have this limitation by using
shared signals. As such the error count is always for the "current"
drive.

Reported-by: Minh Yuan <yuanmingbuaa@gmail.com>
Suggested-by: Linus Torvalds <torvalds@linuxfoundation.org>
Tested-by: Denis Efremov <efremov@linux.com>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 drivers/block/floppy.c | 18 ++++++++----------
 1 file changed, 8 insertions(+), 10 deletions(-)

diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index d5b9ff9bcbb2..015841f50f4e 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -509,8 +509,8 @@ static unsigned long fdc_busy;
 static DECLARE_WAIT_QUEUE_HEAD(fdc_wait);
 static DECLARE_WAIT_QUEUE_HEAD(command_done);
 
-/* Errors during formatting are counted here. */
-static int format_errors;
+/* errors encountered on the current (or last) request */
+static int floppy_errors;
 
 /* Format request descriptor. */
 static struct format_descr format_req;
@@ -530,7 +530,6 @@ static struct format_descr format_req;
 static char *floppy_track_buffer;
 static int max_buffer_sectors;
 
-static int *errors;
 typedef void (*done_f)(int);
 static const struct cont_t {
 	void (*interrupt)(void);
@@ -1455,7 +1454,7 @@ static int interpret_errors(void)
 			if (drive_params[current_drive].flags & FTD_MSG)
 				DPRINT("Over/Underrun - retrying\n");
 			bad = 0;
-		} else if (*errors >= drive_params[current_drive].max_errors.reporting) {
+		} else if (floppy_errors >= drive_params[current_drive].max_errors.reporting) {
 			print_errors();
 		}
 		if (reply_buffer[ST2] & ST2_WC || reply_buffer[ST2] & ST2_BC)
@@ -2095,7 +2094,7 @@ static void bad_flp_intr(void)
 		if (!next_valid_format(current_drive))
 			return;
 	}
-	err_count = ++(*errors);
+	err_count = ++floppy_errors;
 	INFBOUND(write_errors[current_drive].badness, err_count);
 	if (err_count > drive_params[current_drive].max_errors.abort)
 		cont->done(0);
@@ -2241,9 +2240,8 @@ static int do_format(int drive, struct format_descr *tmp_format_req)
 		return -EINVAL;
 	}
 	format_req = *tmp_format_req;
-	format_errors = 0;
 	cont = &format_cont;
-	errors = &format_errors;
+	floppy_errors = 0;
 	ret = wait_til_done(redo_format, true);
 	if (ret == -EINTR)
 		return -EINTR;
@@ -2759,10 +2757,11 @@ static int set_next_request(void)
 	current_req = list_first_entry_or_null(&floppy_reqs, struct request,
 					       queuelist);
 	if (current_req) {
-		current_req->error_count = 0;
+		floppy_errors = 0;
 		list_del_init(&current_req->queuelist);
+		return 1;
 	}
-	return current_req != NULL;
+	return 0;
 }
 
 /* Starts or continues processing request. Will automatically unlock the
@@ -2821,7 +2820,6 @@ static void redo_fd_request(void)
 		_floppy = floppy_type + drive_params[current_drive].autodetect[drive_state[current_drive].probed_format];
 	} else
 		probing = 0;
-	errors = &(current_req->error_count);
 	tmp = make_raw_rw_request();
 	if (tmp < 2) {
 		request_done(tmp);
-- 
2.17.5


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

* [PATCH 2/3] ataflop: use a statically allocated error counters
  2022-05-08  9:37 [PATCH 1/3] floppy: use a statically allocated error counter Willy Tarreau
@ 2022-05-08  9:37 ` Willy Tarreau
  2022-05-08  9:37 ` [PATCH 3/3] blk-mq: remove the error_count from struct request Willy Tarreau
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 11+ messages in thread
From: Willy Tarreau @ 2022-05-08  9:37 UTC (permalink / raw)
  To: linux-block, linux-kernel
  Cc: Denis Efremov, Geert Uytterhoeven, Christoph Hellwig, Minh Yuan,
	Linus Torvalds, Willy Tarreau

This is the last driver making use of fd_request->error_count, which
is easy to get wrong as was shown in floppy.c. We don't need to keep
it there, it can be moved to the atari_floppy_struct instead, so let's
do this.

Suggested-by: Linus Torvalds <torvalds@linuxfoundation.org>
Cc: Minh Yuan <yuanmingbuaa@gmail.com>
Cc: Geert Uytterhoeven <geert@linux-m68k.org>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 drivers/block/ataflop.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c
index 5d819a466e2f..e232cc4fd444 100644
--- a/drivers/block/ataflop.c
+++ b/drivers/block/ataflop.c
@@ -303,6 +303,7 @@ static struct atari_floppy_struct {
 	int ref;
 	int type;
 	struct blk_mq_tag_set tag_set;
+	int error_count;
 } unit[FD_MAX_UNITS];
 
 #define	UD	unit[drive]
@@ -705,14 +706,14 @@ static void fd_error( void )
 	if (!fd_request)
 		return;
 
-	fd_request->error_count++;
-	if (fd_request->error_count >= MAX_ERRORS) {
+	unit[SelectedDrive].error_count++;
+	if (unit[SelectedDrive].error_count >= MAX_ERRORS) {
 		printk(KERN_ERR "fd%d: too many errors.\n", SelectedDrive );
 		fd_end_request_cur(BLK_STS_IOERR);
 		finish_fdc();
 		return;
 	}
-	else if (fd_request->error_count == RECALIBRATE_ERRORS) {
+	else if (unit[SelectedDrive].error_count == RECALIBRATE_ERRORS) {
 		printk(KERN_WARNING "fd%d: recalibrating\n", SelectedDrive );
 		if (SelectedDrive != -1)
 			SUD.track = -1;
@@ -1491,7 +1492,7 @@ static void setup_req_params( int drive )
 	ReqData = ReqBuffer + 512 * ReqCnt;
 
 	if (UseTrackbuffer)
-		read_track = (ReqCmd == READ && fd_request->error_count == 0);
+		read_track = (ReqCmd == READ && unit[drive].error_count == 0);
 	else
 		read_track = 0;
 
@@ -1520,6 +1521,7 @@ static blk_status_t ataflop_queue_rq(struct blk_mq_hw_ctx *hctx,
 		return BLK_STS_RESOURCE;
 	}
 	fd_request = bd->rq;
+	unit[drive].error_count = 0;
 	blk_mq_start_request(fd_request);
 
 	atari_disable_irq( IRQ_MFP_FDC );
-- 
2.17.5


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

* [PATCH 3/3] blk-mq: remove the error_count from struct request
  2022-05-08  9:37 [PATCH 1/3] floppy: use a statically allocated error counter Willy Tarreau
  2022-05-08  9:37 ` [PATCH 2/3] ataflop: use a statically allocated error counters Willy Tarreau
@ 2022-05-08  9:37 ` Willy Tarreau
  2022-05-09  6:14 ` [PATCH 1/3] floppy: use a statically allocated error counter Christoph Hellwig
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 11+ messages in thread
From: Willy Tarreau @ 2022-05-08  9:37 UTC (permalink / raw)
  To: linux-block, linux-kernel
  Cc: Denis Efremov, Geert Uytterhoeven, Christoph Hellwig, Minh Yuan,
	Linus Torvalds, Willy Tarreau

The last two users were floppy.c and ataflop.c respectively, it was
verified that no other drivers makes use of this, so let's remove it.

Suggested-by: Linus Torvalds <torvalds@linuxfoundation.org>
Cc: Minh Yuan <yuanmingbuaa@gmail.com>
Cc: Denis Efremov <efremov@linux.com>,
Cc: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: Christoph Hellwig <hch@lst.de>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 include/linux/blk-mq.h | 1 -
 1 file changed, 1 deletion(-)

diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h
index 7aa5c54901a9..9f07061418db 100644
--- a/include/linux/blk-mq.h
+++ b/include/linux/blk-mq.h
@@ -163,7 +163,6 @@ struct request {
 		struct rb_node rb_node;	/* sort/lookup */
 		struct bio_vec special_vec;
 		void *completion_data;
-		int error_count; /* for legacy drivers, don't use */
 	};
 
 
-- 
2.17.5


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

* Re: [PATCH 1/3] floppy: use a statically allocated error counter
  2022-05-08  9:37 [PATCH 1/3] floppy: use a statically allocated error counter Willy Tarreau
  2022-05-08  9:37 ` [PATCH 2/3] ataflop: use a statically allocated error counters Willy Tarreau
  2022-05-08  9:37 ` [PATCH 3/3] blk-mq: remove the error_count from struct request Willy Tarreau
@ 2022-05-09  6:14 ` Christoph Hellwig
  2022-05-10  3:17   ` Willy Tarreau
  2022-05-17 17:47 ` Denis Efremov
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 11+ messages in thread
From: Christoph Hellwig @ 2022-05-09  6:14 UTC (permalink / raw)
  To: Willy Tarreau
  Cc: linux-block, linux-kernel, Denis Efremov, Geert Uytterhoeven,
	Christoph Hellwig, Minh Yuan, Linus Torvalds

The whole series looks good:

Reviewed-by: Christoph Hellwig <hch@lst.de>

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

* Re: [PATCH 1/3] floppy: use a statically allocated error counter
  2022-05-09  6:14 ` [PATCH 1/3] floppy: use a statically allocated error counter Christoph Hellwig
@ 2022-05-10  3:17   ` Willy Tarreau
  0 siblings, 0 replies; 11+ messages in thread
From: Willy Tarreau @ 2022-05-10  3:17 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: linux-block, linux-kernel, Denis Efremov, Geert Uytterhoeven,
	Minh Yuan, Linus Torvalds

On Mon, May 09, 2022 at 08:14:30AM +0200, Christoph Hellwig wrote:
> The whole series looks good:
> 
> Reviewed-by: Christoph Hellwig <hch@lst.de>

Thank you Christoph!
Willy

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

* Re: [PATCH 1/3] floppy: use a statically allocated error counter
  2022-05-08  9:37 [PATCH 1/3] floppy: use a statically allocated error counter Willy Tarreau
                   ` (2 preceding siblings ...)
  2022-05-09  6:14 ` [PATCH 1/3] floppy: use a statically allocated error counter Christoph Hellwig
@ 2022-05-17 17:47 ` Denis Efremov
  2022-05-19 12:40   ` Greg Kroah-Hartman
  2022-05-17 20:12 ` [PATCH 5.10] " Denis Efremov
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 11+ messages in thread
From: Denis Efremov @ 2022-05-17 17:47 UTC (permalink / raw)
  To: Greg Kroah-Hartman; +Cc: stable, Willy Tarreau

Hi,

On 5/8/22 13:37, Willy Tarreau wrote:
> Interrupt handler bad_flp_intr() may cause a UAF on the recently freed
> request just to increment the error count. There's no point keeping
> that one in the request anyway, and since the interrupt handler uses
> a static pointer to the error which cannot be kept in sync with the
> pending request, better make it use a static error counter that's
> reset for each new request. This reset now happens when entering
> redo_fd_request() for a new request via set_next_request().
> 
> One initial concern about a single error counter was that errors on
> one floppy drive could be reported on another one, but this problem
> is not real given that the driver uses a single drive at a time, as
> that PC-compatible controllers also have this limitation by using
> shared signals. As such the error count is always for the "current"
> drive.
> 
> Reported-by: Minh Yuan <yuanmingbuaa@gmail.com>
> Suggested-by: Linus Torvalds <torvalds@linuxfoundation.org>
> Tested-by: Denis Efremov <efremov@linux.com>
> Signed-off-by: Willy Tarreau <w@1wt.eu>

Could you please take this patch (only this one) to the stable trees?

commit f71f01394f742fc4558b3f9f4c7ef4c4cf3b07c8 upstream.

The patch applies cleanly to 5.17, 5.15, 5.10 kernels.
I'll send a backport for 5.4 and older kernels.

Thanks,
Denis

> ---
>  drivers/block/floppy.c | 18 ++++++++----------
>  1 file changed, 8 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
> index d5b9ff9bcbb2..015841f50f4e 100644
> --- a/drivers/block/floppy.c
> +++ b/drivers/block/floppy.c
> @@ -509,8 +509,8 @@ static unsigned long fdc_busy;
>  static DECLARE_WAIT_QUEUE_HEAD(fdc_wait);
>  static DECLARE_WAIT_QUEUE_HEAD(command_done);
>  
> -/* Errors during formatting are counted here. */
> -static int format_errors;
> +/* errors encountered on the current (or last) request */
> +static int floppy_errors;
>  
>  /* Format request descriptor. */
>  static struct format_descr format_req;
> @@ -530,7 +530,6 @@ static struct format_descr format_req;
>  static char *floppy_track_buffer;
>  static int max_buffer_sectors;
>  
> -static int *errors;
>  typedef void (*done_f)(int);
>  static const struct cont_t {
>  	void (*interrupt)(void);
> @@ -1455,7 +1454,7 @@ static int interpret_errors(void)
>  			if (drive_params[current_drive].flags & FTD_MSG)
>  				DPRINT("Over/Underrun - retrying\n");
>  			bad = 0;
> -		} else if (*errors >= drive_params[current_drive].max_errors.reporting) {
> +		} else if (floppy_errors >= drive_params[current_drive].max_errors.reporting) {
>  			print_errors();
>  		}
>  		if (reply_buffer[ST2] & ST2_WC || reply_buffer[ST2] & ST2_BC)
> @@ -2095,7 +2094,7 @@ static void bad_flp_intr(void)
>  		if (!next_valid_format(current_drive))
>  			return;
>  	}
> -	err_count = ++(*errors);
> +	err_count = ++floppy_errors;
>  	INFBOUND(write_errors[current_drive].badness, err_count);
>  	if (err_count > drive_params[current_drive].max_errors.abort)
>  		cont->done(0);
> @@ -2241,9 +2240,8 @@ static int do_format(int drive, struct format_descr *tmp_format_req)
>  		return -EINVAL;
>  	}
>  	format_req = *tmp_format_req;
> -	format_errors = 0;
>  	cont = &format_cont;
> -	errors = &format_errors;
> +	floppy_errors = 0;
>  	ret = wait_til_done(redo_format, true);
>  	if (ret == -EINTR)
>  		return -EINTR;
> @@ -2759,10 +2757,11 @@ static int set_next_request(void)
>  	current_req = list_first_entry_or_null(&floppy_reqs, struct request,
>  					       queuelist);
>  	if (current_req) {
> -		current_req->error_count = 0;
> +		floppy_errors = 0;
>  		list_del_init(&current_req->queuelist);
> +		return 1;
>  	}
> -	return current_req != NULL;
> +	return 0;
>  }
>  
>  /* Starts or continues processing request. Will automatically unlock the
> @@ -2821,7 +2820,6 @@ static void redo_fd_request(void)
>  		_floppy = floppy_type + drive_params[current_drive].autodetect[drive_state[current_drive].probed_format];
>  	} else
>  		probing = 0;
> -	errors = &(current_req->error_count);
>  	tmp = make_raw_rw_request();
>  	if (tmp < 2) {
>  		request_done(tmp);

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

* [PATCH 5.10] floppy: use a statically allocated error counter
  2022-05-08  9:37 [PATCH 1/3] floppy: use a statically allocated error counter Willy Tarreau
                   ` (3 preceding siblings ...)
  2022-05-17 17:47 ` Denis Efremov
@ 2022-05-17 20:12 ` Denis Efremov
  2022-05-17 20:23 ` [PATCH 5.4] " Denis Efremov
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 11+ messages in thread
From: Denis Efremov @ 2022-05-17 20:12 UTC (permalink / raw)
  To: gregkh
  Cc: Willy Tarreau, stable, Minh Yuan, Linus Torvalds, Denis Efremov,
	Linus Torvalds

From: Willy Tarreau <w@1wt.eu>

commit f71f01394f742fc4558b3f9f4c7ef4c4cf3b07c8 upstream.

Interrupt handler bad_flp_intr() may cause a UAF on the recently freed
request just to increment the error count.  There's no point keeping
that one in the request anyway, and since the interrupt handler uses a
static pointer to the error which cannot be kept in sync with the
pending request, better make it use a static error counter that's reset
for each new request.  This reset now happens when entering
redo_fd_request() for a new request via set_next_request().

One initial concern about a single error counter was that errors on one
floppy drive could be reported on another one, but this problem is not
real given that the driver uses a single drive at a time, as that
PC-compatible controllers also have this limitation by using shared
signals.  As such the error count is always for the "current" drive.

Reported-by: Minh Yuan <yuanmingbuaa@gmail.com>
Suggested-by: Linus Torvalds <torvalds@linuxfoundation.org>
Tested-by: Denis Efremov <efremov@linux.com>
Signed-off-by: Willy Tarreau <w@1wt.eu>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Denis Efremov <efremov@linux.com>
---

Handled *errors in make_raw_rw_request().

 drivers/block/floppy.c | 20 +++++++++-----------
 1 file changed, 9 insertions(+), 11 deletions(-)

diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index c9411fe2f0af..4ef407a33996 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -509,8 +509,8 @@ static unsigned long fdc_busy;
 static DECLARE_WAIT_QUEUE_HEAD(fdc_wait);
 static DECLARE_WAIT_QUEUE_HEAD(command_done);
 
-/* Errors during formatting are counted here. */
-static int format_errors;
+/* errors encountered on the current (or last) request */
+static int floppy_errors;
 
 /* Format request descriptor. */
 static struct format_descr format_req;
@@ -530,7 +530,6 @@ static struct format_descr format_req;
 static char *floppy_track_buffer;
 static int max_buffer_sectors;
 
-static int *errors;
 typedef void (*done_f)(int);
 static const struct cont_t {
 	void (*interrupt)(void);
@@ -1455,7 +1454,7 @@ static int interpret_errors(void)
 			if (drive_params[current_drive].flags & FTD_MSG)
 				DPRINT("Over/Underrun - retrying\n");
 			bad = 0;
-		} else if (*errors >= drive_params[current_drive].max_errors.reporting) {
+		} else if (floppy_errors >= drive_params[current_drive].max_errors.reporting) {
 			print_errors();
 		}
 		if (reply_buffer[ST2] & ST2_WC || reply_buffer[ST2] & ST2_BC)
@@ -2095,7 +2094,7 @@ static void bad_flp_intr(void)
 		if (!next_valid_format(current_drive))
 			return;
 	}
-	err_count = ++(*errors);
+	err_count = ++floppy_errors;
 	INFBOUND(write_errors[current_drive].badness, err_count);
 	if (err_count > drive_params[current_drive].max_errors.abort)
 		cont->done(0);
@@ -2240,9 +2239,8 @@ static int do_format(int drive, struct format_descr *tmp_format_req)
 		return -EINVAL;
 	}
 	format_req = *tmp_format_req;
-	format_errors = 0;
 	cont = &format_cont;
-	errors = &format_errors;
+	floppy_errors = 0;
 	ret = wait_til_done(redo_format, true);
 	if (ret == -EINTR)
 		return -EINTR;
@@ -2721,7 +2719,7 @@ static int make_raw_rw_request(void)
 		 */
 		if (!direct ||
 		    (indirect * 2 > direct * 3 &&
-		     *errors < drive_params[current_drive].max_errors.read_track &&
+		     floppy_errors < drive_params[current_drive].max_errors.read_track &&
 		     ((!probing ||
 		       (drive_params[current_drive].read_track & (1 << drive_state[current_drive].probed_format)))))) {
 			max_size = blk_rq_sectors(current_req);
@@ -2846,10 +2844,11 @@ static int set_next_request(void)
 	current_req = list_first_entry_or_null(&floppy_reqs, struct request,
 					       queuelist);
 	if (current_req) {
-		current_req->error_count = 0;
+		floppy_errors = 0;
 		list_del_init(&current_req->queuelist);
+		return 1;
 	}
-	return current_req != NULL;
+	return 0;
 }
 
 /* Starts or continues processing request. Will automatically unlock the
@@ -2908,7 +2907,6 @@ static void redo_fd_request(void)
 		_floppy = floppy_type + drive_params[current_drive].autodetect[drive_state[current_drive].probed_format];
 	} else
 		probing = 0;
-	errors = &(current_req->error_count);
 	tmp = make_raw_rw_request();
 	if (tmp < 2) {
 		request_done(tmp);
-- 
2.35.3


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

* [PATCH 5.4] floppy: use a statically allocated error counter
  2022-05-08  9:37 [PATCH 1/3] floppy: use a statically allocated error counter Willy Tarreau
                   ` (4 preceding siblings ...)
  2022-05-17 20:12 ` [PATCH 5.10] " Denis Efremov
@ 2022-05-17 20:23 ` Denis Efremov
  2022-05-17 20:35 ` [PATCH 4.19] " Denis Efremov
  2022-05-17 20:46 ` [PATCH 4.9] " Denis Efremov
  7 siblings, 0 replies; 11+ messages in thread
From: Denis Efremov @ 2022-05-17 20:23 UTC (permalink / raw)
  To: gregkh
  Cc: Willy Tarreau, stable, Minh Yuan, Linus Torvalds, Denis Efremov,
	Linus Torvalds

From: Willy Tarreau <w@1wt.eu>

commit f71f01394f742fc4558b3f9f4c7ef4c4cf3b07c8 upstream.

Interrupt handler bad_flp_intr() may cause a UAF on the recently freed
request just to increment the error count.  There's no point keeping
that one in the request anyway, and since the interrupt handler uses a
static pointer to the error which cannot be kept in sync with the
pending request, better make it use a static error counter that's reset
for each new request.  This reset now happens when entering
redo_fd_request() for a new request via set_next_request().

One initial concern about a single error counter was that errors on one
floppy drive could be reported on another one, but this problem is not
real given that the driver uses a single drive at a time, as that
PC-compatible controllers also have this limitation by using shared
signals.  As such the error count is always for the "current" drive.

Reported-by: Minh Yuan <yuanmingbuaa@gmail.com>
Suggested-by: Linus Torvalds <torvalds@linuxfoundation.org>
Tested-by: Denis Efremov <efremov@linux.com>
Signed-off-by: Willy Tarreau <w@1wt.eu>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Denis Efremov <efremov@linux.com>
---
 drivers/block/floppy.c | 20 +++++++++-----------
 1 file changed, 9 insertions(+), 11 deletions(-)

diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index f24e3791e840..e133ff5fa596 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -521,8 +521,8 @@ static unsigned long fdc_busy;
 static DECLARE_WAIT_QUEUE_HEAD(fdc_wait);
 static DECLARE_WAIT_QUEUE_HEAD(command_done);
 
-/* Errors during formatting are counted here. */
-static int format_errors;
+/* errors encountered on the current (or last) request */
+static int floppy_errors;
 
 /* Format request descriptor. */
 static struct format_descr format_req;
@@ -542,7 +542,6 @@ static struct format_descr format_req;
 static char *floppy_track_buffer;
 static int max_buffer_sectors;
 
-static int *errors;
 typedef void (*done_f)(int);
 static const struct cont_t {
 	void (*interrupt)(void);
@@ -1435,7 +1434,7 @@ static int interpret_errors(void)
 			if (DP->flags & FTD_MSG)
 				DPRINT("Over/Underrun - retrying\n");
 			bad = 0;
-		} else if (*errors >= DP->max_errors.reporting) {
+		} else if (floppy_errors >= DP->max_errors.reporting) {
 			print_errors();
 		}
 		if (ST2 & ST2_WC || ST2 & ST2_BC)
@@ -2055,7 +2054,7 @@ static void bad_flp_intr(void)
 		if (!next_valid_format())
 			return;
 	}
-	err_count = ++(*errors);
+	err_count = ++floppy_errors;
 	INFBOUND(DRWE->badness, err_count);
 	if (err_count > DP->max_errors.abort)
 		cont->done(0);
@@ -2200,9 +2199,8 @@ static int do_format(int drive, struct format_descr *tmp_format_req)
 		return -EINVAL;
 	}
 	format_req = *tmp_format_req;
-	format_errors = 0;
 	cont = &format_cont;
-	errors = &format_errors;
+	floppy_errors = 0;
 	ret = wait_til_done(redo_format, true);
 	if (ret == -EINTR)
 		return -EINTR;
@@ -2677,7 +2675,7 @@ static int make_raw_rw_request(void)
 		 */
 		if (!direct ||
 		    (indirect * 2 > direct * 3 &&
-		     *errors < DP->max_errors.read_track &&
+		     floppy_errors < DP->max_errors.read_track &&
 		     ((!probing ||
 		       (DP->read_track & (1 << DRS->probed_format)))))) {
 			max_size = blk_rq_sectors(current_req);
@@ -2801,10 +2799,11 @@ static int set_next_request(void)
 	current_req = list_first_entry_or_null(&floppy_reqs, struct request,
 					       queuelist);
 	if (current_req) {
-		current_req->error_count = 0;
+		floppy_errors = 0;
 		list_del_init(&current_req->queuelist);
+		return 1;
 	}
-	return current_req != NULL;
+	return 0;
 }
 
 static void redo_fd_request(void)
@@ -2860,7 +2859,6 @@ static void redo_fd_request(void)
 		_floppy = floppy_type + DP->autodetect[DRS->probed_format];
 	} else
 		probing = 0;
-	errors = &(current_req->error_count);
 	tmp = make_raw_rw_request();
 	if (tmp < 2) {
 		request_done(tmp);
-- 
2.35.3


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

* [PATCH 4.19] floppy: use a statically allocated error counter
  2022-05-08  9:37 [PATCH 1/3] floppy: use a statically allocated error counter Willy Tarreau
                   ` (5 preceding siblings ...)
  2022-05-17 20:23 ` [PATCH 5.4] " Denis Efremov
@ 2022-05-17 20:35 ` Denis Efremov
  2022-05-17 20:46 ` [PATCH 4.9] " Denis Efremov
  7 siblings, 0 replies; 11+ messages in thread
From: Denis Efremov @ 2022-05-17 20:35 UTC (permalink / raw)
  To: gregkh
  Cc: Willy Tarreau, stable, Minh Yuan, Linus Torvalds, Denis Efremov,
	Linus Torvalds

From: Willy Tarreau <w@1wt.eu>

commit f71f01394f742fc4558b3f9f4c7ef4c4cf3b07c8 upstream.

Interrupt handler bad_flp_intr() may cause a UAF on the recently freed
request just to increment the error count.  There's no point keeping
that one in the request anyway, and since the interrupt handler uses a
static pointer to the error which cannot be kept in sync with the
pending request, better make it use a static error counter that's reset
for each new request.  This reset now happens when entering
redo_fd_request() for a new request via set_next_request().

One initial concern about a single error counter was that errors on one
floppy drive could be reported on another one, but this problem is not
real given that the driver uses a single drive at a time, as that
PC-compatible controllers also have this limitation by using shared
signals.  As such the error count is always for the "current" drive.

Reported-by: Minh Yuan <yuanmingbuaa@gmail.com>
Suggested-by: Linus Torvalds <torvalds@linuxfoundation.org>
Tested-by: Denis Efremov <efremov@linux.com>
Signed-off-by: Willy Tarreau <w@1wt.eu>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Denis Efremov <efremov@linux.com>
---
 drivers/block/floppy.c | 17 +++++++----------
 1 file changed, 7 insertions(+), 10 deletions(-)

diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index 97c8fc4d6e7b..0e66314415c5 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -520,8 +520,8 @@ static unsigned long fdc_busy;
 static DECLARE_WAIT_QUEUE_HEAD(fdc_wait);
 static DECLARE_WAIT_QUEUE_HEAD(command_done);
 
-/* Errors during formatting are counted here. */
-static int format_errors;
+/* errors encountered on the current (or last) request */
+static int floppy_errors;
 
 /* Format request descriptor. */
 static struct format_descr format_req;
@@ -541,7 +541,6 @@ static struct format_descr format_req;
 static char *floppy_track_buffer;
 static int max_buffer_sectors;
 
-static int *errors;
 typedef void (*done_f)(int);
 static const struct cont_t {
 	void (*interrupt)(void);
@@ -1434,7 +1433,7 @@ static int interpret_errors(void)
 			if (DP->flags & FTD_MSG)
 				DPRINT("Over/Underrun - retrying\n");
 			bad = 0;
-		} else if (*errors >= DP->max_errors.reporting) {
+		} else if (floppy_errors >= DP->max_errors.reporting) {
 			print_errors();
 		}
 		if (ST2 & ST2_WC || ST2 & ST2_BC)
@@ -2054,7 +2053,7 @@ static void bad_flp_intr(void)
 		if (!next_valid_format())
 			return;
 	}
-	err_count = ++(*errors);
+	err_count = ++floppy_errors;
 	INFBOUND(DRWE->badness, err_count);
 	if (err_count > DP->max_errors.abort)
 		cont->done(0);
@@ -2199,9 +2198,8 @@ static int do_format(int drive, struct format_descr *tmp_format_req)
 		return -EINVAL;
 	}
 	format_req = *tmp_format_req;
-	format_errors = 0;
 	cont = &format_cont;
-	errors = &format_errors;
+	floppy_errors = 0;
 	ret = wait_til_done(redo_format, true);
 	if (ret == -EINTR)
 		return -EINTR;
@@ -2684,7 +2682,7 @@ static int make_raw_rw_request(void)
 		 */
 		if (!direct ||
 		    (indirect * 2 > direct * 3 &&
-		     *errors < DP->max_errors.read_track &&
+		     floppy_errors < DP->max_errors.read_track &&
 		     ((!probing ||
 		       (DP->read_track & (1 << DRS->probed_format)))))) {
 			max_size = blk_rq_sectors(current_req);
@@ -2818,7 +2816,7 @@ static int set_next_request(void)
 		if (q) {
 			current_req = blk_fetch_request(q);
 			if (current_req) {
-				current_req->error_count = 0;
+				floppy_errors = 0;
 				break;
 			}
 		}
@@ -2880,7 +2878,6 @@ static void redo_fd_request(void)
 		_floppy = floppy_type + DP->autodetect[DRS->probed_format];
 	} else
 		probing = 0;
-	errors = &(current_req->error_count);
 	tmp = make_raw_rw_request();
 	if (tmp < 2) {
 		request_done(tmp);
-- 
2.35.3


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

* [PATCH 4.9] floppy: use a statically allocated error counter
  2022-05-08  9:37 [PATCH 1/3] floppy: use a statically allocated error counter Willy Tarreau
                   ` (6 preceding siblings ...)
  2022-05-17 20:35 ` [PATCH 4.19] " Denis Efremov
@ 2022-05-17 20:46 ` Denis Efremov
  7 siblings, 0 replies; 11+ messages in thread
From: Denis Efremov @ 2022-05-17 20:46 UTC (permalink / raw)
  To: gregkh
  Cc: Willy Tarreau, stable, Minh Yuan, Linus Torvalds, Denis Efremov,
	Linus Torvalds

From: Willy Tarreau <w@1wt.eu>

commit f71f01394f742fc4558b3f9f4c7ef4c4cf3b07c8 upstream.

Interrupt handler bad_flp_intr() may cause a UAF on the recently freed
request just to increment the error count.  There's no point keeping
that one in the request anyway, and since the interrupt handler uses a
static pointer to the error which cannot be kept in sync with the
pending request, better make it use a static error counter that's reset
for each new request.  This reset now happens when entering
redo_fd_request() for a new request via set_next_request().

One initial concern about a single error counter was that errors on one
floppy drive could be reported on another one, but this problem is not
real given that the driver uses a single drive at a time, as that
PC-compatible controllers also have this limitation by using shared
signals.  As such the error count is always for the "current" drive.

Reported-by: Minh Yuan <yuanmingbuaa@gmail.com>
Suggested-by: Linus Torvalds <torvalds@linuxfoundation.org>
Tested-by: Denis Efremov <efremov@linux.com>
Signed-off-by: Willy Tarreau <w@1wt.eu>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Denis Efremov <efremov@linux.com>
---
 drivers/block/floppy.c | 19 +++++++++----------
 1 file changed, 9 insertions(+), 10 deletions(-)

diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index cfe1bfb3c20e..216ee1057b12 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -516,8 +516,8 @@ static unsigned long fdc_busy;
 static DECLARE_WAIT_QUEUE_HEAD(fdc_wait);
 static DECLARE_WAIT_QUEUE_HEAD(command_done);
 
-/* Errors during formatting are counted here. */
-static int format_errors;
+/* errors encountered on the current (or last) request */
+static int floppy_errors;
 
 /* Format request descriptor. */
 static struct format_descr format_req;
@@ -537,7 +537,6 @@ static struct format_descr format_req;
 static char *floppy_track_buffer;
 static int max_buffer_sectors;
 
-static int *errors;
 typedef void (*done_f)(int);
 static const struct cont_t {
 	void (*interrupt)(void);
@@ -1426,7 +1425,7 @@ static int interpret_errors(void)
 			if (DP->flags & FTD_MSG)
 				DPRINT("Over/Underrun - retrying\n");
 			bad = 0;
-		} else if (*errors >= DP->max_errors.reporting) {
+		} else if (floppy_errors >= DP->max_errors.reporting) {
 			print_errors();
 		}
 		if (ST2 & ST2_WC || ST2 & ST2_BC)
@@ -2049,7 +2048,7 @@ static void bad_flp_intr(void)
 		if (!next_valid_format())
 			return;
 	}
-	err_count = ++(*errors);
+	err_count = ++floppy_errors;
 	INFBOUND(DRWE->badness, err_count);
 	if (err_count > DP->max_errors.abort)
 		cont->done(0);
@@ -2194,9 +2193,8 @@ static int do_format(int drive, struct format_descr *tmp_format_req)
 		return -EINVAL;
 	}
 	format_req = *tmp_format_req;
-	format_errors = 0;
 	cont = &format_cont;
-	errors = &format_errors;
+	floppy_errors = 0;
 	ret = wait_til_done(redo_format, true);
 	if (ret == -EINTR)
 		return -EINTR;
@@ -2679,7 +2677,7 @@ static int make_raw_rw_request(void)
 		 */
 		if (!direct ||
 		    (indirect * 2 > direct * 3 &&
-		     *errors < DP->max_errors.read_track &&
+		     floppy_errors < DP->max_errors.read_track &&
 		     ((!probing ||
 		       (DP->read_track & (1 << DRS->probed_format)))))) {
 			max_size = blk_rq_sectors(current_req);
@@ -2812,8 +2810,10 @@ static int set_next_request(void)
 			fdc_queue = 0;
 		if (q) {
 			current_req = blk_fetch_request(q);
-			if (current_req)
+			if (current_req) {
+				floppy_errors = 0;
 				break;
+			}
 		}
 	} while (fdc_queue != old_pos);
 
@@ -2873,7 +2873,6 @@ static void redo_fd_request(void)
 		_floppy = floppy_type + DP->autodetect[DRS->probed_format];
 	} else
 		probing = 0;
-	errors = &(current_req->errors);
 	tmp = make_raw_rw_request();
 	if (tmp < 2) {
 		request_done(tmp);
-- 
2.35.3


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

* Re: [PATCH 1/3] floppy: use a statically allocated error counter
  2022-05-17 17:47 ` Denis Efremov
@ 2022-05-19 12:40   ` Greg Kroah-Hartman
  0 siblings, 0 replies; 11+ messages in thread
From: Greg Kroah-Hartman @ 2022-05-19 12:40 UTC (permalink / raw)
  To: Denis Efremov; +Cc: stable, Willy Tarreau

On Tue, May 17, 2022 at 09:47:57PM +0400, Denis Efremov wrote:
> Hi,
> 
> On 5/8/22 13:37, Willy Tarreau wrote:
> > Interrupt handler bad_flp_intr() may cause a UAF on the recently freed
> > request just to increment the error count. There's no point keeping
> > that one in the request anyway, and since the interrupt handler uses
> > a static pointer to the error which cannot be kept in sync with the
> > pending request, better make it use a static error counter that's
> > reset for each new request. This reset now happens when entering
> > redo_fd_request() for a new request via set_next_request().
> > 
> > One initial concern about a single error counter was that errors on
> > one floppy drive could be reported on another one, but this problem
> > is not real given that the driver uses a single drive at a time, as
> > that PC-compatible controllers also have this limitation by using
> > shared signals. As such the error count is always for the "current"
> > drive.
> > 
> > Reported-by: Minh Yuan <yuanmingbuaa@gmail.com>
> > Suggested-by: Linus Torvalds <torvalds@linuxfoundation.org>
> > Tested-by: Denis Efremov <efremov@linux.com>
> > Signed-off-by: Willy Tarreau <w@1wt.eu>
> 
> Could you please take this patch (only this one) to the stable trees?
> 
> commit f71f01394f742fc4558b3f9f4c7ef4c4cf3b07c8 upstream.
> 
> The patch applies cleanly to 5.17, 5.15, 5.10 kernels.
> I'll send a backport for 5.4 and older kernels.

All now queued up, thanks.

greg k-h

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

end of thread, other threads:[~2022-05-19 12:40 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-05-08  9:37 [PATCH 1/3] floppy: use a statically allocated error counter Willy Tarreau
2022-05-08  9:37 ` [PATCH 2/3] ataflop: use a statically allocated error counters Willy Tarreau
2022-05-08  9:37 ` [PATCH 3/3] blk-mq: remove the error_count from struct request Willy Tarreau
2022-05-09  6:14 ` [PATCH 1/3] floppy: use a statically allocated error counter Christoph Hellwig
2022-05-10  3:17   ` Willy Tarreau
2022-05-17 17:47 ` Denis Efremov
2022-05-19 12:40   ` Greg Kroah-Hartman
2022-05-17 20:12 ` [PATCH 5.10] " Denis Efremov
2022-05-17 20:23 ` [PATCH 5.4] " Denis Efremov
2022-05-17 20:35 ` [PATCH 4.19] " Denis Efremov
2022-05-17 20:46 ` [PATCH 4.9] " Denis Efremov

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.