diff mbox

Send TERMINATING event to Framework upon crash

Message ID 1426700405-10473-1-git-send-email-berthe.ab@gmail.com
State Changes Requested
Headers show

Commit Message

abdoulaye berthe March 18, 2015, 5:40 p.m. UTC
From: Abdoulaye Berthe <berthe.ab@gmail.com>

This sends a terminating event to Android Framework to report
wpa_supplicant crash. It is done by saving the initial crash handler
and regitering a new one. When a crash occurs, the new handler sends
a TERMINATE CTRL-EVENT to Android Framework and call the saved handler.
The TERMINATE CTRL-EVENT allows Android to detect supplicant crash.

Signed-off-by: Abdoulaye Berthe <abdoulaye.berthe@sonymobile.com>
---
 src/utils/eloop.c               | 67 +++++++++++++++++++++++++++++++++++++++++
 src/utils/eloop.h               | 19 ++++++++++++
 wpa_supplicant/wpa_supplicant.c | 23 ++++++++++++++
 3 files changed, 109 insertions(+)

Comments

Jouni Malinen March 18, 2015, 8:44 p.m. UTC | #1
On Wed, Mar 18, 2015 at 06:40:05PM +0100, abdoulaye berthe wrote:
> This sends a terminating event to Android Framework to report
> wpa_supplicant crash. It is done by saving the initial crash handler
> and regitering a new one. When a crash occurs, the new handler sends
> a TERMINATE CTRL-EVENT to Android Framework and call the saved handler.
> The TERMINATE CTRL-EVENT allows Android to detect supplicant crash.

Is this really a safe thing to do? If the process crashes and ends up in
SIGSEGV handler, I would not trust on the ctrl_iface socket or its file
descriptor being in valid state and as such, I would not really want to
write there since who knows where that would go if another file
descriptor is selected accidentally due to some corruption in memory.
diff mbox

Patch

diff --git a/src/utils/eloop.c b/src/utils/eloop.c
index 4a565eb..6e56737 100644
--- a/src/utils/eloop.c
+++ b/src/utils/eloop.c
@@ -30,6 +30,14 @@ 
 #include <sys/epoll.h>
 #endif /* CONFIG_ELOOP_EPOLL */
 
+#ifdef ANDROID
+struct eloop_saved_signal {
+	int signal;
+	void *signal_user_data;
+	signal_handler *handler;
+};
+#endif /* ANDROID */
+
 struct eloop_sock {
 	int sock;
 	void *eloop_data;
@@ -101,6 +109,10 @@  struct eloop_data {
 
 static struct eloop_data eloop;
 
+#ifdef ANDROID
+int saved_signal_count;
+struct eloop_saved_signal *saved_signals;
+#endif /* ANDROID */
 
 #ifdef WPA_TRACE
 
@@ -883,6 +895,34 @@  int eloop_register_signal_terminate(eloop_signal_handler handler,
 	return ret;
 }
 
+#ifdef ANDROID
+int eloop_register_signal_and_save_handler(int sig, void *handler, void *user_data)
+{
+	void (*pret)(int);
+	pret = signal(sig, handler);
+
+	if (pret != SIG_ERR) {
+		struct eloop_saved_signal *tmp;
+		tmp = os_realloc_array(saved_signals, saved_signal_count + 1,
+				       sizeof(struct eloop_saved_signal));
+		if (tmp == NULL) {
+			return -1;
+		}
+
+		tmp[saved_signal_count].signal = sig;
+		tmp[saved_signal_count].handler = (signal_handler *) pret;
+		tmp[saved_signal_count].signal_user_data = user_data;
+		saved_signal_count ++;
+		saved_signals = tmp;
+		wpa_printf(MSG_DEBUG, "eloop_register_signal_sig_segv_handler success");
+	} else {
+		wpa_printf(MSG_ERROR, "eloop_register_signal_sig_segv_handler failure");
+		return -1;
+	}
+
+	return 0;
+}
+#endif /* ANDROID */
 
 int eloop_register_signal_reconfig(eloop_signal_handler handler,
 				   void *user_data)
@@ -1058,6 +1098,9 @@  void eloop_destroy(void)
 	eloop_sock_table_destroy(&eloop.writers);
 	eloop_sock_table_destroy(&eloop.exceptions);
 	os_free(eloop.signals);
+#ifdef ANDROID
+	os_free(saved_signals);
+#endif /* ANDROID */
 
 #ifdef CONFIG_ELOOP_POLL
 	os_free(eloop.pollfds);
@@ -1111,3 +1154,27 @@  void eloop_wait_for_read_sock(int sock)
 #ifdef CONFIG_ELOOP_SELECT
 #undef CONFIG_ELOOP_SELECT
 #endif /* CONFIG_ELOOP_SELECT */
+
+#ifdef ANDROID
+void * eloop_get_saved_signal_user_data(int sig)
+{
+	int i;
+	for (i = 0; i < saved_signal_count; i++) {
+		if (saved_signals[i].signal == sig) {
+			return saved_signals[i].signal_user_data;
+		}
+	}
+	return NULL;
+}
+
+signal_handler * eloop_get_saved_signal_handler(int sig)
+{
+	int i;
+	for (i = 0; i < saved_signal_count; i++) {
+		if (saved_signals[i].signal == sig) {
+			return saved_signals[i].handler;
+		}
+	}
+	return NULL;
+}
+#endif /* ANDROID */
diff --git a/src/utils/eloop.h b/src/utils/eloop.h
index 07b8c0d..1a20bf7 100644
--- a/src/utils/eloop.h
+++ b/src/utils/eloop.h
@@ -65,6 +65,10 @@  typedef void (*eloop_timeout_handler)(void *eloop_data, void *user_ctx);
  */
 typedef void (*eloop_signal_handler)(int sig, void *signal_ctx);
 
+#ifdef ANDROID
+typedef void (*signal_handler)(int sig);
+#endif /* ANDROID */
+
 /**
  * eloop_init() - Initialize global event loop data
  * Returns: 0 on success, -1 on failure
@@ -312,6 +316,15 @@  int eloop_register_signal_terminate(eloop_signal_handler handler,
 int eloop_register_signal_reconfig(eloop_signal_handler handler,
 				   void *user_data);
 
+#ifdef ANDROID
+/*
+ * eloop_register_signal_and_save_handler - Save old handler and register a
+ * new handler for signal.
+ */
+int eloop_register_signal_and_save_handler(int sig, void *handler,
+					   void *user_data);
+#endif /* ANDROID */
+
 /**
  * eloop_run - Start the event loop
  *
@@ -356,4 +369,10 @@  int eloop_terminated(void);
  */
 void eloop_wait_for_read_sock(int sock);
 
+#ifdef ANDROID
+void * eloop_get_saved_signal_user_data(int sig);
+
+signal_handler * eloop_get_saved_signal_handler(int sig);
+#endif /* ANDROID */
+
 #endif /* ELOOP_H */
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 19fb890..29cfdd7 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -812,6 +812,25 @@  static void wpa_supplicant_terminate(int sig, void *signal_ctx)
 	wpa_supplicant_terminate_proc(global);
 }
 
+#ifdef ANDROID
+static void wpa_supplicant_process_crash_signal(int sig)
+{
+	/* Send terminating event to state machine and recall saved handler for crash report */
+	struct wpa_global *global;
+	struct wpa_supplicant *wpa_s;
+	global = (struct wpa_global *) eloop_get_saved_signal_user_data(sig);
+	if (global) {
+		wpa_s = global->ifaces;
+		wpa_dbg(wpa_s, MSG_DEBUG, "%s: sending WPA_EVENT_TERMINATING to ctrl socket", __func__);
+		wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
+	}
+
+	if (eloop_get_saved_signal_handler(sig) != NULL) {
+		(*eloop_get_saved_signal_handler(sig))(sig);
+	}
+}
+#endif /* ANDROID */
+
 
 void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
 {
@@ -4642,6 +4661,10 @@  int wpa_supplicant_run(struct wpa_global *global)
 
 	eloop_register_signal_terminate(wpa_supplicant_terminate, global);
 	eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
+#ifdef ANDROID
+	eloop_register_signal_and_save_handler(SIGSEGV, wpa_supplicant_process_crash_signal,
+					       global);
+#endif /* ANDROID */
 
 	eloop_run();