lkml.org 
[lkml]   [2016]   [Jan]   [6]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 3.16.y-ckt 094/126] sh_eth: fix kernel oops in skb_put()
    Date
    3.16.7-ckt22 -stable review patch.  If anyone has any objections, please let me know.

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

    From: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>

    commit 248be83dcb3feb3f6332eb3d010a016402138484 upstream.

    In a low memory situation the following kernel oops occurs:

    Unable to handle kernel NULL pointer dereference at virtual address 00000050
    pgd = 8490c000
    [00000050] *pgd=4651e831, *pte=00000000, *ppte=00000000
    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...

    Reported-by: Yasushi SHOJI <yashi@atmark-techno.com>
    Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>
    Signed-off-by: Luis Henriques <luis.henriques@canonical.com>
    ---
    drivers/net/ethernet/renesas/sh_eth.c | 4 ++--
    1 file changed, 2 insertions(+), 2 deletions(-)

    diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
    index 7622213beef1..d11546c2e902 100644
    --- a/drivers/net/ethernet/renesas/sh_eth.c
    +++ b/drivers/net/ethernet/renesas/sh_eth.c
    @@ -1427,6 +1427,7 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota)
    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++;
    @@ -1442,12 +1443,11 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota)
    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);

    \
     
     \ /
      Last update: 2016-01-06 12:21    [W:4.266 / U:0.216 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site