Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

locking: add typecheck on irqsave and friends for correct flags

There haave been several areas in the kernel where an int has been used for
flags in local_irq_save() and friends instead of a long. This can cause some
hard to debug problems on some architectures.

This patch adds a typecheck inside the irqsave and restore functions to flag
these cases.

[akpm@linux-foundation.org: coding-style fixes]
[akpm@linux-foundation.org: build fix]
Signed-off-by: Steven Rostedt <srostedt@redhat.com>
Cc: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Steven Rostedt and committed by
Linus Torvalds
3f307891 e0deaff4

+95 -31
+39 -15
include/linux/irqflags.h
··· 11 11 #ifndef _LINUX_TRACE_IRQFLAGS_H 12 12 #define _LINUX_TRACE_IRQFLAGS_H 13 13 14 + #include <linux/typecheck.h> 15 + 14 16 #ifdef CONFIG_TRACE_IRQFLAGS 15 17 extern void trace_softirqs_on(unsigned long ip); 16 18 extern void trace_softirqs_off(unsigned long ip); ··· 60 58 do { trace_hardirqs_on(); raw_local_irq_enable(); } while (0) 61 59 #define local_irq_disable() \ 62 60 do { raw_local_irq_disable(); trace_hardirqs_off(); } while (0) 63 - #define local_irq_save(flags) \ 64 - do { raw_local_irq_save(flags); trace_hardirqs_off(); } while (0) 61 + #define local_irq_save(flags) \ 62 + do { \ 63 + typecheck(unsigned long, flags); \ 64 + raw_local_irq_save(flags); \ 65 + trace_hardirqs_off(); \ 66 + } while (0) 65 67 66 - #define local_irq_restore(flags) \ 67 - do { \ 68 - if (raw_irqs_disabled_flags(flags)) { \ 69 - raw_local_irq_restore(flags); \ 70 - trace_hardirqs_off(); \ 71 - } else { \ 72 - trace_hardirqs_on(); \ 73 - raw_local_irq_restore(flags); \ 74 - } \ 68 + 69 + #define local_irq_restore(flags) \ 70 + do { \ 71 + typecheck(unsigned long, flags); \ 72 + if (raw_irqs_disabled_flags(flags)) { \ 73 + raw_local_irq_restore(flags); \ 74 + trace_hardirqs_off(); \ 75 + } else { \ 76 + trace_hardirqs_on(); \ 77 + raw_local_irq_restore(flags); \ 78 + } \ 75 79 } while (0) 76 80 #else /* !CONFIG_TRACE_IRQFLAGS_SUPPORT */ 77 81 /* ··· 86 78 */ 87 79 # define raw_local_irq_disable() local_irq_disable() 88 80 # define raw_local_irq_enable() local_irq_enable() 89 - # define raw_local_irq_save(flags) local_irq_save(flags) 90 - # define raw_local_irq_restore(flags) local_irq_restore(flags) 81 + # define raw_local_irq_save(flags) \ 82 + do { \ 83 + typecheck(unsigned long, flags); \ 84 + local_irq_save(flags); \ 85 + } while (0) 86 + # define raw_local_irq_restore(flags) \ 87 + do { \ 88 + typecheck(unsigned long, flags); \ 89 + local_irq_restore(flags); \ 90 + } while (0) 91 91 #endif /* CONFIG_TRACE_IRQFLAGS_SUPPORT */ 92 92 93 93 #ifdef CONFIG_TRACE_IRQFLAGS_SUPPORT ··· 105 89 raw_safe_halt(); \ 106 90 } while (0) 107 91 108 - #define local_save_flags(flags) raw_local_save_flags(flags) 92 + #define local_save_flags(flags) \ 93 + do { \ 94 + typecheck(unsigned long, flags); \ 95 + raw_local_save_flags(flags); \ 96 + } while (0) 109 97 110 98 #define irqs_disabled() \ 111 99 ({ \ ··· 119 99 raw_irqs_disabled_flags(_flags); \ 120 100 }) 121 101 122 - #define irqs_disabled_flags(flags) raw_irqs_disabled_flags(flags) 102 + #define irqs_disabled_flags(flags) \ 103 + ({ \ 104 + typecheck(unsigned long, flags); \ 105 + raw_irqs_disabled_flags(flags); \ 106 + }) 123 107 #endif /* CONFIG_X86 */ 124 108 125 109 #endif
+56 -16
include/linux/spinlock.h
··· 46 46 * linux/spinlock.h: builds the final spin_*() APIs. 47 47 */ 48 48 49 + #include <linux/typecheck.h> 49 50 #include <linux/preempt.h> 50 51 #include <linux/linkage.h> 51 52 #include <linux/compiler.h> ··· 192 191 193 192 #if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK) 194 193 195 - #define spin_lock_irqsave(lock, flags) flags = _spin_lock_irqsave(lock) 196 - #define read_lock_irqsave(lock, flags) flags = _read_lock_irqsave(lock) 197 - #define write_lock_irqsave(lock, flags) flags = _write_lock_irqsave(lock) 194 + #define spin_lock_irqsave(lock, flags) \ 195 + do { \ 196 + typecheck(unsigned long, flags); \ 197 + flags = _spin_lock_irqsave(lock); \ 198 + } while (0) 199 + #define read_lock_irqsave(lock, flags) \ 200 + do { \ 201 + typecheck(unsigned long, flags); \ 202 + flags = _read_lock_irqsave(lock); \ 203 + } while (0) 204 + #define write_lock_irqsave(lock, flags) \ 205 + do { \ 206 + typecheck(unsigned long, flags); \ 207 + flags = _write_lock_irqsave(lock); \ 208 + } while (0) 198 209 199 210 #ifdef CONFIG_DEBUG_LOCK_ALLOC 200 - #define spin_lock_irqsave_nested(lock, flags, subclass) \ 201 - flags = _spin_lock_irqsave_nested(lock, subclass) 211 + #define spin_lock_irqsave_nested(lock, flags, subclass) \ 212 + do { \ 213 + typecheck(unsigned long, flags); \ 214 + flags = _spin_lock_irqsave_nested(lock, subclass); \ 215 + } while (0) 202 216 #else 203 - #define spin_lock_irqsave_nested(lock, flags, subclass) \ 204 - flags = _spin_lock_irqsave(lock) 217 + #define spin_lock_irqsave_nested(lock, flags, subclass) \ 218 + do { \ 219 + typecheck(unsigned long, flags); \ 220 + flags = _spin_lock_irqsave(lock); \ 221 + } while (0) 205 222 #endif 206 223 207 224 #else 208 225 209 - #define spin_lock_irqsave(lock, flags) _spin_lock_irqsave(lock, flags) 210 - #define read_lock_irqsave(lock, flags) _read_lock_irqsave(lock, flags) 211 - #define write_lock_irqsave(lock, flags) _write_lock_irqsave(lock, flags) 226 + #define spin_lock_irqsave(lock, flags) \ 227 + do { \ 228 + typecheck(unsigned long, flags); \ 229 + _spin_lock_irqsave(lock, flags); \ 230 + } while (0) 231 + #define read_lock_irqsave(lock, flags) \ 232 + do { \ 233 + typecheck(unsigned long, flags); \ 234 + _read_lock_irqsave(lock, flags); \ 235 + } while (0) 236 + #define write_lock_irqsave(lock, flags) \ 237 + do { \ 238 + typecheck(unsigned long, flags); \ 239 + _write_lock_irqsave(lock, flags); \ 240 + } while (0) 212 241 #define spin_lock_irqsave_nested(lock, flags, subclass) \ 213 242 spin_lock_irqsave(lock, flags) 214 243 ··· 291 260 } while (0) 292 261 #endif 293 262 294 - #define spin_unlock_irqrestore(lock, flags) \ 295 - _spin_unlock_irqrestore(lock, flags) 263 + #define spin_unlock_irqrestore(lock, flags) \ 264 + do { \ 265 + typecheck(unsigned long, flags); \ 266 + _spin_unlock_irqrestore(lock, flags); \ 267 + } while (0) 296 268 #define spin_unlock_bh(lock) _spin_unlock_bh(lock) 297 269 298 - #define read_unlock_irqrestore(lock, flags) \ 299 - _read_unlock_irqrestore(lock, flags) 270 + #define read_unlock_irqrestore(lock, flags) \ 271 + do { \ 272 + typecheck(unsigned long, flags); \ 273 + _read_unlock_irqrestore(lock, flags); \ 274 + } while (0) 300 275 #define read_unlock_bh(lock) _read_unlock_bh(lock) 301 276 302 - #define write_unlock_irqrestore(lock, flags) \ 303 - _write_unlock_irqrestore(lock, flags) 277 + #define write_unlock_irqrestore(lock, flags) \ 278 + do { \ 279 + typecheck(unsigned long, flags); \ 280 + _write_unlock_irqrestore(lock, flags); \ 281 + } while (0) 304 282 #define write_unlock_bh(lock) _write_unlock_bh(lock) 305 283 306 284 #define spin_trylock_bh(lock) __cond_lock(lock, _spin_trylock_bh(lock))