summaryrefslogtreecommitdiffstats
path: root/sys/kern
diff options
context:
space:
mode:
authorphk <phk@FreeBSD.org>2002-09-20 17:51:00 +0000
committerphk <phk@FreeBSD.org>2002-09-20 17:51:00 +0000
commitd376fc4110ce10f8834cc1b4c5916de1912b21b6 (patch)
treedbeca777ba2b4bd9cb736990b6598d6cd54fcfc6 /sys/kern
parent4848209c80a407047dc589e9c7994afe70b55314 (diff)
downloadFreeBSD-src-d376fc4110ce10f8834cc1b4c5916de1912b21b6.zip
FreeBSD-src-d376fc4110ce10f8834cc1b4c5916de1912b21b6.tar.gz
For reasons now lost in historical fog, the bounds_check_with_label()
function were put in i386/i386/machdep.c from where it has been cut and pasted to other architectures with only minor corruption. Disklabel is really a MI format in many ways, at least it certainly is when you operate on struct disklabel. Put bounds_check_with_label() back in subr_disklabel.c where it belongs. Sponsored by: DARPA & NAI Labs.
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/subr_disklabel.c58
1 files changed, 58 insertions, 0 deletions
diff --git a/sys/kern/subr_disklabel.c b/sys/kern/subr_disklabel.c
index 000c1f0..9e27a96 100644
--- a/sys/kern/subr_disklabel.c
+++ b/sys/kern/subr_disklabel.c
@@ -216,3 +216,61 @@ done:
brelse(bp);
return (error);
}
+
+/*
+ * Determine the size of the transfer, and make sure it is
+ * within the boundaries of the partition. Adjust transfer
+ * if needed, and signal errors or early completion.
+ */
+int
+bounds_check_with_label(struct bio *bp, struct disklabel *lp, int wlabel)
+{
+ struct partition *p = lp->d_partitions + dkpart(bp->bio_dev);
+ int labelsect = lp->d_partitions[0].p_offset;
+ int maxsz = p->p_size,
+ sz = (bp->bio_bcount + DEV_BSIZE - 1) >> DEV_BSHIFT;
+
+ /* overwriting disk label ? */
+ /* XXX should also protect bootstrap in first 8K */
+ if (bp->bio_blkno + p->p_offset <= LABELSECTOR + labelsect &&
+#if LABELSECTOR != 0
+ bp->bio_blkno + p->p_offset + sz > LABELSECTOR + labelsect &&
+#endif
+ (bp->bio_cmd == BIO_WRITE) && wlabel == 0) {
+ bp->bio_error = EROFS;
+ goto bad;
+ }
+
+#if defined(DOSBBSECTOR) && defined(notyet)
+ /* overwriting master boot record? */
+ if (bp->bio_blkno + p->p_offset <= DOSBBSECTOR &&
+ (bp->bio_cmd == BIO_WRITE) && wlabel == 0) {
+ bp->bio_error = EROFS;
+ goto bad;
+ }
+#endif
+
+ /* beyond partition? */
+ if (bp->bio_blkno < 0 || bp->bio_blkno + sz > maxsz) {
+ /* if exactly at end of disk, return an EOF */
+ if (bp->bio_blkno == maxsz) {
+ bp->bio_resid = bp->bio_bcount;
+ return(0);
+ }
+ /* or truncate if part of it fits */
+ sz = maxsz - bp->bio_blkno;
+ if (sz <= 0) {
+ bp->bio_error = EINVAL;
+ goto bad;
+ }
+ bp->bio_bcount = sz << DEV_BSHIFT;
+ }
+
+ bp->bio_pblkno = bp->bio_blkno + p->p_offset;
+ return(1);
+
+bad:
+ bp->bio_flags |= BIO_ERROR;
+ return(-1);
+}
+
OpenPOWER on IntegriCloud