Received: by 2002:ac0:a5a6:0:0:0:0:0 with SMTP id m35-v6csp31287imm; Fri, 21 Sep 2018 17:28:16 -0700 (PDT) X-Google-Smtp-Source: ACcGV63RSJgdfD2Ya5IaTHt6eER0uhCK7MwuDwA68TvFyDCDIVA4VDsOIJ4GtsFHqq65+XVb/WzO X-Received: by 2002:a63:ce43:: with SMTP id r3-v6mr110679pgi.439.1537576095981; Fri, 21 Sep 2018 17:28:15 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1537576095; cv=none; d=google.com; s=arc-20160816; b=x4hOCGvzGit5hx3f+0DnJ6XxkVwOLFN9cleUvJrVENLOdUNifpZ6CdsfToMSBu7NX6 HlyZ9PphVgV78UBxTGV6uOwJd2ohNl1b6kVsng8tIt11JwSKNC6egvWCN3Vi9Dkxduhx czF8YyauKPcAL6zGunk6Gxgjk55fIh5F4aAqXLnlD9wKfPEuXs72HfulUmTlZaq4J687 s/eMfLhe7wvXDwDg/6WDiWuFfhscX3Pjn6Pf/R6tM9jkTsD0PcP0iW0bDzpnRuAIPLSc Q1E2vKgmaUPeTJ40D0LNZM84FLaLKTTee8G0EjoLs1fM66JOfxHxKDgy7aEFFTcjYP8n A6Tw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:in-reply-to:subject:message-id:date:cc:to :from:mime-version:content-transfer-encoding:content-disposition; bh=NFCCbIkRBqC/crfUSckOMHHqEBFseM0tPLGVGurI8K8=; b=r2SMo+7Zv7aXXQERTXcRKOqHgjFzdRSx+JWgM107MIlOJjztnUb1OosbWw9t6kIFv0 lrNNThFYoLx4AIgv9ne/pzPDvumifOHDp2yLbfsIp+mQnRWq0+LPGlf1aCDWNGvC36gQ k8HY93AAd4Bc4dlN0Las2XgJIpGQdgdjqzUNETE1UjNBFJrTRBexU1nb+R7gsqyC8jgd hXx4nixmXnStBXBj6I7TyUvzMQSFNo/A7VoDCJ5e/cWO+fOY51cvDFZgvOWUu/edJQIo XOyFRqMJCTqa+LTkkXMVWWAtYxhnCD8EgoIIN9/ghMiaWYiofshmQ/tT6jEgoQoikYza P9FA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id e26-v6si4849616pgb.161.2018.09.21.17.28.00; Fri, 21 Sep 2018 17:28:15 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2391942AbeIVGRQ (ORCPT + 99 others); Sat, 22 Sep 2018 02:17:16 -0400 Received: from shadbolt.e.decadent.org.uk ([88.96.1.126]:44103 "EHLO shadbolt.e.decadent.org.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2391854AbeIVGKn (ORCPT ); Sat, 22 Sep 2018 02:10:43 -0400 Received: from [2a02:8011:400e:2:cbab:f00:c93f:614] (helo=deadeye) by shadbolt.decadent.org.uk with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1g3Vds-0008BP-BX; Sat, 22 Sep 2018 01:19:24 +0100 Received: from ben by deadeye with local (Exim 4.91) (envelope-from ) id 1g3Vdn-0000pw-6Z; Sat, 22 Sep 2018 01:19:19 +0100 Content-Type: text/plain; charset="UTF-8" Content-Disposition: inline Content-Transfer-Encoding: 8bit MIME-Version: 1.0 From: Ben Hutchings To: linux-kernel@vger.kernel.org, stable@vger.kernel.org CC: akpm@linux-foundation.org, "Thomas King" , "David S. Miller" , "Christoph Paasch" , "Eric Dumazet" Date: Sat, 22 Sep 2018 01:15:42 +0100 Message-ID: X-Mailer: LinuxStableQueue (scripts by bwh) Subject: [PATCH 3.16 04/63] net: Set sk_prot_creator when cloning sockets to the right proto In-Reply-To: X-SA-Exim-Connect-IP: 2a02:8011:400e:2:cbab:f00:c93f:614 X-SA-Exim-Mail-From: ben@decadent.org.uk X-SA-Exim-Scanned: No (on shadbolt.decadent.org.uk); SAEximRunCond expanded to false Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 3.16.58-rc1 review patch. If anyone has any objections, please let me know. ------------------ From: Christoph Paasch commit 9d538fa60bad4f7b23193c89e843797a1cf71ef3 upstream. sk->sk_prot and sk->sk_prot_creator can differ when the app uses IPV6_ADDRFORM (transforming an IPv6-socket to an IPv4-one). Which is why sk_prot_creator is there to make sure that sk_prot_free() does the kmem_cache_free() on the right kmem_cache slab. Now, if such a socket gets transformed back to a listening socket (using connect() with AF_UNSPEC) we will allocate an IPv4 tcp_sock through sk_clone_lock() when a new connection comes in. But sk_prot_creator will still point to the IPv6 kmem_cache (as everything got copied in sk_clone_lock()). When freeing, we will thus put this memory back into the IPv6 kmem_cache although it was allocated in the IPv4 cache. I have seen memory corruption happening because of this. With slub-debugging and MEMCG_KMEM enabled this gives the warning "cache_from_obj: Wrong slab cache. TCPv6 but object is from TCP" A C-program to trigger this: void main(void) { int fd = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP); int new_fd, newest_fd, client_fd; struct sockaddr_in6 bind_addr; struct sockaddr_in bind_addr4, client_addr1, client_addr2; struct sockaddr unsp; int val; memset(&bind_addr, 0, sizeof(bind_addr)); bind_addr.sin6_family = AF_INET6; bind_addr.sin6_port = ntohs(42424); memset(&client_addr1, 0, sizeof(client_addr1)); client_addr1.sin_family = AF_INET; client_addr1.sin_port = ntohs(42424); client_addr1.sin_addr.s_addr = inet_addr("127.0.0.1"); memset(&client_addr2, 0, sizeof(client_addr2)); client_addr2.sin_family = AF_INET; client_addr2.sin_port = ntohs(42421); client_addr2.sin_addr.s_addr = inet_addr("127.0.0.1"); memset(&unsp, 0, sizeof(unsp)); unsp.sa_family = AF_UNSPEC; bind(fd, (struct sockaddr *)&bind_addr, sizeof(bind_addr)); listen(fd, 5); client_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); connect(client_fd, (struct sockaddr *)&client_addr1, sizeof(client_addr1)); new_fd = accept(fd, NULL, NULL); close(fd); val = AF_INET; setsockopt(new_fd, SOL_IPV6, IPV6_ADDRFORM, &val, sizeof(val)); connect(new_fd, &unsp, sizeof(unsp)); memset(&bind_addr4, 0, sizeof(bind_addr4)); bind_addr4.sin_family = AF_INET; bind_addr4.sin_port = ntohs(42421); bind(new_fd, (struct sockaddr *)&bind_addr4, sizeof(bind_addr4)); listen(new_fd, 5); client_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); connect(client_fd, (struct sockaddr *)&client_addr2, sizeof(client_addr2)); newest_fd = accept(new_fd, NULL, NULL); close(new_fd); close(client_fd); close(new_fd); } As far as I can see, this bug has been there since the beginning of the git-days. Signed-off-by: Christoph Paasch Reviewed-by: Eric Dumazet Signed-off-by: David S. Miller Cc: Thomas King Signed-off-by: Ben Hutchings --- net/core/sock.c | 2 ++ 1 file changed, 2 insertions(+) --- a/net/core/sock.c +++ b/net/core/sock.c @@ -1512,6 +1512,8 @@ struct sock *sk_clone_lock(const struct sock_copy(newsk, sk); + newsk->sk_prot_creator = sk->sk_prot; + /* SANITY */ get_net(sock_net(newsk)); sk_node_init(&newsk->sk_node);