Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2a4ff3f7 authored by Steven Cahail's avatar Steven Cahail
Browse files

soc: qcom: glink_ssr: Register link state callbacks after adding to list



During probe(), the driver registers link state callbacks for each
subsystem information structure, and then adds structures to a list. In
the link state callback, this list is queried for the structure. If a
callback is triggered before the structure is added to the list, a NULL
pointer dereference can occur.

Only register link state callbacks after adding the subsystem
information structure to the list, and add a check in the link state
callback to see if the structure obtained in the list is NULL before
dereferencing it.

Change-Id: I18d317ba1f70f0051a4adb83c74142d3bd33a1ae
Signed-off-by: default avatarSteven Cahail <scahail@codeaurora.org>
parent 18c43109
Loading
Loading
Loading
Loading
+19 −15
Original line number Diff line number Diff line
/* Copyright (c) 2014, The Linux Foundation. All rights reserved.
/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -189,10 +189,13 @@ static void glink_ssr_link_state_cb(struct glink_link_state_cb_info *cb_info,
		GLINK_INFO("<SSR> %s: LINK DOWN %s:%s\n", __func__,
				cb_info->edge,
				cb_info->transport);
		if (ss_info) {
			GLINK_INFO("<SSR> %s: ss_info is NULL\n", __func__);
			ss_info->link_up = false;
			ss_info->handle = NULL;
		}
	}
}

/**
 * glink_ssr_notify_rx() - RX Notification callback
@@ -761,21 +764,12 @@ static int glink_ssr_probe(struct platform_device *pdev)
	ss_info->handle = NULL;
	ss_info->cb_data = NULL;

	link_state_handle = glink_register_link_state_cb(ss_info->link_info,
			NULL);
	if (IS_ERR_OR_NULL(link_state_handle)) {
		GLINK_ERR("<SSR> %s: Could not register link state cb\n",
				__func__);
		ret = PTR_ERR(link_state_handle);
		goto label_or_edge_missing;
	}

	nb = kmalloc(sizeof(struct restart_notifier_block), GFP_KERNEL);
	if (!nb) {
		GLINK_ERR("<SSR> %s: Could not allocate notifier block\n",
				__func__);
		ret = -ENOMEM;
		goto restart_notifier_fail;
		goto label_or_edge_missing;
	}

	nb->subsystem = subsys_name;
@@ -834,8 +828,20 @@ static int glink_ssr_probe(struct platform_device *pdev)
	}

	list_add_tail(&ss_info->subsystem_list_node, &subsystem_list);

	link_state_handle = glink_register_link_state_cb(ss_info->link_info,
			NULL);
	if (IS_ERR_OR_NULL(link_state_handle)) {
		GLINK_ERR("<SSR> %s: Could not register link state cb\n",
				__func__);
		ret = PTR_ERR(link_state_handle);
		goto link_state_register_fail;
	}

	return 0;

link_state_register_fail:
	list_del(&ss_info->subsystem_list_node);
invalid_dt_node:
	kfree(ss_info_leaf);
notify_edges_not_present:
@@ -843,8 +849,6 @@ notify_edges_not_present:
	delete_ss_info_notify_list(ss_info);
nb_registration_fail:
	kfree(nb);
restart_notifier_fail:
	glink_unregister_link_state_cb(link_state_handle);
label_or_edge_missing:
	kfree(link_info);
link_info_alloc_failed: