Title: [214125] trunk/Source
Revision
214125
Author
s...@apple.com
Date
2017-03-17 14:51:03 -0700 (Fri, 17 Mar 2017)

Log Message

Time channel attack on SVG Filters
https://bugs.webkit.org/show_bug.cgi?id=118689

Reviewed by Simon Fraser.

Source/WebCore:

The time channel attack can happen if the attacker applies FEColorMatrix
or FEConvolveMatrix and provides a matrix which is filled with subnormal
floating point values. Performing floating-point operations on subnormals
is very expensive unless the pixel in the source graphics is black (or
zero). By measuring the time a filter takes to be applied, the attacker
can know whether the pixel he wants to steal from  an iframe is black or
white. By repeating the same process on all the pixels in the iframe, the
attacker can reconstruct the whole page of the iframe.

To fix this issue, the values in the matrices of these filters will clamped
to FLT_MIN. We do not want to consume too much time calculating filtered
pixels because of such tiny values. The difference between applying FLT_MIN
and applying a subnormal should not be even noticeable. Normalizing the
floating-point matrices should happen only at the beginning of the filter
platformApplySoftware().

* platform/graphics/filters/FEColorMatrix.cpp:
(WebCore::FEColorMatrix::platformApplySoftware):
* platform/graphics/filters/FEConvolveMatrix.cpp:
(WebCore::FEConvolveMatrix::fastSetInteriorPixels):
(WebCore::FEConvolveMatrix::fastSetOuterPixels):
(WebCore::FEConvolveMatrix::platformApplySoftware):
* platform/graphics/filters/FEConvolveMatrix.h:
* platform/graphics/filters/FilterEffect.h:
(WebCore::FilterEffect::normalizedFloats):

Source/WTF:

Performing arithmetic operations on subnormal floating-point numbers is
very expensive. Normalizing the floating-point number to the minimum normal
value should accelerate the calculations and there won't be a noticeable
difference in the result since all the subnormal values and the minimum
normal value are all very close to zero.

* wtf/MathExtras.h:
(normalizedFloat):

Modified Paths

Diff

Modified: trunk/Source/WTF/ChangeLog (214124 => 214125)


--- trunk/Source/WTF/ChangeLog	2017-03-17 21:31:49 UTC (rev 214124)
+++ trunk/Source/WTF/ChangeLog	2017-03-17 21:51:03 UTC (rev 214125)
@@ -1,3 +1,19 @@
+2017-03-17  Said Abou-Hallawa  <sabouhall...@apple.com>
+
+        Time channel attack on SVG Filters
+        https://bugs.webkit.org/show_bug.cgi?id=118689
+
+        Reviewed by Simon Fraser.
+
+        Performing arithmetic operations on subnormal floating-point numbers is
+        very expensive. Normalizing the floating-point number to the minimum normal
+        value should accelerate the calculations and there won't be a noticeable
+        difference in the result since all the subnormal values and the minimum
+        normal value are all very close to zero.
+
+        * wtf/MathExtras.h:
+        (normalizedFloat):
+
 2017-03-11  Filip Pizlo  <fpi...@apple.com>
 
         Air should be powerful enough to support Tmp-splitting

Modified: trunk/Source/WTF/wtf/MathExtras.h (214124 => 214125)


--- trunk/Source/WTF/wtf/MathExtras.h	2017-03-17 21:31:49 UTC (rev 214124)
+++ trunk/Source/WTF/wtf/MathExtras.h	2017-03-17 21:51:03 UTC (rev 214125)
@@ -209,6 +209,15 @@
     return x > static_cast<float>(std::numeric_limits<int>::min()) && x < static_cast<float>(std::numeric_limits<int>::max());
 }
 
+inline float normalizedFloat(float value)
+{
+    if (value > 0 && value < std::numeric_limits<float>::min())
+        return std::numeric_limits<float>::min();
+    if (value < 0 && value > -std::numeric_limits<float>::min())
+        return -std::numeric_limits<float>::min();
+    return value;
+}
+
 template<typename T> inline bool hasOneBitSet(T value)
 {
     return !((value - 1) & value) && value;

Modified: trunk/Source/WebCore/ChangeLog (214124 => 214125)


--- trunk/Source/WebCore/ChangeLog	2017-03-17 21:31:49 UTC (rev 214124)
+++ trunk/Source/WebCore/ChangeLog	2017-03-17 21:51:03 UTC (rev 214125)
@@ -1,3 +1,36 @@
+2017-03-17  Said Abou-Hallawa  <sabouhall...@apple.com>
+
+        Time channel attack on SVG Filters
+        https://bugs.webkit.org/show_bug.cgi?id=118689
+
+        Reviewed by Simon Fraser.
+
+        The time channel attack can happen if the attacker applies FEColorMatrix
+        or FEConvolveMatrix and provides a matrix which is filled with subnormal
+        floating point values. Performing floating-point operations on subnormals
+        is very expensive unless the pixel in the source graphics is black (or
+        zero). By measuring the time a filter takes to be applied, the attacker
+        can know whether the pixel he wants to steal from  an iframe is black or
+        white. By repeating the same process on all the pixels in the iframe, the
+        attacker can reconstruct the whole page of the iframe.
+
+        To fix this issue, the values in the matrices of these filters will clamped
+        to FLT_MIN. We do not want to consume too much time calculating filtered
+        pixels because of such tiny values. The difference between applying FLT_MIN
+        and applying a subnormal should not be even noticeable. Normalizing the
+        floating-point matrices should happen only at the beginning of the filter
+        platformApplySoftware().
+
+        * platform/graphics/filters/FEColorMatrix.cpp:
+        (WebCore::FEColorMatrix::platformApplySoftware):
+        * platform/graphics/filters/FEConvolveMatrix.cpp:
+        (WebCore::FEConvolveMatrix::fastSetInteriorPixels):
+        (WebCore::FEConvolveMatrix::fastSetOuterPixels):
+        (WebCore::FEConvolveMatrix::platformApplySoftware):
+        * platform/graphics/filters/FEConvolveMatrix.h:
+        * platform/graphics/filters/FilterEffect.h:
+        (WebCore::FilterEffect::normalizedFloats):
+
 2017-03-17  Jer Noble  <jer.no...@apple.com>
 
         Explicitly resize the audio buffer in RealtimeOutgoingAudioSource.

Modified: trunk/Source/WebCore/platform/graphics/filters/FEColorMatrix.cpp (214124 => 214125)


--- trunk/Source/WebCore/platform/graphics/filters/FEColorMatrix.cpp	2017-03-17 21:31:49 UTC (rev 214124)
+++ trunk/Source/WebCore/platform/graphics/filters/FEColorMatrix.cpp	2017-03-17 21:51:03 UTC (rev 214125)
@@ -153,21 +153,22 @@
 
     IntRect imageRect(IntPoint(), resultImage->logicalSize());
     RefPtr<Uint8ClampedArray> pixelArray = resultImage->getUnmultipliedImageData(imageRect);
+    Vector<float> values = normalizedFloats(m_values);
 
     switch (m_type) {
     case FECOLORMATRIX_TYPE_UNKNOWN:
         break;
     case FECOLORMATRIX_TYPE_MATRIX:
-        effectType<FECOLORMATRIX_TYPE_MATRIX>(pixelArray.get(), m_values);
+        effectType<FECOLORMATRIX_TYPE_MATRIX>(pixelArray.get(), values);
         break;
     case FECOLORMATRIX_TYPE_SATURATE: 
-        effectType<FECOLORMATRIX_TYPE_SATURATE>(pixelArray.get(), m_values);
+        effectType<FECOLORMATRIX_TYPE_SATURATE>(pixelArray.get(), values);
         break;
     case FECOLORMATRIX_TYPE_HUEROTATE:
-        effectType<FECOLORMATRIX_TYPE_HUEROTATE>(pixelArray.get(), m_values);
+        effectType<FECOLORMATRIX_TYPE_HUEROTATE>(pixelArray.get(), values);
         break;
     case FECOLORMATRIX_TYPE_LUMINANCETOALPHA:
-        effectType<FECOLORMATRIX_TYPE_LUMINANCETOALPHA>(pixelArray.get(), m_values);
+        effectType<FECOLORMATRIX_TYPE_LUMINANCETOALPHA>(pixelArray.get(), values);
         setIsAlphaImage(true);
         break;
     }

Modified: trunk/Source/WebCore/platform/graphics/filters/FEConvolveMatrix.cpp (214124 => 214125)


--- trunk/Source/WebCore/platform/graphics/filters/FEConvolveMatrix.cpp	2017-03-17 21:31:49 UTC (rev 214124)
+++ trunk/Source/WebCore/platform/graphics/filters/FEConvolveMatrix.cpp	2017-03-17 21:51:03 UTC (rev 214125)
@@ -267,7 +267,7 @@
 
     for (int y = yEnd + 1; y > yStart; --y) {
         for (int x = clipRight + 1; x > 0; --x) {
-            int kernelValue = m_kernelMatrix.size() - 1;
+            int kernelValue = paintingData.kernelMatrix.size() - 1;
             int kernelPixel = startKernelPixel;
             int width = m_kernelSize.width();
 
@@ -278,11 +278,11 @@
                 totals[3] = 0;
 
             while (kernelValue >= 0) {
-                totals[0] += m_kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->item(kernelPixel++));
-                totals[1] += m_kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->item(kernelPixel++));
-                totals[2] += m_kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->item(kernelPixel++));
+                totals[0] += paintingData.kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->item(kernelPixel++));
+                totals[1] += paintingData.kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->item(kernelPixel++));
+                totals[2] += paintingData.kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->item(kernelPixel++));
                 if (!preserveAlphaValues)
-                    totals[3] += m_kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->item(kernelPixel));
+                    totals[3] += paintingData.kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->item(kernelPixel));
                 ++kernelPixel;
                 --kernelValue;
                 if (!--width) {
@@ -347,7 +347,7 @@
 
     for (int y = height; y > 0; --y) {
         for (int x = width; x > 0; --x) {
-            int kernelValue = m_kernelMatrix.size() - 1;
+            int kernelValue = paintingData.kernelMatrix.size() - 1;
             int kernelPixelX = startKernelPixelX;
             int kernelPixelY = startKernelPixelY;
             int width = m_kernelSize.width();
@@ -361,12 +361,12 @@
             while (kernelValue >= 0) {
                 int pixelIndex = getPixelValue(paintingData, kernelPixelX, kernelPixelY);
                 if (pixelIndex >= 0) {
-                    totals[0] += m_kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->item(pixelIndex));
-                    totals[1] += m_kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->item(pixelIndex + 1));
-                    totals[2] += m_kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->item(pixelIndex + 2));
+                    totals[0] += paintingData.kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->item(pixelIndex));
+                    totals[1] += paintingData.kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->item(pixelIndex + 1));
+                    totals[2] += paintingData.kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->item(pixelIndex + 2));
                 }
                 if (!preserveAlphaValues && pixelIndex >= 0)
-                    totals[3] += m_kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->item(pixelIndex + 3));
+                    totals[3] += paintingData.kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->item(pixelIndex + 3));
                 ++kernelPixelX;
                 --kernelValue;
                 if (!--width) {
@@ -436,6 +436,7 @@
     paintingData.width = paintSize.width();
     paintingData.height = paintSize.height();
     paintingData.bias = m_bias * 255;
+    paintingData.kernelMatrix = normalizedFloats(m_kernelMatrix);
 
     // Drawing fully covered pixels
     int clipRight = paintSize.width() - m_kernelSize.width();

Modified: trunk/Source/WebCore/platform/graphics/filters/FEConvolveMatrix.h (214124 => 214125)


--- trunk/Source/WebCore/platform/graphics/filters/FEConvolveMatrix.h	2017-03-17 21:31:49 UTC (rev 214124)
+++ trunk/Source/WebCore/platform/graphics/filters/FEConvolveMatrix.h	2017-03-17 21:51:03 UTC (rev 214125)
@@ -83,6 +83,7 @@
         int width;
         int height;
         float bias;
+        Vector<float> kernelMatrix;
     };
 
     FEConvolveMatrix(Filter&, const IntSize&, float, float,

Modified: trunk/Source/WebCore/platform/graphics/filters/FilterEffect.h (214124 => 214125)


--- trunk/Source/WebCore/platform/graphics/filters/FilterEffect.h	2017-03-17 21:31:49 UTC (rev 214124)
+++ trunk/Source/WebCore/platform/graphics/filters/FilterEffect.h	2017-03-17 21:51:03 UTC (rev 214125)
@@ -26,6 +26,7 @@
 #include "FloatRect.h"
 #include "IntRect.h"
 #include <runtime/Uint8ClampedArray.h>
+#include <wtf/MathExtras.h>
 #include <wtf/RefCounted.h>
 #include <wtf/RefPtr.h>
 #include <wtf/Vector.h>
@@ -170,6 +171,14 @@
     void forceValidPreMultipliedPixels();
 
     void clipAbsolutePaintRect();
+    
+    static Vector<float> normalizedFloats(const Vector<float>& values)
+    {
+        Vector<float> normalizedValues(values.size());
+        for (size_t i = 0; i < values.size(); ++i)
+            normalizedValues[i] = normalizedFloat(values[i]);
+        return normalizedValues;
+    }
 
 private:
     std::unique_ptr<ImageBuffer> m_imageBufferResult;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to