diff options
author | Nikolay Aleksandrov <nikolay@redhat.com> | 2013-10-24 06:09:24 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-10-25 19:26:58 -0400 |
commit | c7c6effdeffcafd792b9f880ad52e48689eea4ad (patch) | |
tree | b80c4d38acd41a1d7b3afcbc5ba5a2f1958d401e /drivers/net/netconsole.c | |
parent | 45e526e80e6fdc796d3bc05716d5c930a427df4d (diff) |
netconsole: fix multiple race conditions
In every netconsole option that can be set through configfs there's a
race when checking for nt->enabled since it can be modified at the same
time. Probably the most damage can be done by store_enabled when racing
with another instance of itself. Fix all the races with one stone by
moving the mutex lock around the ->store call for all options.
Signed-off-by: Nikolay Aleksandrov <nikolay@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/netconsole.c')
-rw-r--r-- | drivers/net/netconsole.c | 10 |
1 files changed, 3 insertions, 7 deletions
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index 1505dcb950fa..c9a15925a1f7 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c | |||
@@ -325,9 +325,7 @@ static ssize_t store_enabled(struct netconsole_target *nt, | |||
325 | return -EINVAL; | 325 | return -EINVAL; |
326 | } | 326 | } |
327 | 327 | ||
328 | mutex_lock(&nt->mutex); | ||
329 | if (enabled) { /* 1 */ | 328 | if (enabled) { /* 1 */ |
330 | |||
331 | /* | 329 | /* |
332 | * Skip netpoll_parse_options() -- all the attributes are | 330 | * Skip netpoll_parse_options() -- all the attributes are |
333 | * already configured via configfs. Just print them out. | 331 | * already configured via configfs. Just print them out. |
@@ -335,13 +333,10 @@ static ssize_t store_enabled(struct netconsole_target *nt, | |||
335 | netpoll_print_options(&nt->np); | 333 | netpoll_print_options(&nt->np); |
336 | 334 | ||
337 | err = netpoll_setup(&nt->np); | 335 | err = netpoll_setup(&nt->np); |
338 | if (err) { | 336 | if (err) |
339 | mutex_unlock(&nt->mutex); | ||
340 | return err; | 337 | return err; |
341 | } | ||
342 | 338 | ||
343 | printk(KERN_INFO "netconsole: network logging started\n"); | 339 | printk(KERN_INFO "netconsole: network logging started\n"); |
344 | |||
345 | } else { /* 0 */ | 340 | } else { /* 0 */ |
346 | /* We need to disable the netconsole before cleaning it up | 341 | /* We need to disable the netconsole before cleaning it up |
347 | * otherwise we might end up in write_msg() with | 342 | * otherwise we might end up in write_msg() with |
@@ -354,7 +349,6 @@ static ssize_t store_enabled(struct netconsole_target *nt, | |||
354 | } | 349 | } |
355 | 350 | ||
356 | nt->enabled = enabled; | 351 | nt->enabled = enabled; |
357 | mutex_unlock(&nt->mutex); | ||
358 | 352 | ||
359 | return strnlen(buf, count); | 353 | return strnlen(buf, count); |
360 | } | 354 | } |
@@ -571,8 +565,10 @@ static ssize_t netconsole_target_attr_store(struct config_item *item, | |||
571 | struct netconsole_target_attr *na = | 565 | struct netconsole_target_attr *na = |
572 | container_of(attr, struct netconsole_target_attr, attr); | 566 | container_of(attr, struct netconsole_target_attr, attr); |
573 | 567 | ||
568 | mutex_lock(&nt->mutex); | ||
574 | if (na->store) | 569 | if (na->store) |
575 | ret = na->store(nt, buf, count); | 570 | ret = na->store(nt, buf, count); |
571 | mutex_unlock(&nt->mutex); | ||
576 | 572 | ||
577 | return ret; | 573 | return ret; |
578 | } | 574 | } |