linux-stable/drivers
Christoph Schulz a8a3e41c67 net: pppoe: use correct channel MTU when using Multilink PPP
The PPP channel MTU is used with Multilink PPP when ppp_mp_explode() (see
ppp_generic module) tries to determine how big a fragment might be. According
to RFC 1661, the MTU excludes the 2-byte PPP protocol field, see the
corresponding comment and code in ppp_mp_explode():

		/*
		 * hdrlen includes the 2-byte PPP protocol field, but the
		 * MTU counts only the payload excluding the protocol field.
		 * (RFC1661 Section 2)
		 */
		mtu = pch->chan->mtu - (hdrlen - 2);

However, the pppoe module *does* include the PPP protocol field in the channel
MTU, which is wrong as it causes the PPP payload to be 1-2 bytes too big under
certain circumstances (one byte if PPP protocol compression is used, two
otherwise), causing the generated Ethernet packets to be dropped. So the pppoe
module has to subtract two bytes from the channel MTU. This error only
manifests itself when using Multilink PPP, as otherwise the channel MTU is not
used anywhere.

In the following, I will describe how to reproduce this bug. We configure two
pppd instances for multilink PPP over two PPPoE links, say eth2 and eth3, with
a MTU of 1492 bytes for each link and a MRRU of 2976 bytes. (This MRRU is
computed by adding the two link MTUs and subtracting the MP header twice, which
is 4 bytes long.) The necessary pppd statements on both sides are "multilink
mtu 1492 mru 1492 mrru 2976". On the client side, we additionally need "plugin
rp-pppoe.so eth2" and "plugin rp-pppoe.so eth3", respectively; on the server
side, we additionally need to start two pppoe-server instances to be able to
establish two PPPoE sessions, one over eth2 and one over eth3. We set the MTU
of the PPP network interface to the MRRU (2976) on both sides of the connection
in order to make use of the higher bandwidth. (If we didn't do that, IP
fragmentation would kick in, which we want to avoid.)

Now we send a ICMPv4 echo request with a payload of 2948 bytes from client to
server over the PPP link. This results in the following network packet:

   2948 (echo payload)
 +    8 (ICMPv4 header)
 +   20 (IPv4 header)
---------------------
   2976 (PPP payload)

These 2976 bytes do not exceed the MTU of the PPP network interface, so the
IP packet is not fragmented. Now the multilink PPP code in ppp_mp_explode()
prepends one protocol byte (0x21 for IPv4), making the packet one byte bigger
than the negotiated MRRU. So this packet would have to be divided in three
fragments. But this does not happen as each link MTU is assumed to be two bytes
larger. So this packet is diveded into two fragments only, one of size 1489 and
one of size 1488. Now we have for that bigger fragment:

   1489 (PPP payload)
 +    4 (MP header)
 +    2 (PPP protocol field for the MP payload (0x3d))
 +    6 (PPPoE header)
--------------------------
   1501 (Ethernet payload)

This packet exceeds the link MTU and is discarded.

If one configures the link MTU on the client side to 1501, one can see the
discarded Ethernet frames with tcpdump running on the client. A

ping -s 2948 -c 1 192.168.15.254

leads to the smaller fragment that is correctly received on the server side:

(tcpdump -vvvne -i eth3 pppoes and ppp proto 0x3d)
52:54:00:ad:87:fd > 52:54:00:79:5c:d0, ethertype PPPoE S (0x8864),
  length 1514: PPPoE  [ses 0x3] MLPPP (0x003d), length 1494: seq 0x000,
  Flags [end], length 1492

and to the bigger fragment that is not received on the server side:

(tcpdump -vvvne -i eth2 pppoes and ppp proto 0x3d)
52:54:00:70:9e:89 > 52:54:00:5d:6f:b0, ethertype PPPoE S (0x8864),
  length 1515: PPPoE  [ses 0x5] MLPPP (0x003d), length 1495: seq 0x000,
  Flags [begin], length 1493

With the patch below, we correctly obtain three fragments:

52:54:00:ad:87:fd > 52:54:00:79:5c:d0, ethertype PPPoE S (0x8864),
  length 1514: PPPoE  [ses 0x1] MLPPP (0x003d), length 1494: seq 0x000,
  Flags [begin], length 1492
52:54:00:70:9e:89 > 52:54:00:5d:6f:b0, ethertype PPPoE S (0x8864),
  length 1514: PPPoE  [ses 0x1] MLPPP (0x003d), length 1494: seq 0x000,
  Flags [none], length 1492
52:54:00:ad:87:fd > 52:54:00:79:5c:d0, ethertype PPPoE S (0x8864),
  length 27: PPPoE  [ses 0x1] MLPPP (0x003d), length 7: seq 0x000,
  Flags [end], length 5

And the ICMPv4 echo request is successfully received at the server side:

IP (tos 0x0, ttl 64, id 21925, offset 0, flags [DF], proto ICMP (1),
  length 2976)
    192.168.222.2 > 192.168.15.254: ICMP echo request, id 30530, seq 0,
      length 2956

The bug was introduced in commit c9aa689537
("[PPPOE]: Advertise PPPoE MTU") from the very beginning. This patch applies
to 3.10 upwards but the fix can be applied (with minor modifications) to
kernels as old as 2.6.32.

Signed-off-by: Christoph Schulz <develop@kristov.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-07-14 14:35:46 -07:00
..
accessibility
acpi Merge branches 'acpi-general', 'acpi-processor', 'acpi-lpss' and 'acpi-battery' 2014-06-19 14:40:48 +02:00
amba
ata Merge branch 'for-3.16' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/libata 2014-06-09 14:58:36 -07:00
atm atm: fore200e.c: Cleaning up uninitialized variables 2014-06-02 17:11:03 -07:00
auxdisplay
base DMA, CMA: fix possible memory leak 2014-06-23 16:47:44 -07:00
bcma
block rbd: handle parent_overlap on writes correctly 2014-06-23 12:55:37 +04:00
bluetooth Bluetooth: Ignore H5 non-link packets in non-active state 2014-06-23 18:22:48 +02:00
bus bus/arm-cci: add dependency on OF && CPU_V7 2014-06-17 17:09:35 +02:00
cdrom Merge branch 'for-linus' of git://git.kernel.dk/linux-block 2014-06-11 08:41:17 -07:00
char random: fix entropy accounting bug introduced in v3.15 2014-06-17 14:23:14 -10:00
clk This pull request contains the second half the of the clk changes for 2014-06-15 16:02:20 -10:00
clocksource clocksource: exynos_mct: Don't reset the counter during boot and resume 2014-06-17 00:23:29 +09:00
connector Char / misc driver patches for 3.16-rc1 2014-06-03 08:06:56 -07:00
cpufreq cpufreq: unlock when failing cpufreq_update_policy() 2014-06-18 21:52:20 +02:00
cpuidle cpuidle: mvebu: Fix the name of the states 2014-06-18 21:54:46 +02:00
crypto crypto/nx: disable NX on little endian builds 2014-06-11 17:03:19 +10:00
dca
devfreq
dio
dma Merge branch 'for-linus' of git://git.infradead.org/users/vkoul/slave-dma 2014-06-10 10:28:45 -07:00
edac
eisa
extcon
firewire sound updates for 3.16-rc1 2014-06-04 09:08:25 -07:00
firmware Merge branch 'arm64-efi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip into next 2014-06-05 13:15:32 -07:00
fmc
gpio gpio: of: Fix handling for deferred probe for -gpio suffix 2014-06-12 09:57:00 +02:00
gpu sound fixes for 3.16-rc2 2014-06-19 18:49:37 -10:00
hid Most of this is cleaning up various driver sysfs permissions so we can 2014-06-11 16:09:14 -07:00
hsi hsi: omap_ssi_port: use normal module refcounting 2014-06-05 00:59:05 +02:00
hv Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next 2014-06-12 14:27:40 -07:00
hwmon hwmon: (gpio-fan) Change name used in hwmon_device_register_with_groups 2014-06-25 15:16:09 -07:00
hwspinlock
i2c i2c: sun6-p2wi: fix call to snprintf 2014-06-17 14:28:04 +02:00
ide
idle
iio First set of IIO fixes for the 3.16 cycle. 2014-06-18 10:41:08 -07:00
infiniband Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending 2014-06-12 22:38:32 -07:00
input Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input 2014-06-09 18:46:02 -07:00
iommu IOMMU Updates for Linux v3.16 2014-06-06 11:48:46 -07:00
ipack
irqchip Merge branch 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip into next 2014-06-04 15:59:13 -07:00
isdn isdn: hisax: l3ni1.c: Fix for possible null pointer dereference 2014-07-08 16:06:21 -07:00
leds Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/cooloney/linux-leds 2014-06-12 13:08:09 -07:00
lguest
macintosh powerpc/macintosh/smu.c: Fix closing brace followed by if 2014-06-24 12:43:15 +10:00
mailbox
mcb
md . Add dm_accept_partial_bio interface to DM core to allow DM targets 2014-06-12 13:33:29 -07:00
media Merge branch 'topic/omap3isp' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media 2014-06-12 23:04:28 -07:00
memory
memstick drivers/memstick/host/rtsx_pci_ms.c: add cancel_work when remove driver 2014-06-23 16:47:44 -07:00
message
mfd This pull-request contains some misplaced patches from Tony 2014-06-12 12:42:32 -07:00
misc ARM: SoC fixes for 3.16 2014-06-25 12:19:01 -07:00
mmc Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next 2014-06-12 14:27:40 -07:00
mtd Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs 2014-06-12 10:30:18 -07:00
net net: pppoe: use correct channel MTU when using Multilink PPP 2014-07-14 14:35:46 -07:00
nfc
ntb
nubus kernel/printk: use symbolic defines for console loglevels 2014-06-04 16:54:17 -07:00
of net: fix circular dependency in of_mdio code 2014-07-02 00:24:14 -07:00
oprofile
parisc
parport parport: convert use of typedef ctl_table to struct ctl_table 2014-06-06 16:08:15 -07:00
pci PCI changes for the v3.16 merge window (part 2): 2014-06-12 13:20:24 -07:00
pcmcia
phy
pinctrl This is the bulk of pin control changes for the v3.16 2014-06-03 11:20:32 -07:00
platform Merge branch 'for_linus' of git://cavan.codon.org.uk/platform-drivers-x86 2014-06-10 16:58:32 -07:00
pnp Merge branches 'pnp', 'powercap', 'pm-runtime' and 'pm-opp' 2014-06-03 23:13:00 +02:00
power ACPI and power management updates for 3.16-rc1 2014-06-04 08:57:16 -07:00
powercap
pps
ps3
ptp ptp: ptp_pch depends on x86_32 2014-06-17 15:43:48 -07:00
pwm pwm: Changes for v3.16-rc1 2014-06-11 14:06:55 -07:00
rapidio rapidio/tsi721: use pci_enable_msix_exact() instead of pci_enable_msix() 2014-06-06 16:08:13 -07:00
regulator Merge remote-tracking branches 'regulator/fix/as3722', 'regulator/fix/ltc3589' and 'regulator/fix/palmas' into regulator-linus 2014-06-16 16:05:57 +01:00
remoteproc remoteproc: da8xx: don't select CMA on no-MMU 2014-06-17 17:09:36 +02:00
reset ARM: SoC driver changes 2014-06-02 16:35:49 -07:00
rpmsg
rtc drivers/rtc/rtc-puv3.c: remove "&dev->" for typo issue MIME-Version: 1.0 2014-06-20 08:22:39 +08:00
s390 Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux 2014-06-21 06:47:01 -10:00
sbus
scsi drivers: scsi: mvsas: fix compiling issue by adding 'MVS_' for "enum pci_interrupt_cause" 2014-06-20 08:22:39 +08:00
sfi
sh SH Driver Update for v3.16 2014-06-06 11:44:09 -07:00
sn
soc
spi spi/pxa2xx: change default supported DMA burst size to 1 2014-06-06 10:52:46 +01:00
spmi
ssb
staging imx-drm: parallel-display: Fix DPMS default state. 2014-06-19 17:33:37 -07:00
target Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending 2014-06-12 22:38:32 -07:00
tc
thermal Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux 2014-06-11 14:26:21 -07:00
tty ARM: SoC fixes for 3.16 2014-06-25 12:19:01 -07:00
uio Revert "uio: fix vma io range check in mmap" 2014-06-17 16:07:08 -07:00
usb USB: usbtest: add a timeout for scatter-gather tests 2014-06-17 17:05:50 -07:00
uwb
vfio A handful of VFIO bug fixes for v3.16 2014-06-07 20:12:15 -07:00
vhost vhost-scsi: don't open-code kvfree 2014-06-23 09:22:48 +03:00
video Merge branch 'drm-fixes' of git://people.freedesktop.org/~airlied/linux 2014-06-19 18:40:36 -10:00
virt
virtio
vlynq
vme
w1 w1: mxc_w1: Fix incorrect "presence" status 2014-06-19 17:51:46 -07:00
watchdog Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux 2014-06-21 06:47:01 -10:00
xen xen: regression and PVH fixes for 3.16-rc1 2014-06-19 07:53:27 -10:00
zorro
Kconfig
Makefile Char / misc driver patches for 3.16-rc1 2014-06-03 08:06:56 -07:00