Forráskód Böngészése

qcacmn: Add QDF API for ID allocation

In P2P ROC and MGMT tx cases, it use kernel address as cookie and
provides to userspace. Which has security risk. Add QDF API for ID
allocation and map ID to pointer, provides ID to userspace instead
of kernel address.

Change-Id: I4e10109988391474722df5b251fab11a87c7992b
CRs-Fixed: 2237756
Wu Gao 7 éve
szülő
commit
210778359a
3 módosított fájl, 266 hozzáadás és 0 törlés
  1. 82 0
      qdf/inc/qdf_idr.h
  2. 42 0
      qdf/linux/src/i_qdf_idr.h
  3. 142 0
      qdf/linux/src/qdf_idr.c

+ 82 - 0
qdf/inc/qdf_idr.h

@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2018 The Linux Foundation. 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
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ * DOC: qdf_idr(ID Allocation)
+ * QCA driver framework (QDF) ID allocation APIs
+ */
+
+#if !defined(__QDF_IDR_H)
+#define __QDF_IDR_H
+
+/* Include Files */
+#include <qdf_types.h>
+#include <qdf_status.h>
+#include <i_qdf_idr.h>
+
+/**
+ * qdf_idr - platform idr object
+ */
+typedef __qdf_idr qdf_idr;
+
+/**
+ * qdf_idr_create() - idr initialization function
+ * @idp: pointer to qdf idr
+ *
+ * Return: QDF status
+ */
+QDF_STATUS qdf_idr_create(qdf_idr *idp);
+
+/**
+ * qdf_idr_destroy() - idr deinitialization function
+ * @idp: pointer to qdf idr
+ *
+ * Return: QDF status
+ */
+QDF_STATUS qdf_idr_destroy(qdf_idr *idp);
+
+/**
+ * qdf_idr_alloc() - Allocates an unused ID
+ * @idp: pointer to qdf idr
+ * @ptr: pointer to be associated with the new ID
+ * @id:  pointer to return new ID
+ *
+ * Return: QDF status
+ */
+QDF_STATUS qdf_idr_alloc(qdf_idr *idp, void *ptr, int32_t *id);
+
+/**
+ * qdf_idr_remove() - Removes this ID from the IDR.
+ * @idp: pointer to qdf idr
+ * @id:  ID to be remove
+ *
+ * Return: QDF status
+ */
+QDF_STATUS qdf_idr_remove(qdf_idr *idp, int32_t id);
+
+/**
+ * qdf_idr_find() - find the user pointer from the IDR by id.
+ * @idp: pointer to qdf idr
+ * @id:  ID to be remove
+ * @ptr: pointer to return user pointer for given ID
+ *
+ * Return: QDF status
+ */
+QDF_STATUS qdf_idr_find(qdf_idr *idp, int32_t id, void **ptr);
+
+#endif /* __QDF_IDR_H */

+ 42 - 0
qdf/linux/src/i_qdf_idr.h

@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2018 The Linux Foundation. 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
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ * DOC: i_qdf_idr.h (ID Allocation)
+ * Linux-specific definitions for QDF ID Allocation API's
+ */
+
+#if !defined(__I_QDF_IDR_H)
+#define __I_QDF_IDR_H
+
+#include <linux/idr.h>
+#include <qdf_lock.h>
+
+/**
+ * struct __qdf_idr_s
+ * @lock: qdf spinlock
+ * @idr:  idr handler
+ */
+struct __qdf_idr_s {
+	qdf_spinlock_t lock;
+	struct idr idr;
+};
+
+typedef struct __qdf_idr_s __qdf_idr;
+
+#endif /* __I_QDF_IDR_H */

+ 142 - 0
qdf/linux/src/qdf_idr.c

@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2018 The Linux Foundation. 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
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ * DOC: qdf_idr
+ * This file provides the ability to map an ID to a pointer
+ */
+
+/* Include files */
+#include <qdf_idr.h>
+#include <qdf_module.h>
+
+#define QDF_IDR_START     0x100
+#define QDF_IDR_END       0
+
+static int qdf_idr_gpf_flag(void)
+{
+	if (in_interrupt() || irqs_disabled() || in_atomic())
+		return GFP_ATOMIC;
+
+	return GFP_KERNEL;
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0)
+/**
+ * __qdf_idr_alloc() - Allocates an unused ID
+ * @idp:   pointer to qdf idr
+ * @ptr:   pointer to be associated with the new ID
+ * @start: the minimum ID
+ * @end:   the maximum ID
+ *
+ * Return: new ID
+ */
+static inline int32_t
+__qdf_idr_alloc(qdf_idr *idp, void *ptr, int32_t start, int32_t end)
+{
+	int32_t id = 0;
+
+	idr_get_new(&idp->idr, ptr, &id);
+
+	return id;
+}
+#else
+static inline int32_t
+__qdf_idr_alloc(qdf_idr *idp, void *ptr, int32_t start, int32_t end)
+{
+	return idr_alloc(&idp->idr, ptr, start, end, qdf_idr_gpf_flag());
+}
+#endif
+
+QDF_STATUS qdf_idr_create(qdf_idr *idp)
+{
+	if (!idp)
+		return QDF_STATUS_E_INVAL;
+
+	qdf_spinlock_create(&idp->lock);
+
+	idr_init(&idp->idr);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+qdf_export_symbol(qdf_idr_create);
+
+QDF_STATUS qdf_idr_destroy(qdf_idr *idp)
+{
+	if (!idp)
+		return QDF_STATUS_E_INVAL;
+
+	qdf_spinlock_destroy(&idp->lock);
+	idr_destroy(&idp->idr);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+qdf_export_symbol(qdf_idr_destroy);
+
+QDF_STATUS qdf_idr_alloc(qdf_idr *idp, void *ptr, int32_t *id)
+{
+	int local_id;
+
+	if (!idp || !ptr)
+		return QDF_STATUS_E_INVAL;
+
+	qdf_spinlock_acquire(&idp->lock);
+	local_id = __qdf_idr_alloc(idp, ptr, QDF_IDR_START, QDF_IDR_END);
+	qdf_spinlock_release(&idp->lock);
+	if (local_id < QDF_IDR_START)
+		return QDF_STATUS_E_FAILURE;
+
+	*id = local_id;
+
+	return QDF_STATUS_SUCCESS;
+}
+
+qdf_export_symbol(qdf_idr_alloc);
+
+QDF_STATUS qdf_idr_remove(qdf_idr *idp, int32_t id)
+{
+	if (!idp || id < QDF_IDR_START)
+		return QDF_STATUS_E_INVAL;
+
+	qdf_spinlock_acquire(&idp->lock);
+	idr_remove(&idp->idr, id);
+	qdf_spinlock_release(&idp->lock);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+qdf_export_symbol(qdf_idr_remove);
+
+QDF_STATUS qdf_idr_find(qdf_idr *idp, int32_t id, void **ptr)
+{
+	if (!ptr || (id < QDF_IDR_START))
+		return QDF_STATUS_E_INVAL;
+
+	qdf_spinlock_acquire(&idp->lock);
+	*ptr = idr_find(&idp->idr, id);
+	qdf_spinlock_release(&idp->lock);
+	if (!ptr)
+		return QDF_STATUS_E_INVAL;
+	else
+		return QDF_STATUS_SUCCESS;
+}
+
+qdf_export_symbol(qdf_idr_find);
+