diff options
author | alc <alc@FreeBSD.org> | 2002-05-09 02:30:41 +0000 |
---|---|---|
committer | alc <alc@FreeBSD.org> | 2002-05-09 02:30:41 +0000 |
commit | eff7d935338f3a558b05c829782f6205c4912c65 (patch) | |
tree | b17dd197ca2c975298d9ef4adb1530ee6962951f /sys | |
parent | 928dd0df4b092e9cafb77476c7cb8f238409e606 (diff) | |
download | FreeBSD-src-eff7d935338f3a558b05c829782f6205c4912c65.zip FreeBSD-src-eff7d935338f3a558b05c829782f6205c4912c65.tar.gz |
o Correct an error made in revision 1.65: In readv(), if uap->iovcnt is
out-of-range, drop the file reference before returning. (This error
also exists in the RELENG_4 branch.)
o Eliminate the acquisition and release of Giant in readv()
now that malloc() and free() are callable without Giant.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/kern/sys_generic.c | 15 |
1 files changed, 6 insertions, 9 deletions
diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c index 66ee891..f3352b9 100644 --- a/sys/kern/sys_generic.c +++ b/sys/kern/sys_generic.c @@ -232,29 +232,28 @@ readv(td, uap) struct iovec *iov; struct iovec *needfree; struct iovec aiov[UIO_SMALLIOV]; - long i, cnt, error = 0; + long i, cnt; + int error; u_int iovlen; #ifdef KTRACE struct iovec *ktriov = NULL; struct uio ktruio; #endif - mtx_lock(&Giant); if ((error = fget_read(td, uap->fd, &fp)) != 0) - goto done2; + return (error); + needfree = NULL; /* note: can't use iovlen until iovcnt is validated */ iovlen = uap->iovcnt * sizeof (struct iovec); if (uap->iovcnt > UIO_SMALLIOV) { if (uap->iovcnt > UIO_MAXIOV) { error = EINVAL; - goto done2; + goto done; } MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK); needfree = iov; - } else { + } else iov = aiov; - needfree = NULL; - } auio.uio_iov = iov; auio.uio_iovcnt = uap->iovcnt; auio.uio_rw = UIO_READ; @@ -305,8 +304,6 @@ done: fdrop(fp, td); if (needfree) FREE(needfree, M_IOV); -done2: - mtx_unlock(&Giant); return (error); } |