summaryrefslogtreecommitdiffstats
path: root/sys/dev/amr
diff options
context:
space:
mode:
authorscottl <scottl@FreeBSD.org>2005-03-13 06:25:53 +0000
committerscottl <scottl@FreeBSD.org>2005-03-13 06:25:53 +0000
commit4d55eb47b436980a5b3c335bbc3fe3cb7036fd9e (patch)
treeeeb43e7ec386c99b1f31717e34cc748a1f7e0b1d /sys/dev/amr
parent7da6777fea5bf552abf39c845c9a9dfb4d14033b (diff)
downloadFreeBSD-src-4d55eb47b436980a5b3c335bbc3fe3cb7036fd9e.zip
FreeBSD-src-4d55eb47b436980a5b3c335bbc3fe3cb7036fd9e.tar.gz
Fix a null pointer de-ref when passthrough ioctls are issued. This
involves some code shuffle to avoid locking problems. MFC After: 3 days
Diffstat (limited to 'sys/dev/amr')
-rw-r--r--sys/dev/amr/amr.c19
1 files changed, 11 insertions, 8 deletions
diff --git a/sys/dev/amr/amr.c b/sys/dev/amr/amr.c
index 1600020..4fe9ba7 100644
--- a/sys/dev/amr/amr.c
+++ b/sys/dev/amr/amr.c
@@ -471,11 +471,7 @@ amr_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int32_t flag, d_thread_t *
/* handle inbound data buffer */
if (au_length != 0 && au_cmd[0] != 0x06) {
- if ((dp = malloc(au_length, M_DEVBUF, M_WAITOK)) == NULL)
- return(ENOMEM);
-
- if ((ap = malloc(sizeof(struct amr_passthrough ), M_DEVBUF, M_WAITOK)) == NULL)
- return(ENOMEM);
+ dp = malloc(au_length, M_DEVBUF, M_WAITOK|M_ZERO);
if ((error = copyin(au_buffer, dp, au_length)) != 0) {
free(dp, M_DEVBUF);
@@ -484,6 +480,10 @@ amr_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int32_t flag, d_thread_t *
debug(2, "copyin %ld bytes from %p -> %p", au_length, au_buffer, dp);
}
+ /* Allocate this now before the mutex gets held */
+ if (au_cmd[0] == AMR_CMD_PASS)
+ ap = malloc(sizeof(struct amr_passthrough), M_DEVBUF, M_WAITOK|M_ZERO);
+
mtx_lock(&sc->amr_io_lock);
if ((ac = amr_alloccmd(sc)) == NULL) {
error = ENOMEM;
@@ -563,10 +563,13 @@ out:
* At this point, we know that there is a lock held and that these
* objects have been allocated.
*/
- free(dp, M_DEVBUF);
- free(ap, M_DEVBUF);
- amr_releasecmd(ac);
+ if (ac != NULL)
+ amr_releasecmd(ac);
mtx_unlock(&sc->amr_io_lock);
+ if (dp != NULL)
+ free(dp, M_DEVBUF);
+ if (ap != NULL)
+ free(ap, M_DEVBUF);
return(error);
}
OpenPOWER on IntegriCloud