From b8bf80c68cd0434c469dd4b46469be739ddecc55 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Thu, 13 Jul 2017 21:28:18 +0300 Subject: [PATCH] net: context: connect: Make sure local end is bound before connecting Introduce net_context_bind_default() to ensure that local address is set for context if not yet (via explict bind() call). This fixes dereferences of NULL pointer to local address which was exposed when MMU was enabled for qemu_x86. Signed-off-by: Paul Sokolovsky --- subsys/net/ip/net_context.c | 50 ++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/subsys/net/ip/net_context.c b/subsys/net/ip/net_context.c index 137c4f9b73fed..dd0eff9f84191 100644 --- a/subsys/net/ip/net_context.c +++ b/subsys/net/ip/net_context.c @@ -689,6 +689,49 @@ int net_context_put(struct net_context *context) return 0; } +static int bind_default(struct net_context *context, + const struct sockaddr *dest_addr) +{ + struct net_if *iface = net_if_get_default(); + + if (!iface) { + NET_ERR("No default interface to bind"); + return -EADDRNOTAVAIL; + } + +#if defined(CONFIG_NET_IPV6) + if (dest_addr->family == AF_INET6) { + if (net_sin6_ptr(&context->local)->sin6_addr) { + return 0; + } + + net_context_set_iface(context, iface); + net_sin6_ptr(&context->local)->sin6_family = AF_INET6; + net_sin6_ptr(&context->local)->sin6_addr = + (struct in6_addr *)net_ipv6_unspecified_address(); + + return 0; + } +#endif + +#if defined(CONFIG_NET_IPV4) + if (dest_addr->family == AF_INET) { + if (net_sin_ptr(&context->local)->sin_addr) { + return 0; + } + + net_context_set_iface(context, iface); + net_sin_ptr(&context->local)->sin_family = AF_INET; + net_sin_ptr(&context->local)->sin_addr = + (struct in_addr *)net_ipv4_unspecified_address(); + + return 0; + } +#endif + + return -EINVAL; +} + int net_context_bind(struct net_context *context, const struct sockaddr *addr, socklen_t addrlen) { @@ -1331,8 +1374,8 @@ int net_context_connect(struct net_context *context, struct sockaddr *laddr = NULL; struct sockaddr local_addr; u16_t lport, rport; - int ret; #endif + int ret; NET_ASSERT(addr); NET_ASSERT(PART_OF_ARRAY(contexts, context)); @@ -1344,6 +1387,11 @@ int net_context_connect(struct net_context *context, return -EBADF; } + ret = bind_default(context, addr); + if (ret) { + return ret; + } + if (addr->family != net_context_get_family(context)) { NET_ASSERT_INFO(addr->family == \ net_context_get_family(context),