Commit 617aebe6 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull hardened usercopy whitelisting from Kees Cook:
 "Currently, hardened usercopy performs dynamic bounds checking on slab
  cache objects. This is good, but still leaves a lot of kernel memory
  available to be copied to/from userspace in the face of bugs.

  To further restrict what memory is available for copying, this creates
  a way to whitelist specific areas of a given slab cache object for
  copying to/from userspace, allowing much finer granularity of access
  control.

  Slab caches that are never exposed to userspace can declare no
  whitelist for their objects, thereby keeping them unavailable to
  userspace via dynamic copy operations. (Note, an implicit form of
  whitelisting is the use of constant sizes in usercopy operations and
  get_user()/put_user(); these bypass all hardened usercopy checks since
  these sizes cannot change at runtime.)

  This new check is WARN-by-default, so any mistakes can be found over
  the next several releases without breaking anyone's system.

  The series has roughly the following sections:
   - remove %p and improve reporting with offset
   - prepare infrastructure and whitelist kmalloc
   - update VFS subsystem with whitelists
   - update SCSI subsystem with whitelists
   - update network subsystem with whitelists
   - update process memory with whitelists
   - update per-architecture thread_struct with whitelists
   - update KVM with whitelists and fix ioctl bug
   - mark all other allocations as not whitelisted
   - update lkdtm for more sensible test overage"

* tag 'usercopy-v4.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux: (38 commits)
  lkdtm: Update usercopy tests for whitelisting
  usercopy: Restrict non-usercopy caches to size 0
  kvm: x86: fix KVM_XEN_HVM_CONFIG ioctl
  kvm: whitelist struct kvm_vcpu_arch
  arm: Implement thread_struct whitelist for hardened usercopy
  arm64: Implement thread_struct whitelist for hardened usercopy
  x86: Implement thread_struct whitelist for hardened usercopy
  fork: Provide usercopy whitelisting for task_struct
  fork: Define usercopy region in thread_stack slab caches
  fork: Define usercopy region in mm_struct slab caches
  net: Restrict unwhitelisted proto caches to size 0
  sctp: Copy struct sctp_sock.autoclose to userspace using put_user()
  sctp: Define usercopy region in SCTP proto slab cache
  caif: Define usercopy region in caif proto slab cache
  ip: Define usercopy region in IP proto slab cache
  net: Define usercopy region in struct proto slab cache
  scsi: Define usercopy region in scsi_sense_cache slab cache
  cifs: Define usercopy region in cifs_request slab cache
  vxfs: Define usercopy region in vxfs_inode slab cache
  ufs: Define usercopy region in ufs_inode_cache slab cache
  ...
parents 0771ad44 e47e3118
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -245,6 +245,17 @@ config ARCH_TASK_STRUCT_ON_STACK
config ARCH_TASK_STRUCT_ALLOCATOR
	bool

config HAVE_ARCH_THREAD_STRUCT_WHITELIST
	bool
	depends on !ARCH_TASK_STRUCT_ALLOCATOR
	help
	  An architecture should select this to provide hardened usercopy
	  knowledge about what region of the thread_struct should be
	  whitelisted for copying to userspace. Normally this is only the
	  FPU registers. Specifically, arch_thread_struct_whitelist()
	  should be implemented. Without this, the entire thread_struct
	  field in task_struct will be left whitelisted.

# Select if arch has its private alloc_thread_stack() function
config ARCH_THREAD_STACK_ALLOCATOR
	bool
+1 −0
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@ config ARM
	select HAVE_ARCH_KGDB if !CPU_ENDIAN_BE32 && MMU
	select HAVE_ARCH_MMAP_RND_BITS if MMU
	select HAVE_ARCH_SECCOMP_FILTER if (AEABI && !OABI_COMPAT)
	select HAVE_ARCH_THREAD_STRUCT_WHITELIST
	select HAVE_ARCH_TRACEHOOK
	select HAVE_ARM_SMCCC if CPU_V7
	select HAVE_EBPF_JIT if !CPU_ENDIAN_BE32
+10 −0
Original line number Diff line number Diff line
@@ -45,6 +45,16 @@ struct thread_struct {
	struct debug_info	debug;
};

/*
 * Everything usercopied to/from thread_struct is statically-sized, so
 * no hardened usercopy whitelist is needed.
 */
static inline void arch_thread_struct_whitelist(unsigned long *offset,
						unsigned long *size)
{
	*offset = *size = 0;
}

#define INIT_THREAD  {	}

#define start_thread(regs,pc,sp)					\
+1 −0
Original line number Diff line number Diff line
@@ -91,6 +91,7 @@ config ARM64
	select HAVE_ARCH_MMAP_RND_BITS
	select HAVE_ARCH_MMAP_RND_COMPAT_BITS if COMPAT
	select HAVE_ARCH_SECCOMP_FILTER
	select HAVE_ARCH_THREAD_STRUCT_WHITELIST
	select HAVE_ARCH_TRACEHOOK
	select HAVE_ARCH_TRANSPARENT_HUGEPAGE
	select HAVE_ARCH_VMAP_STACK
+10 −0
Original line number Diff line number Diff line
@@ -113,6 +113,16 @@ struct thread_struct {
	struct debug_info	debug;		/* debugging */
};

/*
 * Everything usercopied to/from thread_struct is statically-sized, so
 * no hardened usercopy whitelist is needed.
 */
static inline void arch_thread_struct_whitelist(unsigned long *offset,
						unsigned long *size)
{
	*offset = *size = 0;
}

#ifdef CONFIG_COMPAT
#define task_user_tls(t)						\
({									\
Loading