diff options
author | mjg <mjg@FreeBSD.org> | 2013-05-21 21:58:00 +0000 |
---|---|---|
committer | mjg <mjg@FreeBSD.org> | 2013-05-21 21:58:00 +0000 |
commit | 4072f856ebfac2850f3b1853673d9ba2d85ce1f2 (patch) | |
tree | 89329e28bece418bdba9373f34c25db5beac15b7 /sys/kern/uipc_usrreq.c | |
parent | 0e6ababbb2dcf9f1dd73a40620f02069fb32297b (diff) | |
download | FreeBSD-src-4072f856ebfac2850f3b1853673d9ba2d85ce1f2.zip FreeBSD-src-4072f856ebfac2850f3b1853673d9ba2d85ce1f2.tar.gz |
passing fd over unix socket: fix a corner case where caller
wants to pass no descriptors.
Previously the kernel would leak memory and try to free a potentially
arbitrary pointer.
Reviewed by: pjd
Diffstat (limited to 'sys/kern/uipc_usrreq.c')
-rw-r--r-- | sys/kern/uipc_usrreq.c | 9 |
1 files changed, 8 insertions, 1 deletions
diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c index 33e72e9..0961e6c 100644 --- a/sys/kern/uipc_usrreq.c +++ b/sys/kern/uipc_usrreq.c @@ -1686,6 +1686,8 @@ unp_freerights(struct filedescent **fdep, int fdcount) struct file *fp; int i; + if (fdcount == 0) + return; for (i = 0; i < fdcount; i++) { fp = fdep[i]->fde_file; filecaps_free(&fdep[i]->fde_caps); @@ -1768,7 +1770,8 @@ unp_externalize(struct mbuf *control, struct mbuf **controlp, int flags) unp_externalize_fp(fde->fde_file); } FILEDESC_XUNLOCK(fdesc); - free(fdep[0], M_FILECAPS); + if (newfds != 0) + free(fdep[0], M_FILECAPS); } else { /* We can just copy anything else across. */ if (error || controlp == NULL) @@ -1925,6 +1928,10 @@ unp_internalize(struct mbuf **controlp, struct thread *td) error = E2BIG; goto out; } + if (oldfds == 0) { + FILEDESC_SUNLOCK(fdesc); + break; + } fdp = data; fdep = (struct filedescent **) CMSG_DATA(mtod(*controlp, struct cmsghdr *)); |