Re: [PATCH 1/3] floppy: use a statically allocated error counter

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxx>
> Suggested-by: Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxx>
> Tested-by: Denis Efremov <efremov@xxxxxxxxx>
> Signed-off-by: Willy Tarreau <w@xxxxxx>

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);



[Index of Archives]     [Linux Kernel]     [Kernel Development Newbies]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux