Modify

Opened 22 months ago

Last modified 21 months ago

#22265 new defect

DoS: Memory corruption when receiving packet on disabled port with nf_call_iptables enabled

Reported by: anonymous Owned by: developers
Priority: normal Milestone:
Component: packages Version: Trunk
Keywords: Cc: stephen@…, nbd@…

Description

The patch 120-bridge_allow_receiption_on_disabled_port.patch (by Stephen Hemminger, applied by Felix Fietkau) causes memory corruptions when the bridge has nf_call_iptables enabled. This can be forced by submitting a lot of IP(v4) packets from a client and switching the link speed on the client (which disables the link for a short period of time).

I have a QCA955x node with two ports (eth0+eth1 use AR803x; eth1/GMAC1+SGMII is connected here to the "client"). I am manually changing the configuration of the device (not really important but just wanted to document it here so everyone knows that eth1 is in an active bridge) via:

ifconfig eth0 down
ifconfig br-lan down
brctl delif br-lan eth0
brctl delbr br-lan

ifconfig eth1 up
brctl addbr br-ssid1
ifconfig br-ssid1 up
brctl addif br-ssid1 eth1

Then the nf_call_iptables is enabled for the device. So either CONFIG_BRIDGE_NETFILTER was enabled manually for the kernel build or just ebtables was selected before the build. This setting here is the important one.

echo 1 > /sys/devices/virtual/net/br-ssid1/bridge/nf_call_iptables
echo 1 > /sys/devices/virtual/net/br-ssid1/bridge/nf_call_ip6tables

The "client" (PC with Debian Jessie without any kind of network manager) connected to the eth1 port was running following mini script to send traffic + causing link down/up events:

#!/bin/bash

IN_TIME=5
ETH_DEV=eth4

ifconfig "${ETH_DEV}" 192.168.5.1
ping -b -f 192.168.5.255 &

while true
do
        #100h
        ethtool -s "${ETH_DEV}" speed 100 duplex half
        sleep $IN_TIME
        #100a
        ethtool -s "${ETH_DEV}" speed 100 duplex full autoneg on
        sleep $IN_TIME
        #100h
        ethtool -s "${ETH_DEV}" speed 100 duplex half
        sleep $IN_TIME
        #100a
        ethtool -s "${ETH_DEV}" speed 100 duplex full autoneg on
        sleep $IN_TIME
        #100f
        ethtool -s "${ETH_DEV}" speed 100 duplex full
        sleep $IN_TIME
        #100a
        ethtool -s "${ETH_DEV}" speed 100 duplex full autoneg on
        sleep $IN_TIME
        #100f
        ethtool -s "${ETH_DEV}" speed 100 duplex full
        sleep $IN_TIME
        #1000a
        ethtool -s "${ETH_DEV}" speed 1000 duplex full autoneg on
        sleep $IN_TIME
        #100f
        ethtool -s "${ETH_DEV}" speed 100 duplex full
        sleep $IN_TIME
        #1000a
        ethtool -s "${ETH_DEV}" speed 1000 duplex full autoneg on
        sleep $IN_TIME
        #100h
        ethtool -s "${ETH_DEV}" speed 100 duplex half
        sleep $IN_TIME
        #1000a
        ethtool -s "${ETH_DEV}" speed 1000 duplex full autoneg on
        sleep $IN_TIME
        #100h
        ethtool -s "${ETH_DEV}" speed 100 duplex half
        sleep $IN_TIME
        #1000f
        ethtool -s "${ETH_DEV}" speed 1000 duplex full
        sleep $IN_TIME
        #100f
        ethtool -s "${ETH_DEV}" speed 100 duplex full
        sleep $IN_TIME
        #1000f
        ethtool -s "${ETH_DEV}" speed 1000 duplex full
        sleep $IN_TIME
        #100f
        ethtool -s "${ETH_DEV}" speed 100 duplex full
        sleep $IN_TIME
        #1000f
        ethtool -s "${ETH_DEV}" speed 1000 duplex full
        sleep $IN_TIME
        #100h
        ethtool -s "${ETH_DEV}" speed 100 duplex half
        sleep $IN_TIME
        #1000f
        ethtool -s "${ETH_DEV}" speed 1000 duplex full
        sleep $IN_TIME
        #100h
        ethtool -s "${ETH_DEV}" speed 100 duplex half
        sleep $IN_TIME
        #1000a
        ethtool -s "${ETH_DEV}" speed 1000 duplex full autoneg on
        sleep $IN_TIME
        #100a
        ethtool -s "${ETH_DEV}" speed 100 duplex full autoneg on
        sleep $IN_TIME
        #1000a
        ethtool -s "${ETH_DEV}" speed 1000 duplex full autoneg on
        sleep $IN_TIME
        #100a
        ethtool -s "${ETH_DEV}" speed 100 duplex full autoneg on
        sleep $IN_TIME
done

This problem was discovered on ag71xx with Linux 3.18 (CC) and can still be reproduced with trunk (49223). The stack trace of the crash will look rather unrelated because the memory corruption itself is not catched as pagefault and instead only causes "funny" side effects which will crash the kernel:

eth1: link up (100Mbps/Half duplex)
eth1: link down
br-ssid1: port 1(eth1) entered disabled state
eth1: link up (100Mbps/Full duplex)
br-ssid1: port 1(eth1) entered forwarding state
br-ssid1: port 1(eth1) entered forwarding state
CPU 0 Unable to handle kernel paging request at virtual address 00000000, epc == 80250a28, ra == 802878c4
Oops[#1]:
CPU: 0 PID: 107 Comm: kworker/0:1 Not tainted 4.4.7 #1
Workqueue: events linkwatch_event
task: 878b1e00 ti: 8793a000 task.ti: 8793a000
$ 0   : 00000000 00000001 00000001 00000000
$ 4   : 86e9347c 86f0d780 00000000 10000000
$ 8   : 00000004 c0000000 00000000 00000000
$12   : 00000001 00080010 00000000 00000004
$16   : 86e93400 86f0d780 00000120 86e93464
$20   : 00000000 00000000 00000001 00000000
$24   : 00000000 00000000                  
$28   : 8793a000 8793bc68 00000000 802878c4
Hi    : 00000000
Lo    : 00000000
epc   : 80250a28 skb_queue_tail+0x18/0x44
ra    : 802878c4 __netlink_sendskb+0x44/0x6c
Status: 1100fc02 KERNEL EXL 
Cause : 0080000c (ExcCode 03)
BadVA : 00000000
PrId  : 00019750 (MIPS 74Kc)
Modules linked in: pppoe ppp_async iptable_nat ath9k pppox ppp_generic nf_nat_ipv4 nf_conntrack_ipv6 nf_conntrack_ipv4 ipt_REJECT ipt_MASQUERADE ebtable_nat ebtable_filter ebtable_broute ath9k_common xt_time xt_tcpudp xt_state xt_nat xt_multiport xt_mark xt_mac xt_limit xt_id xt_conntrack xt_comment xt_TCPMSS xt_REDIRECT xt_LOG xt_CT slhc nf_reject_ipv4 nf_nat_redirect nf_nat_masquerade_ipv4 nf_nat nf_log_ipv4 nf_defrag_ipv6 nf_defrag_ipv4 nf_conntrack_rtcache nf_conntrack iptable_raw iptable_mangle iptable_filter ip_tables ebtables ebt_vlan ebt_stp ebt_redirect ebt_pkttype ebt_mark_m ebt_mark ebt_limit ebt_among ebt_802_3 crc_ccitt ath9k_hw ath10k_pci batman_adv ath10k_core ath mac80211 cfg80211 compat libcrc32c ip6t_REJECT nf_reject_ipv6 nf_log_ipv6 nf_log_common ip6table_raw ip6table_mangle ip6table_filter ip6_tables x_tables gpio_button_hotplug crc16 crc32c_generic crypto_hash
Process kworker/0:1 (pid: 107, threadinfo=8793a000, task=878b1e00, tls=00000000)
Stack : 00000000 147f67b2 86f0d780 86e93400 86e93400 86f0d780 86f0d780 80287b60
        80400000 80329140 80400000 803d2708 8793bc98 00000000 8041c0d8 00000000
        00000001 804a0000 00000000 86f0d780 00000000 8784cc00 00000000 87a14800
        80402c40 878aad18 00000008 80287cb4 8784cc00 87b5f050 00000000 8032a114
        02080020 00000000 00000000 87802780 00000010 80289e34 80403406 803a40a8
        ...
Call Trace:
[<80250a28>] skb_queue_tail+0x18/0x44
[<802878c4>] __netlink_sendskb+0x44/0x6c
[<80287b60>] netlink_broadcast_filtered+0x274/0x3ac
[<80287cb4>] netlink_broadcast+0x1c/0x28
[<80289e34>] nlmsg_notify+0x6c/0xf4
[<8032a420>] br_ifinfo_notify+0xe0/0x138
[<803215a8>] br_device_event+0x214/0x240
[<80098664>] notifier_call_chain+0x58/0xa0
[<80098744>] raw_notifier_call_chain+0x14/0x20
[<80261450>] netdev_state_change+0x34/0x60
[<80276e44>] linkwatch_do_dev+0x70/0xac
[<802771d4>] __linkwatch_run_queue+0x120/0x16c
[<8027724c>] linkwatch_event+0x2c/0x38
[<80092a68>] process_one_work+0x1f8/0x334
[<80093864>] worker_thread+0x2b4/0x408
[<80097b9c>] kthread+0xdc/0xe8
[<80060878>] ret_from_kernel_thread+0x14/0x1c

Removing the patch makes the crash unreproducible.

Attachments (0)

Change History (1)

comment:1 Changed 21 months ago by anonymous

Here it is also discussed why this patch is bad:

https://www.spinics.net/lists/netfilter-devel/msg40997.html

Add Comment

Modify Ticket

Action
as new .
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.