1 From: Sven Eckelmann <sven@narfation.org>
2 Date: Fri, 31 Aug 2018 16:56:29 +0200
3 Subject: batman-adv: Fix segfault when writing to sysfs elp_interval
5 The per hardif sysfs file "batman_adv/elp_interval" is using the generic
6 functions to store/show uint values. The helper __batadv_store_uint_attr
7 requires the softif net_device as parameter to print the resulting change
8 as info text when the users writes to this file. It uses the helper
9 function batadv_info to add it at the same time to the kernel ring buffer
10 and to the batman-adv debug log (when CONFIG_BATMAN_ADV_DEBUG is enabled).
12 The function batadv_info requires as first parameter the batman-adv softif
13 net_device. This parameter is then used to find the private buffer which
14 contains the debug log for this batman-adv interface. But
15 batadv_store_throughput_override used as first argument the slave
16 net_device. This slave device doesn't have the batadv_priv private data
17 which is access by batadv_info.
19 Writing to this file with CONFIG_BATMAN_ADV_DEBUG enabled can either lead
20 to a segfault or to memory corruption.
22 Fixes: ec46535b8275 ("batman-adv: Add hard_iface specific sysfs wrapper macros for UINT")
23 Signed-off-by: Sven Eckelmann <sven@narfation.org>
24 Acked-by: Marek Lindner <mareklindner@neomailbox.ch>
26 Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/848be9859b0109a6e428f92f21f2e660153b1c75
28 diff --git a/net/batman-adv/sysfs.c b/net/batman-adv/sysfs.c
29 index ae22db3d6637dde2fcc238826a624ef2d6dbd8f5..a4e6f158de26dea0e8e3fefd5b9aeec3dcd64457 100644
30 --- a/net/batman-adv/sysfs.c
31 +++ b/net/batman-adv/sysfs.c
32 @@ -186,7 +186,8 @@ ssize_t batadv_store_##_name(struct kobject *kobj, \
34 return __batadv_store_uint_attr(buff, count, _min, _max, \
36 - &bat_priv->_var, net_dev); \
37 + &bat_priv->_var, net_dev, \
41 #define BATADV_ATTR_SIF_SHOW_UINT(_name, _var) \
42 @@ -260,7 +261,9 @@ ssize_t batadv_store_##_name(struct kobject *kobj, \
44 length = __batadv_store_uint_attr(buff, count, _min, _max, \
46 - &hard_iface->_var, net_dev); \
47 + &hard_iface->_var, \
48 + hard_iface->soft_iface, \
51 batadv_hardif_put(hard_iface); \
53 @@ -354,10 +357,12 @@ __batadv_store_bool_attr(char *buff, size_t count,
55 static int batadv_store_uint_attr(const char *buff, size_t count,
56 struct net_device *net_dev,
57 + struct net_device *slave_dev,
58 const char *attr_name,
59 unsigned int min, unsigned int max,
62 + char ifname[IFNAMSIZ + 3] = "";
63 unsigned long uint_val;
66 @@ -383,8 +388,11 @@ static int batadv_store_uint_attr(const char *buff, size_t count,
67 if (atomic_read(attr) == uint_val)
70 - batadv_info(net_dev, "%s: Changing from: %i to: %lu\n",
71 - attr_name, atomic_read(attr), uint_val);
73 + snprintf(ifname, sizeof(ifname), "%s: ", slave_dev->name);
75 + batadv_info(net_dev, "%s: %sChanging from: %i to: %lu\n",
76 + attr_name, ifname, atomic_read(attr), uint_val);
78 atomic_set(attr, uint_val);
80 @@ -395,12 +403,13 @@ static ssize_t __batadv_store_uint_attr(const char *buff, size_t count,
81 void (*post_func)(struct net_device *),
82 const struct attribute *attr,
84 - struct net_device *net_dev)
85 + struct net_device *net_dev,
86 + struct net_device *slave_dev)
90 - ret = batadv_store_uint_attr(buff, count, net_dev, attr->name, min, max,
92 + ret = batadv_store_uint_attr(buff, count, net_dev, slave_dev,
93 + attr->name, min, max, attr_store);
97 @@ -569,7 +578,7 @@ static ssize_t batadv_store_gw_sel_class(struct kobject *kobj,
98 return __batadv_store_uint_attr(buff, count, 1, BATADV_TQ_MAX_VALUE,
99 batadv_post_gw_reselect, attr,
100 &bat_priv->gw.sel_class,
101 - bat_priv->soft_iface);
102 + bat_priv->soft_iface, NULL);
105 static ssize_t batadv_show_gw_bwidth(struct kobject *kobj,