Skip to contentSkip to conversation

sh_eth: fix kernel oops in skb_put()

PATCH Superseded Sergei Shtylyov 3 participants 5 messages Oct 24, 2015 – Nov 20, 2015

Subsystems (3)

v2 of 3 Superseded Latest is v3 →

lore
Share & tools
lore
#0 lore raw

PATCH v2 1/1 sh_eth: fix kernel oops in skb_put()

In a low memory situation the following kernel oops occurs:

Unable to handle kernel NULL pointer dereference at virtual address 00000050
pgd = 8490c000
[00000050] *pgdF51e831, *pte000000, *ppte000000
Internal error: Oops: 17 [#1] PREEMPT ARM
Modules linked in:
CPU: 0    Not tainted  (3.4-at16 #9)
PC is at skb_put+0x10/0x98
LR is at sh_eth_poll+0x2c8/0xa10
pc : [<8035f780>]    lr : [<8028bf50>]    psr: 60000113

sp : 84eb1a90 ip : 84eb1ac8 fp : 84eb1ac4
r10: 0000003f r9 : 000005ea r8 : 00000000
r7 : 00000000 r6 : 940453b0 r5 : 00030000 r4 : 9381b180 r3 : 00000000 r2 : 00000000 r1 : 000005ea r0 : 00000000
Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user
Control: 10c53c7d Table: 4248c059 DAC: 00000015 Process klogd (pid: 2046, stack limit = 0x84eb02e8) [...]

This is because netdev_alloc_skb() fails and 'mdp->rx_skbuff[entry]' is left NULL but sh_eth_rx() later uses it without checking. Add such check...

---
This patch is against DaveM's 'net.git' repo.

 drivers/net/ethernet/renesas/sh_eth.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

Index: net/drivers/net/ethernet/renesas/sh_eth.c =================================--- net.orig/drivers/net/ethernet/renesas/sh_eth.c +++ net/drivers/net/ethernet/renesas/sh_eth.c
@@ -1481,6 +1481,7 @@ static int sh_eth_rx(struct net_device *
if (mdp->cd->shift_rd0)
desc_status >>= 16;

+ skb = mdp->rx_skbuff[entry];
if (desc_status & (RD_RFS1 | RD_RFS2 | RD_RFS3 | RD_RFS4 |
RD_RFS5 | RD_RFS6 | RD_RFS10)) {
ndev->stats.rx_errors++;
@@ -1496,12 +1497,11 @@ static int sh_eth_rx(struct net_device *
ndev->stats.rx_missed_errors++;
if (desc_status & RD_RFS10)
ndev->stats.rx_over_errors++;
- } else {
+ } else if (skb) {
if (!mdp->cd->hw_swap)
sh_eth_soft_swap(
phys_to_virt(ALIGN(rxdesc->addr, 4)), pkt_len + 2);
- skb = mdp->rx_skbuff[entry];
mdp->rx_skbuff[entry] = NULL;
if (mdp->cd->rpadir)
skb_reserve(skb, NET_IP_ALIGN);

#1 lore raw

Hi Sergei,

Thank you for your patch!

Quoted 49 lines · Sergei Shtylyov

In a low memory situation the following kernel oops occurs:

Unable to handle kernel NULL pointer dereference at virtual address 00000050
pgd = 8490c000
[00000050] *pgdF51e831, *pte000000, *ppte000000
Internal error: Oops: 17 [#1] PREEMPT ARM
Modules linked in:
CPU: 0    Not tainted  (3.4-at16 #9)
PC is at skb_put+0x10/0x98
LR is at sh_eth_poll+0x2c8/0xa10
pc : [<8035f780>]    lr : [<8028bf50>]    psr: 60000113

sp : 84eb1a90 ip : 84eb1ac8 fp : 84eb1ac4
r10: 0000003f r9 : 000005ea r8 : 00000000
r7 : 00000000 r6 : 940453b0 r5 : 00030000 r4 : 9381b180 r3 : 00000000 r2 : 00000000 r1 : 000005ea r0 : 00000000
Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user
Control: 10c53c7d Table: 4248c059 DAC: 00000015 Process klogd (pid: 2046, stack limit = 0x84eb02e8) [...]

This is because netdev_alloc_skb() fails and 'mdp->rx_skbuff[entry]' is left NULL but sh_eth_rx() later uses it without checking. Add such check...

---
This patch is against DaveM's 'net.git' repo.

 drivers/net/ethernet/renesas/sh_eth.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

Index: net/drivers/net/ethernet/renesas/sh_eth.c =================================> --- net.orig/drivers/net/ethernet/renesas/sh_eth.c +++ net/drivers/net/ethernet/renesas/sh_eth.c

(quoted diff) +1 -0
@@ -1481,6 +1481,7 @@ static int sh_eth_rx(struct net_device *
 		if (mdp->cd->shift_rd0)
 			desc_status >>= 16;
 
+		skb = mdp->rx_skbuff[entry];
 		if (desc_status & (RD_RFS1 | RD_RFS2 | RD_RFS3 | RD_RFS4 |
 				   RD_RFS5 | RD_RFS6 | RD_RFS10)) {
 			ndev->stats.rx_errors++;
@@ -1496,12 +1497,11 @@ static int sh_eth_rx(struct net_device *
 				ndev->stats.rx_missed_errors++;
 			if (desc_status & RD_RFS10)
 				ndev->stats.rx_over_errors++;

Review static int sh_eth_rx(struct net_device * · line 1507

Quoted 10 lines
(quoted diff) +1 -2
-		} else {
+		} else	if (skb) {
 			if (!mdp->cd->hw_swap)
 				sh_eth_soft_swap(
 					phys_to_virt(ALIGN(rxdesc->addr, 4)),
 					pkt_len + 2);
-			skb = mdp->rx_skbuff[entry];
 			mdp->rx_skbuff[entry] = NULL;
 			if (mdp->cd->rpadir)
 				skb_reserve(skb, NET_IP_ALIGN);

This certainly prevents from a bad access, however, some odd thing is going on. Once I hit a low memory situation with this patch, network thorough-put and response is very bad.

telnet, ping, wget takes loong time.

PING 172.16.2.13 (172.16.2.13) 56(84) bytes of data. 64 bytes from 172.16.2.13: icmp_seq=5 ttld time=0.223 ms 64 bytes from 172.16.2.13: icmp_seq=6 ttld time=0.195 ms 64 bytes from 172.16.2.13: icmp_seq=7 ttld time=0.203 ms 64 bytes from 172.16.2.13: icmp_seq=8 ttld time=0.219 ms 64 bytes from 172.16.2.13: icmp_seq=9 ttld time=0.165 ms 64 bytes from 172.16.2.13: icmp_seq ttld time=0.171 ms 64 bytes from 172.16.2.13: icmp_seq=1 ttld time�23 ms 64 bytes from 172.16.2.13: icmp_seq=2 ttld time€22 ms 64 bytes from 172.16.2.13: icmp_seq=3 ttld timep14 ms 64 bytes from 172.16.2.13: icmp_seq=4 ttld time`06 ms

I'll investigate it.

Signature · 5 lines
              yashi
--
To unsubscribe from this list: send the line "unsubscribe linux-sh" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
#2 lore raw

Hello.

Quoted 77 lines · Yasushi SHOJI
Quoted 48 lines

In a low memory situation the following kernel oops occurs:

Unable to handle kernel NULL pointer dereference at virtual address 00000050
pgd = 8490c000
[00000050] *pgdF51e831, *pte000000, *ppte000000
Internal error: Oops: 17 [#1] PREEMPT ARM
Modules linked in:
CPU: 0    Not tainted  (3.4-at16 #9)
PC is at skb_put+0x10/0x98
LR is at sh_eth_poll+0x2c8/0xa10
pc : [<8035f780>]    lr : [<8028bf50>]    psr: 60000113

sp : 84eb1a90 ip : 84eb1ac8 fp : 84eb1ac4
r10: 0000003f r9 : 000005ea r8 : 00000000
r7 : 00000000 r6 : 940453b0 r5 : 00030000 r4 : 9381b180 r3 : 00000000 r2 : 00000000 r1 : 000005ea r0 : 00000000
Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user
Control: 10c53c7d Table: 4248c059 DAC: 00000015 Process klogd (pid: 2046, stack limit = 0x84eb02e8) [...]

This is because netdev_alloc_skb() fails and 'mdp->rx_skbuff[entry]' is left NULL but sh_eth_rx() later uses it without checking. Add such check...

---
This patch is against DaveM's 'net.git' repo.

  drivers/net/ethernet/renesas/sh_eth.c |    4 ++--
  1 file changed, 2 insertions(+), 2 deletions(-)

Index: net/drivers/net/ethernet/renesas/sh_eth.c =================================>> --- net.orig/drivers/net/ethernet/renesas/sh_eth.c +++ net/drivers/net/ethernet/renesas/sh_eth.c

(quoted diff) +1 -0
@@ -1481,6 +1481,7 @@ static int sh_eth_rx(struct net_device *
  		if (mdp->cd->shift_rd0)
  			desc_status >>= 16;
 
+		skb = mdp->rx_skbuff[entry];
  		if (desc_status & (RD_RFS1 | RD_RFS2 | RD_RFS3 | RD_RFS4 |
  				   RD_RFS5 | RD_RFS6 | RD_RFS10)) {
  			ndev->stats.rx_errors++;
@@ -1496,12 +1497,11 @@ static int sh_eth_rx(struct net_device *
  				ndev->stats.rx_missed_errors++;
  			if (desc_status & RD_RFS10)
  				ndev->stats.rx_over_errors++;

Review static int sh_eth_rx(struct net_device * · line 1507

Quoted 10 lines
(quoted diff) +1 -2
-		} else {
+		} else	if (skb) {
  			if (!mdp->cd->hw_swap)
  				sh_eth_soft_swap(
  					phys_to_virt(ALIGN(rxdesc->addr, 4)),
  					pkt_len + 2);
-			skb = mdp->rx_skbuff[entry];
  			mdp->rx_skbuff[entry] = NULL;
  			if (mdp->cd->rpadir)
  				skb_reserve(skb, NET_IP_ALIGN);

This certainly prevents from a bad access, however, some odd thing is going on. Once I hit a low memory situation with this patch, network thorough-put and response is very bad.

telnet, ping, wget takes loong time.

PING 172.16.2.13 (172.16.2.13) 56(84) bytes of data. 64 bytes from 172.16.2.13: icmp_seq=5 ttld time=0.223 ms 64 bytes from 172.16.2.13: icmp_seq=6 ttld time=0.195 ms 64 bytes from 172.16.2.13: icmp_seq=7 ttld time=0.203 ms 64 bytes from 172.16.2.13: icmp_seq=8 ttld time=0.219 ms 64 bytes from 172.16.2.13: icmp_seq=9 ttld time=0.165 ms 64 bytes from 172.16.2.13: icmp_seq ttld time=0.171 ms 64 bytes from 172.16.2.13: icmp_seq=1 ttld time�23 ms 64 bytes from 172.16.2.13: icmp_seq=2 ttld time€22 ms 64 bytes from 172.16.2.13: icmp_seq=3 ttld timep14 ms 64 bytes from 172.16.2.13: icmp_seq=4 ttld time`06 ms

Quoted 1 line

I'll investigate it.

Shoji-san, can I push this patch to net.git? I doubt that it has ill
effects in itself -- the reason of the slowdown you're seeing should be somewhere else...

MBR, Sergei

--
To unsubscribe from this list: send the line "unsubscribe linux-sh" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

#3 lore raw

Hi Sergei,

Quoted 4 lines · Sergei Shtylyov

Shoji-san, can I push this patch to net.git? I doubt that it has
ill effects in itself -- the reason of the slowdown you're seeing should be somewhere else...

Sure. I've tested and the null access problem is gone for sure. I'm pretty sure that the fix won't break anything.

It's going to take, however, some more time to pin down the slow down problem. I'll report when I find the cause.

Thanks,

Signature · 1 line
            yashi
maintainer
#4 lore raw
In reply to Sergei Shtylyov

From: Sergei Shtylyov <[email protected]>
Date: Sun, 25 Oct 2015 01:42:33 +0300

Quoted 1 line

In a low memory situation the following kernel oops occurs:

...

Quoted 5 lines

This is because netdev_alloc_skb() fails and 'mdp->rx_skbuff[entry]' is left NULL but sh_eth_rx() later uses it without checking. Add such check...

This seems to need more investigation and work, therefore I am not applying this at this time.

When a final version is available (or even if this one is deemed appropriate as-is) please resubmit it withut RFT in the Subject.

Thanks.