Merge branch 'work.uaccess' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

Pull uaccess unification updates from Al Viro:
 "This is the uaccess unification pile. It's _not_ the end of uaccess
  work, but the next batch of that will go into the next cycle. This one
  mostly takes copy_from_user() and friends out of arch/* and gets the
  zero-padding behaviour in sync for all architectures.

  Dealing with the nocache/writethrough mess is for the next cycle;
  fortunately, that's x86-only. Same for cleanups in iov_iter.c (I am
  sold on access_ok() in there, BTW; just not in this pile), same for
  reducing __copy_... callsites, strn*... stuff, etc. - there will be a
  pile about as large as this one in the next merge window.

  This one sat in -next for weeks. -3KLoC"

* 'work.uaccess' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (96 commits)
  HAVE_ARCH_HARDENED_USERCOPY is unconditional now
  CONFIG_ARCH_HAS_RAW_COPY_USER is unconditional now
  m32r: switch to RAW_COPY_USER
  hexagon: switch to RAW_COPY_USER
  microblaze: switch to RAW_COPY_USER
  get rid of padding, switch to RAW_COPY_USER
  ia64: get rid of copy_in_user()
  ia64: sanitize __access_ok()
  ia64: get rid of 'segment' argument of __do_{get,put}_user()
  ia64: get rid of 'segment' argument of __{get,put}_user_check()
  ia64: add extable.h
  powerpc: get rid of zeroing, switch to RAW_COPY_USER
  esas2r: don't open-code memdup_user()
  alpha: fix stack smashing in old_adjtimex(2)
  don't open-code kernel_setsockopt()
  mips: switch to RAW_COPY_USER
  mips: get rid of tail-zeroing in primitives
  mips: make copy_from_user() zero tail explicitly
  mips: clean and reorder the forest of macros...
  mips: consolidate __invoke_... wrappers
  ...
This commit is contained in:
Linus Torvalds
2017-05-01 14:41:04 -07:00
176 changed files with 1481 additions and 4358 deletions

View File

@ -52,7 +52,6 @@ config IA64
select MODULES_USE_ELF_RELA
select ARCH_USE_CMPXCHG_LOCKREF
select HAVE_ARCH_AUDITSYSCALL
select HAVE_ARCH_HARDENED_USERCOPY
default y
help
The Itanium Processor Family is Intel's 64-bit successor to

View File

@ -0,0 +1,11 @@
#ifndef _ASM_IA64_EXTABLE_H
#define _ASM_IA64_EXTABLE_H
#define ARCH_HAS_RELATIVE_EXTABLE
struct exception_table_entry {
int insn; /* location-relative address of insn this fixup is for */
int fixup; /* location-relative continuation addr.; if bit 2 is set, r9 is set to 0 */
};
#endif

View File

@ -33,14 +33,13 @@
*/
#include <linux/compiler.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/page-flags.h>
#include <linux/mm.h>
#include <asm/intrinsics.h>
#include <asm/pgtable.h>
#include <asm/io.h>
#include <asm/extable.h>
/*
* For historical reasons, the following macros are grossly misnamed:
@ -48,9 +47,6 @@
#define KERNEL_DS ((mm_segment_t) { ~0UL }) /* cf. access_ok() */
#define USER_DS ((mm_segment_t) { TASK_SIZE-1 }) /* cf. access_ok() */
#define VERIFY_READ 0
#define VERIFY_WRITE 1
#define get_ds() (KERNEL_DS)
#define get_fs() (current_thread_info()->addr_limit)
#define set_fs(x) (current_thread_info()->addr_limit = (x))
@ -63,14 +59,14 @@
* address TASK_SIZE is never valid. We also need to make sure that the address doesn't
* point inside the virtually mapped linear page table.
*/
#define __access_ok(addr, size, segment) \
({ \
__chk_user_ptr(addr); \
(likely((unsigned long) (addr) <= (segment).seg) \
&& ((segment).seg == KERNEL_DS.seg \
|| likely(REGION_OFFSET((unsigned long) (addr)) < RGN_MAP_LIMIT))); \
})
#define access_ok(type, addr, size) __access_ok((addr), (size), get_fs())
static inline int __access_ok(const void __user *p, unsigned long size)
{
unsigned long addr = (unsigned long)p;
unsigned long seg = get_fs().seg;
return likely(addr <= seg) &&
(seg == KERNEL_DS.seg || likely(REGION_OFFSET(addr) < RGN_MAP_LIMIT));
}
#define access_ok(type, addr, size) __access_ok((addr), (size))
/*
* These are the main single-value transfer routines. They automatically
@ -80,8 +76,8 @@
* (a) re-use the arguments for side effects (sizeof/typeof is ok)
* (b) require any knowledge of processes at this stage
*/
#define put_user(x, ptr) __put_user_check((__typeof__(*(ptr))) (x), (ptr), sizeof(*(ptr)), get_fs())
#define get_user(x, ptr) __get_user_check((x), (ptr), sizeof(*(ptr)), get_fs())
#define put_user(x, ptr) __put_user_check((__typeof__(*(ptr))) (x), (ptr), sizeof(*(ptr)))
#define get_user(x, ptr) __get_user_check((x), (ptr), sizeof(*(ptr)))
/*
* The "__xxx" versions do not do address space checking, useful when
@ -184,13 +180,13 @@ extern void __get_user_unknown (void);
* could clobber r8 and r9 (among others). Thus, be careful not to evaluate it while
* using r8/r9.
*/
#define __do_get_user(check, x, ptr, size, segment) \
#define __do_get_user(check, x, ptr, size) \
({ \
const __typeof__(*(ptr)) __user *__gu_ptr = (ptr); \
__typeof__ (size) __gu_size = (size); \
long __gu_err = -EFAULT; \
unsigned long __gu_val = 0; \
if (!check || __access_ok(__gu_ptr, size, segment)) \
if (!check || __access_ok(__gu_ptr, size)) \
switch (__gu_size) { \
case 1: __get_user_size(__gu_val, __gu_ptr, 1, __gu_err); break; \
case 2: __get_user_size(__gu_val, __gu_ptr, 2, __gu_err); break; \
@ -202,8 +198,8 @@ extern void __get_user_unknown (void);
__gu_err; \
})
#define __get_user_nocheck(x, ptr, size) __do_get_user(0, x, ptr, size, KERNEL_DS)
#define __get_user_check(x, ptr, size, segment) __do_get_user(1, x, ptr, size, segment)
#define __get_user_nocheck(x, ptr, size) __do_get_user(0, x, ptr, size)
#define __get_user_check(x, ptr, size) __do_get_user(1, x, ptr, size)
extern void __put_user_unknown (void);
@ -211,14 +207,14 @@ extern void __put_user_unknown (void);
* Evaluating arguments X, PTR, SIZE, and SEGMENT may involve subroutine-calls, which
* could clobber r8 (among others). Thus, be careful not to evaluate them while using r8.
*/
#define __do_put_user(check, x, ptr, size, segment) \
#define __do_put_user(check, x, ptr, size) \
({ \
__typeof__ (x) __pu_x = (x); \
__typeof__ (*(ptr)) __user *__pu_ptr = (ptr); \
__typeof__ (size) __pu_size = (size); \
long __pu_err = -EFAULT; \
\
if (!check || __access_ok(__pu_ptr, __pu_size, segment)) \
if (!check || __access_ok(__pu_ptr, __pu_size)) \
switch (__pu_size) { \
case 1: __put_user_size(__pu_x, __pu_ptr, 1, __pu_err); break; \
case 2: __put_user_size(__pu_x, __pu_ptr, 2, __pu_err); break; \
@ -229,8 +225,8 @@ extern void __put_user_unknown (void);
__pu_err; \
})
#define __put_user_nocheck(x, ptr, size) __do_put_user(0, x, ptr, size, KERNEL_DS)
#define __put_user_check(x, ptr, size, segment) __do_put_user(1, x, ptr, size, segment)
#define __put_user_nocheck(x, ptr, size) __do_put_user(0, x, ptr, size)
#define __put_user_check(x, ptr, size) __do_put_user(1, x, ptr, size)
/*
* Complex access routines
@ -239,56 +235,19 @@ extern unsigned long __must_check __copy_user (void __user *to, const void __use
unsigned long count);
static inline unsigned long
__copy_to_user (void __user *to, const void *from, unsigned long count)
raw_copy_to_user(void __user *to, const void *from, unsigned long count)
{
check_object_size(from, count, true);
return __copy_user(to, (__force void __user *) from, count);
}
static inline unsigned long
__copy_from_user (void *to, const void __user *from, unsigned long count)
raw_copy_from_user(void *to, const void __user *from, unsigned long count)
{
check_object_size(to, count, false);
return __copy_user((__force void __user *) to, from, count);
}
#define __copy_to_user_inatomic __copy_to_user
#define __copy_from_user_inatomic __copy_from_user
#define copy_to_user(to, from, n) \
({ \
void __user *__cu_to = (to); \
const void *__cu_from = (from); \
long __cu_len = (n); \
\
if (__access_ok(__cu_to, __cu_len, get_fs())) { \
check_object_size(__cu_from, __cu_len, true); \
__cu_len = __copy_user(__cu_to, (__force void __user *) __cu_from, __cu_len); \
} \
__cu_len; \
})
static inline unsigned long
copy_from_user(void *to, const void __user *from, unsigned long n)
{
check_object_size(to, n, false);
if (likely(__access_ok(from, n, get_fs())))
n = __copy_user((__force void __user *) to, from, n);
else
memset(to, 0, n);
return n;
}
#define __copy_in_user(to, from, size) __copy_user((to), (from), (size))
static inline unsigned long
copy_in_user (void __user *to, const void __user *from, unsigned long n)
{
if (likely(access_ok(VERIFY_READ, from, n) && access_ok(VERIFY_WRITE, to, n)))
n = __copy_user(to, from, n);
return n;
}
#define INLINE_COPY_FROM_USER
#define INLINE_COPY_TO_USER
extern unsigned long __do_clear_user (void __user *, unsigned long);
@ -297,7 +256,7 @@ extern unsigned long __do_clear_user (void __user *, unsigned long);
#define clear_user(to, n) \
({ \
unsigned long __cu_len = (n); \
if (__access_ok(to, __cu_len, get_fs())) \
if (__access_ok(to, __cu_len)) \
__cu_len = __do_clear_user(to, __cu_len); \
__cu_len; \
})
@ -313,7 +272,7 @@ extern long __must_check __strncpy_from_user (char *to, const char __user *from,
({ \
const char __user * __sfu_from = (from); \
long __sfu_ret = -EFAULT; \
if (__access_ok(__sfu_from, 0, get_fs())) \
if (__access_ok(__sfu_from, 0)) \
__sfu_ret = __strncpy_from_user((to), __sfu_from, (n)); \
__sfu_ret; \
})
@ -325,7 +284,7 @@ extern unsigned long __strlen_user (const char __user *);
({ \
const char __user *__su_str = (str); \
unsigned long __su_ret = 0; \
if (__access_ok(__su_str, 0, get_fs())) \
if (__access_ok(__su_str, 0)) \
__su_ret = __strlen_user(__su_str); \
__su_ret; \
})
@ -341,18 +300,11 @@ extern unsigned long __strnlen_user (const char __user *, long);
({ \
const char __user *__su_str = (str); \
unsigned long __su_ret = 0; \
if (__access_ok(__su_str, 0, get_fs())) \
if (__access_ok(__su_str, 0)) \
__su_ret = __strnlen_user(__su_str, len); \
__su_ret; \
})
#define ARCH_HAS_RELATIVE_EXTABLE
struct exception_table_entry {
int insn; /* location-relative address of insn this fixup is for */
int fixup; /* location-relative continuation addr.; if bit 2 is set, r9 is set to 0 */
};
#define ARCH_HAS_TRANSLATE_MEM_PTR 1
static __inline__ void *
xlate_dev_mem_ptr(phys_addr_t p)

View File

@ -556,9 +556,6 @@ EK(.ex_handler, (p17) st8 [dst1]=r39,8); \
#define D r22
#define F r28
#define memset_arg0 r32
#define memset_arg2 r33
#define saved_retval loc0
#define saved_rtlink loc1
#define saved_pfs_stack loc2
@ -622,7 +619,7 @@ EK(.ex_handler, (p17) st8 [dst1]=r39,8); \
* (faulting_addr - orig_dst) -> len to faulting st address
* B = (cur_dst - orig_dst) -> len copied so far
* C = A - B -> len need to be copied
* D = orig_len - A -> len need to be zeroed
* D = orig_len - A -> len need to be left along
*/
(p6) sub A = F, saved_in0
(p7) sub A = F, saved_in1
@ -638,9 +635,6 @@ EK(.ex_handler, (p17) st8 [dst1]=r39,8); \
sub D = saved_in2, A
;;
cmp.gt p8,p0=C,r0 // more than 1 byte?
add memset_arg0=saved_in0, A
(p6) mov memset_arg2=0 // copy_to_user should not call memset
(p7) mov memset_arg2=D // copy_from_user need to have kbuf zeroed
mov r8=0
mov saved_retval = D
mov saved_rtlink = b0
@ -652,11 +646,6 @@ EK(.ex_handler, (p17) st8 [dst1]=r39,8); \
;;
add saved_retval=saved_retval,r8 // above might return non-zero value
cmp.gt p8,p0=memset_arg2,r0 // more than 1 byte?
mov out0=memset_arg0 // *s
mov out1=r0 // c
mov out2=memset_arg2 // n
(p8) br.call.sptk.few b0=memset
;;
mov retval=saved_retval

View File

@ -5,7 +5,10 @@
* David Mosberger-Tang <davidm@hpl.hp.com>
*/
#include <linux/uaccess.h>
#include <asm/ptrace.h>
#include <asm/extable.h>
#include <asm/errno.h>
#include <asm/processor.h>
void
ia64_handle_exception (struct pt_regs *regs, const struct exception_table_entry *e)