Back in late March, a U.K. based start-up firm specializing in testing GPU reliability approached us with a GPU bug they discovered that causes the Qualcomm Snapdragon 845 Samsung Galaxy S9/S9+ to reboot when visiting a web page. The firm, called GraphicsFuzz, worked with us to report the issue to Qualcomm and Samsung. Some of our readers were interested in learning just how a company like GraphicsFuzz is able to find these vulnerabilities, so we collaborated with the company to showcase how they discovered an older GPU vulnerability. This already-patched vulnerability allowed an attacker to remotely "spy" on the contents of Google Chrome browser tabs on the Samsung Galaxy S6.

This user was viewing their bank's website before visiting the malicious web page. The contents were captured and uploaded to a remote server. Source: GraphicsFuzz.

How GraphicsFuzz finds GPU bugs

A graphics driver works by taking a shader program and sending it to the GPU to be executed and thus render the image. Before sending the shader to the GPU, the graphics driver translates it into a form that the GPU can understand; a faulty translation can lead to rendering failure, program or device crashes, wrong images, and even security issues. GraphicsFuzz has an automated testing suite that allows them to find these bugs based on a set of reference shaders. When a user runs their test, all the resulting images are supposed to look the same. Any image that looks different means there was a bug.

Results of several popular devices running the GraphicsFuzz test suite. The Samsung Galaxy S6, Samsung Galaxy S7, and Samsung Galaxy S8 are included in these charts. Source: GraphicsFuzz.

For the Samsung Galaxy S6, GraphicsFuzz discovered that the images in one of the rows were showing images that were supposed to be in another table. This means that images from earlier tests were leaking into later tests. The team then re-ran the test suite in Google Chrome and discovered that parts of the web page were appearing in the image. Furthermore, they found that opening another tab caused the image to show parts of other tabs. Essentially, this bug allowed one Google Chrome tab to leak information about another Chrome tab! The team behind GraphicsFuzz wasn't intentionally looking for security bugs, but they ended up finding one as a result of their testing. (It should be noted that the team reproduced the bug on the stock Samsung browser on the Galaxy S6 as well as Mozilla Firefox.)

How the bug works

Image used to trigger the long-running bug on the Samsung Galaxy S6. Source: GraphicsFuzz.

The "malicious" web page created by GraphicsFuzz uses WebGL to attempt to draw a space scene inside a canvas as shown above. The color of each pixel is determined by a fragment shader, a program provided by the web page to execute on the GPU. The GraphicsFuzz framework modified the fragment shader which caused it to run for a really long time. When a shader runs for too long, the browser or operating system typically aborts rendering. However, while the GPU aborted rendering after drawing a few pixels, the GPU driver didn’t report this to Google Chrome. (If you take a look at the image at the top of the article showing garbage video memory, you can actually see parts of the space scene in the top left.) This means that the pixels that were rendered before the abort are left untouched, meaning the final rendered image is mostly garbage video memory. Since video memory is continuously used to render other web pages, the "garbage" data actually contains previous renderings of other web pages. Thus, other web pages end up being displayed on the "malicious" web page. Crucially, WebGL allows the web page to capture the contents of whatever is being rendered; this image is then uploaded to a remote server.

Diagram explaining the long-running GPU bug causing Chrome tab data to "leak." Source: GraphicsFuzz.

Google Chrome uses multiple processes so different tabs are often isolated, which makes this exploit seem impossible on the surface. However, Chrome interacts with the GPU using a single "GPU process", which means that all tabs share the same GPU memory, thus allowing this exploit to work. The diagram above shows this in more detail.

The bug is demonstrated in this video during the first 22 seconds. Other security issues found by GraphicsFuzz are also demonstrated.

Lessons to be learned

A misbehaving GPU can bypass all of Google Chrome and Android's security measures since WebGL allows any malicious web page to send code to the GPU for execution. Google can't fix GPU bugs since the company doesn't control the hardware and drivers. In this case, it's up to the GPU vendor (in this case, ARM) to fix the bug and the OEM whose devices are affected (in this case, Samsung) to integrate the fix in an update. Add carriers to the mix and it's easy to see how a bug like this can take a really long time to fix—it took at least 5 months for most Samsung Galaxy S6 users to receive the patch.

GraphicsFuzz helps GPU vendors find hard-to-detect bugs such as miscompilation bugs that cause the wrong code to be generated and executed on the GPU. Their automated testing framework allows them to find bugs such as the one showcased in this article. The long-running loop caused by the "malicious" web page has also been shown to cause issues on other devices such as the HTC One M7 and more recently the Samsung Galaxy S9GraphicsFuzz tests flagship smartphones and publishes a results table which ranks these devices based on their performance on a subset of their tests. Hundreds of crashes and rendering errors have been found during their testing, but most aren't investigated to see if they pose a security threat. However, as shown by this exploit, a misbehaving GPU is a security risk, and it's possible that one or more critical security vulnerabilities are waiting to be discovered. GraphicsFuzz hopes that GPU vendors prioritize improving driver quality in the future.

GraphicsFuzz GPU Stability Results

Comparative reliability of graphics drivers, sorted by the number of total issues. Source: GraphicsFuzz.

Disclosure timeline

  • In December 2016, GraphicsFuzz reported the bug to the Google Chromium bug tracker because it was eligible for the Chrome Reward Program. After GraphicsFuzz submitted the bug to the Google Chromium bug tracker, the bug was accepted by Google and forwarded it to ARM and Samsung for patching.
  • Google forwarded the report to contacts at ARM and Samsung.
  • Samsung silently patched the bug and rolled out the fix in the Android 7.0 Nougat update that was released between March and June of 2017. Although there was no CVE created by Samsung, Google, or ARM and neither Samsung nor ARM released any information on the patch, note that GraphicsFuzz did not report the bug via the proper process.
  • Later, GraphicsFuzz was able to confirm that both Samsung and ARM had seen the report, and that ARM was able to fix the issue due to the report.
  • In August 2017, GraphicsFuzz was rewarded $2,000 by Google for the bug report.
  • In November 2017, the bug report was made public.