Unverified Commit dd865f09 authored by Arnd Bergmann's avatar Arnd Bergmann
Browse files

Merge branch 'set_fs-4' of...

Merge branch 'set_fs-4' of git://git.kernel.org/pub/scm/linux/kernel/git/arnd/asm-generic into asm-generic

Christoph Hellwig and a few others spent a huge effort on removing
set_fs() from most of the important architectures, but about half the
other architectures were never completed even though most of them don't
actually use set_fs() at all.

I did a patch for microblaze at some point, which turned out to be fairly
generic, and now ported it to most other architectures, using new generic
implementations of access_ok() and __{get,put}_kernel_nocheck().

Three architectures (sparc64, ia64, and sh) needed some extra work,
which I also completed.

* 'set_fs-4' of git://git.kernel.org/pub/scm/linux/kernel/git/arnd/asm-generic:
  uaccess: remove CONFIG_SET_FS
  ia64: remove CONFIG_SET_FS support
  sh: remove CONFIG_SET_FS support
  sparc64: remove CONFIG_SET_FS support
  lib/test_lockup: fix kernel pointer check for separate address spaces
  uaccess: generalize access_ok()
  uaccess: fix type mismatch warnings from access_ok()
  arm64: simplify access_ok()
  m68k: fix access_ok for coldfire
  MIPS: use simpler access_ok()
  MIPS: Handle address errors for accesses above CPU max virtual user address
  uaccess: add generic __{get,put}_kernel_nofault
  nios2: drop access_ok() check from __put_user()
  x86: use more conventional access_ok() definition
  x86: remove __range_not_ok()
  sparc64: add __{get,put}_kernel_nofault()
  nds32: fix access_ok() checks in get/put_user
  uaccess: fix nios2 and microblaze get_user_8()
  uaccess: fix integer overflow on access_ok()
parents be92e1de 967747bb
Loading
Loading
Loading
Loading
+7 −3
Original line number Diff line number Diff line
@@ -24,9 +24,6 @@ config KEXEC_ELF
config HAVE_IMA_KEXEC
	bool

config SET_FS
	bool

config HOTPLUG_SMT
	bool

@@ -898,6 +895,13 @@ config HAVE_SOFTIRQ_ON_OWN_STACK
	  Architecture provides a function to run __do_softirq() on a
	  separate stack.

config ALTERNATE_USER_ADDRESS_SPACE
	bool
	help
	  Architectures set this when the CPU uses separate address
	  spaces for kernel and user space pointers. In this case, the
	  access_ok() check on a __user pointer is skipped.

config PGTABLE_LEVELS
	int
	default 2
+0 −1
Original line number Diff line number Diff line
@@ -35,7 +35,6 @@ config ALPHA
	select OLD_SIGSUSPEND
	select CPU_NO_EFFICIENT_FFS if !ALPHA_EV67
	select MMU_GATHER_NO_RANGE
	select SET_FS
	select SPARSEMEM_EXTREME if SPARSEMEM
	select ZONE_DMA
	help
+0 −4
Original line number Diff line number Diff line
@@ -26,10 +26,6 @@
#define TASK_UNMAPPED_BASE \
  ((current->personality & ADDR_LIMIT_32BIT) ? 0x40000000 : TASK_SIZE / 2)

typedef struct {
	unsigned long seg;
} mm_segment_t;

/* This is dead.  Everything has been moved to thread_info.  */
struct thread_struct { };
#define INIT_THREAD  { }
+0 −2
Original line number Diff line number Diff line
@@ -19,7 +19,6 @@ struct thread_info {
	unsigned int		flags;		/* low level flags */
	unsigned int		ieee_state;	/* see fpu.h */

	mm_segment_t		addr_limit;	/* thread address space */
	unsigned		cpu;		/* current CPU */
	int			preempt_count; /* 0 => preemptable, <0 => BUG */
	unsigned int		status;		/* thread-synchronous flags */
@@ -35,7 +34,6 @@ struct thread_info {
#define INIT_THREAD_INFO(tsk)			\
{						\
	.task		= &tsk,			\
	.addr_limit	= KERNEL_DS,		\
	.preempt_count	= INIT_PREEMPT_COUNT,	\
}

+5 −48
Original line number Diff line number Diff line
@@ -2,47 +2,7 @@
#ifndef __ALPHA_UACCESS_H
#define __ALPHA_UACCESS_H

/*
 * The fs value determines whether argument validity checking should be
 * performed or not.  If get_fs() == USER_DS, checking is performed, with
 * get_fs() == KERNEL_DS, checking is bypassed.
 *
 * Or at least it did once upon a time.  Nowadays it is a mask that
 * defines which bits of the address space are off limits.  This is a
 * wee bit faster than the above.
 *
 * For historical reasons, these macros are grossly misnamed.
 */

#define KERNEL_DS	((mm_segment_t) { 0UL })
#define USER_DS		((mm_segment_t) { -0x40000000000UL })

#define get_fs()  (current_thread_info()->addr_limit)
#define set_fs(x) (current_thread_info()->addr_limit = (x))

#define uaccess_kernel()	(get_fs().seg == KERNEL_DS.seg)

/*
 * Is a address valid? This does a straightforward calculation rather
 * than tests.
 *
 * Address valid if:
 *  - "addr" doesn't have any high-bits set
 *  - AND "size" doesn't have any high-bits set
 *  - AND "addr+size-(size != 0)" doesn't have any high-bits set
 *  - OR we are in kernel mode.
 */
#define __access_ok(addr, size) ({				\
	unsigned long __ao_a = (addr), __ao_b = (size);		\
	unsigned long __ao_end = __ao_a + __ao_b - !!__ao_b;	\
	(get_fs().seg & (__ao_a | __ao_b | __ao_end)) == 0; })

#define access_ok(addr, size)				\
({							\
	__chk_user_ptr(addr);				\
	__access_ok(((unsigned long)(addr)), (size));	\
})

#include <asm-generic/access_ok.h>
/*
 * These are the main single-value transfer routines.  They automatically
 * use the right size if we just have the right pointer type.
@@ -105,7 +65,7 @@ extern void __get_user_unknown(void);
	long __gu_err = -EFAULT;				\
	unsigned long __gu_val = 0;				\
	const __typeof__(*(ptr)) __user *__gu_addr = (ptr);	\
	if (__access_ok((unsigned long)__gu_addr, size)) {	\
	if (__access_ok(__gu_addr, size)) {			\
		__gu_err = 0;					\
		switch (size) {					\
		  case 1: __get_user_8(__gu_addr); break;	\
@@ -200,7 +160,7 @@ extern void __put_user_unknown(void);
({								\
	long __pu_err = -EFAULT;				\
	__typeof__(*(ptr)) __user *__pu_addr = (ptr);		\
	if (__access_ok((unsigned long)__pu_addr, size)) {	\
	if (__access_ok(__pu_addr, size)) {			\
		__pu_err = 0;					\
		switch (size) {					\
		  case 1: __put_user_8(x, __pu_addr); break;	\
@@ -316,17 +276,14 @@ raw_copy_to_user(void __user *to, const void *from, unsigned long len)

extern long __clear_user(void __user *to, long len);

extern inline long
static inline long
clear_user(void __user *to, long len)
{
	if (__access_ok((unsigned long)to, len))
	if (__access_ok(to, len))
		len = __clear_user(to, len);
	return len;
}

#define user_addr_max() \
        (uaccess_kernel() ? ~0UL : TASK_SIZE)

extern long strncpy_from_user(char *dest, const char __user *src, long count);
extern __must_check long strnlen_user(const char __user *str, long n);

Loading