diff options
author | 2007-06-09 23:06:45 +0000 | |
---|---|---|
committer | 2007-06-09 23:06:45 +0000 | |
commit | 4ff4a53161b4613edcba251eb046c0f6493b6153 (patch) | |
tree | c90fdbddfff16d1da007cf42e2257ae3876e2be1 /sys/kern/subr_disk.c | |
parent | Enable re* at cardbus?, tested with a D-Link DGE-660TD card. (diff) | |
download | wireguard-openbsd-4ff4a53161b4613edcba251eb046c0f6493b6153.tar.xz wireguard-openbsd-4ff4a53161b4613edcba251eb046c0f6493b6153.zip |
The differences in the last non-homogeneous bounds_check_with_label()
routines (alpha, vax) prove to be not worth keeping. Move
bounds_check_with_label() into the MI world. Eliminate unreliable and
almost certainly useless checks for overwriting a disklabel.
After discussion with deraadt@
Diffstat (limited to 'sys/kern/subr_disk.c')
-rw-r--r-- | sys/kern/subr_disk.c | 48 |
1 files changed, 47 insertions, 1 deletions
diff --git a/sys/kern/subr_disk.c b/sys/kern/subr_disk.c index cc8b2dd29d9..2657372d773 100644 --- a/sys/kern/subr_disk.c +++ b/sys/kern/subr_disk.c @@ -1,4 +1,4 @@ -/* $OpenBSD: subr_disk.c,v 1.56 2007/06/09 17:18:36 deraadt Exp $ */ +/* $OpenBSD: subr_disk.c,v 1.57 2007/06/09 23:06:45 krw Exp $ */ /* $NetBSD: subr_disk.c,v 1.17 1996/03/16 23:17:08 christos Exp $ */ /* @@ -288,6 +288,52 @@ setdisklabel(struct disklabel *olp, struct disklabel *nlp, } /* + * 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 buf *bp, struct disklabel *lp, + struct cpu_disklabel *osdep, int wlabel) +{ +#define blockpersec(count, lp) ((count) * (((lp)->d_secsize) / DEV_BSIZE)) + struct partition *p = lp->d_partitions + DISKPART(bp->b_dev); + int sz = howmany(bp->b_bcount, DEV_BSIZE); + + /* avoid division by zero */ + if (lp->d_secpercyl == 0) { + bp->b_error = EINVAL; + goto bad; + } + + /* beyond partition? */ + if (bp->b_blkno + sz > blockpersec(DL_GETPSIZE(p), lp)) { + sz = blockpersec(DL_GETPSIZE(p), lp) - bp->b_blkno; + if (sz == 0) { + /* If exactly at end of disk, return EOF. */ + bp->b_resid = bp->b_bcount; + return (-1); + } + if (sz < 0) { + /* If past end of disk, return EINVAL. */ + bp->b_error = EINVAL; + goto bad; + } + /* Otherwise, truncate request. */ + bp->b_bcount = sz << DEV_BSHIFT; + } + + /* calculate cylinder for disksort to order transfers with */ + bp->b_cylinder = (bp->b_blkno + blockpersec(DL_GETPOFFSET(p), lp)) / + lp->d_secpercyl; + return (1); + +bad: + bp->b_flags |= B_ERROR; + return (-1); +} + +/* * Disk error is the preface to plaintive error messages * about failing disk transfers. It prints messages of the form |