Received: by 2002:a25:4158:0:0:0:0:0 with SMTP id o85csp952919yba; Wed, 24 Apr 2019 12:20:55 -0700 (PDT) X-Google-Smtp-Source: APXvYqwNOC/w5lEurDkCRTIEFLEBx/cuH5apik8wub5Jyz51UMzmBPsGE8Vv8UlH29YRa32uMlUp X-Received: by 2002:a65:648c:: with SMTP id e12mr32358982pgv.346.1556133655317; Wed, 24 Apr 2019 12:20:55 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1556133655; cv=none; d=google.com; s=arc-20160816; b=g/aCunCX5ucdVA5O3RnH44LN8x5mh1FEfFIllKNj5GM/qYABNmWJSG7QseR6Aecm6S tvulgb/Z6vU8x0Ba8Fc63maJCCpeDcQoK0N7OF6nleayJHUwO2jsjkiH/DoA7asdke1Y 9BZxRiBJooVekYZY4gylfFeAAH9sDrJFzY5Q7ShB0rxGb28UTocT8sKrQWwaMx5ZjuYn h05I+TCqrBtiN9xf9xvnZ5WhmiemwLk3WQb2opwC9z0DNyOCI1GZXpa9DvScvMNoikXK i2cHBJyDGqSKHbUbwOESfRRClfQ3p+0gFYwoG4cOg5D1qD6pvzXENaY51RoRo/yF7wnI foVA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=lJQkIIzLau5HlpvoaCLIoExkDAFmguq39Bbj42dAWto=; b=DRn+EqGuboYvKFUrDoxhwiYx1nr4aw8Z1tPZaj8E0qdmj1JEpQ5eYNemc+GMM88D8F id1OmiQqKTBIwmQjG5ZNC9ypRIQ4eWCBWHbmKi7JKAh8LkNAhkbAbCysmEsoVVZHLdZh yS1BqBuZaNOzYa9FrZD6mzaktCklFZp354XavZ1cgKLtBEX8YGzlqr6AJBN15jkoFBbM wid9ko8Un07Ma7iy1u8fnzrK9iwoBVQ2FJwy8F4clkgjYewImEibJx8sp0KL75fIDsV3 brl0RY/lbrmZboBSYFKagr2lfgY+whPoFd0z3CCqVfdxZKaQxoVo4zoD0yGbN1XpsSvJ 7+hw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=H2hHyoVt; 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; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id b2si19239117pgn.93.2019.04.24.12.20.39; Wed, 24 Apr 2019 12:20:55 -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; dkim=pass header.i=@kernel.org header.s=default header.b=H2hHyoVt; 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; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731127AbfDXOen (ORCPT + 99 others); Wed, 24 Apr 2019 10:34:43 -0400 Received: from mail.kernel.org ([198.145.29.99]:38570 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731105AbfDXOem (ORCPT ); Wed, 24 Apr 2019 10:34:42 -0400 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 BAEEB218FE; Wed, 24 Apr 2019 14:34:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1556116481; bh=sMa0LKSd7ygF4I+5+aKVKoakBEUuxOhlxlH0O8rOr2s=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=H2hHyoVtturDXEaV+ka1oQ2FTfCCVcmYDmsN+/G5NQMXFDFCP873bfhyqrZpJGYDo Z3ay8vOJqwkncKO8f23eJpyfF5dgL1oSIN2Ani12YCM7y1DnEIZ/k3JNXd6rC3eGbO ypcf+dpNdRaMBDU7KwVwajPxAgMnUfTODpGdbsqA= From: Sasha Levin To: linux-kernel@vger.kernel.org, stable@vger.kernel.org Cc: Jesper Dangaard Brouer , Alexei Starovoitov , Sasha Levin , netdev@vger.kernel.org, xdp-newbies@vger.kernel.org, bpf@vger.kernel.org Subject: [PATCH AUTOSEL 5.0 23/66] xdp: fix cpumap redirect SKB creation bug Date: Wed, 24 Apr 2019 10:32:57 -0400 Message-Id: <20190424143341.27665-23-sashal@kernel.org> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190424143341.27665-1-sashal@kernel.org> References: <20190424143341.27665-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: Jesper Dangaard Brouer [ Upstream commit 676e4a6fe703f2dae699ee9d56f14516f9ada4ea ] We want to avoid leaking pointer info from xdp_frame (that is placed in top of frame) like commit 6dfb970d3dbd ("xdp: avoid leaking info stored in frame data on page reuse"), and followup commit 97e19cce05e5 ("bpf: reserve xdp_frame size in xdp headroom") that reserve this headroom. These changes also affected how cpumap constructed SKBs, as xdpf->headroom size changed, the skb data starting point were in-effect shifted with 32 bytes (sizeof xdp_frame). This was still okay, as the cpumap frame_size calculation also included xdpf->headroom which were reduced by same amount. A bug was introduced in commit 77ea5f4cbe20 ("bpf/cpumap: make sure frame_size for build_skb is aligned if headroom isn't"), where the xdpf->headroom became part of the SKB_DATA_ALIGN rounding up. This round-up to find the frame_size is in principle still correct as it does not exceed the 2048 bytes frame_size (which is max for ixgbe and i40e), but the 32 bytes offset of pkt_data_start puts this over the 2048 bytes limit. This cause skb_shared_info to spill into next frame. It is a little hard to trigger, as the SKB need to use above 15 skb_shinfo->frags[] as far as I calculate. This does happen in practise for TCP streams when skb_try_coalesce() kicks in. KASAN can be used to detect these wrong memory accesses, I've seen: BUG: KASAN: use-after-free in skb_try_coalesce+0x3cb/0x760 BUG: KASAN: wild-memory-access in skb_release_data+0xe2/0x250 Driver veth also construct a SKB from xdp_frame in this way, but is not affected, as it doesn't reserve/deduct the room (used by xdp_frame) from the SKB headroom. Instead is clears the pointers via xdp_scrub_frame(), and allows SKB to use this area. The fix in this patch is to do like veth and instead allow SKB to (re)use the area occupied by xdp_frame, by clearing via xdp_scrub_frame(). (This does kill the idea of the SKB being able to access (mem) info from this area, but I guess it was a bad idea anyhow, and it was already killed by the veth changes.) Fixes: 77ea5f4cbe20 ("bpf/cpumap: make sure frame_size for build_skb is aligned if headroom isn't") Signed-off-by: Jesper Dangaard Brouer Signed-off-by: Alexei Starovoitov Signed-off-by: Sasha Levin (Microsoft) --- kernel/bpf/cpumap.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/kernel/bpf/cpumap.c b/kernel/bpf/cpumap.c index 8974b3755670..3c18260403dd 100644 --- a/kernel/bpf/cpumap.c +++ b/kernel/bpf/cpumap.c @@ -162,10 +162,14 @@ static void cpu_map_kthread_stop(struct work_struct *work) static struct sk_buff *cpu_map_build_skb(struct bpf_cpu_map_entry *rcpu, struct xdp_frame *xdpf) { + unsigned int hard_start_headroom; unsigned int frame_size; void *pkt_data_start; struct sk_buff *skb; + /* Part of headroom was reserved to xdpf */ + hard_start_headroom = sizeof(struct xdp_frame) + xdpf->headroom; + /* build_skb need to place skb_shared_info after SKB end, and * also want to know the memory "truesize". Thus, need to * know the memory frame size backing xdp_buff. @@ -183,15 +187,15 @@ static struct sk_buff *cpu_map_build_skb(struct bpf_cpu_map_entry *rcpu, * is not at a fixed memory location, with mixed length * packets, which is bad for cache-line hotness. */ - frame_size = SKB_DATA_ALIGN(xdpf->len + xdpf->headroom) + + frame_size = SKB_DATA_ALIGN(xdpf->len + hard_start_headroom) + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); - pkt_data_start = xdpf->data - xdpf->headroom; + pkt_data_start = xdpf->data - hard_start_headroom; skb = build_skb(pkt_data_start, frame_size); if (!skb) return NULL; - skb_reserve(skb, xdpf->headroom); + skb_reserve(skb, hard_start_headroom); __skb_put(skb, xdpf->len); if (xdpf->metasize) skb_metadata_set(skb, xdpf->metasize); @@ -205,6 +209,9 @@ static struct sk_buff *cpu_map_build_skb(struct bpf_cpu_map_entry *rcpu, * - RX ring dev queue index (skb_record_rx_queue) */ + /* Allow SKB to reuse area used by xdp_frame */ + xdp_scrub_frame(xdpf); + return skb; } -- 2.19.1