diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/parisc/Kconfig.debug | 14 | ||||
-rw-r--r-- | arch/parisc/include/asm/param.h | 23 | ||||
-rw-r--r-- | arch/parisc/include/asm/system.h | 2 | ||||
-rw-r--r-- | arch/parisc/include/asm/uaccess.h | 27 | ||||
-rw-r--r-- | arch/parisc/include/asm/unistd.h | 4 | ||||
-rw-r--r-- | arch/parisc/kernel/cache.c | 4 | ||||
-rw-r--r-- | arch/parisc/kernel/syscall_table.S | 2 | ||||
-rw-r--r-- | arch/parisc/kernel/time.c | 29 | ||||
-rw-r--r-- | arch/parisc/kernel/unaligned.c | 14 | ||||
-rw-r--r-- | arch/parisc/lib/memcpy.c | 3 |
10 files changed, 67 insertions, 55 deletions
diff --git a/arch/parisc/Kconfig.debug b/arch/parisc/Kconfig.debug index bc989e522a04..7305ac8f7f5b 100644 --- a/arch/parisc/Kconfig.debug +++ b/arch/parisc/Kconfig.debug @@ -12,4 +12,18 @@ config DEBUG_RODATA portion of the kernel code won't be covered by a TLB anymore. If in doubt, say "N". +config DEBUG_STRICT_USER_COPY_CHECKS + bool "Strict copy size checks" + depends on DEBUG_KERNEL && !TRACE_BRANCH_PROFILING + ---help--- + Enabling this option turns a certain set of sanity checks for user + copy operations into compile time failures. + + The copy_from_user() etc checks are there to help test if there + are sufficient security checks on the length argument of + the copy operation, by having gcc prove that the argument is + within bounds. + + If unsure, or if you run an older (pre 4.4) gcc, say N. + endmenu diff --git a/arch/parisc/include/asm/param.h b/arch/parisc/include/asm/param.h index 32e03d877858..965d45427975 100644 --- a/arch/parisc/include/asm/param.h +++ b/arch/parisc/include/asm/param.h @@ -1,22 +1 @@ -#ifndef _ASMPARISC_PARAM_H -#define _ASMPARISC_PARAM_H - -#ifdef __KERNEL__ -#define HZ CONFIG_HZ -#define USER_HZ 100 /* some user API use "ticks" */ -#define CLOCKS_PER_SEC (USER_HZ) /* like times() */ -#endif - -#ifndef HZ -#define HZ 100 -#endif - -#define EXEC_PAGESIZE 4096 - -#ifndef NOGROUP -#define NOGROUP (-1) -#endif - -#define MAXHOSTNAMELEN 64 /* max length of hostname */ - -#endif +#include <asm-generic/param.h> diff --git a/arch/parisc/include/asm/system.h b/arch/parisc/include/asm/system.h index d91357bca5b4..4653c77bf9d1 100644 --- a/arch/parisc/include/asm/system.h +++ b/arch/parisc/include/asm/system.h @@ -160,7 +160,7 @@ static inline void set_eiem(unsigned long val) ldcd). */ #define __PA_LDCW_ALIGNMENT 4 -#define __ldcw_align(a) ((volatile unsigned int *)a) +#define __ldcw_align(a) (&(a)->slock) #define __LDCW "ldcw,co" #endif /*!CONFIG_PA20*/ diff --git a/arch/parisc/include/asm/uaccess.h b/arch/parisc/include/asm/uaccess.h index 7cf799d70b4c..ff4cf9dab8d2 100644 --- a/arch/parisc/include/asm/uaccess.h +++ b/arch/parisc/include/asm/uaccess.h @@ -7,6 +7,7 @@ #include <asm/page.h> #include <asm/system.h> #include <asm/cache.h> +#include <asm/errno.h> #include <asm-generic/uaccess-unaligned.h> #define VERIFY_READ 0 @@ -234,13 +235,35 @@ extern long lstrnlen_user(const char __user *,long); unsigned long copy_to_user(void __user *dst, const void *src, unsigned long len); #define __copy_to_user copy_to_user -unsigned long copy_from_user(void *dst, const void __user *src, unsigned long len); -#define __copy_from_user copy_from_user +unsigned long __copy_from_user(void *dst, const void __user *src, unsigned long len); unsigned long copy_in_user(void __user *dst, const void __user *src, unsigned long len); #define __copy_in_user copy_in_user #define __copy_to_user_inatomic __copy_to_user #define __copy_from_user_inatomic __copy_from_user +extern void copy_from_user_overflow(void) +#ifdef CONFIG_DEBUG_STRICT_USER_COPY_CHECKS + __compiletime_error("copy_from_user() buffer size is not provably correct") +#else + __compiletime_warning("copy_from_user() buffer size is not provably correct") +#endif +; + +static inline unsigned long __must_check copy_from_user(void *to, + const void __user *from, + unsigned long n) +{ + int sz = __compiletime_object_size(to); + int ret = -EFAULT; + + if (likely(sz == -1 || !__builtin_constant_p(n) || sz >= n)) + ret = __copy_from_user(to, from, n); + else + copy_from_user_overflow(); + + return ret; +} + struct pt_regs; int fixup_exception(struct pt_regs *regs); diff --git a/arch/parisc/include/asm/unistd.h b/arch/parisc/include/asm/unistd.h index cda158318c62..1ce7d2851d90 100644 --- a/arch/parisc/include/asm/unistd.h +++ b/arch/parisc/include/asm/unistd.h @@ -811,8 +811,10 @@ #define __NR_pwritev (__NR_Linux + 316) #define __NR_rt_tgsigqueueinfo (__NR_Linux + 317) #define __NR_perf_event_open (__NR_Linux + 318) +#define __NR_recvmmsg (__NR_Linux + 319) +#define __NR_accept4 (__NR_Linux + 320) -#define __NR_Linux_syscalls (__NR_perf_event_open + 1) +#define __NR_Linux_syscalls (__NR_accept4 + 1) #define __IGNORE_select /* newselect */ diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c index 1054baa2fc69..d054f3da3ff5 100644 --- a/arch/parisc/kernel/cache.c +++ b/arch/parisc/kernel/cache.c @@ -171,14 +171,14 @@ parisc_cache_init(void) cache_info.ic_conf.cc_cst, cache_info.ic_conf.cc_hv); - printk("D-TLB conf: sh %d page %d cst %d aid %d pad1 %d \n", + printk("D-TLB conf: sh %d page %d cst %d aid %d pad1 %d\n", cache_info.dt_conf.tc_sh, cache_info.dt_conf.tc_page, cache_info.dt_conf.tc_cst, cache_info.dt_conf.tc_aid, cache_info.dt_conf.tc_pad1); - printk("I-TLB conf: sh %d page %d cst %d aid %d pad1 %d \n", + printk("I-TLB conf: sh %d page %d cst %d aid %d pad1 %d\n", cache_info.it_conf.tc_sh, cache_info.it_conf.tc_page, cache_info.it_conf.tc_cst, diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S index 01c4fcf8f481..de5f6dab48b7 100644 --- a/arch/parisc/kernel/syscall_table.S +++ b/arch/parisc/kernel/syscall_table.S @@ -417,6 +417,8 @@ ENTRY_COMP(pwritev) ENTRY_COMP(rt_tgsigqueueinfo) ENTRY_SAME(perf_event_open) + ENTRY_COMP(recvmmsg) + ENTRY_SAME(accept4) /* 320 */ /* Nothing yet */ diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c index a79c6f9e7e2c..05511ccb61d2 100644 --- a/arch/parisc/kernel/time.c +++ b/arch/parisc/kernel/time.c @@ -250,9 +250,21 @@ static int __init rtc_init(void) } module_init(rtc_init); -void __init time_init(void) +void read_persistent_clock(struct timespec *ts) { static struct pdc_tod tod_data; + if (pdc_tod_read(&tod_data) == 0) { + ts->tv_sec = tod_data.tod_sec; + ts->tv_nsec = tod_data.tod_usec * 1000; + } else { + printk(KERN_ERR "Error reading tod clock\n"); + ts->tv_sec = 0; + ts->tv_nsec = 0; + } +} + +void __init time_init(void) +{ unsigned long current_cr16_khz; clocktick = (100 * PAGE0->mem_10msec) / HZ; @@ -264,19 +276,4 @@ void __init time_init(void) clocksource_cr16.mult = clocksource_khz2mult(current_cr16_khz, clocksource_cr16.shift); clocksource_register(&clocksource_cr16); - - if (pdc_tod_read(&tod_data) == 0) { - unsigned long flags; - - write_seqlock_irqsave(&xtime_lock, flags); - xtime.tv_sec = tod_data.tod_sec; - xtime.tv_nsec = tod_data.tod_usec * 1000; - set_normalized_timespec(&wall_to_monotonic, - -xtime.tv_sec, -xtime.tv_nsec); - write_sequnlock_irqrestore(&xtime_lock, flags); - } else { - printk(KERN_ERR "Error reading tod clock\n"); - xtime.tv_sec = 0; - xtime.tv_nsec = 0; - } } diff --git a/arch/parisc/kernel/unaligned.c b/arch/parisc/kernel/unaligned.c index e6f4b7a4b7e3..92d977bb5ea8 100644 --- a/arch/parisc/kernel/unaligned.c +++ b/arch/parisc/kernel/unaligned.c @@ -25,6 +25,7 @@ #include <linux/module.h> #include <linux/sched.h> #include <linux/signal.h> +#include <linux/ratelimit.h> #include <asm/uaccess.h> /* #define DEBUG_UNALIGNED 1 */ @@ -446,8 +447,7 @@ static int emulate_std(struct pt_regs *regs, int frreg, int flop) void handle_unaligned(struct pt_regs *regs) { - static unsigned long unaligned_count = 0; - static unsigned long last_time = 0; + static DEFINE_RATELIMIT_STATE(ratelimit, 5 * HZ, 5); unsigned long newbase = R1(regs->iir)?regs->gr[R1(regs->iir)]:0; int modify = 0; int ret = ERR_NOTHANDLED; @@ -460,14 +460,8 @@ void handle_unaligned(struct pt_regs *regs) goto force_sigbus; } - if (unaligned_count > 5 && - time_after(jiffies, last_time + 5 * HZ)) { - unaligned_count = 0; - last_time = jiffies; - } - - if (!(current->thread.flags & PARISC_UAC_NOPRINT) - && ++unaligned_count < 5) { + if (!(current->thread.flags & PARISC_UAC_NOPRINT) && + __ratelimit(&ratelimit)) { char buf[256]; sprintf(buf, "%s(%d): unaligned access to 0x" RFMT " at ip=0x" RFMT "\n", current->comm, task_pid_nr(current), regs->ior, regs->iaoq[0]); diff --git a/arch/parisc/lib/memcpy.c b/arch/parisc/lib/memcpy.c index abf41f4632a9..1dbca5c31b3c 100644 --- a/arch/parisc/lib/memcpy.c +++ b/arch/parisc/lib/memcpy.c @@ -475,7 +475,8 @@ unsigned long copy_to_user(void __user *dst, const void *src, unsigned long len) return pa_memcpy((void __force *)dst, src, len); } -unsigned long copy_from_user(void *dst, const void __user *src, unsigned long len) +EXPORT_SYMBOL(__copy_from_user); +unsigned long __copy_from_user(void *dst, const void __user *src, unsigned long len) { mtsp(get_user_space(), 1); mtsp(get_kernel_space(), 2); |