Date: Mon, 9 Dec 2002 13:50:14 -0800 (PST)
From: Nate Lawson <nate@root.org>
To: Yar Tikhiy <yar@FreeBSD.ORG>
Cc: "Kenneth D. Merry" <ken@kdm.org>, freebsd-scsi@FreeBSD.ORG
Subject: Re: {da,sa,...}open bug?
Message-ID: <Pine.BSF.4.21.0212091323240.25027-100000@root.org>
In-Reply-To: <20021208170756.A75509@comp.chem.msu.su>
next in thread | previous in thread | raw e-mail | index | archive | help
On Sun, 8 Dec 2002, Yar Tikhiy wrote:
> On Fri, Dec 06, 2002 at 12:34:01PM -0700, Kenneth D. Merry wrote:
> > cam_periph_acquire() only returns an error when periph == NULL. If, for
> > some wild reason, a locked periph manages to get freed (thus causing
> > cam_periph_acquire() to return CAM_REQ_CMP_ERR), cam_periph_unlock()
> > will panic (NULL pointer deference) when called with a NULL periph.
>
> First, I'd like to point out that freeing a periph doesn't cause a
> pointer to it to become NULL. Therefore, cam_periph_unlock() is
> extremely unlikely to panic since cam_periph_lock(), which in turn
> calls cam_periph_acquire(), has been successful (i.e., periph != NULL)
A little confusing here. What do you mean by "freeing a periph"? If you
mean remove a reference to a periph, that's in cam_periph_release(). It
is always an error to deref a periph pointer after cam_periph_release even
though the poniter may still be valid (based on refcount).
However, you are right in that if cam_periph_lock has succeeded, it is
extremely unlikely a later cam_periph_acquire will fail.
> My general impression is that that NULL check at the beginning of
> cam_periph_acquire() is one of safety belts for unwary programmers
> still left out there. I think it should be changed to something
> like this:
>
> KASSERT(periph != NULL, ("cam_periph_acquire: null periph"));
>
> After this change, it will be OK to unlock a periph on cam_periph_acquire()
> failure (granted someone have added code able to fail to the latter
> function.)
See Justin's email re: acquire first, lock second. In that case, acquire
should continue to return an error since it is first in line in the *open
function and ensures we have a referenced periph, allowing us to always
back state out of that periph if things later fail. Also, I think the
NULL check should be moved inside the splsoftcam to ensure exclusive
access. In the future, we'll use mutex(9) for implementing lock and
acquire.
--- /sys/cam/cam_periph.c 14 Nov 2002 05:35:57 -0000 1.43
+++ /sys/cam/cam_periph.c 9 Dec 2002 21:38:02 -0000
@@ -262,15 +262,17 @@
cam_periph_acquire(struct cam_periph *periph)
{
int s;
+ cam_status status;
- if (periph == NULL)
- return(CAM_REQ_CMP_ERR);
-
+ cam_status = CAM_REQ_CMP;
s = splsoftcam();
- periph->refcount++;
+ if (periph != NULL)
+ periph->refcount++;
+ else
+ status = CAM_REQ_CMP_ERR;
splx(s);
- return(CAM_REQ_CMP);
+ return (status);
}
void
If we reorder things according to Justin's suggestion, then we should do
the obvious thing and always unroll state on all returns.
-Nate
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-scsi" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.4.21.0212091323240.25027-100000>
