From: Ka-Cheong Poon Date: Mon, 18 Dec 2017 15:45:18 +0000 (-0800) Subject: rds: Calling getsockname() on unbounded socket generates seg fault X-Git-Tag: v4.1.12-124.31.3~1224 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=56c2ca2103a914455c166f363b5d7d28551b9cbb;p=users%2Fjedix%2Flinux-maple.git rds: Calling getsockname() on unbounded socket generates seg fault If a socket is not yet bound, calling getsockname() should return an unspecified address with family AF_UNSPEC as an RDS socket can be bound to either an IPv4 or an IPv6 address. Hence returning either family is incorrect. Currently, the returned address is set to an unspecified address with family AF_INET6. If the passed in buffer is smaller than sizeof(struct sockaddr_in6), the app may get a segmentation fault error. This is similar to passing a buffer smaller than sizeof(struct sockaddr_in) before the IPv6 changes. Orabug: 27463484 Signed-off-by: Ka-Cheong Poon Reviewed-by: Darren Kenny Reviewed-by: HÃ¥kon Bugge --- diff --git a/net/rds/af_rds.c b/net/rds/af_rds.c index c7b30e619bab..54be1fb5e2d7 100644 --- a/net/rds/af_rds.c +++ b/net/rds/af_rds.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2017 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2018 Oracle and/or its affiliates. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -173,6 +173,17 @@ static int rds_getname(struct socket *sock, struct sockaddr *uaddr, *uaddr_len = sizeof(*sin6); } } else { + /* If socket is not yet bound, set the return address family + * to be AF_UNSPEC (value 0) and the address size to be that + * of an IPv4 address. + */ + if (ipv6_addr_any(&rs->rs_bound_addr)) { + sin = (struct sockaddr_in *)uaddr; + memset(sin, 0, sizeof(*sin)); + sin->sin_family = AF_UNSPEC; + *uaddr_len = sizeof(*sin); + return 0; + } if (ipv6_addr_v4mapped(&rs->rs_bound_addr)) { sin = (struct sockaddr_in *)uaddr; memset(sin->sin_zero, 0, sizeof(sin->sin_zero));