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

Commit 67e2b624 authored by Willy Tarreau's avatar Willy Tarreau Committed by Greg Kroah-Hartman
Browse files

floppy: use a statically allocated error counter



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: default avatarMinh Yuan <yuanmingbuaa@gmail.com>
Suggested-by: default avatarLinus Torvalds <torvalds@linuxfoundation.org>
Tested-by: default avatarDenis Efremov <efremov@linux.com>
Signed-off-by: default avatarWilly Tarreau <w@1wt.eu>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: default avatarDenis Efremov <efremov@linux.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 0187300e
Loading
Loading
Loading
Loading
+9 −11
Original line number Diff line number Diff line
@@ -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);