lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <1687955688-20809-7-git-send-email-quic_mojha@quicinc.com>
Date:   Wed, 28 Jun 2023 18:04:33 +0530
From:   Mukesh Ojha <quic_mojha@...cinc.com>
To:     <corbet@....net>, <agross@...nel.org>, <andersson@...nel.org>,
        <konrad.dybcio@...aro.org>, <robh+dt@...nel.org>,
        <krzysztof.kozlowski+dt@...aro.org>, <conor+dt@...nel.org>,
        <keescook@...omium.org>, <tony.luck@...el.com>,
        <gpiccoli@...lia.com>, <mathieu.poirier@...aro.org>,
        <catalin.marinas@....com>, <will@...nel.org>,
        <linus.walleij@...aro.org>, <andy.shevchenko@...il.com>
CC:     <linux-doc@...r.kernel.org>, <linux-kernel@...r.kernel.org>,
        <linux-arm-msm@...r.kernel.org>, <devicetree@...r.kernel.org>,
        <linux-hardening@...r.kernel.org>,
        <linux-remoteproc@...r.kernel.org>,
        <linux-arm-kernel@...ts.infradead.org>,
        <linux-gpio@...r.kernel.org>,
        "Mukesh Ojha" <quic_mojha@...cinc.com>
Subject: [PATCH v4 06/21] soc: qcom: minidump: Add pending region registration support

Pending regions are those apss minidump regions which came for
registration before minidump was initialized or ready to do
register the region.

We can add regions to pending region list and register them from
apss minidump driver probe in one go.

Signed-off-by: Mukesh Ojha <quic_mojha@...cinc.com>
---
 drivers/soc/qcom/qcom_minidump.c          | 87 ++++++++++++++++++++++++++++---
 drivers/soc/qcom/qcom_minidump_internal.h | 20 +++++++
 2 files changed, 99 insertions(+), 8 deletions(-)

diff --git a/drivers/soc/qcom/qcom_minidump.c b/drivers/soc/qcom/qcom_minidump.c
index 7744e57843ab..cfdb63cc29d6 100644
--- a/drivers/soc/qcom/qcom_minidump.c
+++ b/drivers/soc/qcom/qcom_minidump.c
@@ -9,6 +9,7 @@
 #include <linux/export.h>
 #include <linux/kallsyms.h>
 #include <linux/kernel.h>
+#include <linux/list.h>
 #include <linux/module.h>
 #include <linux/printk.h>
 #include <linux/string.h>
@@ -35,6 +36,10 @@ static DEFINE_MUTEX(md_lock);
 /* Only one front end will be attached to one back-end */
 static struct minidump *md;
 static char *md_backend;
+static struct minidump_plist md_plist = {
+	.plist = LIST_HEAD_INIT(md_plist.plist),
+	.pregion_cnt = 0,
+};
 
 static struct elf_shdr *elf_shdr_entry_addr(struct elfhdr *ehdr, int idx)
 {
@@ -201,6 +206,26 @@ static bool qcom_minidump_valid_region(const struct qcom_minidump_region *region
 		IS_ALIGNED(region->size, 4);
 }
 
+static struct minidump_pregion *
+check_if_pending_region_exist(const struct qcom_minidump_region *region)
+{
+	struct minidump_pregion *md_pregion;
+	struct minidump_pregion *tmp;
+	bool found = false;
+
+	list_for_each_entry_safe(md_pregion, tmp, &md_plist.plist, list) {
+		struct qcom_minidump_region *md_region;
+
+		md_region = &md_pregion->region;
+		if (!strcmp(md_region->name, region->name)) {
+			found = true;
+			break;
+		}
+	}
+
+	return found ? md_pregion : NULL;
+}
+
 /**
  * qcom_minidump_region_register() - Register region in APSS Minidump table.
  * @region: minidump region.
@@ -209,16 +234,40 @@ static bool qcom_minidump_valid_region(const struct qcom_minidump_region *region
  */
 int qcom_minidump_region_register(const struct qcom_minidump_region *region)
 {
-	int ret;
+	struct minidump_pregion *md_pregion;
+	int ret = 0;
 
 	if (!qcom_minidump_valid_region(region))
 		return -EINVAL;
 
 	mutex_lock(&md_lock);
 	if (!md) {
-		mutex_unlock(&md_lock);
-		pr_err("No backend registered yet, try again..");
-		return -EPROBE_DEFER;
+		if (md_plist.pregion_cnt >= MAX_NUM_ENTRIES - 1) {
+			pr_err("maximum region limit %u reached\n", md_plist.pregion_cnt);
+			ret = -ENOSPC;
+			goto unlock;
+		}
+
+		md_pregion = check_if_pending_region_exist(region);
+		if (md_pregion) {
+			pr_info("%s region is already exist\n", region->name);
+			ret = -EEXIST;
+			goto unlock;
+		}
+		/*
+		 * Maintain a list of client regions which came before
+		 * minidump driver was ready and once it is ready,
+		 * register them in one go from minidump probe function.
+		 */
+		md_pregion = kzalloc(sizeof(*md_pregion), GFP_KERNEL);
+		if (!md_pregion) {
+			ret = -ENOMEM;
+			goto unlock;
+		}
+		md_pregion->region = *region;
+		list_add_tail(&md_pregion->list, &md_plist.plist);
+		md_plist.pregion_cnt++;
+		goto unlock;
 	}
 
 	ret = md->ops->md_region_register(md, region);
@@ -240,16 +289,22 @@ EXPORT_SYMBOL_GPL(qcom_minidump_region_register);
  */
 int qcom_minidump_region_unregister(const struct qcom_minidump_region *region)
 {
-	int ret;
+	struct minidump_pregion *md_pregion;
+	int ret = 0;
 
 	if (!qcom_minidump_valid_region(region))
 		return -EINVAL;
 
 	mutex_lock(&md_lock);
 	if (!md) {
-		mutex_unlock(&md_lock);
-		pr_err("No backend registered yet, try again..");
-		return -EPROBE_DEFER;
+		md_pregion = check_if_pending_region_exist(region);
+		if (!md_pregion)
+			goto unlock;
+
+		list_del(&md_pregion->list);
+		kfree(md_pregion);
+		md_plist.pregion_cnt--;
+		goto unlock;
 	}
 
 	ret = md->ops->md_region_unregister(md, region);
@@ -378,6 +433,8 @@ static int qcom_minidump_add_elf_header(struct minidump *md_data)
  */
 int qcom_minidump_backend_register(struct minidump *md_data)
 {
+	struct minidump_pregion *md_pregion;
+	struct minidump_pregion *tmp;
 	int ret;
 
 	if (!md_data->name || !md_data->dev ||
@@ -425,6 +482,20 @@ int qcom_minidump_backend_register(struct minidump *md_data)
 	md_backend = kstrdup(md->name, GFP_KERNEL);
 	dev_info(md->dev, "Registered minidump backend : %s\n", md->name);
 
+	list_for_each_entry_safe(md_pregion, tmp, &md_plist.plist, list) {
+		struct qcom_minidump_region *region;
+
+		region = &md_pregion->region;
+		ret = md->ops->md_region_register(md, region);
+		if (ret)
+			goto unlock;
+
+		qcom_md_update_elf_header(region);
+		list_del(&md_pregion->list);
+		kfree(md_pregion);
+		md_plist.pregion_cnt--;
+	}
+
 unlock:
 	mutex_unlock(&md_lock);
 	return ret;
diff --git a/drivers/soc/qcom/qcom_minidump_internal.h b/drivers/soc/qcom/qcom_minidump_internal.h
index 9031b1b0a046..6993e3be10c2 100644
--- a/drivers/soc/qcom/qcom_minidump_internal.h
+++ b/drivers/soc/qcom/qcom_minidump_internal.h
@@ -65,6 +65,26 @@ struct minidump {
 	void				*apss_data;
 };
 
+/**
+ * struct minidump_pregion - Minidump pending region
+ * @list       : Pending region list pointer
+ * @region     : APSS minidump client region
+ */
+struct minidump_pregion {
+	struct list_head	     list;
+	struct qcom_minidump_region  region;
+};
+
+/**
+ * struct minidump_plist - Minidump pending region list
+ * @plist	: List of pending region to be registered
+ * @pregion_cnt	: Count of the pending region to be registered
+ */
+struct minidump_plist {
+	struct list_head  plist;
+	int		  pregion_cnt;
+};
+
 #if IS_ENABLED(CONFIG_QCOM_MINIDUMP)
 int qcom_minidump_backend_register(struct minidump *md);
 void qcom_minidump_backend_unregister(struct minidump *md);
-- 
2.7.4

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ