Skip to content

Commit

Permalink
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6
Browse files Browse the repository at this point in the history
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6:
  sparc64: Fix clock event multiplier printf format.
  sparc64: Use clock{source,events}_calc_mult_shift().
  sparc64: Use free_bootmem_late() in mdesc_lmb_free().
  sparc: Add alignment and emulation fault perf events.
  sparc64: Add syscall tracepoint support.
  sparc: Stop trying to be so fancy and use __builtin_{memcpy,memset}()
  sparc: Use __builtin_object_size() to validate the buffer size for copy_from_user()
  sparc64: Add some missing __kprobes annotations to kernel fault paths.
  sparc64: Use kprobes_built_in() to avoid ifdefs in fault_64.c
  sparc: Validate that kprobe address is 4-byte aligned.
  sparc64: Don't specify IRQF_SHARED for LDC interrupts.
  sparc64: Fix stack debugging IRQ stack regression.
  sparc64: Fix overly strict range type matching for PCI devices.
  • Loading branch information
Linus Torvalds committed Dec 15, 2009
2 parents 48e902f + 7466bd3 commit 17c330f
Show file tree
Hide file tree
Showing 31 changed files with 154 additions and 210 deletions.
1 change: 1 addition & 0 deletions arch/sparc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ config SPARC64
select HAVE_SYSCALL_WRAPPERS
select HAVE_DYNAMIC_FTRACE
select HAVE_FTRACE_MCOUNT_RECORD
select HAVE_SYSCALL_TRACEPOINTS
select USE_GENERIC_SMP_HELPERS if SMP
select RTC_DRV_CMOS
select RTC_DRV_BQ4802
Expand Down
14 changes: 14 additions & 0 deletions arch/sparc/Kconfig.debug
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,18 @@ config FRAME_POINTER
depends on MCOUNT
default y

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
78 changes: 2 additions & 76 deletions arch/sparc/include/asm/string_32.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@
#ifdef __KERNEL__

extern void __memmove(void *,const void *,__kernel_size_t);
extern __kernel_size_t __memcpy(void *,const void *,__kernel_size_t);
extern __kernel_size_t __memset(void *,int,__kernel_size_t);

#ifndef EXPORT_SYMTAB_STROPS

Expand All @@ -32,82 +30,10 @@ extern __kernel_size_t __memset(void *,int,__kernel_size_t);
})

#define __HAVE_ARCH_MEMCPY

static inline void *__constant_memcpy(void *to, const void *from, __kernel_size_t n)
{
extern void __copy_1page(void *, const void *);

if(n <= 32) {
__builtin_memcpy(to, from, n);
} else if (((unsigned int) to & 7) != 0) {
/* Destination is not aligned on the double-word boundary */
__memcpy(to, from, n);
} else {
switch(n) {
case PAGE_SIZE:
__copy_1page(to, from);
break;
default:
__memcpy(to, from, n);
break;
}
}
return to;
}

static inline void *__nonconstant_memcpy(void *to, const void *from, __kernel_size_t n)
{
__memcpy(to, from, n);
return to;
}

#undef memcpy
#define memcpy(t, f, n) \
(__builtin_constant_p(n) ? \
__constant_memcpy((t),(f),(n)) : \
__nonconstant_memcpy((t),(f),(n)))
#define memcpy(t, f, n) __builtin_memcpy(t, f, n)

#define __HAVE_ARCH_MEMSET

static inline void *__constant_c_and_count_memset(void *s, char c, __kernel_size_t count)
{
extern void bzero_1page(void *);
extern __kernel_size_t __bzero(void *, __kernel_size_t);

if(!c) {
if(count == PAGE_SIZE)
bzero_1page(s);
else
__bzero(s, count);
} else {
__memset(s, c, count);
}
return s;
}

static inline void *__constant_c_memset(void *s, char c, __kernel_size_t count)
{
extern __kernel_size_t __bzero(void *, __kernel_size_t);

if(!c)
__bzero(s, count);
else
__memset(s, c, count);
return s;
}

static inline void *__nonconstant_memset(void *s, char c, __kernel_size_t count)
{
__memset(s, c, count);
return s;
}

#undef memset
#define memset(s, c, count) \
(__builtin_constant_p(c) ? (__builtin_constant_p(count) ? \
__constant_c_and_count_memset((s), (c), (count)) : \
__constant_c_memset((s), (c), (count))) \
: __nonconstant_memset((s), (c), (count)))
#define memset(s, c, count) __builtin_memset(s, c, count)

#define __HAVE_ARCH_MEMSCAN

Expand Down
25 changes: 2 additions & 23 deletions arch/sparc/include/asm/string_64.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,38 +15,17 @@

#include <asm/asi.h>

extern void *__memset(void *,int,__kernel_size_t);

#ifndef EXPORT_SYMTAB_STROPS

/* First the mem*() things. */
#define __HAVE_ARCH_MEMMOVE
extern void *memmove(void *, const void *, __kernel_size_t);

#define __HAVE_ARCH_MEMCPY
extern void *memcpy(void *, const void *, __kernel_size_t);
#define memcpy(t, f, n) __builtin_memcpy(t, f, n)

#define __HAVE_ARCH_MEMSET
extern void *__builtin_memset(void *,int,__kernel_size_t);

static inline void *__constant_memset(void *s, int c, __kernel_size_t count)
{
extern __kernel_size_t __bzero(void *, __kernel_size_t);

if (!c) {
__bzero(s, count);
return s;
} else
return __memset(s, c, count);
}

#undef memset
#define memset(s, c, count) \
((__builtin_constant_p(count) && (count) <= 32) ? \
__builtin_memset((s), (c), (count)) : \
(__builtin_constant_p(c) ? \
__constant_memset((s), (c), (count)) : \
__memset((s), (c), (count))))
#define memset(s, c, count) __builtin_memset(s, c, count)

#define __HAVE_ARCH_MEMSCAN

Expand Down
2 changes: 2 additions & 0 deletions arch/sparc/include/asm/thread_info_64.h
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@ register struct thread_info *current_thread_info_reg asm("g6");
/* flag bit 8 is available */
#define TIF_SECCOMP 9 /* secure computing */
#define TIF_SYSCALL_AUDIT 10 /* syscall auditing active */
#define TIF_SYSCALL_TRACEPOINT 11 /* syscall tracepoint instrumentation */
/* flag bit 11 is available */
/* NOTE: Thread flags >= 12 should be ones we have no interest
* in using in assembly, else we can't use the mask as
Expand All @@ -246,6 +247,7 @@ register struct thread_info *current_thread_info_reg asm("g6");
#define _TIF_32BIT (1<<TIF_32BIT)
#define _TIF_SECCOMP (1<<TIF_SECCOMP)
#define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT)
#define _TIF_SYSCALL_TRACEPOINT (1<<TIF_SYSCALL_TRACEPOINT)
#define _TIF_ABI_PENDING (1<<TIF_ABI_PENDING)
#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
#define _TIF_FREEZE (1<<TIF_FREEZE)
Expand Down
15 changes: 15 additions & 0 deletions arch/sparc/include/asm/uaccess_32.h
Original file line number Diff line number Diff line change
Expand Up @@ -260,8 +260,23 @@ static inline unsigned long __copy_to_user(void __user *to, const void *from, un
return __copy_user(to, (__force void __user *) from, n);
}

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 copy_from_user(void *to, const void __user *from, unsigned long n)
{
int sz = __compiletime_object_size(to);

if (unlikely(sz != -1 && sz < n)) {
copy_from_user_overflow();
return -EFAULT;
}

if (n && __access_ok((unsigned long) from, n))
return __copy_user((__force void __user *) to, from, n);
else
Expand Down
23 changes: 19 additions & 4 deletions arch/sparc/include/asm/uaccess_64.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/

#ifdef __KERNEL__
#include <linux/errno.h>
#include <linux/compiler.h>
#include <linux/string.h>
#include <linux/thread_info.h>
Expand Down Expand Up @@ -204,6 +205,14 @@ __asm__ __volatile__( \

extern int __get_user_bad(void);

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
;

extern unsigned long __must_check ___copy_from_user(void *to,
const void __user *from,
unsigned long size);
Expand All @@ -212,10 +221,16 @@ extern unsigned long copy_from_user_fixup(void *to, const void __user *from,
static inline unsigned long __must_check
copy_from_user(void *to, const void __user *from, unsigned long size)
{
unsigned long ret = ___copy_from_user(to, from, size);

if (unlikely(ret))
ret = copy_from_user_fixup(to, from, size);
unsigned long ret = (unsigned long) -EFAULT;
int sz = __compiletime_object_size(to);

if (likely(sz == -1 || sz >= size)) {
ret = ___copy_from_user(to, from, size);
if (unlikely(ret))
ret = copy_from_user_fixup(to, from, size);
} else {
copy_from_user_overflow();
}
return ret;
}
#define __copy_from_user copy_from_user
Expand Down
2 changes: 1 addition & 1 deletion arch/sparc/include/asm/unistd.h
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,7 @@
#define __NR_perf_event_open 327
#define __NR_recvmmsg 328

#define NR_SYSCALLS 329
#define NR_syscalls 329

#ifdef __32bit_syscall_numbers__
/* Sparc 32-bit only has the "setresuid32", "getresuid32" variants,
Expand Down
2 changes: 1 addition & 1 deletion arch/sparc/kernel/entry.S
Original file line number Diff line number Diff line change
Expand Up @@ -1294,7 +1294,7 @@ linux_sparc_syscall:
sethi %hi(PSR_SYSCALL), %l4
or %l0, %l4, %l0
/* Direct access to user regs, must faster. */
cmp %g1, NR_SYSCALLS
cmp %g1, NR_syscalls
bgeu linux_sparc_ni_syscall
sll %g1, 2, %l4
ld [%l7 + %l4], %l7
Expand Down
11 changes: 11 additions & 0 deletions arch/sparc/kernel/ftrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <linux/percpu.h>
#include <linux/init.h>
#include <linux/list.h>
#include <trace/syscall.h>

#include <asm/ftrace.h>

Expand Down Expand Up @@ -91,3 +92,13 @@ int __init ftrace_dyn_arch_init(void *data)
}
#endif

#ifdef CONFIG_FTRACE_SYSCALLS

extern unsigned int sys_call_table[];

unsigned long __init arch_syscall_addr(int nr)
{
return (unsigned long)sys_call_table[nr];
}

#endif
3 changes: 3 additions & 0 deletions arch/sparc/kernel/kprobes.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ struct kretprobe_blackpoint kretprobe_blacklist[] = {{NULL, NULL}};

int __kprobes arch_prepare_kprobe(struct kprobe *p)
{
if ((unsigned long) p->addr & 0x3UL)
return -EILSEQ;

p->ainsn.insn[0] = *p->addr;
flushi(&p->ainsn.insn[0]);

Expand Down
4 changes: 2 additions & 2 deletions arch/sparc/kernel/ldc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1242,13 +1242,13 @@ int ldc_bind(struct ldc_channel *lp, const char *name)
snprintf(lp->tx_irq_name, LDC_IRQ_NAME_MAX, "%s TX", name);

err = request_irq(lp->cfg.rx_irq, ldc_rx,
IRQF_SAMPLE_RANDOM | IRQF_DISABLED | IRQF_SHARED,
IRQF_SAMPLE_RANDOM | IRQF_DISABLED,
lp->rx_irq_name, lp);
if (err)
return err;

err = request_irq(lp->cfg.tx_irq, ldc_tx,
IRQF_SAMPLE_RANDOM | IRQF_DISABLED | IRQF_SHARED,
IRQF_SAMPLE_RANDOM | IRQF_DISABLED,
lp->tx_irq_name, lp);
if (err) {
free_irq(lp->cfg.rx_irq, lp);
Expand Down
21 changes: 6 additions & 15 deletions arch/sparc/kernel/mdesc.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/miscdevice.h>
#include <linux/bootmem.h>

#include <asm/cpudata.h>
#include <asm/hypervisor.h>
Expand Down Expand Up @@ -108,25 +109,15 @@ static struct mdesc_handle * __init mdesc_lmb_alloc(unsigned int mdesc_size)

static void mdesc_lmb_free(struct mdesc_handle *hp)
{
unsigned int alloc_size, handle_size = hp->handle_size;
unsigned long start, end;
unsigned int alloc_size;
unsigned long start;

BUG_ON(atomic_read(&hp->refcnt) != 0);
BUG_ON(!list_empty(&hp->list));

alloc_size = PAGE_ALIGN(handle_size);

start = (unsigned long) hp;
end = start + alloc_size;

while (start < end) {
struct page *p;

p = virt_to_page(start);
ClearPageReserved(p);
__free_page(p);
start += PAGE_SIZE;
}
alloc_size = PAGE_ALIGN(hp->handle_size);
start = __pa(hp);
free_bootmem_late(start, alloc_size);
}

static struct mdesc_mem_ops lmb_mdesc_ops = {
Expand Down
14 changes: 12 additions & 2 deletions arch/sparc/kernel/of_device_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,19 @@ static int of_bus_pci_map(u32 *addr, const u32 *range,
int i;

/* Check address type match */
if ((addr[0] ^ range[0]) & 0x03000000)
return -EINVAL;
if (!((addr[0] ^ range[0]) & 0x03000000))
goto type_match;

/* Special exception, we can map a 64-bit address into
* a 32-bit range.
*/
if ((addr[0] & 0x03000000) == 0x03000000 &&
(range[0] & 0x03000000) == 0x02000000)
goto type_match;

return -EINVAL;

type_match:
if (of_out_of_range(addr + 1, range + 1, range + na + pna,
na - 1, ns))
return -EINVAL;
Expand Down
Loading

0 comments on commit 17c330f

Please sign in to comment.