diff options
author | scottl <scottl@FreeBSD.org> | 2005-03-13 06:25:53 +0000 |
---|---|---|
committer | scottl <scottl@FreeBSD.org> | 2005-03-13 06:25:53 +0000 |
commit | 4d55eb47b436980a5b3c335bbc3fe3cb7036fd9e (patch) | |
tree | eeb43e7ec386c99b1f31717e34cc748a1f7e0b1d /sys/dev/amr | |
parent | 7da6777fea5bf552abf39c845c9a9dfb4d14033b (diff) | |
download | FreeBSD-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.c | 19 |
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); } |