aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Thompson <daniel.thompson@linaro.org>2015-03-18 16:47:08 +0000
committerDaniel Thompson <daniel.thompson@linaro.org>2015-12-14 16:43:45 +0000
commitc06990c1e3dfbd3af3615615ba6c9620058e477b (patch)
tree9541d53fdf0ce640ae638caf5b79dc30f70f30fb
parent3e23ea073fd5b4026647337e5a533c67abad8c4c (diff)
downloadlinux-c06990c1e3dfbd3af3615615ba6c9620058e477b.tar.gz
bug: Recursion avoidance for WARN_ONCE() and friends
Currently WARN_ONCE() and similar macros set __warned *after* calling the underlying macro. This risks infinite recursion if WARN_ONCE() is used to implement sanity tests in any code that can be called by printk. This can be fixed by restructuring the macros to set __warned before calling further macros. Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org>
-rw-r--r--include/asm-generic/bug.h21
1 files changed, 12 insertions, 9 deletions
diff --git a/include/asm-generic/bug.h b/include/asm-generic/bug.h
index 630dd2372238..f8c8a819c563 100644
--- a/include/asm-generic/bug.h
+++ b/include/asm-generic/bug.h
@@ -110,9 +110,10 @@ extern void warn_slowpath_null(const char *file, const int line);
static bool __section(.data.unlikely) __warned; \
int __ret_warn_once = !!(condition); \
\
- if (unlikely(__ret_warn_once)) \
- if (WARN_ON(!__warned)) \
- __warned = true; \
+ if (unlikely(__ret_warn_once) && !__warned) { \
+ __warned = true; \
+ WARN_ON(true); \
+ } \
unlikely(__ret_warn_once); \
})
@@ -120,9 +121,10 @@ extern void warn_slowpath_null(const char *file, const int line);
static bool __section(.data.unlikely) __warned; \
int __ret_warn_once = !!(condition); \
\
- if (unlikely(__ret_warn_once)) \
- if (WARN(!__warned, format)) \
- __warned = true; \
+ if (unlikely(__ret_warn_once) && !__warned) { \
+ __warned = true; \
+ WARN(true, format); \
+ } \
unlikely(__ret_warn_once); \
})
@@ -130,9 +132,10 @@ extern void warn_slowpath_null(const char *file, const int line);
static bool __section(.data.unlikely) __warned; \
int __ret_warn_once = !!(condition); \
\
- if (unlikely(__ret_warn_once)) \
- if (WARN_TAINT(!__warned, taint, format)) \
- __warned = true; \
+ if (unlikely(__ret_warn_once) && !__warned) { \
+ __warned = true; \
+ WARN_TAINT(true, taint, format); \
+ } \
unlikely(__ret_warn_once); \
})