Commit message: only allow dynamic UnregisterHandler for external handlers, thereby fixing DoS

Trying to unregister an internal handler ended up in a SEGFAULT, because
the tcmur_handler->opaque was NULL. Way to reproduce:

dbus-send --system --print-reply --dest=org.kernel.TCMUService1 /org/kernel/TCMUService1/HandlerManager1 org.kernel.TCMUService1.HandlerManager1.UnregisterHandler string:qcow

we use a newly introduced boolean in struct tcmur_handler for keeping
track of external handlers. As suggested by mikechristie adjusting the
public data structure is acceptable.
CVE: CVE-2017-1000200
CWE: CWE-476
Vulnerability description: tcmu-runner version 1.0.5 to 1.2.0 is vulnerable to a dbus triggered NULL pointer dereference in the tcmu-runner daemon's on_unregister_handler() function resulting in denial of service

Project: tcmu-runner
File: main.c

on_handler_appeared(GDBusConnection *connection,
		    const gchar     *name,
		    const gchar     *name_owner,
		    gpointer         user_data)
{
	struct tcmur_handler *handler = user_data;
	struct dbus_info *info = handler->opaque;
 
 	if (info->register_invocation) {
 		info->connection = connection;
		tcmur_register_dbus_handler(handler);
 		dbus_export_handler(handler, G_CALLBACK(on_dbus_check_config));
 		g_dbus_method_invocation_return_value(info->register_invocation,
 			    g_variant_new("(bs)", TRUE, "succeeded"));
		info->register_invocation = NULL;
	}
}

Project: tcmu-runner
File: main.c

on_handler_vanished(GDBusConnection *connection,
		    const gchar     *name,
		    gpointer         user_data)
{
	struct tcmur_handler *handler = user_data;
	struct dbus_info *info = handler->opaque;

	if (info->register_invocation) {
		char *reason;
		reason = g_strdup_printf("Cannot find handler bus name: "
				"org.kernel.TCMUService1.HandlerManager1.%s",
				handler->subtype);
		g_dbus_method_invocation_return_value(info->register_invocation,
 			    g_variant_new("(bs)", FALSE, reason));
 		g_free(reason);
 	}
	tcmur_unregister_dbus_handler(handler);
 	dbus_unexport_handler(handler);
 }

Project: tcmu-runner
File: main.c

on_register_handler(TCMUService1HandlerManager1 *interface,
		    GDBusMethodInvocation *invocation,
		    gchar *subtype,
		    gchar *cfg_desc,
		    gpointer user_data)
{
	struct tcmur_handler *handler;
	struct dbus_info *info;
	char *bus_name;

	bus_name = g_strdup_printf("org.kernel.TCMUService1.HandlerManager1.%s",
				   subtype);

	handler               = g_new0(struct tcmur_handler, 1);
	handler->subtype      = g_strdup(subtype);
	handler->cfg_desc     = g_strdup(cfg_desc);
	handler->open         = dbus_handler_open;
	handler->close        = dbus_handler_close;
 	handler->handle_cmd   = dbus_handler_handle_cmd;
 
 	info = g_new0(struct dbus_info, 1);
	handler->opaque = info;
	handler->_is_dbus_handler = 1;
 	info->register_invocation = invocation;
 	info->watcher_id = g_bus_watch_name(G_BUS_TYPE_SYSTEM,
 					    bus_name,
					    G_BUS_NAME_WATCHER_FLAGS_NONE,
					    on_handler_appeared,
					    on_handler_vanished,
					    handler,
					    NULL);
	g_free(bus_name);
	handler->opaque = info;
	return TRUE;
}

Project: tcmu-runner
File: main.c

on_unregister_handler(TCMUService1HandlerManager1 *interface,
		      GDBusMethodInvocation *invocation,
		      gchar *subtype,
		      gpointer user_data)
{
	struct tcmur_handler *handler = find_handler_by_subtype(subtype);
	struct dbus_info *info = handler ? handler->opaque : NULL;

	if (!handler) {
		g_dbus_method_invocation_return_value(invocation,
			g_variant_new("(bs)", FALSE,
 				      "unknown subtype"));
 		return TRUE;
 	}
	else if (handler->_is_dbus_handler != 1) {
		g_dbus_method_invocation_return_value(invocation,
			g_variant_new("(bs)", FALSE,
				      "cannot unregister internal handler"));
		return TRUE;
	}

 	dbus_unexport_handler(handler);
	tcmur_unregister_dbus_handler(handler);

 	g_bus_unwatch_name(info->watcher_id);
 	g_free(info);
 	g_free(handler);
	g_dbus_method_invocation_return_value(invocation,
		g_variant_new("(bs)", TRUE, "succeeded"));
	return TRUE;
}