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; }