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

Commit 1e937d5c authored by Utkarsh Bhatnagar's avatar Utkarsh Bhatnagar Committed by Gerrit - the friendly Code Review server
Browse files

qcacld-3.0: Correct the condition to reject TDLS

Reject any incoming get_all_peers TDLS command if there
are any currently in progress.
The later commands will only be processed once the earlier
commands finish, since they are processed sequentially.
However, once a command finishes, the memory allocated for
it from userspace is freed up. Each command is passed the
same address so the later commands will end up writing to
a freed address. To avoid this, reject incoming requests
if there are any still in progress.
For this, the condition should be corrected.
We shouldn't use completion_done here for checking for
completion as this will always return false, as
tdls_user_cmd_comp.done will remain in init state always.
So, the very first command will also not work.
In general completion_done is used to check if there are
multiple threads waiting on the complete event that's
why it will return true only when tdls_user_cmd_comp.done
is set with complete().
Also, if the state is in wait_for_completion, this function
will return true after the wait timer is over or condition
is met as wait_for_completion will hold out the hold lock
and will will prevent completion_done from returning.
Better to use a flag to determine command condition.

Change-Id: I1b6b270dbb9b0b103f10e7ae22a60030ea2fbb98
CRs-Fixed: 3162184
parent 705e9a43
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
/*
 * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved.
 * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
 *
 * Permission to use, copy, modify, and/or distribute this software for
 * any purpose with or without fee is hereby granted, provided that the
@@ -51,6 +52,7 @@
 * @mgmt_tx_completion_status: Tdls mgmt frames TX completion status code
 * @tdls_user_cmd_len: tdls user command written buffer length
 * @tdls_antenna_switch_status: return status after antenna switch
 * @tdls_user_cmd_in_progress: tdls user command progress status.
 */
struct osif_tdls_vdev {
	struct completion tdls_add_peer_comp;
@@ -64,6 +66,7 @@ struct osif_tdls_vdev {
	uint32_t mgmt_tx_completion_status;
	uint32_t tdls_user_cmd_len;
	int tdls_antenna_switch_status;
	bool tdls_user_cmd_in_progress;
};

/**
+20 −1
Original line number Diff line number Diff line
@@ -735,11 +735,29 @@ int wlan_cfg80211_tdls_get_all_peers(struct wlan_objmgr_vdev *vdev,

	tdls_priv = osif_priv->osif_tdls;

	if (!completion_done(&tdls_priv->tdls_user_cmd_comp)) {
	/*
	 * We shouldn't use completion_done here for checking for completion
	 * as this will always return false, as tdls_user_cmd_comp.done will
	 * remain in init state always. So, the very first command will also
	 * not work.
	 * In general completion_done is used to check if there are multiple
	 * threads waiting on the complete event that's why it will return true
	 * only when tdls_user_cmd_comp.done is set with complete()
	 * In general completion_done will return true only when
	 * tdls_user_cmd_comp.done is set that will happen in complete().
	 * Also, if there is already a thread waiting for wait_for_completion,
	 * this function will
	 * return true only after the wait timer is over or condition is
	 * met as wait_for_completion will hold out the hold lock and will
	 * will prevent completion_done from returning.
	 * Better to use a flag to determine command condition.
	 */
	if (tdls_priv->tdls_user_cmd_in_progress) {
		osif_err("TDLS user cmd still in progress, reject this one");
		return -EBUSY;
	}

	tdls_priv->tdls_user_cmd_in_progress = true;
	wlan_cfg80211_update_tdls_peers_rssi(vdev);

	reinit_completion(&tdls_priv->tdls_user_cmd_comp);
@@ -769,6 +787,7 @@ int wlan_cfg80211_tdls_get_all_peers(struct wlan_objmgr_vdev *vdev,
	len = tdls_priv->tdls_user_cmd_len;

error_get_tdls_peers:
	tdls_priv->tdls_user_cmd_in_progress = false;
	return len;
}