From 06a05d30fc026b21f59310986ea9eb7f3ff30d54 Mon Sep 17 00:00:00 2001
From: Sven Gothel <sgothel@jausoft.com>
Date: Thu, 5 Feb 2015 00:25:48 +0100
Subject: Add missing privileged section for NativeLibrary lookup:
 GLContextImpl and FFMPEGDynamicLibraryBundleInfo

Since GlueGen security fix commit 12feaa7d3b1544098f684d851e3caff1ec88cbc8
and its cleanup dd2440cbadc642a561d8f92c502fe822b2f11762
the GLContextImpl func lookup caused a security exception.

Applied fix to FFMPEGDynamicLibraryBundleInfo as well.
---
 .../runtime/opengl/GLProcAddressResolver.java      |   6 +-
 src/jogl/classes/jogamp/opengl/GLContextImpl.java  | 123 ++++++++++++---------
 .../av/impl/FFMPEGDynamicLibraryBundleInfo.java    |  69 ++++++------
 3 files changed, 102 insertions(+), 96 deletions(-)

(limited to 'src/jogl/classes')

diff --git a/src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLProcAddressResolver.java b/src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLProcAddressResolver.java
index 23d4fc3cf..3d23a623f 100644
--- a/src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLProcAddressResolver.java
+++ b/src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLProcAddressResolver.java
@@ -35,16 +35,14 @@ import com.jogamp.common.os.DynamicLookupHelper;
 import com.jogamp.gluegen.runtime.FunctionAddressResolver;
 
 /**
- * @author Sven Gothel
- * @author Michael Bien
+ * @author Michael Bien, et.al.
  */
 public class GLProcAddressResolver implements FunctionAddressResolver {
 
     public static final boolean DEBUG = false;
 
     @Override
-    public long resolve(final String name, final DynamicLookupHelper lookup) {
-
+    public long resolve(final String name, final DynamicLookupHelper lookup) throws SecurityException {
         long newProcAddress = 0;
         final int permutations = GLNameResolver.getFuncNamePermutationNumber(name);
 
diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
index 26a5566c2..1ff64725a 100644
--- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
@@ -100,6 +100,9 @@ public abstract class GLContextImpl extends GLContext {
   private String glRenderer;
   private String glRendererLowerCase;
   private String glVersion;
+  private boolean glGetPtrInit = false;
+  private long glGetStringPtr = 0;
+  private long glGetIntegervPtr = 0;
 
   // Tracks lifecycle of buffer objects to avoid
   // repeated glGet calls upon glMapBuffer operations
@@ -196,6 +199,9 @@ public abstract class GLContextImpl extends GLContext {
       glRenderer = glVendor;
       glRendererLowerCase = glRenderer;
       glVersion = glVendor;
+      glGetPtrInit = false;
+      glGetStringPtr = 0;
+      glGetIntegervPtr = 0;
 
       if ( !isInit && null != boundFBOTarget ) { // <init>: boundFBOTarget is not written yet
           boundFBOTarget[0] = 0; // draw
@@ -1367,17 +1373,32 @@ public abstract class GLContextImpl extends GLContext {
     } );
   }
 
+  private final PrivilegedAction<Object> privInitGLGetPtrAction = new PrivilegedAction<Object>() {
+      @Override
+      public Object run() {
+          final GLDynamicLookupHelper glDynLookupHelper = getDrawableImpl().getGLDynamicLookupHelper();
+          glDynLookupHelper.claimAllLinkPermission();
+          try {
+              glGetStringPtr = glDynLookupHelper.dynamicLookupFunction("glGetString");
+              glGetIntegervPtr = glDynLookupHelper.dynamicLookupFunction("glGetIntegerv");
+          } finally {
+              glDynLookupHelper.releaseAllLinkPermission();
+          }
+          return null;
+      } };
   private final boolean initGLRendererAndGLVersionStrings()  {
-    final GLDynamicLookupHelper glDynLookupHelper = getDrawableImpl().getGLDynamicLookupHelper();
-    final long _glGetString = glDynLookupHelper.dynamicLookupFunction("glGetString");
-    if(0 == _glGetString) {
-        System.err.println("Error: Entry point to 'glGetString' is NULL.");
+    if( !glGetPtrInit ) {
+        AccessController.doPrivileged(privInitGLGetPtrAction);
+        glGetPtrInit = true;
+    }
+    if( 0 == glGetStringPtr || 0 == glGetIntegervPtr ) {
+        System.err.println("Error: Could not lookup: glGetString "+toHexString(glGetStringPtr)+", glGetIntegerv "+toHexString(glGetIntegervPtr));
         if(DEBUG) {
             ExceptionUtils.dumpStack(System.err);
         }
         return false;
     } else {
-        final String _glVendor = glGetStringInt(GL.GL_VENDOR, _glGetString);
+        final String _glVendor = glGetStringInt(GL.GL_VENDOR, glGetStringPtr);
         if(null == _glVendor) {
             if(DEBUG) {
                 System.err.println("Warning: GL_VENDOR is NULL.");
@@ -1387,7 +1408,7 @@ public abstract class GLContextImpl extends GLContext {
         }
         glVendor = _glVendor;
 
-        final String _glRenderer = glGetStringInt(GL.GL_RENDERER, _glGetString);
+        final String _glRenderer = glGetStringInt(GL.GL_RENDERER, glGetStringPtr);
         if(null == _glRenderer) {
             if(DEBUG) {
                 System.err.println("Warning: GL_RENDERER is NULL.");
@@ -1398,7 +1419,7 @@ public abstract class GLContextImpl extends GLContext {
         glRenderer = _glRenderer;
         glRendererLowerCase = glRenderer.toLowerCase();
 
-        final String _glVersion = glGetStringInt(GL.GL_VERSION, _glGetString);
+        final String _glVersion = glGetStringInt(GL.GL_VERSION, glGetStringPtr);
         if(null == _glVersion) {
             // FIXME
             if(DEBUG) {
@@ -1413,6 +1434,26 @@ public abstract class GLContextImpl extends GLContext {
     }
   }
 
+  /**
+   * Returns false if <code>glGetIntegerv</code> is inaccessible, otherwise queries major.minor
+   * version for given arrays.
+   * <p>
+   * If the GL query fails, major will be zero.
+   * </p>
+   */
+  private final void getGLIntVersion(final int[] glIntMajor, final int[] glIntMinor)  {
+    glIntMajor[0] = 0; // clear
+    glIntMinor[0] = 0; // clear
+    if( 0 == glGetIntegervPtr ) {
+        // should not be reached, since initGLRendererAndGLVersionStrings(..)'s failure should abort caller!
+        throw new InternalError("Not initialized: glGetString "+toHexString(glGetStringPtr)+", glGetIntegerv "+toHexString(glGetIntegervPtr));
+    } else {
+        glGetIntegervInt(GL2ES3.GL_MAJOR_VERSION, glIntMajor, 0, glGetIntegervPtr);
+        glGetIntegervInt(GL2ES3.GL_MINOR_VERSION, glIntMinor, 0, glGetIntegervPtr);
+    }
+  }
+
+
   /**
    * Returns null if version string is invalid, otherwise a valid instance.
    * <p>
@@ -1433,30 +1474,6 @@ public abstract class GLContextImpl extends GLContext {
       return null;
   }
 
-  /**
-   * Returns false if <code>glGetIntegerv</code> is inaccessible, otherwise queries major.minor
-   * version for given arrays.
-   * <p>
-   * If the GL query fails, major will be zero.
-   * </p>
-   */
-  private final boolean getGLIntVersion(final int[] glIntMajor, final int[] glIntMinor)  {
-    glIntMajor[0] = 0; // clear
-    final GLDynamicLookupHelper glDynLookupHelper = getDrawableImpl().getGLDynamicLookupHelper();
-    final long _glGetIntegerv = glDynLookupHelper.dynamicLookupFunction("glGetIntegerv");
-    if( 0 == _glGetIntegerv ) {
-        System.err.println("Error: Entry point to 'glGetIntegerv' is NULL.");
-        if(DEBUG) {
-            ExceptionUtils.dumpStack(System.err);
-        }
-        return false;
-    } else {
-        glGetIntegervInt(GL2ES3.GL_MAJOR_VERSION, glIntMajor, 0, _glGetIntegerv);
-        glGetIntegervInt(GL2ES3.GL_MINOR_VERSION, glIntMinor, 0, _glGetIntegerv);
-        return true;
-    }
-  }
-
   protected final int getCtxOptions() {
       return ctxOptions;
   }
@@ -1548,20 +1565,7 @@ public abstract class GLContextImpl extends GLContext {
         final VersionNumber hasGLVersionByInt;
         {
             final int[] glIntMajor = new int[] { 0 }, glIntMinor = new int[] { 0 };
-            final boolean getGLIntVersionOK = getGLIntVersion(glIntMajor, glIntMinor);
-            if( !getGLIntVersionOK ) {
-                final String errMsg = "Fetching GL Integer Version failed. "+adevice+" - "+GLContext.getGLVersion(major, minor, ctxProfileBits, null);
-                if( strictMatch ) {
-                    // query mode .. simply fail
-                    if(DEBUG) {
-                        System.err.println("Warning: setGLFunctionAvailability: "+errMsg);
-                    }
-                    return false;
-                } else {
-                    // unusable GL context - non query mode - hard fail!
-                    throw new GLException(errMsg);
-                }
-            }
+            getGLIntVersion(glIntMajor, glIntMinor);
             hasGLVersionByInt = new VersionNumber(glIntMajor[0], glIntMinor[0], 0);
         }
         if (DEBUG) {
@@ -2235,7 +2239,7 @@ public abstract class GLContextImpl extends GLContext {
   @Override
   public final boolean isFunctionAvailable(final String glFunctionName) {
     // Check GL 1st (cached)
-    if(null!=glProcAddressTable) { // null if this context wasn't not created
+    if( null != glProcAddressTable ) { // null if this context wasn't not created
         try {
             if( glProcAddressTable.isFunctionAvailable( glFunctionName ) ) {
                 return true;
@@ -2256,15 +2260,24 @@ public abstract class GLContextImpl extends GLContext {
     // dynamic function lookup at last incl name aliasing (not cached)
     final DynamicLookupHelper dynLookup = getDrawableImpl().getGLDynamicLookupHelper();
     final String tmpBase = GLNameResolver.normalizeVEN(GLNameResolver.normalizeARB(glFunctionName, true), true);
-    boolean res = false;
-    final int  variants = GLNameResolver.getFuncNamePermutationNumber(tmpBase);
-    for(int i = 0; !res && i < variants; i++) {
-        final String tmp = GLNameResolver.getFuncNamePermutation(tmpBase, i);
-        try {
-            res = dynLookup.isFunctionAvailable(tmp);
-        } catch (final Exception e) { }
-    }
-    return res;
+    return AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
+        @Override
+        public Boolean run() {
+            boolean res = false;
+            dynLookup.claimAllLinkPermission();
+            try {
+                final int  variants = GLNameResolver.getFuncNamePermutationNumber(tmpBase);
+                for(int i = 0; !res && i < variants; i++) {
+                    final String tmp = GLNameResolver.getFuncNamePermutation(tmpBase, i);
+                    try {
+                        res = dynLookup.isFunctionAvailable(tmp);
+                    } catch (final Exception e) { }
+                }
+            } finally {
+                dynLookup.releaseAllLinkPermission();
+            }
+            return Boolean.valueOf(res);
+        } } ).booleanValue();
   }
 
   @Override
diff --git a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGDynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGDynamicLibraryBundleInfo.java
index e4d33b62c..744aefb32 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGDynamicLibraryBundleInfo.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGDynamicLibraryBundleInfo.java
@@ -163,12 +163,11 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo  {
          "swr_convert",
     };
 
+    /** util, format, codec, device, avresample, swresample */
+    private static final boolean[] libLoaded = new boolean[6];
     private static final long[] symbolAddr = new long[symbolCount];
     private static final boolean ready;
     private static final boolean libsUFCLoaded;
-    private static final boolean avresampleLoaded;  // optional
-    private static final boolean swresampleLoaded;  // optional
-    private static final boolean avdeviceLoaded; // optional
     static final VersionNumber avCodecVersion;
     static final VersionNumber avFormatVersion;
     static final VersionNumber avUtilVersion;
@@ -187,19 +186,14 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo  {
         // native ffmpeg media player implementation is included in jogl_desktop and jogl_mobile
         GLProfile.initSingleton();
         boolean _ready = false;
-        /** util, format, codec, device, avresample, swresample */
-        final boolean[] _loaded= new boolean[6];
         /** util, format, codec, avresample, swresample */
         final VersionNumber[] _versions = new VersionNumber[5];
         try {
-            _ready = initSymbols(_loaded, _versions);
+            _ready = initSymbols(_versions);
         } catch (final Throwable t) {
             t.printStackTrace();
         }
-        libsUFCLoaded = _loaded[LIB_IDX_UTI] && _loaded[LIB_IDX_FMT] && _loaded[LIB_IDX_COD];
-        avdeviceLoaded = _loaded[LIB_IDX_DEV];
-        avresampleLoaded = _loaded[LIB_IDX_AVR];
-        swresampleLoaded = _loaded[LIB_IDX_SWR];
+        libsUFCLoaded = libLoaded[LIB_IDX_UTI] && libLoaded[LIB_IDX_FMT] && libLoaded[LIB_IDX_COD];
         avUtilVersion = _versions[0];
         avFormatVersion = _versions[1];
         avCodecVersion = _versions[2];
@@ -239,51 +233,52 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo  {
     }
 
     static boolean libsLoaded() { return libsUFCLoaded; }
-    static boolean avDeviceLoaded() { return avdeviceLoaded; }
-    static boolean avResampleLoaded() { return avresampleLoaded; }
-    static boolean swResampleLoaded() { return swresampleLoaded; }
+    static boolean avDeviceLoaded() { return libLoaded[LIB_IDX_DEV]; }
+    static boolean avResampleLoaded() { return libLoaded[LIB_IDX_AVR]; }
+    static boolean swResampleLoaded() { return libLoaded[LIB_IDX_SWR]; }
     static FFMPEGNatives getNatives() { return natives; }
     static boolean initSingleton() { return ready; }
 
+    private static final PrivilegedAction<DynamicLibraryBundle> privInitSymbolsAction = new PrivilegedAction<DynamicLibraryBundle>() {
+        @Override
+        public DynamicLibraryBundle run() {
+            final DynamicLibraryBundle dl = new DynamicLibraryBundle(new FFMPEGDynamicLibraryBundleInfo());
+            for(int i=0; i<6; i++) {
+                libLoaded[i] = dl.isToolLibLoaded(i);
+            }
+            if( !libLoaded[LIB_IDX_UTI] || !libLoaded[LIB_IDX_FMT] || !libLoaded[LIB_IDX_COD] ) {
+                throw new RuntimeException("FFMPEG Tool library incomplete: [ avutil "+libLoaded[LIB_IDX_UTI]+", avformat "+libLoaded[LIB_IDX_FMT]+", avcodec "+libLoaded[LIB_IDX_COD]+"]");
+            }
+            dl.claimAllLinkPermission();
+            try {
+                for(int i = 0; i<symbolCount; i++) {
+                    symbolAddr[i] = dl.dynamicLookupFunction(symbolNames[i]);
+                }
+            } finally {
+                dl.releaseAllLinkPermission();
+            }
+            return dl;
+        } };
+
     /**
      * @param loaded 6: util, format, codec, device, avresample, swresample
      * @param versions 5: util, format, codec, avresample, swresample
      * @return
      */
-    private static final boolean initSymbols(final boolean[] loaded, final VersionNumber[] versions) {
+    private static final boolean initSymbols(final VersionNumber[] versions) {
         for(int i=0; i<6; i++) {
-            loaded[i] = false;
-        }
-        final DynamicLibraryBundle dl = AccessController.doPrivileged(new PrivilegedAction<DynamicLibraryBundle>() {
-                                          @Override
-                                          public DynamicLibraryBundle run() {
-                                              return new DynamicLibraryBundle(new FFMPEGDynamicLibraryBundleInfo());
-                                          } } );
-        dl.toString();
-        for(int i=0; i<6; i++) {
-            loaded[i] = dl.isToolLibLoaded(i);
-        }
-        if( !loaded[LIB_IDX_UTI] || !loaded[LIB_IDX_FMT] || !loaded[LIB_IDX_COD] ) {
-            throw new RuntimeException("FFMPEG Tool library incomplete: [ avutil "+loaded[LIB_IDX_UTI]+", avformat "+loaded[LIB_IDX_FMT]+", avcodec "+loaded[LIB_IDX_COD]+"]");
+            libLoaded[i] = false;
         }
         if(symbolNames.length != symbolCount) {
             throw new InternalError("XXX0 "+symbolNames.length+" != "+symbolCount);
         }
 
+        AccessController.doPrivileged(privInitSymbolsAction);
+
         // optional symbol name set
         final Set<String> optionalSymbolNameSet = new HashSet<String>();
         optionalSymbolNameSet.addAll(Arrays.asList(optionalSymbolNames));
 
-        // lookup
-        AccessController.doPrivileged(new PrivilegedAction<Object>() {
-            @Override
-            public Object run() {
-                for(int i = 0; i<symbolCount; i++) {
-                    symbolAddr[i] = dl.dynamicLookupFunction(symbolNames[i]);
-                }
-                return null;
-            } } );
-
         // validate results
         boolean res = true;
         for(int i = 0; i<symbolCount; i++) {
-- 
cgit v1.2.3