Skip to content

Commit fb34035

Browse files
committed
sparc: Use __builtin_object_size() to validate the buffer size for copy_from_user()
This mirrors x86 commit 9f0cf4a (x86: Use __builtin_object_size() to validate the buffer size for copy_from_user()) Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 4ed5d5e commit fb34035

File tree

5 files changed

+57
-4
lines changed

5 files changed

+57
-4
lines changed

arch/sparc/Kconfig.debug

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,18 @@ config FRAME_POINTER
3333
depends on MCOUNT
3434
default y
3535

36+
config DEBUG_STRICT_USER_COPY_CHECKS
37+
bool "Strict copy size checks"
38+
depends on DEBUG_KERNEL && !TRACE_BRANCH_PROFILING
39+
---help---
40+
Enabling this option turns a certain set of sanity checks for user
41+
copy operations into compile time failures.
42+
43+
The copy_from_user() etc checks are there to help test if there
44+
are sufficient security checks on the length argument of
45+
the copy operation, by having gcc prove that the argument is
46+
within bounds.
47+
48+
If unsure, or if you run an older (pre 4.4) gcc, say N.
49+
3650
endmenu

arch/sparc/include/asm/uaccess_32.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,8 +260,23 @@ static inline unsigned long __copy_to_user(void __user *to, const void *from, un
260260
return __copy_user(to, (__force void __user *) from, n);
261261
}
262262

263+
extern void copy_from_user_overflow(void)
264+
#ifdef CONFIG_DEBUG_STRICT_USER_COPY_CHECKS
265+
__compiletime_error("copy_from_user() buffer size is not provably correct")
266+
#else
267+
__compiletime_warning("copy_from_user() buffer size is not provably correct")
268+
#endif
269+
;
270+
263271
static inline unsigned long copy_from_user(void *to, const void __user *from, unsigned long n)
264272
{
273+
int sz = __compiletime_object_size(to);
274+
275+
if (unlikely(sz != -1 && sz < n)) {
276+
copy_from_user_overflow();
277+
return -EFAULT;
278+
}
279+
265280
if (n && __access_ok((unsigned long) from, n))
266281
return __copy_user((__force void __user *) to, from, n);
267282
else

arch/sparc/include/asm/uaccess_64.h

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
*/
77

88
#ifdef __KERNEL__
9+
#include <linux/errno.h>
910
#include <linux/compiler.h>
1011
#include <linux/string.h>
1112
#include <linux/thread_info.h>
@@ -204,6 +205,14 @@ __asm__ __volatile__( \
204205

205206
extern int __get_user_bad(void);
206207

208+
extern void copy_from_user_overflow(void)
209+
#ifdef CONFIG_DEBUG_STRICT_USER_COPY_CHECKS
210+
__compiletime_error("copy_from_user() buffer size is not provably correct")
211+
#else
212+
__compiletime_warning("copy_from_user() buffer size is not provably correct")
213+
#endif
214+
;
215+
207216
extern unsigned long __must_check ___copy_from_user(void *to,
208217
const void __user *from,
209218
unsigned long size);
@@ -212,10 +221,16 @@ extern unsigned long copy_from_user_fixup(void *to, const void __user *from,
212221
static inline unsigned long __must_check
213222
copy_from_user(void *to, const void __user *from, unsigned long size)
214223
{
215-
unsigned long ret = ___copy_from_user(to, from, size);
216-
217-
if (unlikely(ret))
218-
ret = copy_from_user_fixup(to, from, size);
224+
unsigned long ret = (unsigned long) -EFAULT;
225+
int sz = __compiletime_object_size(to);
226+
227+
if (likely(sz == -1 || sz >= size)) {
228+
ret = ___copy_from_user(to, from, size);
229+
if (unlikely(ret))
230+
ret = copy_from_user_fixup(to, from, size);
231+
} else {
232+
copy_from_user_overflow();
233+
}
219234
return ret;
220235
}
221236
#define __copy_from_user copy_from_user

arch/sparc/lib/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,4 @@ obj-y += iomap.o
4444
obj-$(CONFIG_SPARC32) += atomic32.o
4545
obj-y += ksyms.o
4646
obj-$(CONFIG_SPARC64) += PeeCeeI.o
47+
obj-y += usercopy.o

arch/sparc/lib/usercopy.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#include <linux/module.h>
2+
#include <linux/bug.h>
3+
4+
void copy_from_user_overflow(void)
5+
{
6+
WARN(1, "Buffer overflow detected!\n");
7+
}
8+
EXPORT_SYMBOL(copy_from_user_overflow);

0 commit comments

Comments
 (0)