Don't permit generation of non-physical disk addresses.

subr_diskmbr.c:
Don't "helpfully" enlarge our idea of the disk size to cover all the
primary slices.  Instead, truncate or discard slices that don't seem
to be on the disk.  The enlargement was a hack for disks that don't
report their size (e.g., MFM disks).  It is just wrong in general.

wd.c:
In CHS mode, limit the disk size so that cylinder numbers >= 65536
cannot occur.  This normally only affects disks larger than 33.8GB.
CHS mode accesses to addresses above the limit are now properly broken
(an error is returned instead of garbage for reads and disk corruption
for writes).

PR:		15611
Reviewed by:	readers of freebsd-bugs did not respond to a request
            	for review
This commit is contained in:
Bruce Evans 2000-01-28 10:22:07 +00:00
parent a35bd5f6f8
commit 7b17f8ffbd
2 changed files with 67 additions and 20 deletions

View file

@ -1760,6 +1760,14 @@ failed:
du->dk_dd.d_ncylinders =
du->dk_dd.d_secperunit / du->dk_dd.d_secpercyl;
}
if (du->dk_dd.d_ncylinders > 0x10000 && !(du->cfg_flags & WDOPT_LBA)) {
du->dk_dd.d_ncylinders = 0x10000;
du->dk_dd.d_secperunit = du->dk_dd.d_secpercyl *
du->dk_dd.d_ncylinders;
printf(
"wd%d: cannot handle %d total sectors; truncating to %lu\n",
du->dk_lunit, wp->wdp_lbasize, du->dk_dd.d_secperunit);
}
#if 0
du->dk_dd.d_partitions[RAW_PART].p_size = du->dk_dd.d_secperunit;
/* dubious ... */

View file

@ -73,6 +73,9 @@ static void mbr_extended __P((dev_t dev, struct disklabel *lp,
u_long ext_size, u_long base_ext_offset,
int nsectors, int ntracks, u_long mbr_offset,
int level));
static int mbr_setslice __P((char *sname, struct disklabel *lp,
struct diskslice *sp, struct dos_partition *dp,
u_long br_offset));
static int
check_part(sname, dp, offset, nsectors, ntracks, mbr_offset )
@ -294,14 +297,26 @@ reread_mbr:
*/
secpercyl = (u_long)max_nsectors * max_ntracks;
if (secpercyl != 0) {
#if 0
u_long secperunit;
#endif
lp->d_nsectors = max_nsectors;
lp->d_ntracks = max_ntracks;
lp->d_secpercyl = secpercyl;
/*
* Temporarily, don't even consider adjusting the drive's
* size, since the adjusted size may exceed the hardware's
* addressing capabilities. The adjustment helped mainly
* for ancient MFM drives with > 1024 cylinders, but now
* breaks at least IDE drives with 63*16*65536 sectors if
* they are controlled by the wd driver in CHS mode.
*/
#if 0
secperunit = secpercyl * max_ncyls;
if (lp->d_secperunit < secperunit)
lp->d_secperunit = secperunit;
#endif
lp->d_ncylinders = lp->d_secperunit / secpercyl;
}
@ -319,18 +334,9 @@ reread_mbr:
/* Initialize normal slices. */
sp = &ssp->dss_slices[BASE_SLICE];
for (dospart = 0, dp = dp0; dospart < NDOSPART; dospart++, dp++, sp++) {
sp->ds_offset = mbr_offset + dp->dp_start;
sp->ds_size = dp->dp_size;
sp->ds_type = dp->dp_typ;
#ifdef PC98_ATCOMPAT
/* Fake FreeBSD(98). */
if (sp->ds_type == DOSPTYP_386BSD)
sp->ds_type = 0x94;
#endif
#if 0
lp->d_subtype |= (lp->d_subtype & 3) | dospart
| DSTYPE_INDOSPART;
#endif
sname = dsname(dev, dkunit(dev), BASE_SLICE + dospart,
RAW_PART, partname);
(void)mbr_setslice(sname, lp, sp, dp, mbr_offset);
}
ssp->dss_nslices = BASE_SLICE + NDOSPART;
@ -451,14 +457,8 @@ mbr_extended(dev, lp, ssp, ext_offset, ext_size, base_ext_offset, nsectors,
continue;
}
sp = &ssp->dss_slices[slice];
sp->ds_offset = ext_offset + dp->dp_start;
sp->ds_size = dp->dp_size;
sp->ds_type = dp->dp_typ;
#ifdef PC98_ATCOMPAT
/* Fake FreeBSD(98). */
if (sp->ds_type == DOSPTYP_386BSD)
sp->ds_type = 0x94;
#endif
if (mbr_setslice(sname, lp, sp, dp, ext_offset) != 0)
continue;
slice++;
}
}
@ -476,6 +476,45 @@ done:
brelse(bp);
}
static int
mbr_setslice(sname, lp, sp, dp, br_offset)
char *sname;
struct disklabel *lp;
struct diskslice *sp;
struct dos_partition *dp;
u_long br_offset;
{
u_long offset;
u_long size;
offset = br_offset + dp->dp_start;
if (offset > lp->d_secperunit || offset < br_offset) {
printf(
"%s: slice starts beyond end of the disk: rejecting it\n",
sname);
return (1);
}
size = lp->d_secperunit - offset;
if (size >= dp->dp_size)
size = dp->dp_size;
else
printf(
"%s: slice extends beyond end of disk: truncating from %lu to %lu sectors\n",
sname, (u_long)dp->dp_size, size);
sp->ds_offset = offset;
sp->ds_size = size;
sp->ds_type = dp->dp_typ;
#ifdef PC98_ATCOMPAT
/* Fake FreeBSD(98). */
if (sp->ds_type == DOSPTYP_386BSD)
sp->ds_type = 0x94;
#endif
#if 0
lp->d_subtype |= (lp->d_subtype & 3) | dospart | DSTYPE_INDOSPART;
#endif
return (0);
}
#ifdef __alpha__
void
alpha_fix_srm_checksum(bp)