floppy: fix div-by-zero in setup_format_params [Linux 4.9.187]

This Linux kernel change "floppy: fix div-by-zero in setup_format_params" is included in the Linux 4.9.187 release. This change is authored by Denis Efremov <efremov [at] ispras.ru> on Fri Jul 12 21:55:20 2019 +0300. The commit for this change in Linux stable tree is 604206c (patch) which is from upstream commit f3554ae. The same Linux upstream change may have been applied to various maintained Linux releases and you can find all Linux releases containing changes from upstream f3554ae.

floppy: fix div-by-zero in setup_format_params

[ Upstream commit f3554aeb991214cbfafd17d55e2bfddb50282e32 ]

This fixes a divide by zero error in the setup_format_params function of
the floppy driver.

Two consecutive ioctls can trigger the bug: The first one should set the
drive geometry with such .sect and .rate values for the F_SECT_PER_TRACK
to become zero.  Next, the floppy format operation should be called.

A floppy disk is not required to be inserted.  An unprivileged user
could trigger the bug if the device is accessible.

The patch checks F_SECT_PER_TRACK for a non-zero value in the
set_geometry function.  The proper check should involve a reasonable
upper limit for the .sect and .rate fields, but it could change the

The patch also checks F_SECT_PER_TRACK in the setup_format_params, and
cancels the formatting operation in case of zero.

The bug was found by syzkaller.

Signed-off-by: Denis Efremov <efremov@ispras.ru>
Tested-by: Willy Tarreau <w@1wt.eu>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

There are 5 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 drivers/block/floppy.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index 896dea2..d39dc88 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -2114,6 +2114,9 @@ static void setup_format_params(int track)
    raw_cmd->kernel_data = floppy_track_buffer;
    raw_cmd->length = 4 * F_SECT_PER_TRACK;

+   if (!F_SECT_PER_TRACK)
+       return;
    /* allow for about 30ms for data transport per track */
    head_shift = (F_SECT_PER_TRACK + 5) / 6;

@@ -3236,6 +3239,8 @@ static int set_geometry(unsigned int cmd, struct floppy_struct *g,
    /* sanity checking for parameters. */
    if (g->sect <= 0 ||
        g->head <= 0 ||
+       /* check for zero in F_SECT_PER_TRACK */
+       (unsigned char)((g->sect << 2) >> FD_SIZECODE(g)) == 0 ||
        g->track <= 0 || g->track > UDP->tracks >> STRETCH(g) ||
        /* check if reserved bits are set */
        (g->stretch & ~(FD_STRETCH | FD_SWAPSIDES | FD_SECTBASEMASK)) != 0)

Leave a Reply

Your email address will not be published. Required fields are marked *