diff options
author | Nikolay Aleksandrov <nikolay@redhat.com> | 2013-10-23 09:04:49 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-10-25 19:26:58 -0400 |
commit | 45e526e80e6fdc796d3bc05716d5c930a427df4d (patch) | |
tree | 1d6909c66190e5e5a30c28fa66b6edd760126f07 /drivers/net/netconsole.c | |
parent | 0e67d9903d71ce3c5889fa2e1788d4335794a0f6 (diff) |
netconsole: fix NULL pointer dereference
We need to disable the netconsole (enabled = 0) before setting nt->np.dev
to NULL because otherwise we might still have users after the
netpoll_cleanup() since nt->enabled is set afterwards and we can
have a message which will result in a NULL pointer dereference.
It is very easy to hit dereferences all over the netpoll_send_udp function
by running the following two loops in parallel:
while [ 1 ]; do echo 1 > enabled; echo 0 > enabled; done;
while [ 1 ]; do echo 00:11:22:33:44:55 > remote_mac; done;
(the second loop is to generate messages, it can be done by anything)
We're safe to set nt->np.dev = NULL and nt->enabled = 0 with the spinlock
since it's required in the write_msg() function.
Signed-off-by: Nikolay Aleksandrov <nikolay@redhat.com>
Reviewed-by: Veacelsav Falico <vfalico@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 | 8 |
1 files changed, 8 insertions, 0 deletions
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index adeee615dd19..1505dcb950fa 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c | |||
@@ -310,6 +310,7 @@ static ssize_t store_enabled(struct netconsole_target *nt, | |||
310 | const char *buf, | 310 | const char *buf, |
311 | size_t count) | 311 | size_t count) |
312 | { | 312 | { |
313 | unsigned long flags; | ||
313 | int enabled; | 314 | int enabled; |
314 | int err; | 315 | int err; |
315 | 316 | ||
@@ -342,6 +343,13 @@ static ssize_t store_enabled(struct netconsole_target *nt, | |||
342 | printk(KERN_INFO "netconsole: network logging started\n"); | 343 | printk(KERN_INFO "netconsole: network logging started\n"); |
343 | 344 | ||
344 | } else { /* 0 */ | 345 | } else { /* 0 */ |
346 | /* We need to disable the netconsole before cleaning it up | ||
347 | * otherwise we might end up in write_msg() with | ||
348 | * nt->np.dev == NULL and nt->enabled == 1 | ||
349 | */ | ||
350 | spin_lock_irqsave(&target_list_lock, flags); | ||
351 | nt->enabled = 0; | ||
352 | spin_unlock_irqrestore(&target_list_lock, flags); | ||
345 | netpoll_cleanup(&nt->np); | 353 | netpoll_cleanup(&nt->np); |
346 | } | 354 | } |
347 | 355 | ||