On Wed, Mar 28, 2018 at 10:23:04AM -0700, Roland Dreier wrote: > From: Roland Dreier <roland@xxxxxxxxxxxxxxx> > > If userspace passes a sockaddr with sa_family == AF_IB to the ucma join IP > multicast command, the kernel will memcpy() past the end of the cmd.addr buffer, > because sockaddr_ib is bigger than sockaddr_in6. > > Fix this by returning EINVAL if the addr_size we get back is bigger than the > address buffers we're copying between. > > Reported-and-tested-by: syzbot+6800425d54ed3ed8135d@xxxxxxxxxxxxxxxxxxxxxxxxx > Signed-off-by: Roland Dreier <roland@xxxxxxxxxxxxxxx> > #syz test: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git master > > drivers/infiniband/core/ucma.c | 3 ++- > 1 file changed, 2 insertions(+), 1 deletion(-) > > diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c > index e5a1e7d81326..7684fd54318a 100644 > +++ b/drivers/infiniband/core/ucma.c > @@ -1427,7 +1427,8 @@ static ssize_t ucma_join_ip_multicast(struct ucma_file *file, > join_cmd.uid = cmd.uid; > join_cmd.id = cmd.id; > join_cmd.addr_size = rdma_addr_size((struct sockaddr *) &cmd.addr); Ugh, this is a systemic mistake. Looks like every place in the uapi that uses struct sockaddr_in6 has this bug. Eg look at ucma_bind_ip I think I'd prefer to fix this via revising the API to size_t rdma_addr_size_in6(struct sockaddr_in6 *addr) size_t rdma_addr_size_kss(struct struct __kernel_sockaddr_storage *addr) And getting rid of all the dangerous (struct sockaddr *) casting at all the various call sites. The function will return 0 if the given storage is too small for the requested AF, or the AF is not supported. Jason -- To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html