BSDSec

deadsimple BSD Security Advisories and Announcements

NetBSD Security Advisory 2017-003: Xen-amd64: weak privilege separation

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1


		NetBSD Security Advisory 2017-00X
		=================================

Topic:		Xen-amd64: weak privilege separation


Version:	NetBSD-current:		source prior to Sun, Mar 5th 2017
		NetBSD 7.1:		not affected
		NetBSD 7.0 - 7.0.2:	affected
		NetBSD 6.1 - 6.1.4:	affected
		NetBSD 6.0 - 6.0.5:	affected

Severity:	Privilege escalation

Fixed:		NetBSD-current:		Sun, Mar 5th 2017
		NetBSD-7-0 branch:	Mon, Mar 6th 2017
		NetBSD-7 branch:	Mon, Mar 6th 2017
		NetBSD-6-0 branch:	Mon, Mar 6th 2017
		NetBSD-6-1 branch:	Mon, Mar 6th 2017
		NetBSD-6 branch:	Mon, Mar 6th 2017

Teeny versions released later than the fix date will contain the fix.

Please note that NetBSD releases prior to 6.0 are no longer supported.
It is recommended that all users upgrade to a supported release.


Abstract
========

A design mistake in the Xen-amd64 port allows userland to read and write to
several kernel pages. An unprivileged user can therefore modify critical kernel
structures in order to escalate privileges.


Technical Details
=================

Under a Xen hypervisor, any 64bit para-virtualized OS runs in ring3, the same
privilege level as userland. In order to provide privilege separation, Xen
intercepts the syscalls and traps, switches the virtual memory (VM) space to
map the system kernel, and manually jumps into it. Later, when returning to
userland, Xen switches back to the userland-only VM space, and flushes the
Translation Look-Aside Buffer (TLB).

TLB flushes are costly from a performance point of view, so in order to optimize
VM space switches Xen marks the userland pages as "global" - which means they
are not flushed under a local TLB flush -, while keeping the kernel pages as
"local". This way, when returning to userland from a syscall or a trap, the
userland pages are not cleared from the TLB.

In order to differentiate userland pages from kernel pages, Xen looks at the
PG_u ("userland") bit in the Page Table Directory (PTD) created by the OS: if a
page has PG_u, Xen believes the page in question is for userland so it marks it
as global, otherwise it is a kernel page and Xen adds PG_u but keeps the page as
local. In either case the page ends up with the PG_u bit set, since everything
runs in ring3.

Therefore, the privilege separation regarding memory relies solely on the fact
that the kernel pages are never present in the VM space when running in
userland.

A subtle mistake existed in NetBSD that caused this separation to be flawed:
the kernel pages in the OS PTD had the PG_u bit, which made Xen mark them as
global. When returning to userland, the VM space was indeed switched as
expected, but the TLB flush would not remove the kernel pages from the cache.
Userland thus had a small window where it could read or write to kernel pages
that were still cached and accessible to the CPU, even if not present in the
VM space.

It has been demonstrated that userland can exploit this bug to patch the kernel
syscall array, and have code injected in the kernel.


Solutions and Workarounds
=========================

For all NetBSD versions, you need to obtain fixed kernel sources,
rebuild and install the new kernel, and reboot the system.

The fixed source may be obtained from the NetBSD CVS repository.
The following instructions briefly summarise how to upgrade your
kernel. In these instructions, replace:

  ARCH     with your architecture (from uname -m),
  KERNCONF with the name of your kernel configuration file and
  VERSION  with the file version below

File versions containing the fixes:

 FILE  HEAD   netbsd-7   netbsd-7-0    netbsd-6   netbsd-6-1    netbsd-6-0
 ----  ----   --------   ----------    --------   ----------    ----------
 sys/arch/x86/include/pmap.h
       1.63   1.55.4.3   1.55.4.1.2.2  1.49.2.3   1.49.2.2.6.1  1.49.2.2.4.1
 sys/arch/x86/x86/pmap.c
       1.241  1.183.2.6  1.183.2.2.2.3 1.164.2.6  1.164.2.4.6.2 1.164.2.4.4.2

To update from CVS, re-build, and re-install the kernel:

	# cd src
	# cvs update -d -P -r VERSION sys/arch/x86/include/pmap.h
	# cvs update -d -P -r VERSION sys/arch/x86/x86/pmap.c
	# ./build.sh kernel=KERNCONF
	# mv /netbsd /netbsd.old
	# cp sys/arch/ARCH/compile/obj/KERNCONF/netbsd /netbsd
	# shutdown -r now

For more information on how to do this, see:

   http://www.NetBSD.org/guide/en/chap-kernel.html


Thanks To
=========

Maxime Villard for finding the issue and writing a fix.


Revision History
================

	2017-03-24	Initial release


More Information
================

Advisories may be updated as new information becomes available.
The most recent version of this advisory (PGP signed) can be found at 
  http://ftp.NetBSD.org/pub/NetBSD/security/advisories/NetBSD-SA2017-XXX.txt.asc

Information about NetBSD and NetBSD security can be found at
http://www.NetBSD.org/ and http://www.NetBSD.org/Security/ .


Copyright 2017, The NetBSD Foundation, Inc.  All Rights Reserved.
Redistribution permitted only in full, unmodified form.
-----BEGIN PGP SIGNATURE-----

iQIcBAEBAgAGBQJY1ShfAAoJEAZJc6xMSnBuWSQP/RNNUbmLPLYCGeNWKg8fkrbl
C0MsmF7MVOsOR+jKQABe7LFBeFKlg7YNRDYxyIaYAe7yNbJp0ybJOPQ4TUt8HYzH
pfsgpEPLRQSFOt6FI0+i134nvDUgxURwasuLTGqOW2C5ctPr01wWLOFOjad3FmAN
1njMgUBJeK3Jkeov4HdkzPZ7Vq+YnqK1rgyCxeo7C3ezwm+JDiA+oZplOlJwT+f6
kaviGEaNmhKDn1Lo36zTi66S1rRZjw714C023CK6YyfTQM4PHw0ssHqWMadwEN60
w6/cLwRN2rD3cOq5qNiiMsJXro3iTwHXR8BstNrfLuJ8dPELMTVSSFObgWzG71zk
0SkU106jtBZZjWmPxx/PDyw+k7Hi91ky+1rQdamgETHAl1bJOQCf4RuVNtFe4MpJ
Ta7U7oLB7SxehU4rPYIu7KE3+m8KDDdn2nel9u5bJLKb28dikvhF1wxjX1ftENVw
BBetiTo2AazUVAfY5wOklSMD+vZ5fycV/+J4apwelhsu9CRFmHSZFYaOZheLVmWB
UcPNPnnwjKJJK27uH622Wd26nv/eD9bFcQTkXu/VSYXYzeoUxUqy/K275ZdQDCkd
Ln18XZgIZioeFmdilRsiB2Ol+LxxHEoKaToOdxSJeW2fdc65ZAE4zSKE4Bs6xJRD
V6zC79fQ185FaccTyfcV
=Rwol
-----END PGP SIGNATURE-----