From patchwork Mon Jun 26 15:47:15 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amit Pundir X-Patchwork-Id: 106349 Delivered-To: patch@linaro.org Received: by 10.140.101.48 with SMTP id t45csp161286qge; Mon, 26 Jun 2017 08:47:41 -0700 (PDT) X-Received: by 10.98.135.140 with SMTP id i134mr725492pfe.237.1498492060926; Mon, 26 Jun 2017 08:47:40 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1498492060; cv=none; d=google.com; s=arc-20160816; b=K57xg75x/qtcIcQaaA7nYEWyIvpV++Z43vjH+b853nHZgIut2VRaLGiMNQ9mGVIayC PX27FZA09W1NKg/FwNBNauzOe8Ab6UP/0PK8gV3kmhILL9PIkK8Zkjm+oBSxbRMJDUyY TmCIgA9shDm9umqv1r/uuONFcD8IGE+y6h9Yp8cKk+UKkhOGJnjLthR5bi/KZAmJn0ST imNaW7YhwnQHNlCVfob2KnUgqz8h0GiThAfN9glsb++VkbBF14feqX7IQbIImMn8l2t/ kMPxC3kG+9qUnWAsumDRFMScDEdlaksBRBSGDzlUxzCwa2fbf48X4052kL53j+PHjGx8 Psdg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=qpJCWHaNGV/2c0uUgAschRusRLR7ElygXndz0L0fknY=; b=C6blUAo4VduIsFjk0xEpcmRJyzAh05USQAwD5l9v9GqosQmc8bAS/VR23pZMuoDwth fuT2YIgg2xHtsgJisyOey0j1TsYw/6UbxHgdChsZ9px6+6cKU5/NOQ9dl5WaIU122KOb vVX6Pn8MUcBqLuVTACs7cT3b3BAdu0IsWdG/0HcZmE+lMXbdalvExNmjmh5IWmodEmaT 75rKP2UE7AToZfLHqvlLydGbXIquIbhAB9xdw71PjneCwWFjdqhw78cMN4GlSfKOHFGO kGgC5sBSO3JDZTYr8WwKdlLxkET2+MPjGhKENWAPmo3wPwR4uzZhyv8Soa7p1pJizfu/ +R6Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.b=cdUSz1Ii; spf=pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=stable-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 63si282868plf.50.2017.06.26.08.47.40; Mon, 26 Jun 2017 08:47:40 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of stable-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=@linaro.org header.b=cdUSz1Ii; spf=pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=stable-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751960AbdFZPr3 (ORCPT + 6 others); Mon, 26 Jun 2017 11:47:29 -0400 Received: from mail-pf0-f173.google.com ([209.85.192.173]:36624 "EHLO mail-pf0-f173.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751940AbdFZPr3 (ORCPT ); Mon, 26 Jun 2017 11:47:29 -0400 Received: by mail-pf0-f173.google.com with SMTP id q86so2214135pfl.3 for ; Mon, 26 Jun 2017 08:47:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=qpJCWHaNGV/2c0uUgAschRusRLR7ElygXndz0L0fknY=; b=cdUSz1IinvHDdPSO+IKKBqZVM7E1++ozd1gAynUQ38SDVoPPNeP8Vl2555QnWCUbHp D0qk8SNpvAFmNxwm3LF3S0OieHZZfTRig66a1E6G7PbCpAdMuzw7bX6xF9aiy3FhBb0r 7GAz0Nfw5meIUo1oYhbtLxGWyzL0Xn6yMdxAs= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=qpJCWHaNGV/2c0uUgAschRusRLR7ElygXndz0L0fknY=; b=UpGSVqI+1BHekXDr8aH1X2UAA/t0he9LmBmfRxUnUzAcpbTmJr4AhbXRJL5yztXmuM ypq6/+1SEqscYTjxwaQt4pgF2BD+5poyInd2ul1TA4/xfROnRui+nXKAiigFKOtLGJTF buva+Mbi+oon7OHKfU3VYTjzD4LmThDn/wT3gGk4mru2MTHzgxi8/md9sjw2YsKLTMiw 6w6mcUMnF4ntJ2Qe1IGqJ40HtxwqZG+51C/mZBD4/tJHGjWIPQMzD3/LayIhl2Kx7TmD WJKKiPwyIpx4hff6nVZbSKphVoS2eidROGAKgd6k80Ev1Wew1OYraD4PgOn/kOLvLCcJ Q71g== X-Gm-Message-State: AKS2vOziT6pweciq/845iluBb3indtdR96YQesqzgFLyonDwj2xpGkMO 27h74vckAVqfhmky X-Received: by 10.101.75.199 with SMTP id p7mr776737pgr.164.1498492048292; Mon, 26 Jun 2017 08:47:28 -0700 (PDT) Received: from localhost.localdomain ([106.51.139.251]) by smtp.gmail.com with ESMTPSA id s9sm829854pfe.21.2017.06.26.08.47.25 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 26 Jun 2017 08:47:27 -0700 (PDT) From: Amit Pundir To: Greg KH , Guillaume Nault , "David S . Miller" Cc: Stable Subject: [PATCH for-4.9 1/5] l2tp: fix race in l2tp_recv_common() Date: Mon, 26 Jun 2017 21:17:15 +0530 Message-Id: <1498492039-26905-2-git-send-email-amit.pundir@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1498492039-26905-1-git-send-email-amit.pundir@linaro.org> References: <1498492039-26905-1-git-send-email-amit.pundir@linaro.org> Sender: stable-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: stable@vger.kernel.org From: Guillaume Nault commit 61b9a047729bb230978178bca6729689d0c50ca2 upstream. Taking a reference on sessions in l2tp_recv_common() is racy; this has to be done by the callers. To this end, a new function is required (l2tp_session_get()) to atomically lookup a session and take a reference on it. Callers then have to manually drop this reference. Fixes: fd558d186df2 ("l2tp: Split pppol2tp patch into separate l2tp and ppp parts") Signed-off-by: Guillaume Nault Signed-off-by: David S. Miller Signed-off-by: Amit Pundir --- net/l2tp/l2tp_core.c | 73 ++++++++++++++++++++++++++++++++++++++++++---------- net/l2tp/l2tp_core.h | 3 +++ net/l2tp/l2tp_ip.c | 17 ++++++++---- net/l2tp/l2tp_ip6.c | 18 +++++++++---- 4 files changed, 88 insertions(+), 23 deletions(-) -- 2.7.4 diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c index e702cb95b89b..046a5ba0ebd2 100644 --- a/net/l2tp/l2tp_core.c +++ b/net/l2tp/l2tp_core.c @@ -278,6 +278,55 @@ struct l2tp_session *l2tp_session_find(struct net *net, struct l2tp_tunnel *tunn } EXPORT_SYMBOL_GPL(l2tp_session_find); +/* Like l2tp_session_find() but takes a reference on the returned session. + * Optionally calls session->ref() too if do_ref is true. + */ +struct l2tp_session *l2tp_session_get(struct net *net, + struct l2tp_tunnel *tunnel, + u32 session_id, bool do_ref) +{ + struct hlist_head *session_list; + struct l2tp_session *session; + + if (!tunnel) { + struct l2tp_net *pn = l2tp_pernet(net); + + session_list = l2tp_session_id_hash_2(pn, session_id); + + rcu_read_lock_bh(); + hlist_for_each_entry_rcu(session, session_list, global_hlist) { + if (session->session_id == session_id) { + l2tp_session_inc_refcount(session); + if (do_ref && session->ref) + session->ref(session); + rcu_read_unlock_bh(); + + return session; + } + } + rcu_read_unlock_bh(); + + return NULL; + } + + session_list = l2tp_session_id_hash(tunnel, session_id); + read_lock_bh(&tunnel->hlist_lock); + hlist_for_each_entry(session, session_list, hlist) { + if (session->session_id == session_id) { + l2tp_session_inc_refcount(session); + if (do_ref && session->ref) + session->ref(session); + read_unlock_bh(&tunnel->hlist_lock); + + return session; + } + } + read_unlock_bh(&tunnel->hlist_lock); + + return NULL; +} +EXPORT_SYMBOL_GPL(l2tp_session_get); + struct l2tp_session *l2tp_session_get_nth(struct l2tp_tunnel *tunnel, int nth, bool do_ref) { @@ -637,6 +686,9 @@ static int l2tp_recv_data_seq(struct l2tp_session *session, struct sk_buff *skb) * a data (not control) frame before coming here. Fields up to the * session-id have already been parsed and ptr points to the data * after the session-id. + * + * session->ref() must have been called prior to l2tp_recv_common(). + * session->deref() will be called automatically after skb is processed. */ void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb, unsigned char *ptr, unsigned char *optr, u16 hdrflags, @@ -646,14 +698,6 @@ void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb, int offset; u32 ns, nr; - /* The ref count is increased since we now hold a pointer to - * the session. Take care to decrement the refcnt when exiting - * this function from now on... - */ - l2tp_session_inc_refcount(session); - if (session->ref) - (*session->ref)(session); - /* Parse and check optional cookie */ if (session->peer_cookie_len > 0) { if (memcmp(ptr, &session->peer_cookie[0], session->peer_cookie_len)) { @@ -806,8 +850,6 @@ void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb, /* Try to dequeue as many skbs from reorder_q as we can. */ l2tp_recv_dequeue(session); - l2tp_session_dec_refcount(session); - return; discard: @@ -816,8 +858,6 @@ void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb, if (session->deref) (*session->deref)(session); - - l2tp_session_dec_refcount(session); } EXPORT_SYMBOL(l2tp_recv_common); @@ -924,8 +964,14 @@ static int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb, } /* Find the session context */ - session = l2tp_session_find(tunnel->l2tp_net, tunnel, session_id); + session = l2tp_session_get(tunnel->l2tp_net, tunnel, session_id, true); if (!session || !session->recv_skb) { + if (session) { + if (session->deref) + session->deref(session); + l2tp_session_dec_refcount(session); + } + /* Not found? Pass to userspace to deal with */ l2tp_info(tunnel, L2TP_MSG_DATA, "%s: no session found (%u/%u). Passing up.\n", @@ -934,6 +980,7 @@ static int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb, } l2tp_recv_common(session, skb, ptr, optr, hdrflags, length, payload_hook); + l2tp_session_dec_refcount(session); return 0; diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h index e7233bad65e0..1d020505bf06 100644 --- a/net/l2tp/l2tp_core.h +++ b/net/l2tp/l2tp_core.h @@ -240,6 +240,9 @@ static inline struct l2tp_tunnel *l2tp_sock_to_tunnel(struct sock *sk) return tunnel; } +struct l2tp_session *l2tp_session_get(struct net *net, + struct l2tp_tunnel *tunnel, + u32 session_id, bool do_ref); struct l2tp_session *l2tp_session_find(struct net *net, struct l2tp_tunnel *tunnel, u32 session_id); diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c index 20669537816e..3468d5635d0a 100644 --- a/net/l2tp/l2tp_ip.c +++ b/net/l2tp/l2tp_ip.c @@ -143,19 +143,19 @@ static int l2tp_ip_recv(struct sk_buff *skb) } /* Ok, this is a data packet. Lookup the session. */ - session = l2tp_session_find(net, NULL, session_id); - if (session == NULL) + session = l2tp_session_get(net, NULL, session_id, true); + if (!session) goto discard; tunnel = session->tunnel; - if (tunnel == NULL) - goto discard; + if (!tunnel) + goto discard_sess; /* Trace packet contents, if enabled */ if (tunnel->debug & L2TP_MSG_DATA) { length = min(32u, skb->len); if (!pskb_may_pull(skb, length)) - goto discard; + goto discard_sess; /* Point to L2TP header */ optr = ptr = skb->data; @@ -165,6 +165,7 @@ static int l2tp_ip_recv(struct sk_buff *skb) } l2tp_recv_common(session, skb, ptr, optr, 0, skb->len, tunnel->recv_payload_hook); + l2tp_session_dec_refcount(session); return 0; @@ -203,6 +204,12 @@ static int l2tp_ip_recv(struct sk_buff *skb) return sk_receive_skb(sk, skb, 1); +discard_sess: + if (session->deref) + session->deref(session); + l2tp_session_dec_refcount(session); + goto discard; + discard_put: sock_put(sk); diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c index a4b0c9232bf1..b10abef6b0a0 100644 --- a/net/l2tp/l2tp_ip6.c +++ b/net/l2tp/l2tp_ip6.c @@ -156,19 +156,19 @@ static int l2tp_ip6_recv(struct sk_buff *skb) } /* Ok, this is a data packet. Lookup the session. */ - session = l2tp_session_find(net, NULL, session_id); - if (session == NULL) + session = l2tp_session_get(net, NULL, session_id, true); + if (!session) goto discard; tunnel = session->tunnel; - if (tunnel == NULL) - goto discard; + if (!tunnel) + goto discard_sess; /* Trace packet contents, if enabled */ if (tunnel->debug & L2TP_MSG_DATA) { length = min(32u, skb->len); if (!pskb_may_pull(skb, length)) - goto discard; + goto discard_sess; /* Point to L2TP header */ optr = ptr = skb->data; @@ -179,6 +179,8 @@ static int l2tp_ip6_recv(struct sk_buff *skb) l2tp_recv_common(session, skb, ptr, optr, 0, skb->len, tunnel->recv_payload_hook); + l2tp_session_dec_refcount(session); + return 0; pass_up: @@ -216,6 +218,12 @@ static int l2tp_ip6_recv(struct sk_buff *skb) return sk_receive_skb(sk, skb, 1); +discard_sess: + if (session->deref) + session->deref(session); + l2tp_session_dec_refcount(session); + goto discard; + discard_put: sock_put(sk); From patchwork Mon Jun 26 15:47:16 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amit Pundir X-Patchwork-Id: 106350 Delivered-To: patch@linaro.org Received: by 10.140.101.48 with SMTP id t45csp161290qge; Mon, 26 Jun 2017 08:47:41 -0700 (PDT) X-Received: by 10.98.69.76 with SMTP id s73mr774547pfa.94.1498492061310; Mon, 26 Jun 2017 08:47:41 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1498492061; cv=none; d=google.com; s=arc-20160816; b=QoDI6FRewhaTcQ4xLh54K3SJvqD5MxRYk8otGGrEEIRLcoYuIBm9AW+jNiYKMeV++y u8eMPNdPoVXeHRbzFDFX0l7KFpXdzSqeCUCRwa9HD/6FfCL2VJX7QUrYJWv0NEdehjSw 3dS5ZQJieqhBL8Iuh1wrS7/o+mfBNdUkVpuQvKAm8FLCXgHXHahE3IuV4lM8jUDnmVZu UJ047UOteMP/LWtK00+RhwlOKIIBRwGMNmvPLqdY1mAvznhRtcdCNzJvzoDBWoGD8FpS oKxVlpI1uqFL9pEd8fSSqajUBANEE5uVE/58Kp0PiLmu6BaI+/DbZmb23LaMIKNyGGv8 w0ww== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=bh3V9Vd6MtwFPfOjfPWKBBdhYJ1FVGLBtEgzauAzeXo=; b=jJvGqDXhN8wfENCPGUL8xzQ+Ig/ijgerg7ekNy3eMA6cJxzFsUdLbWMlBvRmezA405 quOehwVC/FEmj2CmRO4nBuwc9Udy/x8dVlYUxFVmkp/sQO8G0q/ILVVhOxLujWTzBWRc pNYokAJJzXOa8+iYdoJ5NU/aCfOtFte5ZBdzek6tRXC2Eo1izWjqF5/oYS2Cwyr5o9rz Yep8Z9xfihRc5aAzdZw6dNfbgzKzuI4mhVRlzDBc7UGVP24vzGgv4b/TYjpdMGZFWuEU PWH5n2o4OIXdkr0l3NGqF6Ze1K2OlPLp67DjQViWplzkKZ/48K8WY8IzHrnCRlNp7hrp nHJA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.b=Efkvh+LK; spf=pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=stable-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 63si282868plf.50.2017.06.26.08.47.41; Mon, 26 Jun 2017 08:47:41 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of stable-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=@linaro.org header.b=Efkvh+LK; spf=pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=stable-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751963AbdFZPrc (ORCPT + 6 others); Mon, 26 Jun 2017 11:47:32 -0400 Received: from mail-pg0-f51.google.com ([74.125.83.51]:36473 "EHLO mail-pg0-f51.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751940AbdFZPrb (ORCPT ); Mon, 26 Jun 2017 11:47:31 -0400 Received: by mail-pg0-f51.google.com with SMTP id u62so2115866pgb.3 for ; Mon, 26 Jun 2017 08:47:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=bh3V9Vd6MtwFPfOjfPWKBBdhYJ1FVGLBtEgzauAzeXo=; b=Efkvh+LKolw0VQd/Q8VvxO40z04uQOxR7qjhBCI6HV+RL63A2HNemszaaNp1iB2Md1 jkAKFfAdcigJb8mlv357Re7gbqkFB2uMnUt4WhNMuomfenj0rSLAHSsapoSnNY8xCr0f wIInlebxVB0Uys8deQbGauXrQTs/1kRJB4wGk= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=bh3V9Vd6MtwFPfOjfPWKBBdhYJ1FVGLBtEgzauAzeXo=; b=EYNaTTZUSBYyEzAruG/Jd7Rptota1IwNyHXr+rM5bq0J5OHhLH4AhEaXEUziLLZKaH nUelnx5y0KSvqfTfHwX75cOoJjZMD9U9cRplqeJ+eWFiHBm6pI8Ydl+5gVMPNBW/iJKP ie1QCRojBl7QocEZ+SgyFHHBB6pZh7zWXIIa8yJUJ00kcNTx8zTGQ9x+YsYYP6j9oe0B tDKgZv6hdgWeh3aLVMaZEBJgBBh28G6+EFVAL9uIf5FtumpKH63srEou6roDKBHk/XQh 7brshpE4/CTtvaY0eLAd+YftYGkGxWTSVBhhwR0C+xnJmb7zlqWwABtABSTmZXO9aulZ l7xQ== X-Gm-Message-State: AKS2vOxe/p2cB143ZDNHGzrIIwpYm0hNyomgNoTOarzPNlOEaVXwzmMP BVHho4O3dZEIh1D9 X-Received: by 10.84.197.3 with SMTP id m3mr882503pld.40.1498492051120; Mon, 26 Jun 2017 08:47:31 -0700 (PDT) Received: from localhost.localdomain ([106.51.139.251]) by smtp.gmail.com with ESMTPSA id s9sm829854pfe.21.2017.06.26.08.47.28 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 26 Jun 2017 08:47:30 -0700 (PDT) From: Amit Pundir To: Greg KH , Guillaume Nault , "David S . Miller" Cc: Stable Subject: [PATCH for-4.9 2/5] l2tp: ensure session can't get removed during pppol2tp_session_ioctl() Date: Mon, 26 Jun 2017 21:17:16 +0530 Message-Id: <1498492039-26905-3-git-send-email-amit.pundir@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1498492039-26905-1-git-send-email-amit.pundir@linaro.org> References: <1498492039-26905-1-git-send-email-amit.pundir@linaro.org> Sender: stable-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: stable@vger.kernel.org From: Guillaume Nault commit 57377d63547861919ee634b845c7caa38de4a452 upstream. Holding a reference on session is required before calling pppol2tp_session_ioctl(). The session could get freed while processing the ioctl otherwise. Since pppol2tp_session_ioctl() uses the session's socket, we also need to take a reference on it in l2tp_session_get(). Fixes: fd558d186df2 ("l2tp: Split pppol2tp patch into separate l2tp and ppp parts") Signed-off-by: Guillaume Nault Signed-off-by: David S. Miller Signed-off-by: Amit Pundir --- net/l2tp/l2tp_ppp.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) -- 2.7.4 diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c index 1387f547a09e..c1c9a9e08d08 100644 --- a/net/l2tp/l2tp_ppp.c +++ b/net/l2tp/l2tp_ppp.c @@ -1141,11 +1141,18 @@ static int pppol2tp_tunnel_ioctl(struct l2tp_tunnel *tunnel, if (stats.session_id != 0) { /* resend to session ioctl handler */ struct l2tp_session *session = - l2tp_session_find(sock_net(sk), tunnel, stats.session_id); - if (session != NULL) - err = pppol2tp_session_ioctl(session, cmd, arg); - else + l2tp_session_get(sock_net(sk), tunnel, + stats.session_id, true); + + if (session) { + err = pppol2tp_session_ioctl(session, cmd, + arg); + if (session->deref) + session->deref(session); + l2tp_session_dec_refcount(session); + } else { err = -EBADR; + } break; } #ifdef CONFIG_XFRM From patchwork Mon Jun 26 15:47:17 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amit Pundir X-Patchwork-Id: 106352 Delivered-To: patch@linaro.org Received: by 10.140.101.48 with SMTP id t45csp161306qge; Mon, 26 Jun 2017 08:47:42 -0700 (PDT) X-Received: by 10.99.168.67 with SMTP id i3mr743946pgp.23.1498492062462; Mon, 26 Jun 2017 08:47:42 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1498492062; cv=none; d=google.com; s=arc-20160816; b=frOJ+nPAmC7rxv8XaLEZ2WhRynb9RXKGvToZt8tt4lpWsSOv+I6JFStHp04chtpJs/ mFjvDmA5xUliChfbjRAsNLfgQ53BDWv48xivBEwxJu0UmZmAMki/Y30CYwkDT61C23hS tSjv4M+Q6E2sSu+cHGMbYecJ8D8fQXUqlUgMLJEkM4gv3RXIHTWqvTTCM2MCczGOe0dg 9rLeqKHmx4/xgJnYaotVGTFj2oqfxkG35QQw6d+Wawjm8XRarzXjq/WtGpUUPoA390f1 98z0Gz1YqZiAoqMXTrIVKLlN3dEGwhwxHKTTiXRxKMpiVx0P53Ih8TfC2f2Xj1J6audR 5BCA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=bKOziGCW5wbW58HOoYQrV0JbgGc4QB8YkDuYYfcTcRc=; b=ycotIKQ9ZdywXxxTFETgD6JCYrYeheAmAf9crPqfiATF6ZNqAL4dxtzAXibA41nwi0 FGZWzxYqwm/jt4i5eZGY8yx9+WztwbSdA3S5M/uZHxjQd7uTdRBSHghuGeJlpaBbNaZw DPjM37dsdif4gNF82mTeNOAtbn/Py6/XcMUMuO6kOpaLKI9utKribnM+BCQKYbaDdACb W2IK4DsJtlSEvj8sNNhAoCTuDa+UV659fbvTNShSW4Z+ZzqBy4fxLwjjlxyfjYf0eOqn QW2hrzBQzCelk1huomp741sGXPBYq65emaRNVLjlGgziaV0egMKULzxB5d7CJqSxmN6h mfYg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.b=CF1wvNH9; spf=pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=stable-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 63si282868plf.50.2017.06.26.08.47.42; Mon, 26 Jun 2017 08:47:42 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of stable-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=@linaro.org header.b=CF1wvNH9; spf=pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=stable-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751976AbdFZPrk (ORCPT + 6 others); Mon, 26 Jun 2017 11:47:40 -0400 Received: from mail-pf0-f181.google.com ([209.85.192.181]:32818 "EHLO mail-pf0-f181.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751473AbdFZPrj (ORCPT ); Mon, 26 Jun 2017 11:47:39 -0400 Received: by mail-pf0-f181.google.com with SMTP id e7so2269758pfk.0 for ; Mon, 26 Jun 2017 08:47:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=bKOziGCW5wbW58HOoYQrV0JbgGc4QB8YkDuYYfcTcRc=; b=CF1wvNH9IKXOQg459BEcszfF+J8GDVR61hKZHIfLbScIu+m0mm+4Z9vlEoXcKdFPY/ i7HzzT4U4iSr2lJT1RadUJYu1C8Fsf+R2WwTsZwh6LJGtCv432NrW73gxAmWG1MChFs9 Bj0k6XfmvG5HmonK92bkwgnKld6jh+fUGHNfg= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=bKOziGCW5wbW58HOoYQrV0JbgGc4QB8YkDuYYfcTcRc=; b=ZUq05p0cqintRFGaW5vvjkPpUDZ/vgbjCPLaU625B2gVbXiW4sJWWb63EFAaF7kicj wzb+C7Xo2PzTurRgTQvYhl0OuP1/mUMPwRl6ReA7FpwWIIY+aJUpxmLJns94zqmi1bBM reA7ksb6TxXg6QI8US8buD+SDU2Fdb3KrcMp2cClfLBWW3RjuhXKNr6wGmzaEpj1WlON yuloWsGqLHwxhmXrmDpMBm/QXUEjY3G9mUKaN6EyHJX0dAv2Sn5tQCR88xv4g4s0nAo2 RR5BMlJXcfgZvLPFRdPuMWa9mG9DzRwgQ2W3gkMiV0WOxvnnKLIXQNdYzzLyhO67tZAj 1ULQ== X-Gm-Message-State: AKS2vOyPr+mpIfEtgACfsnS+Q0XGwRoOZKnDekivvZHJZRQYcobI9Hc7 GgcXcEZVkghQkCo3c1cjzA== X-Received: by 10.98.156.131 with SMTP id u3mr807436pfk.16.1498492053921; Mon, 26 Jun 2017 08:47:33 -0700 (PDT) Received: from localhost.localdomain ([106.51.139.251]) by smtp.gmail.com with ESMTPSA id s9sm829854pfe.21.2017.06.26.08.47.31 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 26 Jun 2017 08:47:32 -0700 (PDT) From: Amit Pundir To: Greg KH , Guillaume Nault , "David S . Miller" Cc: Stable Subject: [PATCH for-4.9 3/5] l2tp: fix duplicate session creation Date: Mon, 26 Jun 2017 21:17:17 +0530 Message-Id: <1498492039-26905-4-git-send-email-amit.pundir@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1498492039-26905-1-git-send-email-amit.pundir@linaro.org> References: <1498492039-26905-1-git-send-email-amit.pundir@linaro.org> Sender: stable-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: stable@vger.kernel.org From: Guillaume Nault commit dbdbc73b44782e22b3b4b6e8b51e7a3d245f3086 upstream. l2tp_session_create() relies on its caller for checking for duplicate sessions. This is racy since a session can be concurrently inserted after the caller's verification. Fix this by letting l2tp_session_create() verify sessions uniqueness upon insertion. Callers need to be adapted to check for l2tp_session_create()'s return code instead of calling l2tp_session_find(). pppol2tp_connect() is a bit special because it has to work on existing sessions (if they're not connected) or to create a new session if none is found. When acting on a preexisting session, a reference must be held or it could go away on us. So we have to use l2tp_session_get() instead of l2tp_session_find() and drop the reference before exiting. Fixes: d9e31d17ceba ("l2tp: Add L2TP ethernet pseudowire support") Fixes: fd558d186df2 ("l2tp: Split pppol2tp patch into separate l2tp and ppp parts") Signed-off-by: Guillaume Nault Signed-off-by: David S. Miller Signed-off-by: Amit Pundir --- net/l2tp/l2tp_core.c | 70 +++++++++++++++++++++++++++++++++++++++------------- net/l2tp/l2tp_eth.c | 10 ++------ net/l2tp/l2tp_ppp.c | 60 ++++++++++++++++++++++---------------------- 3 files changed, 84 insertions(+), 56 deletions(-) -- 2.7.4 diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c index 046a5ba0ebd2..f29911ab3b80 100644 --- a/net/l2tp/l2tp_core.c +++ b/net/l2tp/l2tp_core.c @@ -378,6 +378,48 @@ struct l2tp_session *l2tp_session_find_by_ifname(struct net *net, char *ifname) } EXPORT_SYMBOL_GPL(l2tp_session_find_by_ifname); +static int l2tp_session_add_to_tunnel(struct l2tp_tunnel *tunnel, + struct l2tp_session *session) +{ + struct l2tp_session *session_walk; + struct hlist_head *g_head; + struct hlist_head *head; + struct l2tp_net *pn; + + head = l2tp_session_id_hash(tunnel, session->session_id); + + write_lock_bh(&tunnel->hlist_lock); + hlist_for_each_entry(session_walk, head, hlist) + if (session_walk->session_id == session->session_id) + goto exist; + + if (tunnel->version == L2TP_HDR_VER_3) { + pn = l2tp_pernet(tunnel->l2tp_net); + g_head = l2tp_session_id_hash_2(l2tp_pernet(tunnel->l2tp_net), + session->session_id); + + spin_lock_bh(&pn->l2tp_session_hlist_lock); + hlist_for_each_entry(session_walk, g_head, global_hlist) + if (session_walk->session_id == session->session_id) + goto exist_glob; + + hlist_add_head_rcu(&session->global_hlist, g_head); + spin_unlock_bh(&pn->l2tp_session_hlist_lock); + } + + hlist_add_head(&session->hlist, head); + write_unlock_bh(&tunnel->hlist_lock); + + return 0; + +exist_glob: + spin_unlock_bh(&pn->l2tp_session_hlist_lock); +exist: + write_unlock_bh(&tunnel->hlist_lock); + + return -EEXIST; +} + /* Lookup a tunnel by id */ struct l2tp_tunnel *l2tp_tunnel_find(struct net *net, u32 tunnel_id) @@ -1787,6 +1829,7 @@ EXPORT_SYMBOL_GPL(l2tp_session_set_header_len); struct l2tp_session *l2tp_session_create(int priv_size, struct l2tp_tunnel *tunnel, u32 session_id, u32 peer_session_id, struct l2tp_session_cfg *cfg) { struct l2tp_session *session; + int err; session = kzalloc(sizeof(struct l2tp_session) + priv_size, GFP_KERNEL); if (session != NULL) { @@ -1842,6 +1885,13 @@ struct l2tp_session *l2tp_session_create(int priv_size, struct l2tp_tunnel *tunn l2tp_session_set_header_len(session, tunnel->version); + err = l2tp_session_add_to_tunnel(tunnel, session); + if (err) { + kfree(session); + + return ERR_PTR(err); + } + /* Bump the reference count. The session context is deleted * only when this drops to zero. */ @@ -1851,28 +1901,14 @@ struct l2tp_session *l2tp_session_create(int priv_size, struct l2tp_tunnel *tunn /* Ensure tunnel socket isn't deleted */ sock_hold(tunnel->sock); - /* Add session to the tunnel's hash list */ - write_lock_bh(&tunnel->hlist_lock); - hlist_add_head(&session->hlist, - l2tp_session_id_hash(tunnel, session_id)); - write_unlock_bh(&tunnel->hlist_lock); - - /* And to the global session list if L2TPv3 */ - if (tunnel->version != L2TP_HDR_VER_2) { - struct l2tp_net *pn = l2tp_pernet(tunnel->l2tp_net); - - spin_lock_bh(&pn->l2tp_session_hlist_lock); - hlist_add_head_rcu(&session->global_hlist, - l2tp_session_id_hash_2(pn, session_id)); - spin_unlock_bh(&pn->l2tp_session_hlist_lock); - } - /* Ignore management session in session count value */ if (session->session_id != 0) atomic_inc(&l2tp_session_count); + + return session; } - return session; + return ERR_PTR(-ENOMEM); } EXPORT_SYMBOL_GPL(l2tp_session_create); diff --git a/net/l2tp/l2tp_eth.c b/net/l2tp/l2tp_eth.c index 965f7e344cef..eecc64e138de 100644 --- a/net/l2tp/l2tp_eth.c +++ b/net/l2tp/l2tp_eth.c @@ -223,12 +223,6 @@ static int l2tp_eth_create(struct net *net, u32 tunnel_id, u32 session_id, u32 p goto out; } - session = l2tp_session_find(net, tunnel, session_id); - if (session) { - rc = -EEXIST; - goto out; - } - if (cfg->ifname) { dev = dev_get_by_name(net, cfg->ifname); if (dev) { @@ -242,8 +236,8 @@ static int l2tp_eth_create(struct net *net, u32 tunnel_id, u32 session_id, u32 p session = l2tp_session_create(sizeof(*spriv), tunnel, session_id, peer_session_id, cfg); - if (!session) { - rc = -ENOMEM; + if (IS_ERR(session)) { + rc = PTR_ERR(session); goto out; } diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c index c1c9a9e08d08..1696f1fd5877 100644 --- a/net/l2tp/l2tp_ppp.c +++ b/net/l2tp/l2tp_ppp.c @@ -583,6 +583,7 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr, int error = 0; u32 tunnel_id, peer_tunnel_id; u32 session_id, peer_session_id; + bool drop_refcnt = false; int ver = 2; int fd; @@ -684,36 +685,36 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr, if (tunnel->peer_tunnel_id == 0) tunnel->peer_tunnel_id = peer_tunnel_id; - /* Create session if it doesn't already exist. We handle the - * case where a session was previously created by the netlink - * interface by checking that the session doesn't already have - * a socket and its tunnel socket are what we expect. If any - * of those checks fail, return EEXIST to the caller. - */ - session = l2tp_session_find(sock_net(sk), tunnel, session_id); - if (session == NULL) { - /* Default MTU must allow space for UDP/L2TP/PPP - * headers. + session = l2tp_session_get(sock_net(sk), tunnel, session_id, false); + if (session) { + drop_refcnt = true; + ps = l2tp_session_priv(session); + + /* Using a pre-existing session is fine as long as it hasn't + * been connected yet. */ - cfg.mtu = cfg.mru = 1500 - PPPOL2TP_HEADER_OVERHEAD; + if (ps->sock) { + error = -EEXIST; + goto end; + } - /* Allocate and initialize a new session context. */ - session = l2tp_session_create(sizeof(struct pppol2tp_session), - tunnel, session_id, - peer_session_id, &cfg); - if (session == NULL) { - error = -ENOMEM; + /* consistency checks */ + if (ps->tunnel_sock != tunnel->sock) { + error = -EEXIST; goto end; } } else { - ps = l2tp_session_priv(session); - error = -EEXIST; - if (ps->sock != NULL) - goto end; + /* Default MTU must allow space for UDP/L2TP/PPP headers */ + cfg.mtu = 1500 - PPPOL2TP_HEADER_OVERHEAD; + cfg.mru = cfg.mtu; - /* consistency checks */ - if (ps->tunnel_sock != tunnel->sock) + session = l2tp_session_create(sizeof(struct pppol2tp_session), + tunnel, session_id, + peer_session_id, &cfg); + if (IS_ERR(session)) { + error = PTR_ERR(session); goto end; + } } /* Associate session with its PPPoL2TP socket */ @@ -778,6 +779,8 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr, session->name); end: + if (drop_refcnt) + l2tp_session_dec_refcount(session); release_sock(sk); return error; @@ -805,12 +808,6 @@ static int pppol2tp_session_create(struct net *net, u32 tunnel_id, u32 session_i if (tunnel->sock == NULL) goto out; - /* Check that this session doesn't already exist */ - error = -EEXIST; - session = l2tp_session_find(net, tunnel, session_id); - if (session != NULL) - goto out; - /* Default MTU values. */ if (cfg->mtu == 0) cfg->mtu = 1500 - PPPOL2TP_HEADER_OVERHEAD; @@ -818,12 +815,13 @@ static int pppol2tp_session_create(struct net *net, u32 tunnel_id, u32 session_i cfg->mru = cfg->mtu; /* Allocate and initialize a new session context. */ - error = -ENOMEM; session = l2tp_session_create(sizeof(struct pppol2tp_session), tunnel, session_id, peer_session_id, cfg); - if (session == NULL) + if (IS_ERR(session)) { + error = PTR_ERR(session); goto out; + } ps = l2tp_session_priv(session); ps->tunnel_sock = tunnel->sock; From patchwork Mon Jun 26 15:47:18 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amit Pundir X-Patchwork-Id: 106351 Delivered-To: patch@linaro.org Received: by 10.140.101.48 with SMTP id t45csp161295qge; Mon, 26 Jun 2017 08:47:41 -0700 (PDT) X-Received: by 10.99.102.7 with SMTP id a7mr769948pgc.216.1498492061830; Mon, 26 Jun 2017 08:47:41 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1498492061; cv=none; d=google.com; s=arc-20160816; b=tUVWd5UQ8j14bLHOXzatVgGaZfz62rBuL11ztlz/8blg+AJxqLGULHU5jvulVEXF1H +QEzBtI5ei2Qn0q+1QwHCAemkBcmqU6nn/WPtWjkJDYKuw4H5MGyz2ZUdkpC6J+svk3Z NdRnkJQkYGSXkTL+pg4EzmlprQai1MuxvjN78VZI0L3AZfoxLvz+tEWN/qI9i0r4HJvF ZmUd/NNbEpAmnuTsoxv0/bBV2A+WCbHjVGWReKZRVFWeIzK6mB7Hb3tJ/b4cgut/Vfh5 wEes1+WSCdNJBLqjsFzloHlLpud7rYSm2Uxhi/ftvYoY/Jxj2saPEpHvPpNlsDfSxYoP RL0g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=DRE7E5jJ8OgrHDPMjLL/LtzzvVWUTABeUzZx70jAV0g=; b=d9hxcN5EFCzVToU+J1HFq1Dm4eBUvOv7B8XDZqiOEsTYxrCv1HuPmiVMUSKzniteM3 xMDMuo8hZmWi7cDuu+5Htqtygg3KjhDgGWqPOeINEmGkll5UcRX3OKsx7f5TtMqdSqMO gPlCMRVjz9vCPnrOAzzwVMv7I1N5inOPUhfxm6DNSplsxzzG4PXNqduKtID3fOc77N4T ++qFIM8MmZc+cUb5G3W3KLeiqGtGnAgjHPhUKmeEBp6zWD35eLrGrVYmoSPlokDwjJNf JmRmFlU2DkLsL+Zg5I/z0/qu+YVIMiavTE+GVq30ZvgrkmWV5C6dfKTVOb1gH+bVKIxE roBA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.b=Zw5MhzBi; spf=pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=stable-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 63si282868plf.50.2017.06.26.08.47.41; Mon, 26 Jun 2017 08:47:41 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of stable-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=@linaro.org header.b=Zw5MhzBi; spf=pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=stable-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751940AbdFZPri (ORCPT + 6 others); Mon, 26 Jun 2017 11:47:38 -0400 Received: from mail-pg0-f44.google.com ([74.125.83.44]:36499 "EHLO mail-pg0-f44.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751460AbdFZPrh (ORCPT ); Mon, 26 Jun 2017 11:47:37 -0400 Received: by mail-pg0-f44.google.com with SMTP id u62so2117004pgb.3 for ; Mon, 26 Jun 2017 08:47:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=DRE7E5jJ8OgrHDPMjLL/LtzzvVWUTABeUzZx70jAV0g=; b=Zw5MhzBiV7wPl7AlzVQJB/dakpRvW6BvIBvmxs9giBvaOGs4KGZp8y7sUzNmeVj7zw nR9fIN1XBNdhxfSKP70oH5WRaY1/Xi7GpsAsQHOsuTuHzUROLGoR9Iy50g8pScwSP1QZ vkJbyukRc5jRhvU2McNAUZkAwzXD7wRhN/swk= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=DRE7E5jJ8OgrHDPMjLL/LtzzvVWUTABeUzZx70jAV0g=; b=ry/CFuBRd6rfvyFtnpoGexUXFjySoLST3uM3hL378aI0a+0OU8DgHFYk35M3HzOlGc 7uY7DuFU/WK1iayhREsy+6pbZzQFNc9fiyOIITF/uN2hCwM6a0wVUL9X3yERUBcVHxlz 988d/FJtDSiYoVJmK8r81cAPSNjv6I5HvBNftR/3wP+7jiD9rqZ4aTIG+MkzFWHp+3a+ UiZp3KIVBgPH6F6kh3EV0nbU6/XBPK6WPVfdrHMeD73lf/vpCeExhX8GoOCv3hBWk+kO Ipde77SdMpWZrUysJzb3surYsN9o1q1FZf89BAiP4KoKYrZV08CmL3A2Q9lX5CDdo1lT jAdg== X-Gm-Message-State: AKS2vOz4SKsWqWgZ3+WnCR0sDh9nKjlBpOEoIijjG1zoexEv/mqY7Qqf Z29KqrNinmY/SPRL X-Received: by 10.99.122.3 with SMTP id v3mr769296pgc.98.1498492056779; Mon, 26 Jun 2017 08:47:36 -0700 (PDT) Received: from localhost.localdomain ([106.51.139.251]) by smtp.gmail.com with ESMTPSA id s9sm829854pfe.21.2017.06.26.08.47.34 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 26 Jun 2017 08:47:35 -0700 (PDT) From: Amit Pundir To: Greg KH , Guillaume Nault , "David S . Miller" Cc: Stable Subject: [PATCH for-4.9 4/5] l2tp: hold session while sending creation notifications Date: Mon, 26 Jun 2017 21:17:18 +0530 Message-Id: <1498492039-26905-5-git-send-email-amit.pundir@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1498492039-26905-1-git-send-email-amit.pundir@linaro.org> References: <1498492039-26905-1-git-send-email-amit.pundir@linaro.org> Sender: stable-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: stable@vger.kernel.org From: Guillaume Nault commit 5e6a9e5a3554a5b3db09cdc22253af1849c65dff upstream. l2tp_session_find() doesn't take any reference on the returned session. Therefore, the session may disappear while sending the notification. Use l2tp_session_get() instead and decrement session's refcount once the notification is sent. Fixes: 33f72e6f0c67 ("l2tp : multicast notification to the registered listeners") Signed-off-by: Guillaume Nault Signed-off-by: David S. Miller Signed-off-by: Amit Pundir --- net/l2tp/l2tp_netlink.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) -- 2.7.4 diff --git a/net/l2tp/l2tp_netlink.c b/net/l2tp/l2tp_netlink.c index 9f66272b163b..8c0f48350027 100644 --- a/net/l2tp/l2tp_netlink.c +++ b/net/l2tp/l2tp_netlink.c @@ -634,10 +634,12 @@ static int l2tp_nl_cmd_session_create(struct sk_buff *skb, struct genl_info *inf session_id, peer_session_id, &cfg); if (ret >= 0) { - session = l2tp_session_find(net, tunnel, session_id); - if (session) + session = l2tp_session_get(net, tunnel, session_id, false); + if (session) { ret = l2tp_session_notify(&l2tp_nl_family, info, session, L2TP_CMD_SESSION_CREATE); + l2tp_session_dec_refcount(session); + } } out: From patchwork Mon Jun 26 15:47:19 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amit Pundir X-Patchwork-Id: 106353 Delivered-To: patch@linaro.org Received: by 10.140.101.48 with SMTP id t45csp161309qge; Mon, 26 Jun 2017 08:47:42 -0700 (PDT) X-Received: by 10.84.197.69 with SMTP id m63mr887108pld.50.1498492062831; Mon, 26 Jun 2017 08:47:42 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1498492062; cv=none; d=google.com; s=arc-20160816; b=C933yfkS4PifalG3UGwzFQb7ZMzQ6/s3aqctuKDIQiqjr3twhf/QpQPuogOCqt4ZGh 2KcDhfvc3p+Q+8omMb5S1jYDDjBMuEzxenlQZ/1dJsqS0/zSUOXNAIieSFNMTsmNRXWd Cx1VlQbu3oygv+zjX/pf8vjYmF5BnExvZ6OwRae7GXMYw9CEXGxMb8duPxI56XDpHxBe nzSCO+ANibWMfF8LdH5kx1GhqKrdrQ720KP6sauwAXMeYyJR5snDgEU2zaC7vecxgeeW 2iXNX/OdUhyhSqAtR0jMYEo5fZvmmySN9B03/5+s6VuElWh0ab1pKxrjDz/SXMROEOZg Lohg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=gxQZxUz8ZaylihnY9l54mKax1KijzmAtjt04Su6ETOU=; b=cZGH/+XwdFTysPJ5vyofRmzMsuP3Tco850kfF222Wsj5C4ebDL7bc+okf8ChLJ9xui Mjz5Tx4Daa7uVB8HeTkuzIcA5qYu78Dr5Oe/LEt8d0o7TNIlRVr1WugctFspqXcRR8nA YJwfCoyxAYsSV97UQTv/eabmGcdSdUTz5ym9HAJDXqmeh+VGWwtOGJdxYdICYtdTAyYl MFgBVQdxrhLQyYCh7o3YAtvLv3hmKB23ojCj1nYFJqXvHhYMNggy3l5+qWpcfB3fIpHX BqsKTjQBLzvZB92XvFSuomX6YP0Bk1H23YUtUednXA0dLjfLnfJ5Xk2UWxbwfayc5Nq1 uVUg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.b=JVU41Rki; spf=pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=stable-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 63si282868plf.50.2017.06.26.08.47.42; Mon, 26 Jun 2017 08:47:42 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of stable-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=@linaro.org header.b=JVU41Rki; spf=pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=stable-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751473AbdFZPrl (ORCPT + 6 others); Mon, 26 Jun 2017 11:47:41 -0400 Received: from mail-pg0-f41.google.com ([74.125.83.41]:33208 "EHLO mail-pg0-f41.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751464AbdFZPrk (ORCPT ); Mon, 26 Jun 2017 11:47:40 -0400 Received: by mail-pg0-f41.google.com with SMTP id f127so2164366pgc.0 for ; Mon, 26 Jun 2017 08:47:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=gxQZxUz8ZaylihnY9l54mKax1KijzmAtjt04Su6ETOU=; b=JVU41RkiFkTZf3ZDR+ctwdI1MDbuXE1kG9Z9qVsnBp0ZBwC2ohQd4fJ++8WbmD8Zgi X4u3Nn6bd711lqwCjwEESaUj+pN4nVX4hjMaoDqCaSXB6Iot7NLEPy15zQFFDxxKr+6x Rw0QRGODeu5Q0WkshQUuPzMag3e79cixcVC88= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=gxQZxUz8ZaylihnY9l54mKax1KijzmAtjt04Su6ETOU=; b=IkES0EAY9xysPP6chDAoFMIDiQcouT/IQs4cyqIdmFv9ziAogLL4QwLjW66BI/4pIH gXBjTjsqMSpGi8mARUCQ2EddxmxhF6h33jSK8RVsF/7GX4LcJUPz7Bq0+2zKaIydRrnA NQjGW188YyuMruzrbJDZGlBowL8UQfh+LYJ4uCHCPDj1PTMueyfvb/SdBOOucAgYgXKn l9MrS/D70ToBHtQpoyIsP+tzDdZiM8Eq062YiXnHh16S45dL73zeBUJP+w+gxTb6Yva0 Pgu5Vp9Lfk8xi8YstxwKe8akb50mOJj5RwJl10CULuHpkz3iHnVPjnYR5EZ6Yj8GtDUv 98kQ== X-Gm-Message-State: AKS2vOwuXHoeDprSsChW1Td2MRkfznuv2osT65vftEeT2lY25gpXRYDn Xoln2ZF2XtpfffKR X-Received: by 10.84.179.195 with SMTP id b61mr881252plc.178.1498492059615; Mon, 26 Jun 2017 08:47:39 -0700 (PDT) Received: from localhost.localdomain ([106.51.139.251]) by smtp.gmail.com with ESMTPSA id s9sm829854pfe.21.2017.06.26.08.47.36 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 26 Jun 2017 08:47:38 -0700 (PDT) From: Amit Pundir To: Greg KH , Guillaume Nault , "David S . Miller" Cc: Stable Subject: [PATCH for-4.9 5/5] l2tp: take a reference on sessions used in genetlink handlers Date: Mon, 26 Jun 2017 21:17:19 +0530 Message-Id: <1498492039-26905-6-git-send-email-amit.pundir@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1498492039-26905-1-git-send-email-amit.pundir@linaro.org> References: <1498492039-26905-1-git-send-email-amit.pundir@linaro.org> Sender: stable-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: stable@vger.kernel.org From: Guillaume Nault commit 2777e2ab5a9cf2b4524486c6db1517a6ded25261 upstream. Callers of l2tp_nl_session_find() need to hold a reference on the returned session since there's no guarantee that it isn't going to disappear from under them. Relying on the fact that no l2tp netlink message may be processed concurrently isn't enough: sessions can be deleted by other means (e.g. by closing the PPPOL2TP socket of a ppp pseudowire). l2tp_nl_cmd_session_delete() is a bit special: it runs a callback function that may require a previous call to session->ref(). In particular, for ppp pseudowires, the callback is l2tp_session_delete(), which then calls pppol2tp_session_close() and dereferences the PPPOL2TP socket. The socket might already be gone at the moment l2tp_session_delete() calls session->ref(), so we need to take a reference during the session lookup. So we need to pass the do_ref variable down to l2tp_session_get() and l2tp_session_get_by_ifname(). Since all callers have to be updated, l2tp_session_find_by_ifname() and l2tp_nl_session_find() are renamed to reflect their new behaviour. Fixes: 309795f4bec2 ("l2tp: Add netlink control API for L2TP") Signed-off-by: Guillaume Nault Signed-off-by: David S. Miller Signed-off-by: Amit Pundir --- net/l2tp/l2tp_core.c | 9 +++++++-- net/l2tp/l2tp_core.h | 3 ++- net/l2tp/l2tp_netlink.c | 39 ++++++++++++++++++++++++++------------- 3 files changed, 35 insertions(+), 16 deletions(-) -- 2.7.4 diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c index f29911ab3b80..3bce65183c95 100644 --- a/net/l2tp/l2tp_core.c +++ b/net/l2tp/l2tp_core.c @@ -356,7 +356,8 @@ EXPORT_SYMBOL_GPL(l2tp_session_get_nth); /* Lookup a session by interface name. * This is very inefficient but is only used by management interfaces. */ -struct l2tp_session *l2tp_session_find_by_ifname(struct net *net, char *ifname) +struct l2tp_session *l2tp_session_get_by_ifname(struct net *net, char *ifname, + bool do_ref) { struct l2tp_net *pn = l2tp_pernet(net); int hash; @@ -366,7 +367,11 @@ struct l2tp_session *l2tp_session_find_by_ifname(struct net *net, char *ifname) for (hash = 0; hash < L2TP_HASH_SIZE_2; hash++) { hlist_for_each_entry_rcu(session, &pn->l2tp_session_hlist[hash], global_hlist) { if (!strcmp(session->ifname, ifname)) { + l2tp_session_inc_refcount(session); + if (do_ref && session->ref) + session->ref(session); rcu_read_unlock_bh(); + return session; } } @@ -376,7 +381,7 @@ struct l2tp_session *l2tp_session_find_by_ifname(struct net *net, char *ifname) return NULL; } -EXPORT_SYMBOL_GPL(l2tp_session_find_by_ifname); +EXPORT_SYMBOL_GPL(l2tp_session_get_by_ifname); static int l2tp_session_add_to_tunnel(struct l2tp_tunnel *tunnel, struct l2tp_session *session) diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h index 1d020505bf06..0095012509ac 100644 --- a/net/l2tp/l2tp_core.h +++ b/net/l2tp/l2tp_core.h @@ -248,7 +248,8 @@ struct l2tp_session *l2tp_session_find(struct net *net, u32 session_id); struct l2tp_session *l2tp_session_get_nth(struct l2tp_tunnel *tunnel, int nth, bool do_ref); -struct l2tp_session *l2tp_session_find_by_ifname(struct net *net, char *ifname); +struct l2tp_session *l2tp_session_get_by_ifname(struct net *net, char *ifname, + bool do_ref); struct l2tp_tunnel *l2tp_tunnel_find(struct net *net, u32 tunnel_id); struct l2tp_tunnel *l2tp_tunnel_find_nth(struct net *net, int nth); diff --git a/net/l2tp/l2tp_netlink.c b/net/l2tp/l2tp_netlink.c index 8c0f48350027..1ccd310d01a5 100644 --- a/net/l2tp/l2tp_netlink.c +++ b/net/l2tp/l2tp_netlink.c @@ -55,7 +55,8 @@ static int l2tp_nl_session_send(struct sk_buff *skb, u32 portid, u32 seq, /* Accessed under genl lock */ static const struct l2tp_nl_cmd_ops *l2tp_nl_cmd_ops[__L2TP_PWTYPE_MAX]; -static struct l2tp_session *l2tp_nl_session_find(struct genl_info *info) +static struct l2tp_session *l2tp_nl_session_get(struct genl_info *info, + bool do_ref) { u32 tunnel_id; u32 session_id; @@ -66,14 +67,15 @@ static struct l2tp_session *l2tp_nl_session_find(struct genl_info *info) if (info->attrs[L2TP_ATTR_IFNAME]) { ifname = nla_data(info->attrs[L2TP_ATTR_IFNAME]); - session = l2tp_session_find_by_ifname(net, ifname); + session = l2tp_session_get_by_ifname(net, ifname, do_ref); } else if ((info->attrs[L2TP_ATTR_SESSION_ID]) && (info->attrs[L2TP_ATTR_CONN_ID])) { tunnel_id = nla_get_u32(info->attrs[L2TP_ATTR_CONN_ID]); session_id = nla_get_u32(info->attrs[L2TP_ATTR_SESSION_ID]); tunnel = l2tp_tunnel_find(net, tunnel_id); if (tunnel) - session = l2tp_session_find(net, tunnel, session_id); + session = l2tp_session_get(net, tunnel, session_id, + do_ref); } return session; @@ -652,7 +654,7 @@ static int l2tp_nl_cmd_session_delete(struct sk_buff *skb, struct genl_info *inf struct l2tp_session *session; u16 pw_type; - session = l2tp_nl_session_find(info); + session = l2tp_nl_session_get(info, true); if (session == NULL) { ret = -ENODEV; goto out; @@ -666,6 +668,10 @@ static int l2tp_nl_cmd_session_delete(struct sk_buff *skb, struct genl_info *inf if (l2tp_nl_cmd_ops[pw_type] && l2tp_nl_cmd_ops[pw_type]->session_delete) ret = (*l2tp_nl_cmd_ops[pw_type]->session_delete)(session); + if (session->deref) + session->deref(session); + l2tp_session_dec_refcount(session); + out: return ret; } @@ -675,7 +681,7 @@ static int l2tp_nl_cmd_session_modify(struct sk_buff *skb, struct genl_info *inf int ret = 0; struct l2tp_session *session; - session = l2tp_nl_session_find(info); + session = l2tp_nl_session_get(info, false); if (session == NULL) { ret = -ENODEV; goto out; @@ -710,6 +716,8 @@ static int l2tp_nl_cmd_session_modify(struct sk_buff *skb, struct genl_info *inf ret = l2tp_session_notify(&l2tp_nl_family, info, session, L2TP_CMD_SESSION_MODIFY); + l2tp_session_dec_refcount(session); + out: return ret; } @@ -805,29 +813,34 @@ static int l2tp_nl_cmd_session_get(struct sk_buff *skb, struct genl_info *info) struct sk_buff *msg; int ret; - session = l2tp_nl_session_find(info); + session = l2tp_nl_session_get(info, false); if (session == NULL) { ret = -ENODEV; - goto out; + goto err; } msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!msg) { ret = -ENOMEM; - goto out; + goto err_ref; } ret = l2tp_nl_session_send(msg, info->snd_portid, info->snd_seq, 0, session, L2TP_CMD_SESSION_GET); if (ret < 0) - goto err_out; + goto err_ref_msg; - return genlmsg_unicast(genl_info_net(info), msg, info->snd_portid); + ret = genlmsg_unicast(genl_info_net(info), msg, info->snd_portid); -err_out: - nlmsg_free(msg); + l2tp_session_dec_refcount(session); -out: + return ret; + +err_ref_msg: + nlmsg_free(msg); +err_ref: + l2tp_session_dec_refcount(session); +err: return ret; }