From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-10.1 required=3.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D43CFC43603 for ; Fri, 20 Dec 2019 14:36:51 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id A3B0121D7E for ; Fri, 20 Dec 2019 14:36:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1576852611; bh=dv+JqRDbCcIOhSLjp+k6A9kZqZ63vaPQJPej8O9jRGk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-ID:From; b=erwIO1Q600uiB7zN62Ey1+FhMEWYDKYyMVTzMBSyhOkzqEyw631OMoFQwMF4dTbzy cH5P+9vZkrDSuKMqHQS5hopVfLq+TqEfgw9p8TrKOVIYCtPnxFGX4fngZcvZWsOt6/ C6Z3gGXmIk5Ji0c9BsRAKuVsiPS+JxzF2G/Vw2fI= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727967AbfLTOgu (ORCPT ); Fri, 20 Dec 2019 09:36:50 -0500 Received: from mail.kernel.org ([198.145.29.99]:38914 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728289AbfLTOer (ORCPT ); Fri, 20 Dec 2019 09:34:47 -0500 Received: from sasha-vm.mshome.net (c-73-47-72-35.hsd1.nh.comcast.net [73.47.72.35]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 16A11222C2; Fri, 20 Dec 2019 14:34:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1576852486; bh=dv+JqRDbCcIOhSLjp+k6A9kZqZ63vaPQJPej8O9jRGk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ES024Ypz8p7oHiA8uPdKQZSDJNeEczr99yIR7QfByeUuio8lD0JhQ0zeOr8sgW584 oAuk0t5QALwqVbvMkkdHTurjDtyrLqAbinVxXzx34OU2oZYU4dUhrQsebwcloLU67G 9I6qWgHdujZmgABdc4l6B1tjup7ln73JaxhK/udg= From: Sasha Levin To: linux-kernel@vger.kernel.org, stable@vger.kernel.org Cc: Marc Dionne , David Howells , Sasha Levin , linux-afs@lists.infradead.org Subject: [PATCH AUTOSEL 4.19 10/34] afs: Fix afs_find_server lookups for ipv4 peers Date: Fri, 20 Dec 2019 09:34:09 -0500 Message-Id: <20191220143433.9922-10-sashal@kernel.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20191220143433.9922-1-sashal@kernel.org> References: <20191220143433.9922-1-sashal@kernel.org> MIME-Version: 1.0 X-stable: review X-Patchwork-Hint: Ignore Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Marc Dionne [ Upstream commit 9bd0160d12370a076e44f8d1320cde9c83f2c647 ] afs_find_server tries to find a server that has an address that matches the transport address of an rxrpc peer. The code assumes that the transport address is always ipv6, with ipv4 represented as ipv4 mapped addresses, but that's not the case. If the transport family is AF_INET, srx->transport.sin6.sin6_addr.s6_addr32[] will be beyond the actual ipv4 address and will always be 0, and all ipv4 addresses will be seen as matching. As a result, the first ipv4 address seen on any server will be considered a match, and the server returned may be the wrong one. One of the consequences is that callbacks received over ipv4 will only be correctly applied for the server that happens to have the first ipv4 address on the fs_addresses4 list. Callbacks over ipv4 from all other servers are dropped, causing the client to serve stale data. This is fixed by looking at the transport family, and comparing ipv4 addresses based on a sockaddr_in structure rather than a sockaddr_in6. Fixes: d2ddc776a458 ("afs: Overhaul volume and server record caching and fileserver rotation") Signed-off-by: Marc Dionne Signed-off-by: David Howells Signed-off-by: Sasha Levin --- fs/afs/server.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/fs/afs/server.c b/fs/afs/server.c index 1d329e6981d51..2c7f6211c3601 100644 --- a/fs/afs/server.c +++ b/fs/afs/server.c @@ -34,18 +34,11 @@ static void afs_dec_servers_outstanding(struct afs_net *net) struct afs_server *afs_find_server(struct afs_net *net, const struct sockaddr_rxrpc *srx) { - const struct sockaddr_in6 *a = &srx->transport.sin6, *b; const struct afs_addr_list *alist; struct afs_server *server = NULL; unsigned int i; - bool ipv6 = true; int seq = 0, diff; - if (srx->transport.sin6.sin6_addr.s6_addr32[0] == 0 || - srx->transport.sin6.sin6_addr.s6_addr32[1] == 0 || - srx->transport.sin6.sin6_addr.s6_addr32[2] == htonl(0xffff)) - ipv6 = false; - rcu_read_lock(); do { @@ -54,7 +47,8 @@ struct afs_server *afs_find_server(struct afs_net *net, server = NULL; read_seqbegin_or_lock(&net->fs_addr_lock, &seq); - if (ipv6) { + if (srx->transport.family == AF_INET6) { + const struct sockaddr_in6 *a = &srx->transport.sin6, *b; hlist_for_each_entry_rcu(server, &net->fs_addresses6, addr6_link) { alist = rcu_dereference(server->addresses); for (i = alist->nr_ipv4; i < alist->nr_addrs; i++) { @@ -70,15 +64,16 @@ struct afs_server *afs_find_server(struct afs_net *net, } } } else { + const struct sockaddr_in *a = &srx->transport.sin, *b; hlist_for_each_entry_rcu(server, &net->fs_addresses4, addr4_link) { alist = rcu_dereference(server->addresses); for (i = 0; i < alist->nr_ipv4; i++) { - b = &alist->addrs[i].transport.sin6; - diff = ((u16 __force)a->sin6_port - - (u16 __force)b->sin6_port); + b = &alist->addrs[i].transport.sin; + diff = ((u16 __force)a->sin_port - + (u16 __force)b->sin_port); if (diff == 0) - diff = ((u32 __force)a->sin6_addr.s6_addr32[3] - - (u32 __force)b->sin6_addr.s6_addr32[3]); + diff = ((u32 __force)a->sin_addr.s_addr - + (u32 __force)b->sin_addr.s_addr); if (diff == 0) goto found; } -- 2.20.1