The branch main has been updated by markj:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=9a6ba186e0ca4269021d8843dbc8409ea78da4a6

commit 9a6ba186e0ca4269021d8843dbc8409ea78da4a6
Author:     Mark Johnston <ma...@freebsd.org>
AuthorDate: 2025-07-28 19:30:37 +0000
Commit:     Mark Johnston <ma...@freebsd.org>
CommitDate: 2025-07-28 20:32:39 +0000

    sdt: Initialize probes in two passes
    
    Suppose a kernel module A defines an SDT provider and probes, and kernel
    linker file B, dependant on A, contains tracepoints for those probes.
    When sdt.ko is loaded, it iterates over all loaded KLDs to initialize
    probe structures and register them with dtrace.  In particular it uses
    linker_file_foreach(), which is not sorted; in the above scenario, B may
    be visited before A.  Thus, it's possible for sdt_kld_load_probes() to
    try to add tracepoints to an uninitialized SDT probe.
    
    An example of the above arises when pfsync, pf, and sdt are loaded in
    that exact order after commit 4bb3b36577645.
    
    Fix this by initializing probe structures in the first pass over loaded
    KLDs.  Then, the second pass can safely add tracepoints to any probe
    structure.
    
    Note that the scenario where B and A are loaded after sdt.ko is already
    handled properly, as there, the kld_load eventhandler is responsible for
    registering probes with dtrace, and that eventhandler fires for
    dependencies before it does for the dependent KLD.  This presumes,
    however, that there are no cycles in the dependency graph.
    
    Reported by:    jenkins
    MFC after:      2 weeks
---
 sys/cddl/dev/sdt/sdt.c | 23 +++++++++++++++++------
 1 file changed, 17 insertions(+), 6 deletions(-)

diff --git a/sys/cddl/dev/sdt/sdt.c b/sys/cddl/dev/sdt/sdt.c
index a8da618204af..0a9059104671 100644
--- a/sys/cddl/dev/sdt/sdt.c
+++ b/sys/cddl/dev/sdt/sdt.c
@@ -72,6 +72,7 @@ static void   sdt_load(void);
 static int     sdt_unload(void);
 static void    sdt_create_provider(struct sdt_provider *);
 static void    sdt_create_probe(struct sdt_probe *);
+static void    sdt_init_probe(struct sdt_probe *, linker_file_t);
 static void    sdt_kld_load(void *, struct linker_file *);
 static void    sdt_kld_unload_try(void *, struct linker_file *, int *);
 
@@ -204,6 +205,14 @@ sdt_create_probe(struct sdt_probe *probe)
        (void)dtrace_probe_create(prov->id, mod, func, name, aframes, probe);
 }
 
+static void
+sdt_init_probe(struct sdt_probe *probe, linker_file_t lf)
+{
+       probe->sdtp_lf = lf;
+       TAILQ_INIT(&probe->argtype_list);
+       STAILQ_INIT(&probe->tracepoint_list);
+}
+
 /*
  * Probes are created through the SDT module load/unload hook, so this function
  * has nothing to do. It only exists because the DTrace provider framework
@@ -361,12 +370,19 @@ static void
 sdt_kld_load_providers(struct linker_file *lf)
 {
        struct sdt_provider **prov, **begin, **end;
+       struct sdt_probe **p_begin, **p_end;
 
        if (linker_file_lookup_set(lf, "sdt_providers_set", &begin, &end,
            NULL) == 0) {
                for (prov = begin; prov < end; prov++)
                        sdt_create_provider(*prov);
        }
+
+       if (linker_file_lookup_set(lf, "sdt_probes_set", &p_begin, &p_end,
+           NULL) == 0) {
+               for (struct sdt_probe **probe = p_begin; probe < p_end; probe++)
+                       sdt_init_probe(*probe, lf);
+       }
 }
 
 static void
@@ -378,13 +394,8 @@ sdt_kld_load_probes(struct linker_file *lf)
 
        if (linker_file_lookup_set(lf, "sdt_probes_set", &p_begin, &p_end,
            NULL) == 0) {
-               for (struct sdt_probe **probe = p_begin; probe < p_end;
-                   probe++) {
-                       (*probe)->sdtp_lf = lf;
+               for (struct sdt_probe **probe = p_begin; probe < p_end; probe++)
                        sdt_create_probe(*probe);
-                       TAILQ_INIT(&(*probe)->argtype_list);
-                       STAILQ_INIT(&(*probe)->tracepoint_list);
-               }
        }
 
        if (linker_file_lookup_set(lf, "sdt_argtypes_set", &a_begin, &a_end,

Reply via email to