mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-22 03:27:30 -04:00
Merge tag 'batadv-net-pullrequest-20260708' of https://git.open-mesh.org/batadv
Simon Wunderlich says: ==================== Here are some batman-adv bugfixes, all by Sven Eckelmann: - ensure minimal ethernet header on TX - fix VLAN priority offset - clean untagged VLAN on netdev registration failure - tt: avoid request storms during pending request - tt: prevent TVLV OOB check overflow - frag: free unfragmentable packet - frag: fix primary_if leak on failed linearization - mcast: avoid OOB read of num_dests header - dat: fix tie-break for candidate selection * tag 'batadv-net-pullrequest-20260708' of https://git.open-mesh.org/batadv: batman-adv: dat: fix tie-break for candidate selection batman-adv: mcast: avoid OOB read of num_dests header batman-adv: frag: fix primary_if leak on failed linearization batman-adv: frag: free unfragmentable packet batman-adv: tt: prevent TVLV OOB check overflow batman-adv: tt: avoid request storms during pending request batman-adv: clean untagged VLAN on netdev registration failure batman-adv: fix VLAN priority offset batman-adv: ensure minimal ethernet header on TX ==================== Link: https://patch.msgid.link/20260708091821.314516-1-sw@simonwunderlich.de Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
@@ -546,7 +546,7 @@ static bool batadv_is_orig_node_eligible(struct batadv_dat_candidate *res,
|
||||
* the one with the lowest address
|
||||
*/
|
||||
if (tmp_max == max && max_orig_node &&
|
||||
batadv_compare_eth(candidate->orig, max_orig_node->orig))
|
||||
memcmp(candidate->orig, max_orig_node->orig, ETH_ALEN) >= 0)
|
||||
goto out;
|
||||
|
||||
ret = true;
|
||||
|
||||
@@ -518,8 +518,10 @@ int batadv_frag_send_packet(struct sk_buff *skb,
|
||||
mtu = min_t(unsigned int, mtu, BATADV_FRAG_MAX_FRAG_SIZE);
|
||||
max_fragment_size = mtu - header_size;
|
||||
|
||||
if (skb->len == 0 || max_fragment_size == 0)
|
||||
return -EINVAL;
|
||||
if (skb->len == 0 || max_fragment_size == 0) {
|
||||
ret = -EINVAL;
|
||||
goto free_skb;
|
||||
}
|
||||
|
||||
num_fragments = (skb->len - 1) / max_fragment_size + 1;
|
||||
max_fragment_size = (skb->len - 1) / num_fragments + 1;
|
||||
@@ -545,7 +547,7 @@ int batadv_frag_send_packet(struct sk_buff *skb,
|
||||
*/
|
||||
if (skb_has_frag_list(skb) && __skb_linearize(skb)) {
|
||||
ret = -ENOMEM;
|
||||
goto free_skb;
|
||||
goto put_primary_if;
|
||||
}
|
||||
|
||||
/* Create one header to be copied to all fragments */
|
||||
|
||||
@@ -259,6 +259,7 @@ int batadv_mesh_init(struct net_device *mesh_iface)
|
||||
void batadv_mesh_free(struct net_device *mesh_iface)
|
||||
{
|
||||
struct batadv_priv *bat_priv = netdev_priv(mesh_iface);
|
||||
struct batadv_meshif_vlan *vlan;
|
||||
|
||||
WRITE_ONCE(bat_priv->mesh_state, BATADV_MESH_DEACTIVATING);
|
||||
|
||||
@@ -273,6 +274,13 @@ void batadv_mesh_free(struct net_device *mesh_iface)
|
||||
|
||||
batadv_mcast_free(bat_priv);
|
||||
|
||||
/* destroy the "untagged" VLAN */
|
||||
vlan = batadv_meshif_vlan_get(bat_priv, BATADV_NO_FLAGS);
|
||||
if (vlan) {
|
||||
batadv_meshif_destroy_vlan(bat_priv, vlan);
|
||||
batadv_meshif_vlan_put(vlan);
|
||||
}
|
||||
|
||||
/* Free the TT and the originator tables only after having terminated
|
||||
* all the other depending components which may use these structures for
|
||||
* their purposes.
|
||||
@@ -368,7 +376,7 @@ void batadv_skb_set_priority(struct sk_buff *skb, int offset)
|
||||
|
||||
switch (ethhdr->h_proto) {
|
||||
case htons(ETH_P_8021Q):
|
||||
vhdr = skb_header_pointer(skb, offset + sizeof(*vhdr),
|
||||
vhdr = skb_header_pointer(skb, offset,
|
||||
sizeof(*vhdr), &vhdr_tmp);
|
||||
if (!vhdr)
|
||||
return;
|
||||
|
||||
@@ -195,6 +195,9 @@ static netdev_tx_t batadv_interface_tx(struct sk_buff *skb,
|
||||
if (READ_ONCE(bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
|
||||
goto dropped;
|
||||
|
||||
if (!pskb_may_pull(skb, ETH_HLEN))
|
||||
goto dropped;
|
||||
|
||||
/* reset control block to avoid left overs from previous users */
|
||||
memset(skb->cb, 0, sizeof(struct batadv_skb_cb));
|
||||
|
||||
@@ -592,8 +595,8 @@ int batadv_meshif_create_vlan(struct batadv_priv *bat_priv, unsigned short vid)
|
||||
* @bat_priv: the bat priv with all the mesh interface information
|
||||
* @vlan: the object to remove
|
||||
*/
|
||||
static void batadv_meshif_destroy_vlan(struct batadv_priv *bat_priv,
|
||||
struct batadv_meshif_vlan *vlan)
|
||||
void batadv_meshif_destroy_vlan(struct batadv_priv *bat_priv,
|
||||
struct batadv_meshif_vlan *vlan)
|
||||
{
|
||||
/* explicitly remove the associated TT local entry because it is marked
|
||||
* with the NOPURGE flag
|
||||
@@ -1088,22 +1091,13 @@ static int batadv_meshif_newlink(struct net_device *dev,
|
||||
static void batadv_meshif_destroy_netlink(struct net_device *mesh_iface,
|
||||
struct list_head *head)
|
||||
{
|
||||
struct batadv_priv *bat_priv = netdev_priv(mesh_iface);
|
||||
struct batadv_hard_iface *hard_iface;
|
||||
struct batadv_meshif_vlan *vlan;
|
||||
|
||||
while (!list_empty(&mesh_iface->adj_list.lower)) {
|
||||
hard_iface = netdev_adjacent_get_private(mesh_iface->adj_list.lower.next);
|
||||
batadv_hardif_disable_interface(hard_iface);
|
||||
}
|
||||
|
||||
/* destroy the "untagged" VLAN */
|
||||
vlan = batadv_meshif_vlan_get(bat_priv, BATADV_NO_FLAGS);
|
||||
if (vlan) {
|
||||
batadv_meshif_destroy_vlan(bat_priv, vlan);
|
||||
batadv_meshif_vlan_put(vlan);
|
||||
}
|
||||
|
||||
unregister_netdevice_queue(mesh_iface, head);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,8 @@ void batadv_interface_rx(struct net_device *mesh_iface,
|
||||
bool batadv_meshif_is_valid(const struct net_device *net_dev);
|
||||
extern struct rtnl_link_ops batadv_link_ops;
|
||||
int batadv_meshif_create_vlan(struct batadv_priv *bat_priv, unsigned short vid);
|
||||
void batadv_meshif_destroy_vlan(struct batadv_priv *bat_priv,
|
||||
struct batadv_meshif_vlan *vlan);
|
||||
void batadv_meshif_vlan_release(struct kref *ref);
|
||||
struct batadv_meshif_vlan *batadv_meshif_vlan_get(struct batadv_priv *bat_priv,
|
||||
unsigned short vid);
|
||||
|
||||
@@ -927,11 +927,11 @@ static int batadv_mcast_forw_packet(struct batadv_priv *bat_priv,
|
||||
{
|
||||
struct batadv_tvlv_mcast_tracker *mcast_tracker;
|
||||
struct batadv_neigh_node *neigh_node;
|
||||
unsigned long offset, num_dests_off;
|
||||
struct sk_buff *nexthop_skb;
|
||||
unsigned char *skb_net_hdr;
|
||||
bool local_recv = false;
|
||||
unsigned int tvlv_len;
|
||||
unsigned long offset;
|
||||
bool xmitted = false;
|
||||
u8 *dest, *next_dest;
|
||||
u16 num_dests;
|
||||
@@ -940,9 +940,8 @@ static int batadv_mcast_forw_packet(struct batadv_priv *bat_priv,
|
||||
/* (at least) TVLV part needs to be linearized */
|
||||
SKB_LINEAR_ASSERT(skb);
|
||||
|
||||
/* check if num_dests is within skb length */
|
||||
num_dests_off = offsetof(struct batadv_tvlv_mcast_tracker, num_dests);
|
||||
if (num_dests_off > skb_network_header_len(skb))
|
||||
/* check if batadv_tvlv_mcast_tracker header is within skb length */
|
||||
if (sizeof(*mcast_tracker) > skb_network_header_len(skb))
|
||||
return -EINVAL;
|
||||
|
||||
skb_net_hdr = skb_network_header(skb);
|
||||
|
||||
@@ -2971,7 +2971,7 @@ static bool batadv_send_tt_request(struct batadv_priv *bat_priv,
|
||||
out:
|
||||
batadv_hardif_put(primary_if);
|
||||
|
||||
if (ret && tt_req_node) {
|
||||
if (!ret && tt_req_node) {
|
||||
spin_lock_bh(&bat_priv->tt.req_list_lock);
|
||||
if (!hlist_unhashed(&tt_req_node->list)) {
|
||||
hlist_del_init(&tt_req_node->list);
|
||||
@@ -4033,7 +4033,8 @@ static int batadv_tt_tvlv_unicast_handler_v1(struct batadv_priv *bat_priv,
|
||||
u16 tvlv_value_len)
|
||||
{
|
||||
struct batadv_tvlv_tt_data *tt_data;
|
||||
u16 tt_vlan_len, tt_num_entries;
|
||||
u16 tt_num_entries;
|
||||
size_t tt_vlan_len;
|
||||
char tt_flag;
|
||||
bool ret;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user