summaryrefslogtreecommitdiffstats
path: root/sys/dev/ccd
diff options
context:
space:
mode:
authordillon <dillon@FreeBSD.org>1999-09-27 00:12:36 +0000
committerdillon <dillon@FreeBSD.org>1999-09-27 00:12:36 +0000
commit69d7d3a5b457b03e8a4698834c824001fe2e05e7 (patch)
tree2b31d64e2d25634a56abecc2ce6ae667cf827999 /sys/dev/ccd
parent960ae0fee65634802393a8f3526e541f760a0e0e (diff)
downloadFreeBSD-src-69d7d3a5b457b03e8a4698834c824001fe2e05e7.zip
FreeBSD-src-69d7d3a5b457b03e8a4698834c824001fe2e05e7.tar.gz
Buffer locking code failed to use BUF_KERNPROC and BUF_UNLOCK and
BUF_LOCKFREE a buffer prior to physically freeing it. While these bugs did not cause a crash, they might in the future. Added eof handling for unlabeled partitions. Submitted by: Tor.Egge@fast.no
Diffstat (limited to 'sys/dev/ccd')
-rw-r--r--sys/dev/ccd/ccd.c35
1 files changed, 34 insertions, 1 deletions
diff --git a/sys/dev/ccd/ccd.c b/sys/dev/ccd/ccd.c
index f5309b8..f2c9a6e 100644
--- a/sys/dev/ccd/ccd.c
+++ b/sys/dev/ccd/ccd.c
@@ -254,6 +254,7 @@ getccdbuf(struct ccdbuf *cpy)
LIST_INIT(&cbp->cb_buf.b_dep);
BUF_LOCKINIT(&cbp->cb_buf);
BUF_LOCK(&cbp->cb_buf, LK_EXCLUSIVE);
+ BUF_KERNPROC(&cbp->cb_buf);
return(cbp);
}
@@ -268,6 +269,9 @@ static __inline
void
putccdbuf(struct ccdbuf *cbp)
{
+ BUF_UNLOCK(&cbp->cb_buf);
+ BUF_LOCKFREE(&cbp->cb_buf);
+
if (numccdfreebufs < NCCDFREEHIWAT) {
cbp->cb_freenext = ccdfreebufs;
ccdfreebufs = cbp;
@@ -812,9 +816,38 @@ ccdstrategy(bp)
* error, the bounds check will flag that for us.
*/
wlabel = cs->sc_flags & (CCDF_WLABEL|CCDF_LABELLING);
- if (ccdpart(bp->b_dev) != RAW_PART)
+ if (ccdpart(bp->b_dev) != RAW_PART) {
if (bounds_check_with_label(bp, lp, wlabel) <= 0)
goto done;
+ } else {
+ int pbn; /* in sc_secsize chunks */
+ long sz; /* in sc_secsize chunks */
+
+ pbn = bp->b_blkno / (cs->sc_geom.ccg_secsize / DEV_BSIZE);
+ sz = howmany(bp->b_bcount, cs->sc_geom.ccg_secsize);
+
+ /*
+ * If out of bounds return an error. If at the EOF point,
+ * simply read or write less.
+ */
+
+ if (pbn < 0 || pbn >= cs->sc_size) {
+ bp->b_resid = bp->b_bcount;
+ if (pbn != cs->sc_size) {
+ bp->b_error = EINVAL;
+ bp->b_flags |= B_ERROR | B_INVAL;
+ }
+ goto done;
+ }
+
+ /*
+ * If the request crosses EOF, truncate the request.
+ */
+ if (pbn + sz > cs->sc_size) {
+ bp->b_bcount = (cs->sc_size - pbn) *
+ cs->sc_geom.ccg_secsize;
+ }
+ }
bp->b_resid = bp->b_bcount;
OpenPOWER on IntegriCloud