2014-11-06 06:33:43

by 박수현

[permalink] [raw]
Subject: [PATCH] bridge: missing null bridge device check causing null pointer dereference (bugfix)

the bridge device can be null if the bridge is being deleted while processing
the packet, which causes the null pointer dereference in switch statement.

crash dump snippet:

<1>BUG: unable to handle kernel NULL pointer dereference at 0000000000000021
<1>IP: [<ffffffff814179f6>] br_handle_frame+0xe6/0x270

<0>Code: 4c 0f 44 f0 89 f8 66 33 15 32 52 24 00 66 33 05 29 52 24 00 09 c2 89
f0 66 33 05 22 52 24 00 80 e4 f0 66 09 c2 0f 84 eb 00 00 00 <41> 0f b6 46 21
3c 02 74 61 3c 03 74 1d 48 89 df e8 d5 bc f0 ff
---
net/bridge/br_input.c | 2 ++
1 file changed, 2 insertions(+)

diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index 6fd5522..7e899ca 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -176,6 +176,8 @@ rx_handler_result_t br_handle_frame(struct sk_buff **pskb)
return RX_HANDLER_CONSUMED;

p = br_port_get_rcu(skb->dev);
+ if (!p)
+ goto drop;

if (unlikely(is_link_local_ether_addr(dest))) {
u16 fwd_mask = p->br->group_fwd_mask_required;
--
1.8.1.4


2014-11-06 07:07:33

by Toshiaki Makita

[permalink] [raw]
Subject: Re: [PATCH] bridge: missing null bridge device check causing null pointer dereference (bugfix)

On 2014/11/06 15:26, Su-Hyun Park wrote:
> the bridge device can be null if the bridge is being deleted while processing
> the packet, which causes the null pointer dereference in switch statement.

How can this happen??
It is guarded by rcu.
netdev_rx_handler_unregister() ensures rx_handler_data is non NULL.

Thanks,
Toshiaki Makita

>
> crash dump snippet:
>
> <1>BUG: unable to handle kernel NULL pointer dereference at 0000000000000021
> <1>IP: [<ffffffff814179f6>] br_handle_frame+0xe6/0x270
>
> <0>Code: 4c 0f 44 f0 89 f8 66 33 15 32 52 24 00 66 33 05 29 52 24 00 09 c2 89
> f0 66 33 05 22 52 24 00 80 e4 f0 66 09 c2 0f 84 eb 00 00 00 <41> 0f b6 46 21
> 3c 02 74 61 3c 03 74 1d 48 89 df e8 d5 bc f0 ff
> ---
> net/bridge/br_input.c | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
> index 6fd5522..7e899ca 100644
> --- a/net/bridge/br_input.c
> +++ b/net/bridge/br_input.c
> @@ -176,6 +176,8 @@ rx_handler_result_t br_handle_frame(struct sk_buff **pskb)
> return RX_HANDLER_CONSUMED;
>
> p = br_port_get_rcu(skb->dev);
> + if (!p)
> + goto drop;
>
> if (unlikely(is_link_local_ether_addr(dest))) {
> u16 fwd_mask = p->br->group_fwd_mask_required;
>

2014-11-06 07:58:47

by 박수현

[permalink] [raw]
Subject: RE: [PATCH] bridge: missing null bridge device check causing null pointer dereference (bugfix)

>-----Original Message-----
>From: Toshiaki Makita [mailto:[email protected]]
>Sent: Thursday, November 06, 2014 4:07 PM
>To: ?ڼ???; Stephen Hemminger; David S. Miller
>Cc: [email protected]; [email protected]; linux-
>[email protected]
>Subject: Re: [PATCH] bridge: missing null bridge device check causing null
>pointer dereference (bugfix)
>
>On 2014/11/06 15:26, Su-Hyun Park wrote:
>> the bridge device can be null if the bridge is being deleted while
>> processing the packet, which causes the null pointer dereference in
>switch statement.
>
>How can this happen??
>It is guarded by rcu.
>netdev_rx_handler_unregister() ensures rx_handler_data is non NULL.
>

The RCU protect rx_handler_data, not the bridge member port. It can be NULL according to below code.

static inline struct net_bridge_port *br_port_get_rcu(const struct net_device *dev) {
struct net_bridge_port *port = rcu_dereference(dev->rx_handler_data);
return br_port_exists(dev) ? port : NULL;
}

The crash happens at the below switch statement in br_handle_frame, where p is NULL.

switch (p->state)

>>
>> crash dump snippet:
>>
>> <1>BUG: unable to handle kernel NULL pointer dereference at
>> 0000000000000021
>> <1>IP: [<ffffffff814179f6>] br_handle_frame+0xe6/0x270
>>
>> <0>Code: 4c 0f 44 f0 89 f8 66 33 15 32 52 24 00 66 33 05 29 52 24 00
>> 09 c2 89
>> f0 66 33 05 22 52 24 00 80 e4 f0 66 09 c2 0f 84 eb 00 00 00 <41> 0f b6
>> 46 21 3c 02 74 61 3c 03 74 1d 48 89 df e8 d5 bc f0 ff
>> ---
>> net/bridge/br_input.c | 2 ++
>> 1 file changed, 2 insertions(+)
>>
>> diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index
>> 6fd5522..7e899ca 100644
>> --- a/net/bridge/br_input.c
>> +++ b/net/bridge/br_input.c
>> @@ -176,6 +176,8 @@ rx_handler_result_t br_handle_frame(struct sk_buff
>**pskb)
>> return RX_HANDLER_CONSUMED;
>>
>> p = br_port_get_rcu(skb->dev);
>> + if (!p)
>> + goto drop;
>>
>> if (unlikely(is_link_local_ether_addr(dest))) {
>> u16 fwd_mask = p->br->group_fwd_mask_required;
>>
>

????{.n?+???????+%?????ݶ??w??{.n?+????{??G?????{ay?ʇڙ?,j??f???h?????????z_??(?階?ݢj"???m??????G????????????&???~???iO???z??v?^?m???? ????????I?

2014-11-06 08:29:13

by Toshiaki Makita

[permalink] [raw]
Subject: Re: [PATCH] bridge: missing null bridge device check causing null pointer dereference (bugfix)

On 2014/11/06 16:58, ?ڼ??? wrote:
>> -----Original Message-----
>> From: Toshiaki Makita [mailto:[email protected]]
>> Sent: Thursday, November 06, 2014 4:07 PM
>> To: ?ڼ???; Stephen Hemminger; David S. Miller
>> Cc: [email protected]; [email protected]; linux-
>> [email protected]
>> Subject: Re: [PATCH] bridge: missing null bridge device check causing null
>> pointer dereference (bugfix)
>>
>> On 2014/11/06 15:26, Su-Hyun Park wrote:
>>> the bridge device can be null if the bridge is being deleted while
>>> processing the packet, which causes the null pointer dereference in
>> switch statement.
>>
>> How can this happen??
>> It is guarded by rcu.
>> netdev_rx_handler_unregister() ensures rx_handler_data is non NULL.
>>
>
> The RCU protect rx_handler_data, not the bridge member port. It can be NULL according to below code.
>
> static inline struct net_bridge_port *br_port_get_rcu(const struct net_device *dev) {
> struct net_bridge_port *port = rcu_dereference(dev->rx_handler_data);
> return br_port_exists(dev) ? port : NULL;
> }

Seems to have been fixed for a year.
716ec052d228 ("bridge: fix NULL pointer deref of br_port_get_rcu")

Thanks,
Toshiaki Makita

2014-11-06 11:35:21

by Eric Dumazet

[permalink] [raw]
Subject: Re: [PATCH] bridge: missing null bridge device check causing null pointer dereference (bugfix)

On Thu, 2014-11-06 at 07:58 +0000, 박수현 wrote:
> >-----Original Message-----
> >From: Toshiaki Makita [mailto:[email protected]]
> >Sent: Thursday, November 06, 2014 4:07 PM
> >To: 박수현; Stephen Hemminger; David S. Miller
> >Cc: [email protected]; [email protected]; linux-
> >[email protected]
> >Subject: Re: [PATCH] bridge: missing null bridge device check causing null
> >pointer dereference (bugfix)
> >
> >On 2014/11/06 15:26, Su-Hyun Park wrote:
> >> the bridge device can be null if the bridge is being deleted while
> >> processing the packet, which causes the null pointer dereference in
> >switch statement.
> >
> >How can this happen??
> >It is guarded by rcu.
> >netdev_rx_handler_unregister() ensures rx_handler_data is non NULL.
> >
>
> The RCU protect rx_handler_data, not the bridge member port. It can be NULL according to below code.
>

Where do you find this 'below code' ?

Are you sending a patch for an old linux kernel ?

> static inline struct net_bridge_port *br_port_get_rcu(const struct net_device *dev) {
> struct net_bridge_port *port = rcu_dereference(dev->rx_handler_data);
> return br_port_exists(dev) ? port : NULL;
> }

Actual code is :

static inline struct net_bridge_port *br_port_get_rcu(const struct net_device *dev)
{
return rcu_dereference(dev->rx_handler_data);
}


>
> The crash happens at the below switch statement in br_handle_frame, where p is NULL.
>
> switch (p->state)

Is your tree really including the fix we already did to fix this issue ?

(commit 716ec052d2280d511e10e90ad54a86f5b5d4dcc2 )
bridge: fix NULL pointer deref of br_port_get_rcu


2014-11-06 11:52:44

by 박수현

[permalink] [raw]
Subject: RE: [PATCH] bridge: missing null bridge device check causing null pointer dereference (bugfix)

My appologies,

I was working on kernel 3.2.30 when I hit the crash. I only looked at the up-to-date kernel for br_handle_frame function where I still found "p->state" reference.

Please disregard my patch.

Thanks,
Su-Hyun Park

-----Original Message-----
From: Eric Dumazet [mailto:[email protected]]
Sent: Thursday, November 06, 2014 8:35 PM
To: 박수현
Cc: Toshiaki Makita; Stephen Hemminger; David S. Miller; [email protected]; [email protected]; [email protected]
Subject: Re: [PATCH] bridge: missing null bridge device check causing null pointer dereference (bugfix)

On Thu, 2014-11-06 at 07:58 +0000, 박수현 wrote:
> >-----Original Message-----
> >From: Toshiaki Makita [mailto:[email protected]]
> >Sent: Thursday, November 06, 2014 4:07 PM
> >To: 박수현; Stephen Hemminger; David S. Miller
> >Cc: [email protected]; [email protected]; linux-
> >[email protected]
> >Subject: Re: [PATCH] bridge: missing null bridge device check causing
> >null pointer dereference (bugfix)
> >
> >On 2014/11/06 15:26, Su-Hyun Park wrote:
> >> the bridge device can be null if the bridge is being deleted while
> >> processing the packet, which causes the null pointer dereference in
> >switch statement.
> >
> >How can this happen??
> >It is guarded by rcu.
> >netdev_rx_handler_unregister() ensures rx_handler_data is non NULL.
> >
>
> The RCU protect rx_handler_data, not the bridge member port. It can be NULL according to below code.
>

Where do you find this 'below code' ?

Are you sending a patch for an old linux kernel ?

> static inline struct net_bridge_port *br_port_get_rcu(const struct net_device *dev) {
> struct net_bridge_port *port = rcu_dereference(dev->rx_handler_data);
> return br_port_exists(dev) ? port : NULL; }

Actual code is :

static inline struct net_bridge_port *br_port_get_rcu(const struct net_device *dev) {
return rcu_dereference(dev->rx_handler_data);
}


>
> The crash happens at the below switch statement in br_handle_frame, where p is NULL.
>
> switch (p->state)

Is your tree really including the fix we already did to fix this issue ?

(commit 716ec052d2280d511e10e90ad54a86f5b5d4dcc2 )
bridge: fix NULL pointer deref of br_port_get_rcu




????{.n?+???????+%?????ݶ??w??{.n?+????{??G?????{ay?ʇڙ?,j??f???h?????????z_??(?階?ݢj"???m??????G????????????&???~???iO???z??v?^?m???? ????????I?