summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorbde <bde@FreeBSD.org>2000-01-28 10:22:07 +0000
committerbde <bde@FreeBSD.org>2000-01-28 10:22:07 +0000
commitdff980d98b9f7bee87ebee9c2273ede358e115e0 (patch)
treed333b8a29578a8b49f6a5a37eb31ff979617ebe4 /sys
parentd32ad2b60dbf440447d99a5234e49155e1090162 (diff)
downloadFreeBSD-src-dff980d98b9f7bee87ebee9c2273ede358e115e0.zip
FreeBSD-src-dff980d98b9f7bee87ebee9c2273ede358e115e0.tar.gz
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
Diffstat (limited to 'sys')
-rw-r--r--sys/i386/isa/wd.c8
-rw-r--r--sys/kern/subr_diskmbr.c79
2 files changed, 67 insertions, 20 deletions
diff --git a/sys/i386/isa/wd.c b/sys/i386/isa/wd.c
index 3069366..66ae5fc 100644
--- a/sys/i386/isa/wd.c
+++ b/sys/i386/isa/wd.c
@@ -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 ... */
diff --git a/sys/kern/subr_diskmbr.c b/sys/kern/subr_diskmbr.c
index 591fc8b..c16f5d7 100644
--- a/sys/kern/subr_diskmbr.c
+++ b/sys/kern/subr_diskmbr.c
@@ -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)
OpenPOWER on IntegriCloud