aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSven Eckelmann <sven@narfation.org>2018-08-31 10:56:29 -0400
committerSimon Wunderlich <sw@simonwunderlich.de>2018-09-06 07:54:48 -0400
commita25bab9d723a08bd0bdafb1529faf9094c690b70 (patch)
tree284b63130f2d9a96cf1cc82d2f7a809805a7afbf
parentb9fd14c20871e6189f635e49b32d7789e430b3c8 (diff)
batman-adv: Fix segfault when writing to sysfs elp_interval
The per hardif sysfs file "batman_adv/elp_interval" is using the generic functions to store/show uint values. The helper __batadv_store_uint_attr requires the softif net_device as parameter to print the resulting change as info text when the users writes to this file. It uses the helper function batadv_info to add it at the same time to the kernel ring buffer and to the batman-adv debug log (when CONFIG_BATMAN_ADV_DEBUG is enabled). The function batadv_info requires as first parameter the batman-adv softif net_device. This parameter is then used to find the private buffer which contains the debug log for this batman-adv interface. But batadv_store_throughput_override used as first argument the slave net_device. This slave device doesn't have the batadv_priv private data which is access by batadv_info. Writing to this file with CONFIG_BATMAN_ADV_DEBUG enabled can either lead to a segfault or to memory corruption. Fixes: 0744ff8fa8fa ("batman-adv: Add hard_iface specific sysfs wrapper macros for UINT") Signed-off-by: Sven Eckelmann <sven@narfation.org> Acked-by: Marek Lindner <mareklindner@neomailbox.ch> Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
-rw-r--r--net/batman-adv/sysfs.c25
1 files changed, 17 insertions, 8 deletions
diff --git a/net/batman-adv/sysfs.c b/net/batman-adv/sysfs.c
index 3a76e8970c02..09427fc6494a 100644
--- a/net/batman-adv/sysfs.c
+++ b/net/batman-adv/sysfs.c
@@ -188,7 +188,8 @@ ssize_t batadv_store_##_name(struct kobject *kobj, \
188 \ 188 \
189 return __batadv_store_uint_attr(buff, count, _min, _max, \ 189 return __batadv_store_uint_attr(buff, count, _min, _max, \
190 _post_func, attr, \ 190 _post_func, attr, \
191 &bat_priv->_var, net_dev); \ 191 &bat_priv->_var, net_dev, \
192 NULL); \
192} 193}
193 194
194#define BATADV_ATTR_SIF_SHOW_UINT(_name, _var) \ 195#define BATADV_ATTR_SIF_SHOW_UINT(_name, _var) \
@@ -262,7 +263,9 @@ ssize_t batadv_store_##_name(struct kobject *kobj, \
262 \ 263 \
263 length = __batadv_store_uint_attr(buff, count, _min, _max, \ 264 length = __batadv_store_uint_attr(buff, count, _min, _max, \
264 _post_func, attr, \ 265 _post_func, attr, \
265 &hard_iface->_var, net_dev); \ 266 &hard_iface->_var, \
267 hard_iface->soft_iface, \
268 net_dev); \
266 \ 269 \
267 batadv_hardif_put(hard_iface); \ 270 batadv_hardif_put(hard_iface); \
268 return length; \ 271 return length; \
@@ -356,10 +359,12 @@ __batadv_store_bool_attr(char *buff, size_t count,
356 359
357static int batadv_store_uint_attr(const char *buff, size_t count, 360static int batadv_store_uint_attr(const char *buff, size_t count,
358 struct net_device *net_dev, 361 struct net_device *net_dev,
362 struct net_device *slave_dev,
359 const char *attr_name, 363 const char *attr_name,
360 unsigned int min, unsigned int max, 364 unsigned int min, unsigned int max,
361 atomic_t *attr) 365 atomic_t *attr)
362{ 366{
367 char ifname[IFNAMSIZ + 3] = "";
363 unsigned long uint_val; 368 unsigned long uint_val;
364 int ret; 369 int ret;
365 370
@@ -385,8 +390,11 @@ static int batadv_store_uint_attr(const char *buff, size_t count,
385 if (atomic_read(attr) == uint_val) 390 if (atomic_read(attr) == uint_val)
386 return count; 391 return count;
387 392
388 batadv_info(net_dev, "%s: Changing from: %i to: %lu\n", 393 if (slave_dev)
389 attr_name, atomic_read(attr), uint_val); 394 snprintf(ifname, sizeof(ifname), "%s: ", slave_dev->name);
395
396 batadv_info(net_dev, "%s: %sChanging from: %i to: %lu\n",
397 attr_name, ifname, atomic_read(attr), uint_val);
390 398
391 atomic_set(attr, uint_val); 399 atomic_set(attr, uint_val);
392 return count; 400 return count;
@@ -397,12 +405,13 @@ static ssize_t __batadv_store_uint_attr(const char *buff, size_t count,
397 void (*post_func)(struct net_device *), 405 void (*post_func)(struct net_device *),
398 const struct attribute *attr, 406 const struct attribute *attr,
399 atomic_t *attr_store, 407 atomic_t *attr_store,
400 struct net_device *net_dev) 408 struct net_device *net_dev,
409 struct net_device *slave_dev)
401{ 410{
402 int ret; 411 int ret;
403 412
404 ret = batadv_store_uint_attr(buff, count, net_dev, attr->name, min, max, 413 ret = batadv_store_uint_attr(buff, count, net_dev, slave_dev,
405 attr_store); 414 attr->name, min, max, attr_store);
406 if (post_func && ret) 415 if (post_func && ret)
407 post_func(net_dev); 416 post_func(net_dev);
408 417
@@ -571,7 +580,7 @@ static ssize_t batadv_store_gw_sel_class(struct kobject *kobj,
571 return __batadv_store_uint_attr(buff, count, 1, BATADV_TQ_MAX_VALUE, 580 return __batadv_store_uint_attr(buff, count, 1, BATADV_TQ_MAX_VALUE,
572 batadv_post_gw_reselect, attr, 581 batadv_post_gw_reselect, attr,
573 &bat_priv->gw.sel_class, 582 &bat_priv->gw.sel_class,
574 bat_priv->soft_iface); 583 bat_priv->soft_iface, NULL);
575} 584}
576 585
577static ssize_t batadv_show_gw_bwidth(struct kobject *kobj, 586static ssize_t batadv_show_gw_bwidth(struct kobject *kobj,