From 33fae2d0107fb6166b4eac3fdffd277829849ab0 Mon Sep 17 00:00:00 2001
From: Martin Cermak <mcermak@redhat.com>
Date: Fri, 2 Jun 2023 23:28:07 +0200
Subject: [PATCH] =?UTF-8?q?PR30415:=20conflicting=20types=20for=20?=
 =?UTF-8?q?=E2=80=98kallsyms=5Fon=5Feach=5Fsymbol=E2=80=99?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 runtime/linux/kprobes.c       | 28 ++++++++++++++++++++++++-
 runtime/linux/runtime.h       |  8 +++++--
 runtime/sym.c                 | 39 +++++++++++++++++++++++++++++++++++
 runtime/transport/symbols.c   |  4 ++++
 runtime/transport/transport.c |  1 +
 staprun/staprun.c             | 13 +++++++++++-
 6 files changed, 89 insertions(+), 4 deletions(-)

diff --git a/runtime/linux/kprobes.c b/runtime/linux/kprobes.c
index 1875092c5..6b30f2c52 100644
--- a/runtime/linux/kprobes.c
+++ b/runtime/linux/kprobes.c
@@ -28,6 +28,9 @@ extern void *_stp_kallsyms_on_each_symbol;
 #endif
 #endif
 
+// No export check and gates.  This one seems simply like a non-export.
+extern void *_stp_module_kallsyms_on_each_symbol;
+
 #if defined(STAPCONF_KALLSYMS_ON_EACH_SYMBOL) && defined(STAPCONF_KALLSYMS_ON_EACH_SYMBOL_EXPORTED)
 #define USE_KALLSYMS_ON_EACH_SYMBOL (1)
 #elif defined(STAPCONF_KALLSYMS_ON_EACH_SYMBOL)
@@ -684,7 +687,7 @@ struct stapkp_symbol_data {
 
 
 static int
-stapkp_symbol_callback(void *data, const char *name,
+__stapkp_symbol_callback(void *data, const char *name,
 		       struct module *mod, unsigned long addr)
 {
    struct stapkp_symbol_data *sd = data;
@@ -733,6 +736,19 @@ stapkp_symbol_callback(void *data, const char *name,
    return 0;
 }
 
+static int
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,4,0)
+stapkp_symbol_callback(void *data, const char *name,
+			unsigned long addr)
+{
+    struct module *mod = NULL;
+#else
+stapkp_symbol_callback(void *data, const char *name,
+			struct module *mod, unsigned long addr)
+{
+#endif
+    return __stapkp_symbol_callback(data, name, mod, addr);
+}
 
 static int
 stapkp_init(struct stap_kprobe_probe *probes,
@@ -764,6 +780,11 @@ stapkp_init(struct stap_kprobe_probe *probes,
        mutex_lock(&module_mutex);
 #endif
        kallsyms_on_each_symbol(stapkp_symbol_callback, &sd);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,3,0)
+       module_kallsyms_on_each_symbol(sd.modname, stapkp_symbol_callback, &sd);
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(5,12,0)
+       module_kallsyms_on_each_symbol(stapkp_symbol_callback, &sd);
+#endif
 #ifdef STAPCONF_MODULE_MUTEX
        mutex_unlock(&module_mutex);
 #endif
@@ -834,6 +855,11 @@ stapkp_refresh(const char *modname,
          mutex_lock(&module_mutex);
 #endif
 	 kallsyms_on_each_symbol(stapkp_symbol_callback, &sd);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,3,0)
+	 module_kallsyms_on_each_symbol(sd.modname, stapkp_symbol_callback, &sd);
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(5,12,0)
+	 module_kallsyms_on_each_symbol(stapkp_symbol_callback, &sd);
+#endif
 #ifdef STAPCONF_MODULE_MUTEX
          mutex_unlock(&module_mutex);
 #endif
diff --git a/runtime/linux/runtime.h b/runtime/linux/runtime.h
index 86d64fd0d..f7b3cdcf0 100644
--- a/runtime/linux/runtime.h
+++ b/runtime/linux/runtime.h
@@ -221,11 +221,15 @@ static void *_stp_kallsyms_lookup_name;
 #ifndef CONFIG_PPC64
 #define STAPCONF_KALLSYMS_ON_EACH_SYMBOL
 #if !defined(STAPCONF_KALLSYMS_ON_EACH_SYMBOL_EXPORTED)
-// XXX Should not be static, since it is linked into kprobes.c.
-static void *_stp_kallsyms_on_each_symbol;
+// Not static, since it is linked into kprobes.c:
+void *_stp_kallsyms_on_each_symbol;
 #endif
 #endif
 
+// No export check and gates.  This one seems simply like a non-export.
+// Not static, since it is linked into kprobes.c:
+void *_stp_module_kallsyms_on_each_symbol;
+
 // PR13489, inode-uprobes sometimes lacks the necessary SYMBOL_EXPORT's.
 #if !defined(STAPCONF_TASK_USER_REGSET_VIEW_EXPORTED)
 static void *kallsyms_task_user_regset_view;
diff --git a/runtime/sym.c b/runtime/sym.c
index fc81ac5e8..29171b45f 100644
--- a/runtime/sym.c
+++ b/runtime/sym.c
@@ -1155,9 +1155,15 @@ unsigned long kallsyms_lookup_name (const char *name)
 typedef typeof(&kallsyms_on_each_symbol) kallsyms_on_each_symbol_fn;
 
 // XXX Will be linked in place of the kernel's kallsyms_on_each_symbol:
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,4,0)
+int kallsyms_on_each_symbol(int (*fn)(void *, const char *,
+				      unsigned long),
+                            void *data)
+#else
 int kallsyms_on_each_symbol(int (*fn)(void *, const char *, struct module *,
 				      unsigned long),
                             void *data)
+#endif
 {
         /* First, try to use a kallsyms_lookup_name address passed to us
            through the relocation mechanism. */
@@ -1170,6 +1176,39 @@ int kallsyms_on_each_symbol(int (*fn)(void *, const char *, struct module *,
         _stp_error("BUG: attempting to use unavailable kallsyms_on_each_symbol!!\n");
         return 0;
 }
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,12,0)
+typedef typeof(&module_kallsyms_on_each_symbol) module_kallsyms_on_each_symbol_fn;
+
+// XXX Will be linked in place of the kernel's module_kallsyms_on_each_symbol:
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,4,0)
+int module_kallsyms_on_each_symbol(const char *modname,
+                                   int (*fn)(void *, const char *,
+				      unsigned long),
+                            void *data)
+#else
+int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *, struct module *,
+				      unsigned long),
+                            void *data)
+#endif
+{
+        /* First, try to use a kallsyms_lookup_name address passed to us
+           through the relocation mechanism. */
+        if (_stp_module_kallsyms_on_each_symbol != NULL)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,4,0)
+                return (* (module_kallsyms_on_each_symbol_fn)_stp_module_kallsyms_on_each_symbol)(modname, fn, data);
+#else
+                return (* (module_kallsyms_on_each_symbol_fn)_stp_module_kallsyms_on_each_symbol)(fn, data);
+#endif
+
+        /* Next, give up and signal a BUG. We should have detected
+           that this function is not available and used a different
+           mechanism! */
+        _stp_error("BUG: attempting to use unavailable module_kallsyms_on_each_symbol!!\n");
+        return 0;
+}
+#endif
+
 #endif
 
 
diff --git a/runtime/transport/symbols.c b/runtime/transport/symbols.c
index 7f2fe0fc8..3af9a1098 100644
--- a/runtime/transport/symbols.c
+++ b/runtime/transport/symbols.c
@@ -119,6 +119,10 @@ static void _stp_do_relocation(const char __user *buf, size_t count)
           _stp_kallsyms_on_each_symbol = (void *) msg.address;
   }
 #endif
+  if (!strcmp ("kernel", msg.module)
+      && !strcmp ("module_kallsyms_on_each_symbol", msg.reloc)) {
+          _stp_module_kallsyms_on_each_symbol = (void *) msg.address;
+  }
 
   _stp_kmodule_update_address(msg.module, msg.reloc, msg.address);
 }
diff --git a/runtime/transport/transport.c b/runtime/transport/transport.c
index 3db76badf..cf57d4286 100644
--- a/runtime/transport/transport.c
+++ b/runtime/transport/transport.c
@@ -614,6 +614,7 @@ static int _stp_transport_init(void)
 #if defined(STAPCONF_KALLSYMS_ON_EACH_SYMBOL) && !defined(STAPCONF_KALLSYMS_ON_EACH_SYMBOL_EXPORTED)
         _stp_kallsyms_on_each_symbol = NULL;
 #endif
+        _stp_module_kallsyms_on_each_symbol = NULL;
 #if defined(CONFIG_KALLSYMS) && !defined(STAPCONF_KALLSYMS_LOOKUP_NAME_EXPORTED)
         _stp_need_kallsyms_stext = 0;
 #endif
diff --git a/staprun/staprun.c b/staprun/staprun.c
index edd1bc67a..8437f3af6 100644
--- a/staprun/staprun.c
+++ b/staprun/staprun.c
@@ -640,6 +640,7 @@ int send_relocation_kernel ()
       int found_stext = 0;
       int found_kallsyms_lookup_name = 0;
       int found_kallsyms_on_each_symbol = 0;
+      int found_module_kallsyms_on_each_symbol = 0;
       int done_with_kallsyms = 0;
       char *line = NULL;
       size_t linesz = 0;
@@ -681,10 +682,20 @@ int send_relocation_kernel ()
 
                   found_kallsyms_on_each_symbol = 1;
                 }
+              else if (linesize - pos == sizeof "module_kallsyms_on_each_symbol"
+                       && !strcmp(line + pos, "module_kallsyms_on_each_symbol" "\n"))
+                {
+                  rc = send_a_relocation ("kernel", "module_kallsyms_on_each_symbol", address);
+		  if (rc != 0) // non fatal, follows perror()
+                    dbug(1, "Relocation was reloc module_kallsyms_on_each_symbol=%llx\n", address);
+
+                  found_module_kallsyms_on_each_symbol = 1;
+                }
             }
           done_with_kallsyms = found_stext
             && found_kallsyms_lookup_name
-            && found_kallsyms_on_each_symbol;
+            && found_kallsyms_on_each_symbol
+            && found_module_kallsyms_on_each_symbol;
         }
       free (line);
       fclose (kallsyms);
-- 
2.39.1

