Summary
A missing nullptr-check in handle_ra_input
can cause a nullptr-deref.
Description
The reachable_time
update in handle_ra_input
is missing a nullptr-check for net_pkt_iface(pkt)->config.ip.ipv6
before calling net_if_ipv6_set_reachable_time
:
if (reachable_time && reachable_time <= MAX_REACHABLE_TIME && (net_if_ipv6_get_reachable_time(net_pkt_iface(pkt)) != reachable_time)) {
net_if_ipv6_set_base_reachable_time(net_pkt_iface(pkt), reachable_time);
net_if_ipv6_set_reachable_time(net_pkt_iface(pkt)->config.ip.ipv6);
}
|
if (reachable_time && reachable_time <= MAX_REACHABLE_TIME && |
|
(net_if_ipv6_get_reachable_time(net_pkt_iface(pkt)) != |
|
reachable_time)) { |
|
net_if_ipv6_set_base_reachable_time(net_pkt_iface(pkt), |
|
reachable_time); |
|
net_if_ipv6_set_reachable_time( |
|
net_pkt_iface(pkt)->config.ip.ipv6); |
|
} |
The ipv6
interface pointer is passed into net_if_ipv6_calc_reachable_time
in net_if_ipv6_set_reachable_time
:
ipv6->reachable_time = net_if_ipv6_calc_reachable_time(ipv6);
|
/** |
|
* @brief Set IPv6 reachable time for a given interface. This requires |
|
* that base reachable time is set for the interface. |
|
* |
|
* @param ipv6 IPv6 address configuration |
|
*/ |
|
static inline void net_if_ipv6_set_reachable_time(struct net_if_ipv6 *ipv6) |
|
{ |
|
#if defined(CONFIG_NET_NATIVE_IPV6) |
|
ipv6->reachable_time = net_if_ipv6_calc_reachable_time(ipv6); |
|
#endif |
|
} |
The ipv6
interface pointer is then used without an additional check in net_if_ipv6_calc_reachable_time
:
min_reachable = (MIN_RANDOM_NUMER * ipv6->base_reachable_time) / MIN_RANDOM_DENOM;
max_reachable = (MAX_RANDOM_NUMER * ipv6->base_reachable_time) / MAX_RANDOM_DENOM;
|
uint32_t net_if_ipv6_calc_reachable_time(struct net_if_ipv6 *ipv6) |
|
{ |
|
uint32_t min_reachable, max_reachable; |
|
|
|
k_mutex_lock(&lock, K_FOREVER); |
|
|
|
min_reachable = (MIN_RANDOM_NUMER * ipv6->base_reachable_time) |
|
/ MIN_RANDOM_DENOM; |
|
max_reachable = (MAX_RANDOM_NUMER * ipv6->base_reachable_time) |
|
/ MAX_RANDOM_DENOM; |
|
|
|
k_mutex_unlock(&lock); |
|
|
|
NET_DBG("min_reachable:%u max_reachable:%u", min_reachable, |
|
max_reachable); |
|
|
|
return min_reachable + |
|
sys_rand32_get() % (max_reachable - min_reachable); |
|
} |
However the other usages in handle_ra_input
do check for a nullptr:
Impact
- Potentially cause a Denial of Service.
- Note: We are able to cause a DoS in Zephyr 2.2.0 with fuzzing, but did not try to reproduce in current versions.
Proposed Fix
- Add a nullptr check in
net_if_ipv6_set_reachable_time
or add a wrapper function with a check similar to net_if_ipv6_get_reachable_time
or net_if_ipv6_set_base_reachable_time
.
Summary
A missing nullptr-check in
handle_ra_input
can cause a nullptr-deref.Description
The
reachable_time
update inhandle_ra_input
is missing a nullptr-check fornet_pkt_iface(pkt)->config.ip.ipv6
before callingnet_if_ipv6_set_reachable_time
:zephyr/subsys/net/ip/ipv6_nbr.c
Lines 2377 to 2384 in 98580f1
The
ipv6
interface pointer is passed intonet_if_ipv6_calc_reachable_time
innet_if_ipv6_set_reachable_time
:zephyr/include/zephyr/net/net_if.h
Lines 1424 to 1435 in 98580f1
The
ipv6
interface pointer is then used without an additional check innet_if_ipv6_calc_reachable_time
:zephyr/subsys/net/ip/net_if.c
Lines 2756 to 2774 in 98580f1
However the other usages in
handle_ra_input
do check for a nullptr:net_if_ipv6_get_reachable_time
:zephyr/include/zephyr/net/net_if.h
Lines 1395 to 1413 in 98580f1
net_if_ipv6_set_base_reachable_time
zephyr/include/zephyr/net/net_if.h
Lines 1377 to 1393 in 98580f1
Impact
Proposed Fix
net_if_ipv6_set_reachable_time
or add a wrapper function with a check similar tonet_if_ipv6_get_reachable_time
ornet_if_ipv6_set_base_reachable_time
.