kernel: backport all current pppoe kernel fixes to 3.18
authorFelix Fietkau <nbd@openwrt.org>
Wed, 23 Dec 2015 11:15:02 +0000 (11:15 +0000)
committerFelix Fietkau <nbd@openwrt.org>
Wed, 23 Dec 2015 11:15:02 +0000 (11:15 +0000)
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
SVN-Revision: 47963

12 files changed:
target/linux/generic/patches-3.18/081-01-pppoe-Use-workqueue-to-die-properly-when-a-PADT-is-r.patch [new file with mode: 0644]
target/linux/generic/patches-3.18/081-02-pppoe-Lacks-DST-MAC-address-check.patch [new file with mode: 0644]
target/linux/generic/patches-3.18/081-03-pppoe-drop-pppoe-device-in-pppoe_unbind_sock_work.patch [new file with mode: 0644]
target/linux/generic/patches-3.18/081-04-ppp-don-t-override-sk-sk_state-in-pppoe_flush_dev.patch [new file with mode: 0644]
target/linux/generic/patches-3.18/081-05-ppp-fix-pppoe_dev-deletion-condition-in-pppoe_releas.patch [new file with mode: 0644]
target/linux/generic/patches-3.18/081-06-ppp-don-t-set-sk_state-to-PPPOX_ZOMBIE-in-pppoe_disc.patch [new file with mode: 0644]
target/linux/generic/patches-3.18/081-07-ppp-remove-PPPOX_ZOMBIE-socket-state.patch [new file with mode: 0644]
target/linux/generic/patches-3.18/081-08-pppoe-fix-memory-corruption-in-padt-work-structure.patch [new file with mode: 0644]
target/linux/generic/patches-3.18/081-pppoe-Use-workqueue-to-die-properly-when-a-PADT-is-r.patch [deleted file]
target/linux/generic/patches-3.18/100-pppoe-drop-pppoe-device-in-pppoe_unbind_sock_work.patch [deleted file]
target/linux/generic/patches-3.18/101-pppoe-fix-disconnect-crash.patch [deleted file]
target/linux/generic/patches-3.18/650-pppoe_header_pad.patch

diff --git a/target/linux/generic/patches-3.18/081-01-pppoe-Use-workqueue-to-die-properly-when-a-PADT-is-r.patch b/target/linux/generic/patches-3.18/081-01-pppoe-Use-workqueue-to-die-properly-when-a-PADT-is-r.patch
new file mode 100644 (file)
index 0000000..de85830
--- /dev/null
@@ -0,0 +1,89 @@
+From: Simon Farnsworth <simon@farnz.org.uk>
+Date: Sun, 1 Mar 2015 10:54:39 +0000
+Subject: [PATCH] pppoe: Use workqueue to die properly when a PADT is received
+
+When a PADT frame is received, the socket may not be in a good state to
+close down the PPP interface. The current implementation handles this by
+simply blocking all further PPP traffic, and hoping that the lack of traffic
+will trigger the user to investigate.
+
+Use schedule_work to get to a process context from which we clear down the
+PPP interface, in a fashion analogous to hangup on a TTY-based PPP
+interface. This causes pppd to disconnect immediately, and allows tools to
+take immediate corrective action.
+
+Note that pppd's rp_pppoe.so plugin has code in it to disable the session
+when it disconnects; however, as a consequence of this patch, the session is
+already disabled before rp_pppoe.so is asked to disable the session. The
+result is a harmless error message:
+
+Failed to disconnect PPPoE socket: 114 Operation already in progress
+
+This message is safe to ignore, as long as the error is 114 Operation
+already in progress; in that specific case, it means that the PPPoE session
+has already been disabled before pppd tried to disable it.
+
+Signed-off-by: Simon Farnsworth <simon@farnz.org.uk>
+Tested-by: Dan Williams <dcbw@redhat.com>
+Tested-by: Christoph Schulz <develop@kristov.de>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+
+--- a/drivers/net/ppp/pppoe.c
++++ b/drivers/net/ppp/pppoe.c
+@@ -455,6 +455,18 @@ out:
+       return NET_RX_DROP;
+ }
++static void pppoe_unbind_sock_work(struct work_struct *work)
++{
++      struct pppox_sock *po = container_of(work, struct pppox_sock,
++                                           proto.pppoe.padt_work);
++      struct sock *sk = sk_pppox(po);
++
++      lock_sock(sk);
++      pppox_unbind_sock(sk);
++      release_sock(sk);
++      sock_put(sk);
++}
++
+ /************************************************************************
+  *
+  * Receive a PPPoE Discovery frame.
+@@ -500,7 +512,8 @@ static int pppoe_disc_rcv(struct sk_buff
+               }
+               bh_unlock_sock(sk);
+-              sock_put(sk);
++              if (!schedule_work(&po->proto.pppoe.padt_work))
++                      sock_put(sk);
+       }
+ abort:
+@@ -613,6 +626,8 @@ static int pppoe_connect(struct socket *
+       lock_sock(sk);
++      INIT_WORK(&po->proto.pppoe.padt_work, pppoe_unbind_sock_work);
++
+       error = -EINVAL;
+       if (sp->sa_protocol != PX_PROTO_OE)
+               goto end;
+--- a/include/linux/if_pppox.h
++++ b/include/linux/if_pppox.h
+@@ -19,6 +19,7 @@
+ #include <linux/netdevice.h>
+ #include <linux/ppp_channel.h>
+ #include <linux/skbuff.h>
++#include <linux/workqueue.h>
+ #include <uapi/linux/if_pppox.h>
+ static inline struct pppoe_hdr *pppoe_hdr(const struct sk_buff *skb)
+@@ -32,6 +33,7 @@ struct pppoe_opt {
+       struct pppoe_addr       pa;       /* what this socket is bound to*/
+       struct sockaddr_pppox   relay;    /* what socket data will be
+                                            relayed to (PPPoE relaying) */
++      struct work_struct      padt_work;/* Work item for handling PADT */
+ };
+ struct pptp_opt {
diff --git a/target/linux/generic/patches-3.18/081-02-pppoe-Lacks-DST-MAC-address-check.patch b/target/linux/generic/patches-3.18/081-02-pppoe-Lacks-DST-MAC-address-check.patch
new file mode 100644 (file)
index 0000000..3ce778e
--- /dev/null
@@ -0,0 +1,25 @@
+From: Joakim Tjernlund <Joakim.Tjernlund@transmode.se>
+Date: Mon, 20 Apr 2015 21:07:48 +0200
+Subject: [PATCH] pppoe: Lacks DST MAC address check
+
+A pppoe session is identified by its session ID and MAC address.
+Currently pppoe does not check if the received pkg has the correct
+MAC address. This is a problem when the eth I/F is in promisc mode
+as then any DST MAC address is accepted.
+
+Signed-off-by: Joakim Tjernlund <joakim.tjernlund@transmode.se>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+
+--- a/drivers/net/ppp/pppoe.c
++++ b/drivers/net/ppp/pppoe.c
+@@ -380,6 +380,9 @@ static int pppoe_rcv_core(struct sock *s
+        * can't change.
+        */
++      if (skb->pkt_type == PACKET_OTHERHOST)
++              goto abort_kfree;
++
+       if (sk->sk_state & PPPOX_BOUND) {
+               ppp_input(&po->chan, skb);
+       } else if (sk->sk_state & PPPOX_RELAY) {
diff --git a/target/linux/generic/patches-3.18/081-03-pppoe-drop-pppoe-device-in-pppoe_unbind_sock_work.patch b/target/linux/generic/patches-3.18/081-03-pppoe-drop-pppoe-device-in-pppoe_unbind_sock_work.patch
new file mode 100644 (file)
index 0000000..f672c67
--- /dev/null
@@ -0,0 +1,28 @@
+From: Felix Fietkau <nbd@openwrt.org>
+Date: Sat, 9 May 2015 23:08:38 +0200
+Subject: [PATCH] pppoe: drop pppoe device in pppoe_unbind_sock_work
+
+After receiving a PADT and the socket is closed, user space will no
+longer drop the reference to the pppoe device.
+This leads to errors like this:
+
+[  488.570000] unregister_netdevice: waiting for eth0.2 to become free. Usage count = 2
+
+Fixes: 287f3a943fe ("pppoe: Use workqueue to die properly when a PADT is received")
+Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+
+--- a/drivers/net/ppp/pppoe.c
++++ b/drivers/net/ppp/pppoe.c
+@@ -465,6 +465,10 @@ static void pppoe_unbind_sock_work(struc
+       struct sock *sk = sk_pppox(po);
+       lock_sock(sk);
++      if (po->pppoe_dev) {
++              dev_put(po->pppoe_dev);
++              po->pppoe_dev = NULL;
++      }
+       pppox_unbind_sock(sk);
+       release_sock(sk);
+       sock_put(sk);
diff --git a/target/linux/generic/patches-3.18/081-04-ppp-don-t-override-sk-sk_state-in-pppoe_flush_dev.patch b/target/linux/generic/patches-3.18/081-04-ppp-don-t-override-sk-sk_state-in-pppoe_flush_dev.patch
new file mode 100644 (file)
index 0000000..73f2e3d
--- /dev/null
@@ -0,0 +1,68 @@
+From: Guillaume Nault <g.nault@alphalink.fr>
+Date: Wed, 30 Sep 2015 11:45:33 +0200
+Subject: [PATCH] ppp: don't override sk->sk_state in pppoe_flush_dev()
+
+Since commit 2b018d57ff18 ("pppoe: drop PPPOX_ZOMBIEs in pppoe_release"),
+pppoe_release() calls dev_put(po->pppoe_dev) if sk is in the
+PPPOX_ZOMBIE state. But pppoe_flush_dev() can set sk->sk_state to
+PPPOX_ZOMBIE _and_ reset po->pppoe_dev to NULL. This leads to the
+following oops:
+
+[  570.140800] BUG: unable to handle kernel NULL pointer dereference at 00000000000004e0
+[  570.142931] IP: [<ffffffffa018c701>] pppoe_release+0x50/0x101 [pppoe]
+[  570.144601] PGD 3d119067 PUD 3dbc1067 PMD 0
+[  570.144601] Oops: 0000 [#1] SMP
+[  570.144601] Modules linked in: l2tp_ppp l2tp_netlink l2tp_core ip6_udp_tunnel udp_tunnel pppoe pppox ppp_generic slhc loop crc32c_intel ghash_clmulni_intel jitterentropy_rng sha256_generic hmac drbg ansi_cprng aesni_intel aes_x86_64 ablk_helper cryptd lrw gf128mul glue_helper acpi_cpufreq evdev serio_raw processor button ext4 crc16 mbcache jbd2 virtio_net virtio_blk virtio_pci virtio_ring virtio
+[  570.144601] CPU: 1 PID: 15738 Comm: ppp-apitest Not tainted 4.2.0 #1
+[  570.144601] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Debian-1.8.2-1 04/01/2014
+[  570.144601] task: ffff88003d30d600 ti: ffff880036b60000 task.ti: ffff880036b60000
+[  570.144601] RIP: 0010:[<ffffffffa018c701>]  [<ffffffffa018c701>] pppoe_release+0x50/0x101 [pppoe]
+[  570.144601] RSP: 0018:ffff880036b63e08  EFLAGS: 00010202
+[  570.144601] RAX: 0000000000000000 RBX: ffff880034340000 RCX: 0000000000000206
+[  570.144601] RDX: 0000000000000006 RSI: ffff88003d30dd20 RDI: ffff88003d30dd20
+[  570.144601] RBP: ffff880036b63e28 R08: 0000000000000001 R09: 0000000000000000
+[  570.144601] R10: 00007ffee9b50420 R11: ffff880034340078 R12: ffff8800387ec780
+[  570.144601] R13: ffff8800387ec7b0 R14: ffff88003e222aa0 R15: ffff8800387ec7b0
+[  570.144601] FS:  00007f5672f48700(0000) GS:ffff88003fc80000(0000) knlGS:0000000000000000
+[  570.144601] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+[  570.144601] CR2: 00000000000004e0 CR3: 0000000037f7e000 CR4: 00000000000406a0
+[  570.144601] Stack:
+[  570.144601]  ffffffffa018f240 ffff8800387ec780 ffffffffa018f240 ffff8800387ec7b0
+[  570.144601]  ffff880036b63e48 ffffffff812caabe ffff880039e4e000 0000000000000008
+[  570.144601]  ffff880036b63e58 ffffffff812cabad ffff880036b63ea8 ffffffff811347f5
+[  570.144601] Call Trace:
+[  570.144601]  [<ffffffff812caabe>] sock_release+0x1a/0x75
+[  570.144601]  [<ffffffff812cabad>] sock_close+0xd/0x11
+[  570.144601]  [<ffffffff811347f5>] __fput+0xff/0x1a5
+[  570.144601]  [<ffffffff811348cb>] ____fput+0x9/0xb
+[  570.144601]  [<ffffffff81056682>] task_work_run+0x66/0x90
+[  570.144601]  [<ffffffff8100189e>] prepare_exit_to_usermode+0x8c/0xa7
+[  570.144601]  [<ffffffff81001a26>] syscall_return_slowpath+0x16d/0x19b
+[  570.144601]  [<ffffffff813babb1>] int_ret_from_sys_call+0x25/0x9f
+[  570.144601] Code: 48 8b 83 c8 01 00 00 a8 01 74 12 48 89 df e8 8b 27 14 e1 b8 f7 ff ff ff e9 b7 00 00 00 8a 43 12 a8 0b 74 1c 48 8b 83 a8 04 00 00 <48> 8b 80 e0 04 00 00 65 ff 08 48 c7 83 a8 04 00 00 00 00 00 00
+[  570.144601] RIP  [<ffffffffa018c701>] pppoe_release+0x50/0x101 [pppoe]
+[  570.144601]  RSP <ffff880036b63e08>
+[  570.144601] CR2: 00000000000004e0
+[  570.200518] ---[ end trace 46956baf17349563 ]---
+
+pppoe_flush_dev() has no reason to override sk->sk_state with
+PPPOX_ZOMBIE. pppox_unbind_sock() already sets sk->sk_state to
+PPPOX_DEAD, which is the correct state given that sk is unbound and
+po->pppoe_dev is NULL.
+
+Fixes: 2b018d57ff18 ("pppoe: drop PPPOX_ZOMBIEs in pppoe_release")
+Tested-by: Oleksii Berezhniak <core@irc.lg.ua>
+Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+
+--- a/drivers/net/ppp/pppoe.c
++++ b/drivers/net/ppp/pppoe.c
+@@ -313,7 +313,6 @@ static void pppoe_flush_dev(struct net_d
+                       if (po->pppoe_dev == dev &&
+                           sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND | PPPOX_ZOMBIE)) {
+                               pppox_unbind_sock(sk);
+-                              sk->sk_state = PPPOX_ZOMBIE;
+                               sk->sk_state_change(sk);
+                               po->pppoe_dev = NULL;
+                               dev_put(dev);
diff --git a/target/linux/generic/patches-3.18/081-05-ppp-fix-pppoe_dev-deletion-condition-in-pppoe_releas.patch b/target/linux/generic/patches-3.18/081-05-ppp-fix-pppoe_dev-deletion-condition-in-pppoe_releas.patch
new file mode 100644 (file)
index 0000000..b1ae60b
--- /dev/null
@@ -0,0 +1,29 @@
+From: Guillaume Nault <g.nault@alphalink.fr>
+Date: Thu, 22 Oct 2015 16:57:10 +0200
+Subject: [PATCH] ppp: fix pppoe_dev deletion condition in pppoe_release()
+
+We can't rely on PPPOX_ZOMBIE to decide whether to clear po->pppoe_dev.
+PPPOX_ZOMBIE can be set by pppoe_disc_rcv() even when po->pppoe_dev is
+NULL. So we have no guarantee that (sk->sk_state & PPPOX_ZOMBIE) implies
+(po->pppoe_dev != NULL).
+Since we're releasing a PPPoE socket, we want to release the pppoe_dev
+if it exists and reset sk_state to PPPOX_DEAD, no matter the previous
+value of sk_state. So we can just check for po->pppoe_dev and avoid any
+assumption on sk->sk_state.
+
+Fixes: 2b018d57ff18 ("pppoe: drop PPPOX_ZOMBIEs in pppoe_release")
+Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+
+--- a/drivers/net/ppp/pppoe.c
++++ b/drivers/net/ppp/pppoe.c
+@@ -589,7 +589,7 @@ static int pppoe_release(struct socket *
+       po = pppox_sk(sk);
+-      if (sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND | PPPOX_ZOMBIE)) {
++      if (po->pppoe_dev) {
+               dev_put(po->pppoe_dev);
+               po->pppoe_dev = NULL;
+       }
diff --git a/target/linux/generic/patches-3.18/081-06-ppp-don-t-set-sk_state-to-PPPOX_ZOMBIE-in-pppoe_disc.patch b/target/linux/generic/patches-3.18/081-06-ppp-don-t-set-sk_state-to-PPPOX_ZOMBIE-in-pppoe_disc.patch
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/target/linux/generic/patches-3.18/081-07-ppp-remove-PPPOX_ZOMBIE-socket-state.patch b/target/linux/generic/patches-3.18/081-07-ppp-remove-PPPOX_ZOMBIE-socket-state.patch
new file mode 100644 (file)
index 0000000..ffdba4d
--- /dev/null
@@ -0,0 +1,51 @@
+From: Guillaume Nault <g.nault@alphalink.fr>
+Date: Thu, 19 Nov 2015 12:53:21 +0100
+Subject: [PATCH] ppp: remove PPPOX_ZOMBIE socket state
+
+PPPOX_ZOMBIE is never set anymore.
+
+Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+
+--- a/drivers/net/ppp/pppoe.c
++++ b/drivers/net/ppp/pppoe.c
+@@ -311,7 +311,7 @@ static void pppoe_flush_dev(struct net_d
+                       lock_sock(sk);
+                       if (po->pppoe_dev == dev &&
+-                          sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND | PPPOX_ZOMBIE)) {
++                          sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND)) {
+                               pppox_unbind_sock(sk);
+                               sk->sk_state_change(sk);
+                               po->pppoe_dev = NULL;
+@@ -775,7 +775,7 @@ static int pppoe_ioctl(struct socket *so
+               struct pppox_sock *relay_po;
+               err = -EBUSY;
+-              if (sk->sk_state & (PPPOX_BOUND | PPPOX_ZOMBIE | PPPOX_DEAD))
++              if (sk->sk_state & (PPPOX_BOUND | PPPOX_DEAD))
+                       break;
+               err = -ENOTCONN;
+--- a/drivers/net/ppp/pppox.c
++++ b/drivers/net/ppp/pppox.c
+@@ -58,7 +58,7 @@ void pppox_unbind_sock(struct sock *sk)
+ {
+       /* Clear connection to ppp device, if attached. */
+-      if (sk->sk_state & (PPPOX_BOUND | PPPOX_CONNECTED | PPPOX_ZOMBIE)) {
++      if (sk->sk_state & (PPPOX_BOUND | PPPOX_CONNECTED)) {
+               ppp_unregister_channel(&pppox_sk(sk)->chan);
+               sk->sk_state = PPPOX_DEAD;
+       }
+--- a/include/linux/if_pppox.h
++++ b/include/linux/if_pppox.h
+@@ -91,7 +91,6 @@ enum {
+     PPPOX_CONNECTED   = 1,  /* connection established ==TCP_ESTABLISHED */
+     PPPOX_BOUND               = 2,  /* bound to ppp device */
+     PPPOX_RELAY               = 4,  /* forwarding is enabled */
+-    PPPOX_ZOMBIE      = 8,  /* dead, but still bound to ppp device */
+     PPPOX_DEAD                = 16  /* dead, useless, please clean me up!*/
+ };
diff --git a/target/linux/generic/patches-3.18/081-08-pppoe-fix-memory-corruption-in-padt-work-structure.patch b/target/linux/generic/patches-3.18/081-08-pppoe-fix-memory-corruption-in-padt-work-structure.patch
new file mode 100644 (file)
index 0000000..147e971
--- /dev/null
@@ -0,0 +1,82 @@
+From: Guillaume Nault <g.nault@alphalink.fr>
+Date: Thu, 3 Dec 2015 16:49:32 +0100
+Subject: [PATCH] pppoe: fix memory corruption in padt work structure
+
+pppoe_connect() mustn't touch the padt_work field of pppoe sockets
+because that work could be already pending.
+
+[   21.473147] BUG: unable to handle kernel NULL pointer dereference at 00000004
+[   21.474523] IP: [<c1043177>] process_one_work+0x29/0x31c
+[   21.475164] *pde = 00000000
+[   21.475513] Oops: 0000 [#1] SMP
+[   21.475910] Modules linked in: pppoe pppox ppp_generic slhc crc32c_intel aesni_intel virtio_net xts aes_i586 lrw gf128mul ablk_helper cryptd evdev acpi_cpufreq processor serio_raw button ext4 crc16 mbcache jbd2 virtio_blk virtio_pci virtio_ring virtio
+[   21.476168] CPU: 2 PID: 164 Comm: kworker/2:2 Not tainted 4.4.0-rc1 #1
+[   21.476168] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Debian-1.8.2-1 04/01/2014
+[   21.476168] task: f5f83c00 ti: f5e28000 task.ti: f5e28000
+[   21.476168] EIP: 0060:[<c1043177>] EFLAGS: 00010046 CPU: 2
+[   21.476168] EIP is at process_one_work+0x29/0x31c
+[   21.484082] EAX: 00000000 EBX: f678b2a0 ECX: 00000004 EDX: 00000000
+[   21.484082] ESI: f6c69940 EDI: f5e29ef0 EBP: f5e29f0c ESP: f5e29edc
+[   21.484082]  DS: 007b ES: 007b FS: 00d8 GS: 0000 SS: 0068
+[   21.484082] CR0: 80050033 CR2: 000000a4 CR3: 317ad000 CR4: 00040690
+[   21.484082] Stack:
+[   21.484082]  00000000 f6c69950 00000000 f6c69940 c0042338 f5e29f0c c1327945 00000000
+[   21.484082]  00000008 f678b2a0 f6c69940 f678b2b8 f5e29f30 c1043984 f5f83c00 f6c69970
+[   21.484082]  f678b2a0 c10437d3 f6775e80 f678b2a0 c10437d3 f5e29fac c1047059 f5e29f74
+[   21.484082] Call Trace:
+[   21.484082]  [<c1327945>] ? _raw_spin_lock_irq+0x28/0x30
+[   21.484082]  [<c1043984>] worker_thread+0x1b1/0x244
+[   21.484082]  [<c10437d3>] ? rescuer_thread+0x229/0x229
+[   21.484082]  [<c10437d3>] ? rescuer_thread+0x229/0x229
+[   21.484082]  [<c1047059>] kthread+0x8f/0x94
+[   21.484082]  [<c1327a32>] ? _raw_spin_unlock_irq+0x22/0x26
+[   21.484082]  [<c1327ee9>] ret_from_kernel_thread+0x21/0x38
+[   21.484082]  [<c1046fca>] ? kthread_parkme+0x19/0x19
+[   21.496082] Code: 5d c3 55 89 e5 57 56 53 89 c3 83 ec 24 89 d0 89 55 e0 8d 7d e4 e8 6c d8 ff ff b9 04 00 00 00 89 45 d8 8b 43 24 89 45 dc 8b 45 d8 <8b> 40 04 8b 80 e0 00 00 00 c1 e8 05 24 01 88 45 d7 8b 45 e0 8d
+[   21.496082] EIP: [<c1043177>] process_one_work+0x29/0x31c SS:ESP 0068:f5e29edc
+[   21.496082] CR2: 0000000000000004
+[   21.496082] ---[ end trace e362cc9cf10dae89 ]---
+
+Reported-by: Andrew <nitr0@seti.kr.ua>
+Fixes: 287f3a943fef ("pppoe: Use workqueue to die properly when a PADT is received")
+Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+
+--- a/drivers/net/ppp/pppoe.c
++++ b/drivers/net/ppp/pppoe.c
+@@ -550,6 +550,9 @@ static int pppoe_create(struct net *net,
+       sk->sk_family           = PF_PPPOX;
+       sk->sk_protocol         = PX_PROTO_OE;
++      INIT_WORK(&pppox_sk(sk)->proto.pppoe.padt_work,
++                pppoe_unbind_sock_work);
++
+       return 0;
+ }
+@@ -614,8 +617,6 @@ static int pppoe_connect(struct socket *
+       lock_sock(sk);
+-      INIT_WORK(&po->proto.pppoe.padt_work, pppoe_unbind_sock_work);
+-
+       error = -EINVAL;
+       if (sp->sa_protocol != PX_PROTO_OE)
+               goto end;
+@@ -645,8 +646,13 @@ static int pppoe_connect(struct socket *
+                       po->pppoe_dev = NULL;
+               }
+-              memset(sk_pppox(po) + 1, 0,
+-                     sizeof(struct pppox_sock) - sizeof(struct sock));
++              po->pppoe_ifindex = 0;
++              memset(&po->pppoe_pa, 0, sizeof(po->pppoe_pa));
++              memset(&po->pppoe_relay, 0, sizeof(po->pppoe_relay));
++              memset(&po->chan, 0, sizeof(po->chan));
++              po->next = NULL;
++              po->num = 0;
++
+               sk->sk_state = PPPOX_NONE;
+       }
diff --git a/target/linux/generic/patches-3.18/081-pppoe-Use-workqueue-to-die-properly-when-a-PADT-is-r.patch b/target/linux/generic/patches-3.18/081-pppoe-Use-workqueue-to-die-properly-when-a-PADT-is-r.patch
deleted file mode 100644 (file)
index de85830..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-From: Simon Farnsworth <simon@farnz.org.uk>
-Date: Sun, 1 Mar 2015 10:54:39 +0000
-Subject: [PATCH] pppoe: Use workqueue to die properly when a PADT is received
-
-When a PADT frame is received, the socket may not be in a good state to
-close down the PPP interface. The current implementation handles this by
-simply blocking all further PPP traffic, and hoping that the lack of traffic
-will trigger the user to investigate.
-
-Use schedule_work to get to a process context from which we clear down the
-PPP interface, in a fashion analogous to hangup on a TTY-based PPP
-interface. This causes pppd to disconnect immediately, and allows tools to
-take immediate corrective action.
-
-Note that pppd's rp_pppoe.so plugin has code in it to disable the session
-when it disconnects; however, as a consequence of this patch, the session is
-already disabled before rp_pppoe.so is asked to disable the session. The
-result is a harmless error message:
-
-Failed to disconnect PPPoE socket: 114 Operation already in progress
-
-This message is safe to ignore, as long as the error is 114 Operation
-already in progress; in that specific case, it means that the PPPoE session
-has already been disabled before pppd tried to disable it.
-
-Signed-off-by: Simon Farnsworth <simon@farnz.org.uk>
-Tested-by: Dan Williams <dcbw@redhat.com>
-Tested-by: Christoph Schulz <develop@kristov.de>
-Signed-off-by: David S. Miller <davem@davemloft.net>
----
-
---- a/drivers/net/ppp/pppoe.c
-+++ b/drivers/net/ppp/pppoe.c
-@@ -455,6 +455,18 @@ out:
-       return NET_RX_DROP;
- }
-+static void pppoe_unbind_sock_work(struct work_struct *work)
-+{
-+      struct pppox_sock *po = container_of(work, struct pppox_sock,
-+                                           proto.pppoe.padt_work);
-+      struct sock *sk = sk_pppox(po);
-+
-+      lock_sock(sk);
-+      pppox_unbind_sock(sk);
-+      release_sock(sk);
-+      sock_put(sk);
-+}
-+
- /************************************************************************
-  *
-  * Receive a PPPoE Discovery frame.
-@@ -500,7 +512,8 @@ static int pppoe_disc_rcv(struct sk_buff
-               }
-               bh_unlock_sock(sk);
--              sock_put(sk);
-+              if (!schedule_work(&po->proto.pppoe.padt_work))
-+                      sock_put(sk);
-       }
- abort:
-@@ -613,6 +626,8 @@ static int pppoe_connect(struct socket *
-       lock_sock(sk);
-+      INIT_WORK(&po->proto.pppoe.padt_work, pppoe_unbind_sock_work);
-+
-       error = -EINVAL;
-       if (sp->sa_protocol != PX_PROTO_OE)
-               goto end;
---- a/include/linux/if_pppox.h
-+++ b/include/linux/if_pppox.h
-@@ -19,6 +19,7 @@
- #include <linux/netdevice.h>
- #include <linux/ppp_channel.h>
- #include <linux/skbuff.h>
-+#include <linux/workqueue.h>
- #include <uapi/linux/if_pppox.h>
- static inline struct pppoe_hdr *pppoe_hdr(const struct sk_buff *skb)
-@@ -32,6 +33,7 @@ struct pppoe_opt {
-       struct pppoe_addr       pa;       /* what this socket is bound to*/
-       struct sockaddr_pppox   relay;    /* what socket data will be
-                                            relayed to (PPPoE relaying) */
-+      struct work_struct      padt_work;/* Work item for handling PADT */
- };
- struct pptp_opt {
diff --git a/target/linux/generic/patches-3.18/100-pppoe-drop-pppoe-device-in-pppoe_unbind_sock_work.patch b/target/linux/generic/patches-3.18/100-pppoe-drop-pppoe-device-in-pppoe_unbind_sock_work.patch
deleted file mode 100644 (file)
index c461b3e..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-From: Felix Fietkau <nbd@openwrt.org>
-Date: Sat, 9 May 2015 23:03:47 +0200
-Subject: [PATCH] pppoe: drop pppoe device in pppoe_unbind_sock_work
-
-After receiving a PADT and the socket is closed, user space will no
-longer drop the reference to the pppoe device.
-This leads to errors like this:
-
-[  488.570000] unregister_netdevice: waiting for eth0.2 to become free. Usage count = 2
-
-Fixes: 287f3a943fe ("pppoe: Use workqueue to die properly when a PADT is received")
-Signed-off-by: Felix Fietkau <nbd@openwrt.org>
----
-
---- a/drivers/net/ppp/pppoe.c
-+++ b/drivers/net/ppp/pppoe.c
-@@ -462,6 +462,10 @@ static void pppoe_unbind_sock_work(struc
-       struct sock *sk = sk_pppox(po);
-       lock_sock(sk);
-+      if (po->pppoe_dev) {
-+              dev_put(po->pppoe_dev);
-+              po->pppoe_dev = NULL;
-+      }
-       pppox_unbind_sock(sk);
-       release_sock(sk);
-       sock_put(sk);
diff --git a/target/linux/generic/patches-3.18/101-pppoe-fix-disconnect-crash.patch b/target/linux/generic/patches-3.18/101-pppoe-fix-disconnect-crash.patch
deleted file mode 100644 (file)
index f2e6e45..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-Fix crash with actions performed on the underlying interface (MAC address,
-MTU or link state update). This triggers pppoe_flush_dev(), which cleans up
-the device without announcing it in sk->sk_state.
-
-Patch by Guillaume Nault (pulled from netdev@vger)
-
---- a/drivers/net/ppp/pppoe.c
-+++ b/drivers/net/ppp/pppoe.c
-@@ -313,7 +313,6 @@ static void pppoe_flush_dev(struct net_d
-                       if (po->pppoe_dev == dev &&
-                           sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND | PPPOX_ZOMBIE)) {
-                               pppox_unbind_sock(sk);
--                              sk->sk_state = PPPOX_ZOMBIE;
-                               sk->sk_state_change(sk);
-                               po->pppoe_dev = NULL;
-                               dev_put(dev);
index 4b623fad29911fb6d861f290f251e67b9e0f2ca0..eb9b4bfd151ae7be856bf54d6392a8404c685dce 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/net/ppp/pppoe.c
 +++ b/drivers/net/ppp/pppoe.c
-@@ -868,7 +868,7 @@ static int pppoe_sendmsg(struct kiocb *i
+@@ -859,7 +859,7 @@ static int pppoe_sendmsg(struct kiocb *i
                goto end;
  
  
@@ -9,7 +9,7 @@
                           0, GFP_KERNEL);
        if (!skb) {
                error = -ENOMEM;
-@@ -876,7 +876,7 @@ static int pppoe_sendmsg(struct kiocb *i
+@@ -867,7 +867,7 @@ static int pppoe_sendmsg(struct kiocb *i
        }
  
        /* Reserve space for headers. */