summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Sommerseth <davids@redhat.com>2012-11-16 12:02:06 +0100
committerDavid Sommerseth <davids@redhat.com>2012-11-29 21:47:57 +0100
commit5541ea21691b5b39adc4bd3e1ff1af86a050c71d (patch)
tree59243d471b7ba79c40076f4f68eb252bbf624b49
parent28d9e57638d66fde792a53a3eb6391ddb8bb426f (diff)
downloadopenvpn-5541ea21691b5b39adc4bd3e1ff1af86a050c71d.tar.gz
openvpn-5541ea21691b5b39adc4bd3e1ff1af86a050c71d.tar.xz
openvpn-5541ea21691b5b39adc4bd3e1ff1af86a050c71d.zip
Avoid recursion in virtual_output_callback_func()
This solves a SEGV situation when using the management API while OpenVPN is closing down. The situation happens when the management socket has closed and OpenVPN tries to write an error about this to the management socket. What happens is that virtual_output_callback_func() is called, which then calls -> man_output_list_push_finalize() -> man_output_standalone() -> man_write() <-- this does the socket write -> man_io_error() -> x_msg() -> virtual_output_print() -> virtual_output_callback_func() (recursion start) virtual_output_callback_func() do have a mechanism to avoid recursion, but that did not keep the recurse counter when man_output_list_push_finalize() is called. This patch just reorganise the recursion block to also keep the counter while calling the other functions from virtual_output_callback_func() Signed-off-by: David Sommerseth <davids@redhat.com> Acked-by: Gert Doering <gert@greenie.muc.de> Message-Id: 1353063726-25113-1-git-send-email-dazo@users.sourceforge.net URL: http://article.gmane.org/gmane.network.openvpn.devel/7130 (cherry picked from commit b2b66179f6dcc37de9582d5c3044f0357dda3df3)
-rw-r--r--src/openvpn/manage.c15
1 files changed, 8 insertions, 7 deletions
diff --git a/src/openvpn/manage.c b/src/openvpn/manage.c
index d0bb416..0a4542a 100644
--- a/src/openvpn/manage.c
+++ b/src/openvpn/manage.c
@@ -287,13 +287,13 @@ virtual_output_callback_func (void *arg, const unsigned int flags, const char *s
# define AF_DID_PUSH (1<<0)
# define AF_DID_RESET (1<<1)
- unsigned int action_flags = 0;
if (!recursive_level) /* don't allow recursion */
{
struct gc_arena gc = gc_new ();
struct log_entry e;
const char *out = NULL;
+ unsigned int action_flags = 0;
++recursive_level;
@@ -334,14 +334,15 @@ virtual_output_callback_func (void *arg, const unsigned int flags, const char *s
}
}
- --recursive_level;
gc_free (&gc);
- }
- if (action_flags & AF_DID_PUSH)
- man_output_list_push_finalize (man);
- if (action_flags & AF_DID_RESET)
- man_reset_client_socket (man, true);
+ if (action_flags & AF_DID_PUSH)
+ man_output_list_push_finalize (man);
+ if (action_flags & AF_DID_RESET)
+ man_reset_client_socket (man, true);
+
+ --recursive_level;
+ }
}
/*