diff options
author | Mark Johnston <markj@FreeBSD.org> | 2021-05-03 16:51:04 +0000 |
---|---|---|
committer | Mark Johnston <markj@FreeBSD.org> | 2021-05-17 17:43:07 +0000 |
commit | 1e066db6cdad4f3d4934bad487db68d3a7872727 (patch) | |
tree | d583d412be812686ef680fe130aea7055d029c43 /sys/ofed | |
parent | 3eebc6234b007e467d58f570e560c08385dd2319 (diff) | |
download | src-1e066db6cdad4f3d4934bad487db68d3a7872727.tar.gz src-1e066db6cdad4f3d4934bad487db68d3a7872727.zip |
Add missing sockaddr length and family validation to various protocols
Several protocol methods take a sockaddr as input. In some cases the
sockaddr lengths were not being validated, or were validated after some
out-of-bounds accesses could occur. Add requisite checking to various
protocol entry points, and convert some existing checks to assertions
where appropriate.
Reported by: syzkaller+KASAN
Reviewed by: tuexen, melifaro
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D29519
(cherry picked from commit f161d294b92732df6254a89f393ab24999e122bf)
Diffstat (limited to 'sys/ofed')
-rw-r--r-- | sys/ofed/drivers/infiniband/ulp/sdp/sdp_main.c | 23 |
1 files changed, 19 insertions, 4 deletions
diff --git a/sys/ofed/drivers/infiniband/ulp/sdp/sdp_main.c b/sys/ofed/drivers/infiniband/ulp/sdp/sdp_main.c index e7ae4e03365e..a38bdfcbed59 100644 --- a/sys/ofed/drivers/infiniband/ulp/sdp/sdp_main.c +++ b/sys/ofed/drivers/infiniband/ulp/sdp/sdp_main.c @@ -519,9 +519,9 @@ sdp_bind(struct socket *so, struct sockaddr *nam, struct thread *td) struct sockaddr_in *sin; sin = (struct sockaddr_in *)nam; - if (nam->sa_len != sizeof (*sin)) - return (EINVAL); if (sin->sin_family != AF_INET) + return (EAFNOSUPPORT); + if (nam->sa_len != sizeof(*sin)) return (EINVAL); if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) return (EAFNOSUPPORT); @@ -617,10 +617,10 @@ sdp_connect(struct socket *so, struct sockaddr *nam, struct thread *td) struct sockaddr_in *sin; sin = (struct sockaddr_in *)nam; - if (nam->sa_len != sizeof (*sin)) + if (nam->sa_len != sizeof(*sin)) return (EINVAL); if (sin->sin_family != AF_INET) - return (EINVAL); + return (EAFNOSUPPORT); if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) return (EAFNOSUPPORT); if ((error = prison_remote_ip4(td->td_ucred, &sin->sin_addr)) != 0) @@ -932,6 +932,21 @@ sdp_send(struct socket *so, int flags, struct mbuf *m, int error; int cnt; + if (nam != NULL) { + if (nam->sa_family != AF_INET) { + if (control) + m_freem(control); + m_freem(m); + return (EAFNOSUPPORT); + } + if (nam->sa_len != sizeof(struct sockaddr_in)) { + if (control) + m_freem(control); + m_freem(m); + return (EINVAL); + } + } + error = 0; ssk = sdp_sk(so); KASSERT(m->m_flags & M_PKTHDR, |