mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Ben Hutchings <ben@decadent.org.uk>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: akpm@linux-foundation.org,
	"David S. Miller" <davem@davemloft.net>,
	"Guillaume Nault" <g.nault@alphalink.fr>
Subject: [PATCH 3.2 61/95] l2tp: fix race in l2tp_recv_common()
Date: Sun, 16 Jul 2017 14:56:38 +0100	[thread overview]
Message-ID: <lsq.1500213398.934238576@decadent.org.uk> (raw)
In-Reply-To: <lsq.1500213394.718669679@decadent.org.uk>

3.2.91-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Guillaume Nault <g.nault@alphalink.fr>

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 <g.nault@alphalink.fr>
Signed-off-by: David S. Miller <davem@davemloft.net>
[bwh: Backported to 3.2:
 - Drop changes to l2tp_ip6.c
 - Add 'pos' parameter to hlist_for_each_entry{,_rcu}() calls
 - Adjust context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
--- a/net/l2tp/l2tp_core.c
+++ b/net/l2tp/l2tp_core.c
@@ -225,6 +225,56 @@ struct l2tp_session *l2tp_session_find(s
 }
 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;
+	struct hlist_node *walk;
+
+	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, walk, 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, walk, 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_find_nth(struct l2tp_tunnel *tunnel, int nth)
 {
 	int hash;
@@ -524,6 +574,9 @@ static inline int l2tp_verify_udp_checks
  * 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,
@@ -533,14 +586,6 @@ void l2tp_recv_common(struct l2tp_sessio
 	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)) {
@@ -711,8 +756,6 @@ void l2tp_recv_common(struct l2tp_sessio
 	/* Try to dequeue as many skbs from reorder_q as we can. */
 	l2tp_recv_dequeue(session);
 
-	l2tp_session_dec_refcount(session);
-
 	return;
 
 discard:
@@ -721,8 +764,6 @@ discard:
 
 	if (session->deref)
 		(*session->deref)(session);
-
-	l2tp_session_dec_refcount(session);
 }
 EXPORT_SYMBOL(l2tp_recv_common);
 
@@ -818,8 +859,14 @@ static int l2tp_udp_recv_core(struct l2t
 	}
 
 	/* 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 */
 		PRINTK(tunnel->debug, L2TP_MSG_DATA, KERN_INFO,
 		       "%s: no session found (%u/%u). Passing up.\n",
@@ -828,6 +875,7 @@ static int l2tp_udp_recv_core(struct l2t
 	}
 
 	l2tp_recv_common(session, skb, ptr, optr, hdrflags, length, payload_hook);
+	l2tp_session_dec_refcount(session);
 
 	return 0;
 
--- a/net/l2tp/l2tp_core.h
+++ b/net/l2tp/l2tp_core.h
@@ -222,6 +222,9 @@ out:
 	return tunnel;
 }
 
+struct l2tp_session *l2tp_session_get(struct net *net,
+				      struct l2tp_tunnel *tunnel,
+				      u32 session_id, bool do_ref);
 extern struct l2tp_session *l2tp_session_find(struct net *net, struct l2tp_tunnel *tunnel, u32 session_id);
 extern struct l2tp_session *l2tp_session_find_nth(struct l2tp_tunnel *tunnel, int nth);
 extern struct l2tp_session *l2tp_session_find_by_ifname(struct net *net, char *ifname);
--- a/net/l2tp/l2tp_ip.c
+++ b/net/l2tp/l2tp_ip.c
@@ -148,19 +148,19 @@ static int l2tp_ip_recv(struct sk_buff *
 	}
 
 	/* Ok, this is a data packet. Lookup the session. */
-	session = l2tp_session_find(&init_net, NULL, session_id);
-	if (session == NULL)
+	session = l2tp_session_get(&init_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;
@@ -176,6 +176,7 @@ static int l2tp_ip_recv(struct sk_buff *
 	}
 
 	l2tp_recv_common(session, skb, ptr, optr, 0, skb->len, tunnel->recv_payload_hook);
+	l2tp_session_dec_refcount(session);
 
 	return 0;
 
@@ -211,6 +212,12 @@ pass_up:
 
 	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);
 

  parent reply	other threads:[~2017-07-16 14:58 UTC|newest]

Thread overview: 98+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-07-16 13:56 [PATCH 3.2 00/95] 3.2.91-rc1 review Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 46/95] net: phy: handle state correctly in phy_stop_machine Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 65/95] iscsi-target: Drop work-around for legacy GlobalSAN initiator Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 02/95] tracing: Add #undef to fix compile error Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 40/95] bpf: try harder on clones when writing into skb Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 70/95] scsi: sr: Sanity check returned mode data Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 75/95] x86/vdso: Plug race between mapping and ELF header setup Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 09/95] [media] dvb-usb: don't use stack for firmware load Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 12/95] udp: avoid ufo handling on IP payload compression packets Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 30/95] Input: hanwang - validate number of endpoints before using them Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 27/95] Input: iforce " Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 29/95] Input: yealink " Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 07/95] USB: serial: io_ti: fix NULL-deref in interrupt callback Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 23/95] futex: Add missing error handling to FUTEX_REQUEUE_PI Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 42/95] s390/decompressor: fix initrd corruption caused by bss clear Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 71/95] scsi: sd: Fix capacity calculation with 32-bit sector_t Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 04/95] scsi: aacraid: Fix typo in blink status Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 41/95] sch_dsmark: fix invalid skb_cow() usage Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 20/95] usb-core: Add LINEAR_FRAME_INTR_BINTERVAL USB quirk Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 87/95] net: tc35815: move free after the dereference Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 83/95] ring-buffer: Have ring_buffer_iter_empty() return true when empty Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 13/95] isdn/gigaset: fix NULL-deref at probe Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 03/95] usb: dwc3: gadget: make Set Endpoint Configuration macros safe Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 55/95] drm/vmwgfx: Type-check lookups of fence objects Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 01/95] xen: do not re-use pirq number cached in pci device msi msg data Ben Hutchings
2017-07-16 13:56 ` Ben Hutchings [this message]
2017-07-16 13:56 ` [PATCH 3.2 63/95] l2tp: fix duplicate session creation Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 25/95] perf/core: Fix event inheritance on fork() Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 78/95] cpupower: Fix turbo frequency reporting for pre-Sandy Bridge cores Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 92/95] char: lp: fix possible integer overflow in lp_setup() Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 90/95] mm: Tighten x86 /dev/mem with zeroing reads Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 82/95] ACPI / power: Avoid maybe-uninitialized warning Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 52/95] ACPI: Fix incompatibility with mcount-based function graph tracing Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 37/95] scsi: libsas: fix ata xfer length Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 45/95] ALSA: seq: Fix race during FIFO resize Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 21/95] USB: serial: option: add Quectel UC15, UC20, EC21, and EC25 modems Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 17/95] USB: wusbcore: fix NULL-deref at probe Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 26/95] mmc: ushc: " Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 86/95] cx82310_eth: use skb_cow_head() to deal with cloned skbs Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 69/95] xen, fbfront: fix connecting to backend Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 16/95] USB: uss720: fix NULL-deref at probe Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 24/95] sched/loadavg: Avoid loadavg spikes caused by delayed NO_HZ accounting Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 93/95] fs/exec.c: account for argv/envp pointers Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 94/95] ALSA: timer: Fix race between read and ioctl Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 31/95] Input: kbtab - validate number of endpoints before using them Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 66/95] af_key: Add lock to key dump Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 76/95] MIPS: KGDB: Use kernel context for sleeping threads Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 08/95] USB: serial: safe_serial: fix information leak in completion handler Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 84/95] mac80211: reject ToDS broadcast data frames Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 60/95] serial: mxs-auart: Fix baudrate calculation Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 80/95] p9_client_readdir() fix Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 43/95] mmc: sdhci: Do not disable interrupts while waiting for clock Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 10/95] [media] dvb-usb-firmware: don't do DMA on stack Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 47/95] IB/qib: fix false-postive maybe-uninitialized warning Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 53/95] xhci: Manually give back cancelled URB if we can't queue it for cancel Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 44/95] hwmon: (asus_atk0110) fix uninitialized data access Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 58/95] mmc: sdhci: Disable runtime pm when the sdio_irq is enabled Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 64/95] l2tp: take a reference on sessions used in genetlink handlers Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 88/95] Input: i8042 - add Clevo P650RS to the i8042 reset list Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 51/95] ACPI / APEI: Add missing synchronize_rcu() on NOTIFY_SCI removal Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 18/95] uwb: hwa-rc: fix NULL-deref at probe Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 77/95] ALSA: seq: Don't break snd_use_lock_sync() loop by timeout Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 74/95] l2tp: don't mask errors in pppol2tp_getsockopt() Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 28/95] Input: cm109 - validate number of endpoints before using them Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 56/95] drm/vmwgfx: avoid calling vzalloc with a 0 size in vmw_get_cap_3d_ioctl() Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 39/95] net: unix: properly re-increment inflight counter of GC discarded candidates Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 57/95] drm/vmwgfx: Remove getparam error message Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 48/95] netfilter: nf_nat_snmp: Fix panic when snmp_trap_helper fails to register Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 91/95] xen-blkback: don't leak stack data via response ring Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 50/95] virtio_balloon: prevent uninitialized variable use Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 62/95] l2tp: ensure session can't get removed during pppol2tp_session_ioctl() Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 35/95] perf symbols: Fix symbols__fixup_end heuristic for corner cases Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 19/95] uwb: i1480-dfu: fix NULL-deref at probe Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 67/95] powerpc: Don't try to fix up misaligned load-with-reservation instructions Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 89/95] x86/mm/init.c: Fix devmem_is_allowed() off by one Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 14/95] net: wimax/i2400m: fix NULL-deref at probe Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 95/95] ALSA: timer: Fix missing queue indices reset at SNDRV_TIMER_IOCTL_SELECT Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 49/95] virtio_balloon: init 1st buffer in stats vq Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 79/95] ftrace/x86: Fix triple fault with graph tracing and suspend-to-ram Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 72/95] ptrace: fix PTRACE_LISTEN race corrupting task->state Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 54/95] ubi/upd: Always flush after prepared for an update Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 32/95] net: ipv6: set route type for anycast routes Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 05/95] Input: i8042 - add noloop quirk for Dell Embedded Box PC 3000 Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 34/95] ACM gadget: fix endianness in notifications Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 11/95] USB: iowarrior: fix NULL-deref in write Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 59/95] serial: mxs-auart: fix baud rate range Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 73/95] l2tp: don't mask errors in pppol2tp_setsockopt() Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 06/95] scsi: lpfc: Add shutdown method for kexec Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 36/95] ALSA: ctxfi: Fix the incorrect check of dma_set_mask() call Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 38/95] ALSA: seq: Fix racy cell insertions during snd_seq_pool_done() Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 81/95] KEYS: Change the name of the dead type to ".dead" to prevent user access Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 22/95] futex: Fix potential use-after-free in FUTEX_REQUEUE_PI Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 68/95] l2tp: take reference on sessions being dumped Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 15/95] USB: idmouse: fix NULL-deref at probe Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 33/95] USB: usbtmc: add missing endpoint sanity check Ben Hutchings
2017-07-16 13:56 ` [PATCH 3.2 85/95] smsc75xx: use skb_cow_head() to deal with cloned skbs Ben Hutchings
2017-07-16 14:30 ` [PATCH 3.2 00/95] 3.2.91-rc1 review Guenter Roeck
2017-07-16 16:32 ` Ben Hutchings

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=lsq.1500213398.934238576@decadent.org.uk \
    --to=ben@decadent.org.uk \
    --cc=akpm@linux-foundation.org \
    --cc=davem@davemloft.net \
    --cc=g.nault@alphalink.fr \
    --cc=linux-kernel@vger.kernel.org \
    --cc=stable@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®