From e1aeb288fe0a7c65252982a4f3deab282d031a64 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Mon, 17 Jul 2017 13:51:37 +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 | 54 ++++++++++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/subsys/net/ip/net_context.c b/subsys/net/ip/net_context.c index 137c4f9b73fed3..e09ab0f79b457a 100644 --- a/subsys/net/ip/net_context.c +++ b/subsys/net/ip/net_context.c @@ -689,6 +689,53 @@ int net_context_put(struct net_context *context) return 0; } +/* If local address is not bound, bind it to INADDR_ANY and random port. */ +static int bind_default(struct net_context *context) +{ + sa_family_t family = net_context_get_family(context); + +#if defined(CONFIG_NET_IPV6) + if (family == AF_INET6) { + struct sockaddr_in6 addr6; + + if (net_sin6_ptr(&context->local)->sin6_addr) { + return 0; + } + + addr6.sin6_family = AF_INET6; + memcpy(&addr6.sin6_addr, net_ipv6_unspecified_address(), + sizeof(addr6.sin6_addr)); + addr6.sin6_port = + find_available_port(context, + (struct sockaddr *)&addr6); + + return net_context_bind(context, (struct sockaddr *)&addr6, + sizeof(addr6)); + } +#endif + +#if defined(CONFIG_NET_IPV4) + if (family == AF_INET) { + struct sockaddr_in addr4; + + if (net_sin_ptr(&context->local)->sin_addr) { + return 0; + } + + addr4.sin_family = AF_INET; + addr4.sin_addr.s_addr = INADDR_ANY; + addr4.sin_port = + find_available_port(context, + (struct sockaddr *)&addr4); + + return net_context_bind(context, (struct sockaddr *)&addr4, + sizeof(addr4)); + } +#endif + + return -EINVAL; +} + int net_context_bind(struct net_context *context, const struct sockaddr *addr, socklen_t addrlen) { @@ -1331,8 +1378,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 +1391,11 @@ int net_context_connect(struct net_context *context, return -EBADF; } + ret = bind_default(context); + if (ret) { + return ret; + } + if (addr->family != net_context_get_family(context)) { NET_ASSERT_INFO(addr->family == \ net_context_get_family(context),