The descriptor flags are accessed concurrently. Use
READ_ONCE()/WRITE_ONCE() to keep their contents consistent.

Signed-off-by: Thomas Weißschuh <[email protected]>

---
I am not entirely sure about this. We are only using single bits, so
torn reads/writes should not matter. But LKMM has no guidance on this as
far as I can see. Also for Rust this seems to be necessary.
---
 include/linux/dynamic_debug.h |  6 +++---
 lib/dynamic_debug.c           | 24 +++++++++++++-----------
 2 files changed, 16 insertions(+), 14 deletions(-)

diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index b1ff7c0e9a5f..6986142928ef 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -164,7 +164,7 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
 
 #define __dynamic_dump_stack(desc)                             \
 {                                                              \
-       if (desc.flags & _DPRINTK_FLAGS_INCL_STACK)             \
+       if (READ_ONCE(desc.flags) & _DPRINTK_FLAGS_INCL_STACK)  \
                dump_stack();                                   \
 }
 
@@ -207,10 +207,10 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
 
 #ifdef DEBUG
 #define DYNAMIC_DEBUG_BRANCH(descriptor) \
-       likely(descriptor.flags & _DPRINTK_FLAGS_PRINT)
+       likely(READ_ONCE(descriptor.flags) & _DPRINTK_FLAGS_PRINT)
 #else
 #define DYNAMIC_DEBUG_BRANCH(descriptor) \
-       unlikely(descriptor.flags & _DPRINTK_FLAGS_PRINT)
+       unlikely(READ_ONCE(descriptor.flags) & _DPRINTK_FLAGS_PRINT)
 #endif
 
 #endif /* CONFIG_JUMP_LABEL */
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index 18a71a9108d3..6dfd125fa6be 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -244,7 +244,7 @@ static int ddebug_change(const struct ddebug_query *query,
 
                        nfound++;
 
-                       newflags = (dp->flags & modifiers->mask) | 
modifiers->flags;
+                       newflags = (READ_ONCE(dp->flags) & modifiers->mask) | 
modifiers->flags;
                        if (newflags == dp->flags)
                                continue;
 #ifdef CONFIG_JUMP_LABEL
@@ -260,7 +260,7 @@ static int ddebug_change(const struct ddebug_query *query,
                                  dt->mod_name, dp->function,
                                  ddebug_describe_flags(dp->flags, &fbuf),
                                  ddebug_describe_flags(newflags, &nbuf));
-                       dp->flags = newflags;
+                       WRITE_ONCE(dp->flags, newflags);
                }
        }
        mutex_unlock(&ddebug_lock);
@@ -822,12 +822,12 @@ static int remaining(int wrote)
        return 0;
 }
 
-static char *__dynamic_emit_prefix(const struct _ddebug *desc, char *buf)
+static char *__dynamic_emit_prefix(const struct _ddebug *desc, u8 flags, char 
*buf)
 {
        int pos_after_tid;
        int pos = 0;
 
-       if (desc->flags & _DPRINTK_FLAGS_INCL_TID) {
+       if (flags & _DPRINTK_FLAGS_INCL_TID) {
                if (in_interrupt())
                        pos += snprintf(buf + pos, remaining(pos), "<intr> ");
                else
@@ -835,16 +835,16 @@ static char *__dynamic_emit_prefix(const struct _ddebug 
*desc, char *buf)
                                        task_pid_vnr(current));
        }
        pos_after_tid = pos;
-       if (desc->flags & _DPRINTK_FLAGS_INCL_MODNAME)
+       if (flags & _DPRINTK_FLAGS_INCL_MODNAME)
                pos += snprintf(buf + pos, remaining(pos), "%s:",
                                desc->modname);
-       if (desc->flags & _DPRINTK_FLAGS_INCL_FUNCNAME)
+       if (flags & _DPRINTK_FLAGS_INCL_FUNCNAME)
                pos += snprintf(buf + pos, remaining(pos), "%s:",
                                desc->function);
-       if (desc->flags & _DPRINTK_FLAGS_INCL_SOURCENAME)
+       if (flags & _DPRINTK_FLAGS_INCL_SOURCENAME)
                pos += snprintf(buf + pos, remaining(pos), "%s:",
                                trim_prefix(desc->filename));
-       if (desc->flags & _DPRINTK_FLAGS_INCL_LINENO)
+       if (flags & _DPRINTK_FLAGS_INCL_LINENO)
                pos += snprintf(buf + pos, remaining(pos), "%d:",
                                desc->lineno);
        if (pos - pos_after_tid)
@@ -857,8 +857,10 @@ static char *__dynamic_emit_prefix(const struct _ddebug 
*desc, char *buf)
 
 static inline char *dynamic_emit_prefix(struct _ddebug *desc, char *buf)
 {
-       if (unlikely(desc->flags & _DPRINTK_FLAGS_INCL_ANY))
-               return __dynamic_emit_prefix(desc, buf);
+       u8 flags = READ_ONCE(desc->flags);
+
+       if (unlikely(flags & _DPRINTK_FLAGS_INCL_ANY))
+               return __dynamic_emit_prefix(desc, flags, buf);
        return buf;
 }
 
@@ -1146,7 +1148,7 @@ static int ddebug_proc_show(struct seq_file *m, void *p)
        seq_printf(m, "%s:%u [%s]%s =%s \"",
                   trim_prefix(dp->filename), dp->lineno,
                   iter->table->mod_name, dp->function,
-                  ddebug_describe_flags(dp->flags, &flags));
+                  ddebug_describe_flags(READ_ONCE(dp->flags), &flags));
        seq_escape_str(m, dp->format, ESCAPE_SPACE, "\t\r\n\"");
        seq_putc(m, '"');
 

-- 
2.56.0


Reply via email to