Commit f0f4725f authored by Peter Zijlstra's avatar Peter Zijlstra Committed by Thadeu Lima de Souza Cascardo

x86/uaccess, sched/preempt: Verify access_ok() context

BugLink: http://bugs.launchpad.net/bugs/1732698

commit 7c478895 upstream.

I recently encountered wreckage because access_ok() was used where it
should not be, add an explicit WARN when access_ok() is used wrongly.
Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-kernel@vger.kernel.org
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
[add include/preempt.h to fix build error - gregkh]
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarStefan Bader <stefan.bader@canonical.com>
Signed-off-by: default avatarThadeu Lima de Souza Cascardo <cascardo@canonical.com>
parent 9dae9f53
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <linux/compiler.h> #include <linux/compiler.h>
#include <linux/thread_info.h> #include <linux/thread_info.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/preempt.h>
#include <asm/asm.h> #include <asm/asm.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/smap.h> #include <asm/smap.h>
...@@ -66,6 +67,12 @@ static inline bool __chk_range_not_ok(unsigned long addr, unsigned long size, un ...@@ -66,6 +67,12 @@ static inline bool __chk_range_not_ok(unsigned long addr, unsigned long size, un
__chk_range_not_ok((unsigned long __force)(addr), size, limit); \ __chk_range_not_ok((unsigned long __force)(addr), size, limit); \
}) })
#ifdef CONFIG_DEBUG_ATOMIC_SLEEP
# define WARN_ON_IN_IRQ() WARN_ON_ONCE(!in_task())
#else
# define WARN_ON_IN_IRQ()
#endif
/** /**
* access_ok: - Checks if a user space pointer is valid * access_ok: - Checks if a user space pointer is valid
* @type: Type of access: %VERIFY_READ or %VERIFY_WRITE. Note that * @type: Type of access: %VERIFY_READ or %VERIFY_WRITE. Note that
...@@ -87,7 +94,10 @@ static inline bool __chk_range_not_ok(unsigned long addr, unsigned long size, un ...@@ -87,7 +94,10 @@ static inline bool __chk_range_not_ok(unsigned long addr, unsigned long size, un
* this function, memory access functions may still return -EFAULT. * this function, memory access functions may still return -EFAULT.
*/ */
#define access_ok(type, addr, size) \ #define access_ok(type, addr, size) \
likely(!__range_not_ok(addr, size, user_addr_max())) ({ \
WARN_ON_IN_IRQ(); \
likely(!__range_not_ok(addr, size, user_addr_max())); \
})
/* /*
* The exception table consists of pairs of addresses relative to the * The exception table consists of pairs of addresses relative to the
......
...@@ -65,19 +65,24 @@ ...@@ -65,19 +65,24 @@
/* /*
* Are we doing bottom half or hardware interrupt processing? * Are we doing bottom half or hardware interrupt processing?
* Are we in a softirq context? Interrupt context? *
* in_softirq - Are we currently processing softirq or have bh disabled? * in_irq() - We're in (hard) IRQ context
* in_serving_softirq - Are we currently processing softirq? * in_softirq() - We have BH disabled, or are processing softirqs
* in_interrupt() - We're in NMI,IRQ,SoftIRQ context or have BH disabled
* in_serving_softirq() - We're in softirq context
* in_nmi() - We're in NMI context
* in_task() - We're in task context
*
* Note: due to the BH disabled confusion: in_softirq(),in_interrupt() really
* should not be used in new code.
*/ */
#define in_irq() (hardirq_count()) #define in_irq() (hardirq_count())
#define in_softirq() (softirq_count()) #define in_softirq() (softirq_count())
#define in_interrupt() (irq_count()) #define in_interrupt() (irq_count())
#define in_serving_softirq() (softirq_count() & SOFTIRQ_OFFSET) #define in_serving_softirq() (softirq_count() & SOFTIRQ_OFFSET)
/*
* Are we in NMI context?
*/
#define in_nmi() (preempt_count() & NMI_MASK) #define in_nmi() (preempt_count() & NMI_MASK)
#define in_task() (!(preempt_count() & \
(NMI_MASK | HARDIRQ_MASK | SOFTIRQ_OFFSET)))
/* /*
* The preempt_count offset after preempt_disable(); * The preempt_count offset after preempt_disable();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment