234 lines
8.9 KiB
Diff
234 lines
8.9 KiB
Diff
From: Sven Eckelmann <sven@narfation.org>
|
|
Date: Tue, 26 Dec 2017 15:14:01 +0100
|
|
Subject: batman-adv: Fix internal interface indices types
|
|
|
|
batman-adv uses internal indices for each enabled and active interface.
|
|
It is currently used by the B.A.T.M.A.N. IV algorithm to identifify the
|
|
correct position in the ogm_cnt bitmaps.
|
|
|
|
The type for the number of enabled interfaces (which defines the next
|
|
interface index) was set to char. This type can be (depending on the
|
|
architecture) either signed (limiting batman-adv to 127 active slave
|
|
interfaces) or unsigned (limiting batman-adv to 255 active slave
|
|
interfaces).
|
|
|
|
This limit was not correctly checked when an interface was enabled and thus
|
|
an overflow happened. This was only catched on systems with the signed char
|
|
type when the B.A.T.M.A.N. IV code tried to resize its counter arrays with
|
|
a negative size.
|
|
|
|
The if_num interface index was only a s16 and therefore significantly
|
|
smaller than the ifindex (int) used by the code net code.
|
|
|
|
Both &batadv_hard_iface->if_num and &batadv_priv->num_ifaces must be
|
|
(unsigned) int to support the same number of slave interfaces as the net
|
|
core code. And the interface activation code must check the number of
|
|
active slave interfaces to avoid integer overflows.
|
|
|
|
Fixes: d1fbb61d0534 ("raw socket operations added: create / destroy / bind / send broadcast of own OGMs implemented orig interval configurable via /proc/net/batman-adv/orig_interval")
|
|
Fixes: ea6f8d42a595 ("batman-adv: move /proc interface handling to /sys")
|
|
Signed-off-by: Sven Eckelmann <sven@narfation.org>
|
|
Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
|
|
|
|
Origin: backport, https://git.open-mesh.org/batman-adv.git/commit/d5db560de1352d3ec6933bca25b3aaad7ddd15e1
|
|
|
|
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
|
|
index 1847898906d495980a71eb6a0e5a7b510e55d003..bf389adbb2694746d6397a0a38353cdcd8008899 100644
|
|
--- a/net/batman-adv/bat_iv_ogm.c
|
|
+++ b/net/batman-adv/bat_iv_ogm.c
|
|
@@ -149,7 +149,7 @@ static void batadv_iv_ogm_orig_free(struct batadv_orig_node *orig_node)
|
|
* Return: 0 on success, a negative error code otherwise.
|
|
*/
|
|
static int batadv_iv_ogm_orig_add_if(struct batadv_orig_node *orig_node,
|
|
- int max_if_num)
|
|
+ unsigned int max_if_num)
|
|
{
|
|
void *data_ptr;
|
|
size_t old_size;
|
|
@@ -193,7 +193,8 @@ unlock:
|
|
*/
|
|
static void
|
|
batadv_iv_ogm_drop_bcast_own_entry(struct batadv_orig_node *orig_node,
|
|
- int max_if_num, int del_if_num)
|
|
+ unsigned int max_if_num,
|
|
+ unsigned int del_if_num)
|
|
{
|
|
size_t chunk_size;
|
|
size_t if_offset;
|
|
@@ -231,7 +232,8 @@ batadv_iv_ogm_drop_bcast_own_entry(struct batadv_orig_node *orig_node,
|
|
*/
|
|
static void
|
|
batadv_iv_ogm_drop_bcast_own_sum_entry(struct batadv_orig_node *orig_node,
|
|
- int max_if_num, int del_if_num)
|
|
+ unsigned int max_if_num,
|
|
+ unsigned int del_if_num)
|
|
{
|
|
size_t if_offset;
|
|
void *data_ptr;
|
|
@@ -268,7 +270,8 @@ batadv_iv_ogm_drop_bcast_own_sum_entry(struct batadv_orig_node *orig_node,
|
|
* Return: 0 on success, a negative error code otherwise.
|
|
*/
|
|
static int batadv_iv_ogm_orig_del_if(struct batadv_orig_node *orig_node,
|
|
- int max_if_num, int del_if_num)
|
|
+ unsigned int max_if_num,
|
|
+ unsigned int del_if_num)
|
|
{
|
|
spin_lock_bh(&orig_node->bat_iv.ogm_cnt_lock);
|
|
|
|
@@ -302,7 +305,8 @@ static struct batadv_orig_node *
|
|
batadv_iv_ogm_orig_get(struct batadv_priv *bat_priv, const u8 *addr)
|
|
{
|
|
struct batadv_orig_node *orig_node;
|
|
- int size, hash_added;
|
|
+ int hash_added;
|
|
+ size_t size;
|
|
|
|
orig_node = batadv_orig_hash_find(bat_priv, addr);
|
|
if (orig_node)
|
|
@@ -885,7 +889,7 @@ batadv_iv_ogm_slide_own_bcast_window(struct batadv_hard_iface *hard_iface)
|
|
u32 i;
|
|
size_t word_index;
|
|
u8 *w;
|
|
- int if_num;
|
|
+ unsigned int if_num;
|
|
|
|
for (i = 0; i < hash->size; i++) {
|
|
head = &hash->table[i];
|
|
@@ -1015,7 +1019,7 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
|
|
struct batadv_neigh_node *tmp_neigh_node = NULL;
|
|
struct batadv_neigh_node *router = NULL;
|
|
struct batadv_orig_node *orig_node_tmp;
|
|
- int if_num;
|
|
+ unsigned int if_num;
|
|
u8 sum_orig, sum_neigh;
|
|
u8 *neigh_addr;
|
|
u8 tq_avg;
|
|
@@ -1173,7 +1177,7 @@ static bool batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node,
|
|
u8 total_count;
|
|
u8 orig_eq_count, neigh_rq_count, neigh_rq_inv, tq_own;
|
|
unsigned int neigh_rq_inv_cube, neigh_rq_max_cube;
|
|
- int if_num;
|
|
+ unsigned int if_num;
|
|
unsigned int tq_asym_penalty, inv_asym_penalty;
|
|
unsigned int combined_tq;
|
|
unsigned int tq_iface_penalty;
|
|
@@ -1692,9 +1696,9 @@ static void batadv_iv_ogm_process(const struct sk_buff *skb, int ogm_offset,
|
|
|
|
if (is_my_orig) {
|
|
unsigned long *word;
|
|
- int offset;
|
|
+ size_t offset;
|
|
s32 bit_pos;
|
|
- s16 if_num;
|
|
+ unsigned int if_num;
|
|
u8 *weight;
|
|
|
|
orig_neigh_node = batadv_iv_ogm_orig_get(bat_priv,
|
|
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c
|
|
index 6969f580d0bfd0428f1c6985eaec8bbbf5a0d38b..ebeea5816a06b33c4944b01e40cee157c88bdff7 100644
|
|
--- a/net/batman-adv/hard-interface.c
|
|
+++ b/net/batman-adv/hard-interface.c
|
|
@@ -741,6 +741,11 @@ int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
|
|
hard_iface->soft_iface = soft_iface;
|
|
bat_priv = netdev_priv(hard_iface->soft_iface);
|
|
|
|
+ if (bat_priv->num_ifaces >= UINT_MAX) {
|
|
+ ret = -ENOSPC;
|
|
+ goto err_dev;
|
|
+ }
|
|
+
|
|
ret = netdev_master_upper_dev_link(hard_iface->net_dev,
|
|
soft_iface, NULL, NULL);
|
|
if (ret)
|
|
@@ -848,7 +853,7 @@ void batadv_hardif_disable_interface(struct batadv_hard_iface *hard_iface,
|
|
batadv_hardif_recalc_extra_skbroom(hard_iface->soft_iface);
|
|
|
|
/* nobody uses this interface anymore */
|
|
- if (!bat_priv->num_ifaces) {
|
|
+ if (bat_priv->num_ifaces == 0) {
|
|
batadv_gw_check_client_stop(bat_priv);
|
|
|
|
if (autodel == BATADV_IF_CLEANUP_AUTO)
|
|
@@ -884,7 +889,7 @@ batadv_hardif_add_interface(struct net_device *net_dev)
|
|
if (ret)
|
|
goto free_if;
|
|
|
|
- hard_iface->if_num = -1;
|
|
+ hard_iface->if_num = 0;
|
|
hard_iface->net_dev = net_dev;
|
|
hard_iface->soft_iface = NULL;
|
|
hard_iface->if_status = BATADV_IF_NOT_IN_USE;
|
|
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c
|
|
index 8f3b2969cc4e3044e714086329166b9a3b7517a4..d9ee84340d93bd03f1de504f7223c7f894818906 100644
|
|
--- a/net/batman-adv/originator.c
|
|
+++ b/net/batman-adv/originator.c
|
|
@@ -1500,7 +1500,7 @@ int batadv_orig_dump(struct sk_buff *msg, struct netlink_callback *cb)
|
|
}
|
|
|
|
int batadv_orig_hash_add_if(struct batadv_hard_iface *hard_iface,
|
|
- int max_if_num)
|
|
+ unsigned int max_if_num)
|
|
{
|
|
struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
|
|
struct batadv_algo_ops *bao = bat_priv->algo_ops;
|
|
@@ -1535,7 +1535,7 @@ err:
|
|
}
|
|
|
|
int batadv_orig_hash_del_if(struct batadv_hard_iface *hard_iface,
|
|
- int max_if_num)
|
|
+ unsigned int max_if_num)
|
|
{
|
|
struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
|
|
struct batadv_hashtable *hash = bat_priv->orig_hash;
|
|
diff --git a/net/batman-adv/originator.h b/net/batman-adv/originator.h
|
|
index ebc56183f3581835c899272425a212ff092033b6..fab0b2cc141d9affdbcf68f1d0ce7aad753c3857 100644
|
|
--- a/net/batman-adv/originator.h
|
|
+++ b/net/batman-adv/originator.h
|
|
@@ -78,9 +78,9 @@ int batadv_orig_seq_print_text(struct seq_file *seq, void *offset);
|
|
int batadv_orig_dump(struct sk_buff *msg, struct netlink_callback *cb);
|
|
int batadv_orig_hardif_seq_print_text(struct seq_file *seq, void *offset);
|
|
int batadv_orig_hash_add_if(struct batadv_hard_iface *hard_iface,
|
|
- int max_if_num);
|
|
+ unsigned int max_if_num);
|
|
int batadv_orig_hash_del_if(struct batadv_hard_iface *hard_iface,
|
|
- int max_if_num);
|
|
+ unsigned int max_if_num);
|
|
struct batadv_orig_node_vlan *
|
|
batadv_orig_node_vlan_new(struct batadv_orig_node *orig_node,
|
|
unsigned short vid);
|
|
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
|
|
index 7c928938b22dcae681294700252c0ae74378f999..bf1d3f0258ffb2fb8ee483337012798b20462cd6 100644
|
|
--- a/net/batman-adv/types.h
|
|
+++ b/net/batman-adv/types.h
|
|
@@ -155,7 +155,7 @@ enum batadv_hard_iface_wifi_flags {
|
|
*/
|
|
struct batadv_hard_iface {
|
|
struct list_head list;
|
|
- s16 if_num;
|
|
+ unsigned int if_num;
|
|
char if_status;
|
|
u8 num_bcasts;
|
|
u32 wifi_flags;
|
|
@@ -1081,7 +1081,7 @@ struct batadv_priv {
|
|
atomic_t bcast_seqno;
|
|
atomic_t bcast_queue_left;
|
|
atomic_t batman_queue_left;
|
|
- char num_ifaces;
|
|
+ unsigned int num_ifaces;
|
|
struct kobject *mesh_obj;
|
|
struct dentry *debug_dir;
|
|
struct hlist_head forw_bat_list;
|
|
@@ -1477,9 +1477,10 @@ struct batadv_algo_neigh_ops {
|
|
*/
|
|
struct batadv_algo_orig_ops {
|
|
void (*free)(struct batadv_orig_node *orig_node);
|
|
- int (*add_if)(struct batadv_orig_node *orig_node, int max_if_num);
|
|
- int (*del_if)(struct batadv_orig_node *orig_node, int max_if_num,
|
|
- int del_if_num);
|
|
+ int (*add_if)(struct batadv_orig_node *orig_node,
|
|
+ unsigned int max_if_num);
|
|
+ int (*del_if)(struct batadv_orig_node *orig_node,
|
|
+ unsigned int max_if_num, unsigned int del_if_num);
|
|
#ifdef CONFIG_BATMAN_ADV_DEBUGFS
|
|
void (*print)(struct batadv_priv *priv, struct seq_file *seq,
|
|
struct batadv_hard_iface *hard_iface);
|