Bug#415164: grub: GRUB tries to read past end of device in LBA mode if a file is at the end of the device.

Len Sorensen lennartsorensen at ruggedcom.com
Fri Mar 16 17:09:52 CET 2007


Package: grub
Version: 0.97-23
Severity: important
Tags: patch

If a file happens to use the last sectors on a device which is using LBA
mode access, grub will ask the bios to read past the end of the disk
which on some bioses causing a long delay (which looks like the system
is hung).  I have seen 2 minutes on some of my systems and a couple of
hours on another type of system.

The issue occours because in LBA mode grub only knows the total_sectors
of the device, and hence always reads 63 sectors at a time for its
vtrack buffering.  Since the device might not have 63 sectors per track
(almost all hard disks do of course, but a compact flash card that is
256MB almost certainly doesn't).  My flash card is 16 heads, 32
sectors/track, 978 cylinders or similar).  Occationally a kernel or
ramdisk file happens to be in the last sectors of the filesystem which
is hence the end of the disk.  When grub tries to read the last sectors,
it asks the bios to read 63 sectors starting at the last vtrack start of
the disk, where there may only be 16 or 28 or something sectors left,
and the bios doesn't appreciate going past the end of the disk.
Eventually it returns an error and grub retries the read one sector at a
time which works fine.

The fix is to check that read_start + read_len <= total_sectors, and if
it isn't, then adjust the read_len down to the difference between
read_start and total_sectors.  With this change there is no hang and
everything works fine since the bios is never asked to read past the end
of the device.

I imagine this was never caught in the past since almost all devices
that use LBA are large harddisks which always use 63 sectors per track
and 255 heads in order to give the lowest possible cylinder count.

This problem almost certainly exists in every grub 0.x version,
including sarge.  If a user happens to have a disk where sectors per
track is not 63 when in LBA mode, and they happen to have a kernel or
initrd file end up at the end of the device, then they will not be able
to boot that kernel.

Here is the patch:

diff -ruN grub-0.97.ori/stage2/disk_io.c grub-0.97/stage2/disk_io.c
--- grub-0.97.ori/stage2/disk_io.c	2007-03-16 11:25:46.000000000 -0400
+++ grub-0.97/stage2/disk_io.c	2004-05-23 12:35:24.000000000 -0400
@@ -205,6 +205,14 @@
 	      bufaddr = (char *) BUFFERADDR + byte_offset;
 	    }
 
+          /* 
+	   *  Make sure not to ask the bios to read past end of disk
+           *  since some bioses take a long time to fail
+	   */
+          if ((read_start + read_len) > buf_geom.total_sectors) 
+	    {
+              read_len = (buf_geom.total_sectors) - read_start;
+	    }
 	  bios_err = biosdisk (BIOSDISK_READ, drive, &buf_geom,
 			       read_start, read_len, BUFFERSEG);
 	  if (bios_err)


-- System Information:
Debian Release: 4.0
  APT prefers testing
  APT policy: (500, 'testing')
Architecture: i386 (i686)
Shell:  /bin/sh linked to /bin/bash
Kernel: Linux 2.6.18-3-k7
Locale: LANG=C, LC_CTYPE=C (charmap=ANSI_X3.4-1968)

Versions of packages grub depends on:
ii  libc6                       2.3.6.ds1-13 GNU C Library: Shared libraries
ii  libncurses5                 5.5-5        Shared libraries for terminal hand

grub recommends no packages.

-- no debconf information




More information about the Pkg-grub-devel mailing list