Received: by 2002:ac0:a582:0:0:0:0:0 with SMTP id m2-v6csp3940680imm; Mon, 8 Oct 2018 12:02:36 -0700 (PDT) X-Google-Smtp-Source: ACcGV60JVLBuoYvoRc93RxIQwUBLupgO7IGYcQOpd/edRxYtsIFvRhp/QqU84JSF1tLDac7svHWU X-Received: by 2002:a63:5558:: with SMTP id f24-v6mr22894580pgm.37.1539025356459; Mon, 08 Oct 2018 12:02:36 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1539025356; cv=none; d=google.com; s=arc-20160816; b=oLAHfZkSCuPkmevbjN63W/GqVdqTLyoTY2kacWTsu6htzVXONXI+98d1bu6DiMHD8J GnrbEYnfHqnmE8PpnByuBYGT5KsJ23hRenBkriMJ3HlnMQIH+Jn4BtSH6u7IP+lalc0t sWYo6AWDqSVb8bnmpFGuIUU2vvK89Im5tdDYcfB1Gjx3WyUMtW++Ea6O8upPsbkCVeT9 1L4q9L4bdiJWEuumxlFU3BlMXzMpzoYrqv+/njqrc/r5LPjzDYaKoFft5Iojx9bkQzU1 C1oCZ1pZj/oOsgDcmJrmymVxdHxMnHXJWM3r4EZ71ytWT9PK1WLmicNC6GA6pnJ2hJQE ma9A== 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 :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=0MRZDAdokzXaVClcgS+DIrRr9eQWDOWNxn3zRwv96es=; b=fq4aKfZlk404c496IOYanl2BT9QRXFQgMVsasHKKrcqaHGevETybtG4f/2BBrumgls Fr2jh5UCH/nh9A8bt2tlHaIZgXiguCc3lyCKnPlFKseFfSIZRPUbWxLFMlGDCVP/y5AE 5w4Wc9ip9ruzkEAP+456UFiQPPY6EhZgq4ReS0YlgGrL2Hcpvi8BwbsBCSB7v0SAHxAl v+5GaXHpBWerkJoO8Doqa1TjRQdIp3Nag7sTunQer3GD/4Rji7AqT4EpumOKs9Jqjwhc rmQvsWf1o2O+ekOLEf5cyA2XNFeD6PG8Zzki6dUW9QGdnMpeASHBEVndvl2/A1b+IR1X Lj0w== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=SJ4gjIdQ; 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 j13-v6si17016233pfn.288.2018.10.08.12.02.21; Mon, 08 Oct 2018 12:02:36 -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=SJ4gjIdQ; 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 S1731390AbeJICAX (ORCPT + 99 others); Mon, 8 Oct 2018 22:00:23 -0400 Received: from mail.kernel.org ([198.145.29.99]:49028 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730764AbeJICAX (ORCPT ); Mon, 8 Oct 2018 22:00:23 -0400 Received: from localhost (ip-213-127-77-176.ip.prioritytelecom.net [213.127.77.176]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 931CB204FD; Mon, 8 Oct 2018 18:47:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1539024436; bh=h8ccCx1vyp0/9iC3KVBX62hVtbcwjKAVYIL0sx5z01E=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=SJ4gjIdQ0pwjDFFWlHOx5nsXfkQ1aKVguo1Y77hiVIOhMOiXUq+V3v0tAjGqf5a5I FrCQpPnU4hV0+UAxMKDJ19sqsSPlshXcAwgWQLKwmW5HXf0dCvIH+/yVg5H4wXZLF8 U9uaJGYo0iolJfs/3Hyq1vHqy0Cu2gm++/dUZ5Eg= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, John Fastabend , Daniel Borkmann , Sasha Levin Subject: [PATCH 4.18 014/168] bpf: sockmap, decrement copied count correctly in redirect error case Date: Mon, 8 Oct 2018 20:29:54 +0200 Message-Id: <20181008175620.579835286@linuxfoundation.org> X-Mailer: git-send-email 2.19.0 In-Reply-To: <20181008175620.043587728@linuxfoundation.org> References: <20181008175620.043587728@linuxfoundation.org> User-Agent: quilt/0.65 X-stable: review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 4.18-stable review patch. If anyone has any objections, please let me know. ------------------ From: John Fastabend [ Upstream commit 501ca81760c204ec59b73e4a00bee5971fc0f1b1 ] Currently, when a redirect occurs in sockmap and an error occurs in the redirect call we unwind the scatterlist once in the error path of bpf_tcp_sendmsg_do_redirect() and then again in sendmsg(). Then in the error path of sendmsg we decrement the copied count by the send size. However, its possible we partially sent data before the error was generated. This can happen if do_tcp_sendpages() partially sends the scatterlist before encountering a memory pressure error. If this happens we need to decrement the copied value (the value tracking how many bytes were actually sent to TCP stack) by the number of remaining bytes _not_ the entire send size. Otherwise we risk confusing userspace. Also we don't need two calls to free the scatterlist one is good enough. So remove the one in bpf_tcp_sendmsg_do_redirect() and then properly reduce copied by the number of remaining bytes which may in fact be the entire send size if no bytes were sent. To do this use bool to indicate if free_start_sg() should do mem accounting or not. Signed-off-by: John Fastabend Signed-off-by: Daniel Borkmann Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- kernel/bpf/sockmap.c | 45 ++++++++++++++++++++++----------------------- 1 file changed, 22 insertions(+), 23 deletions(-) --- a/kernel/bpf/sockmap.c +++ b/kernel/bpf/sockmap.c @@ -236,7 +236,7 @@ static int bpf_tcp_init(struct sock *sk) } static void smap_release_sock(struct smap_psock *psock, struct sock *sock); -static int free_start_sg(struct sock *sk, struct sk_msg_buff *md); +static int free_start_sg(struct sock *sk, struct sk_msg_buff *md, bool charge); static void bpf_tcp_release(struct sock *sk) { @@ -248,7 +248,7 @@ static void bpf_tcp_release(struct sock goto out; if (psock->cork) { - free_start_sg(psock->sock, psock->cork); + free_start_sg(psock->sock, psock->cork, true); kfree(psock->cork); psock->cork = NULL; } @@ -330,14 +330,14 @@ static void bpf_tcp_close(struct sock *s close_fun = psock->save_close; if (psock->cork) { - free_start_sg(psock->sock, psock->cork); + free_start_sg(psock->sock, psock->cork, true); kfree(psock->cork); psock->cork = NULL; } list_for_each_entry_safe(md, mtmp, &psock->ingress, list) { list_del(&md->list); - free_start_sg(psock->sock, md); + free_start_sg(psock->sock, md, true); kfree(md); } @@ -570,14 +570,16 @@ static void free_bytes_sg(struct sock *s md->sg_start = i; } -static int free_sg(struct sock *sk, int start, struct sk_msg_buff *md) +static int free_sg(struct sock *sk, int start, + struct sk_msg_buff *md, bool charge) { struct scatterlist *sg = md->sg_data; int i = start, free = 0; while (sg[i].length) { free += sg[i].length; - sk_mem_uncharge(sk, sg[i].length); + if (charge) + sk_mem_uncharge(sk, sg[i].length); if (!md->skb) put_page(sg_page(&sg[i])); sg[i].length = 0; @@ -594,9 +596,9 @@ static int free_sg(struct sock *sk, int return free; } -static int free_start_sg(struct sock *sk, struct sk_msg_buff *md) +static int free_start_sg(struct sock *sk, struct sk_msg_buff *md, bool charge) { - int free = free_sg(sk, md->sg_start, md); + int free = free_sg(sk, md->sg_start, md, charge); md->sg_start = md->sg_end; return free; @@ -604,7 +606,7 @@ static int free_start_sg(struct sock *sk static int free_curr_sg(struct sock *sk, struct sk_msg_buff *md) { - return free_sg(sk, md->sg_curr, md); + return free_sg(sk, md->sg_curr, md, true); } static int bpf_map_msg_verdict(int _rc, struct sk_msg_buff *md) @@ -718,7 +720,7 @@ static int bpf_tcp_ingress(struct sock * list_add_tail(&r->list, &psock->ingress); sk->sk_data_ready(sk); } else { - free_start_sg(sk, r); + free_start_sg(sk, r, true); kfree(r); } @@ -755,14 +757,10 @@ static int bpf_tcp_sendmsg_do_redirect(s release_sock(sk); } smap_release_sock(psock, sk); - if (unlikely(err)) - goto out; - return 0; + return err; out_rcu: rcu_read_unlock(); -out: - free_bytes_sg(NULL, send, md, false); - return err; + return 0; } static inline void bpf_md_init(struct smap_psock *psock) @@ -825,7 +823,7 @@ more_data: case __SK_PASS: err = bpf_tcp_push(sk, send, m, flags, true); if (unlikely(err)) { - *copied -= free_start_sg(sk, m); + *copied -= free_start_sg(sk, m, true); break; } @@ -848,16 +846,17 @@ more_data: lock_sock(sk); if (unlikely(err < 0)) { - free_start_sg(sk, m); + int free = free_start_sg(sk, m, false); + psock->sg_size = 0; if (!cork) - *copied -= send; + *copied -= free; } else { psock->sg_size -= send; } if (cork) { - free_start_sg(sk, m); + free_start_sg(sk, m, true); psock->sg_size = 0; kfree(m); m = NULL; @@ -1124,7 +1123,7 @@ wait_for_memory: err = sk_stream_wait_memory(sk, &timeo); if (err) { if (m && m != psock->cork) - free_start_sg(sk, m); + free_start_sg(sk, m, true); goto out_err; } } @@ -1583,13 +1582,13 @@ static void smap_gc_work(struct work_str bpf_prog_put(psock->bpf_tx_msg); if (psock->cork) { - free_start_sg(psock->sock, psock->cork); + free_start_sg(psock->sock, psock->cork, true); kfree(psock->cork); } list_for_each_entry_safe(md, mtmp, &psock->ingress, list) { list_del(&md->list); - free_start_sg(psock->sock, md); + free_start_sg(psock->sock, md, true); kfree(md); }