Skip to content

Commit f71f013

Browse files
wtarreautorvalds
authored andcommitted
floppy: use a statically allocated error counter
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>
1 parent 30c8e80 commit f71f013

1 file changed

Lines changed: 8 additions & 10 deletions

File tree

drivers/block/floppy.c

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -509,8 +509,8 @@ static unsigned long fdc_busy;
509509
static DECLARE_WAIT_QUEUE_HEAD(fdc_wait);
510510
static DECLARE_WAIT_QUEUE_HEAD(command_done);
511511

512-
/* Errors during formatting are counted here. */
513-
static int format_errors;
512+
/* errors encountered on the current (or last) request */
513+
static int floppy_errors;
514514

515515
/* Format request descriptor. */
516516
static struct format_descr format_req;
@@ -530,7 +530,6 @@ static struct format_descr format_req;
530530
static char *floppy_track_buffer;
531531
static int max_buffer_sectors;
532532

533-
static int *errors;
534533
typedef void (*done_f)(int);
535534
static const struct cont_t {
536535
void (*interrupt)(void);
@@ -1455,7 +1454,7 @@ static int interpret_errors(void)
14551454
if (drive_params[current_drive].flags & FTD_MSG)
14561455
DPRINT("Over/Underrun - retrying\n");
14571456
bad = 0;
1458-
} else if (*errors >= drive_params[current_drive].max_errors.reporting) {
1457+
} else if (floppy_errors >= drive_params[current_drive].max_errors.reporting) {
14591458
print_errors();
14601459
}
14611460
if (reply_buffer[ST2] & ST2_WC || reply_buffer[ST2] & ST2_BC)
@@ -2095,7 +2094,7 @@ static void bad_flp_intr(void)
20952094
if (!next_valid_format(current_drive))
20962095
return;
20972096
}
2098-
err_count = ++(*errors);
2097+
err_count = ++floppy_errors;
20992098
INFBOUND(write_errors[current_drive].badness, err_count);
21002099
if (err_count > drive_params[current_drive].max_errors.abort)
21012100
cont->done(0);
@@ -2241,9 +2240,8 @@ static int do_format(int drive, struct format_descr *tmp_format_req)
22412240
return -EINVAL;
22422241
}
22432242
format_req = *tmp_format_req;
2244-
format_errors = 0;
22452243
cont = &format_cont;
2246-
errors = &format_errors;
2244+
floppy_errors = 0;
22472245
ret = wait_til_done(redo_format, true);
22482246
if (ret == -EINTR)
22492247
return -EINTR;
@@ -2759,10 +2757,11 @@ static int set_next_request(void)
27592757
current_req = list_first_entry_or_null(&floppy_reqs, struct request,
27602758
queuelist);
27612759
if (current_req) {
2762-
current_req->error_count = 0;
2760+
floppy_errors = 0;
27632761
list_del_init(&current_req->queuelist);
2762+
return 1;
27642763
}
2765-
return current_req != NULL;
2764+
return 0;
27662765
}
27672766

27682767
/* Starts or continues processing request. Will automatically unlock the
@@ -2821,7 +2820,6 @@ static void redo_fd_request(void)
28212820
_floppy = floppy_type + drive_params[current_drive].autodetect[drive_state[current_drive].probed_format];
28222821
} else
28232822
probing = 0;
2824-
errors = &(current_req->error_count);
28252823
tmp = make_raw_rw_request();
28262824
if (tmp < 2) {
28272825
request_done(tmp);

0 commit comments

Comments
 (0)