Skip to content

Commit

Permalink
Security: Tighten DynamicLinker*, NativeLibrary and DynamicLibraryBun…
Browse files Browse the repository at this point in the history
…dle access (2)

- Completes 23341a2

- Replace 'DynamicLinker' interface w/ well documented one

- All DynamicLinker methods are now considered secure, i.e.:
  - open/lookup and close utilize reference counting on handle via a hash map.

  - lookupSymbol(..) and close(..) impl. validate the passed library handle
    whether it's retrieved via open*.
    This is the fast path, not that expensive.

  - lookupSymbolGlobal(..) performs
    Check acccess of 'new RuntimePermission("loadLibrary.*")' if SecurityManager is installed.
    This is the slow path.

- DynamicLibraryBundleInfo now reflects the security requirements,
  i.e. whether priviledged access is needed.
  • Loading branch information
sgothel committed Jun 21, 2013
1 parent 19bef68 commit eb84281
Show file tree
Hide file tree
Showing 10 changed files with 198 additions and 111 deletions.
2 changes: 1 addition & 1 deletion src/java/com/jogamp/common/os/DynamicLibraryBundle.java
Expand Up @@ -324,7 +324,7 @@ private final long dynamicLookupFunctionOnLibs(String funcName) {
long addr = 0;
NativeLibrary lib = null;

if(info.shallLookupGlobal()) {
if( info.shallLookupGlobal() ) {
// Try a global symbol lookup first ..
addr = NativeLibrary.dynamicLookupFunctionGlobal(funcName);
}
Expand Down
33 changes: 23 additions & 10 deletions src/java/com/jogamp/common/os/DynamicLibraryBundleInfo.java
Expand Up @@ -28,14 +28,19 @@

package com.jogamp.common.os;

import java.util.*;
import java.util.List;

import com.jogamp.common.util.RunnableExecutor;


public interface DynamicLibraryBundleInfo {
public static final boolean DEBUG = DynamicLibraryBundle.DEBUG;

/** @return a list of Tool library names or alternative library name lists.<br>
/**
* If a {@link SecurityManager} is installed, user needs link permissions
* for the named libraries.
*
* @return a list of Tool library names or alternative library name lists.<br>
* <ul>
* <li>GL/GLU example Unix: [ [ "libGL.so.1", "libGL.so", "GL" ], [ "libGLU.so", "GLU" ] ] </li>
* <li>GL/GLU example Windows: [ "OpenGL32", "GLU32" ] </li>
Expand All @@ -44,7 +49,11 @@ public interface DynamicLibraryBundleInfo {
*/
public List<List<String>> getToolLibNames();

/** @return a list of Glue library names.<br>
/**
* If a {@link SecurityManager} is installed, user needs link permissions
* for the named libraries.
*
* @return a list of Glue library names.<br>
* <ul>
* <li>GL: [ "nativewindow_x11", "jogl_gl2es12", "jogl_desktop" ] </li>
* <li>NEWT: [ "nativewindow_x11", "newt" ] </li>
Expand All @@ -55,23 +64,21 @@ public interface DynamicLibraryBundleInfo {
*/
public List<String> getGlueLibNames();

/** May return the native libraries <pre>GetProcAddressFunc</pre> names, the first found function is being used.<br>
/**
* May return the native libraries <pre>GetProcAddressFunc</pre> names, the first found function is being used.<br>
* This could be eg: <pre> glXGetProcAddressARB, glXGetProcAddressARB </pre>.<br>
* If your Tool does not has this facility, just return null.
* @see #toolGetProcAddress(long, String)
*/
public List<String> getToolGetProcAddressFuncNameList() ;

/** May implement the lookup function using the Tools facility.<br>
/**
* May implement the lookup function using the Tools facility.<br>
* The actual function pointer is provided to allow proper bootstrapping of the ProcAddressTable,
* using one of the provided function names by {@link #getToolGetProcAddressFuncNameList()}.<br>
*/
public long toolGetProcAddress(long toolGetProcAddressHandle, String funcName);

/** May implement the lookup function using the Tools facility.<br>
* The actual function pointer is provided to allow proper bootstrapping of the ProcAddressTable.<br>
*/

/**
* @param funcName
* @return true if {@link #toolGetProcAddress(long, String)} shall be tried before
Expand All @@ -83,7 +90,13 @@ public interface DynamicLibraryBundleInfo {
/** @return true if the native library symbols shall be made available for symbol resolution of subsequently loaded libraries. */
public boolean shallLinkGlobal();

/** @return true if the dynamic symbol lookup shall happen system wide, over all loaded libraries. Otherwise only the loaded native libraries are used for lookup, which shall be the default. */
/**
* If method returns <code>true</code> <i>and</i> if a {@link SecurityManager} is installed, user needs link permissions
* for <b>all</b> libraries, i.e. for <code>new RuntimePermission("loadLibrary.*");</code>!
*
* @return true if the dynamic symbol lookup shall happen system wide, over all loaded libraries.
* Otherwise only the loaded native libraries are used for lookup, which shall be the default.
*/
public boolean shallLookupGlobal();

/**
Expand Down
135 changes: 91 additions & 44 deletions src/java/com/jogamp/common/os/DynamicLinker.java
@@ -1,55 +1,102 @@
/*
* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
* MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
* ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
* DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
* ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
* DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
*
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
/**
* Copyright 2013 JogAmp Community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/

package com.jogamp.common.os;

/** Provides an abstract interface to the OS's low-level dynamic
linking functionality. */

/** Low level secure dynamic linker access. */
public interface DynamicLinker {
public static final boolean DEBUG = NativeLibrary.DEBUG;
public static final boolean DEBUG_LOOKUP = NativeLibrary.DEBUG_LOOKUP;


/**
* If a {@link SecurityManager} is installed, user needs link permissions
* for the named library.
* <p>
* Opens the named library, allowing system wide access for other <i>users</i>.
* </p>
*
* @param pathname the full pathname for the library to open
* @param debug set to true to enable debugging
* @return the library handle, maybe 0 if not found.
* @throws SecurityException if user is not granted access for the named library.
*/
public long openLibraryGlobal(String pathname, boolean debug) throws SecurityException;

/**
* If a {@link SecurityManager} is installed, user needs link permissions
* for the named library.
* <p>
* Opens the named library, restricting access to this process.
* </p>
*
* @param pathname the full pathname for the library to open
* @param debug set to true to enable debugging
* @return the library handle, maybe 0 if not found.
* @throws SecurityException if user is not granted access for the named library.
*/
public long openLibraryLocal(String pathname, boolean debug) throws SecurityException;
public long lookupSymbol(long libraryHandle, String symbolName);
public long lookupSymbolGlobal(String symbolName);
public void closeLibrary(long libraryHandle);

/**
* If a {@link SecurityManager} is installed, user needs link permissions
* for <b>all</b> libraries, i.e. for <code>new RuntimePermission("loadLibrary.*");</code>!
*
* @param symbolName global symbol name to lookup up system wide.
* @return the library handle, maybe 0 if not found.
* @throws SecurityException if user is not granted access for all libraries.
*/
public long lookupSymbolGlobal(String symbolName) throws SecurityException;

/**
* Security checks are implicit by previous call of
* {@link #openLibraryLocal(String, boolean)} or {@link #openLibraryGlobal(String, boolean)}
* retrieving the <code>librarHandle</code>.
*
* @param libraryHandle a library handle previously retrieved via {@link #openLibraryLocal(String, boolean)} or {@link #openLibraryGlobal(String, boolean)}.
* @param symbolName global symbol name to lookup up system wide.
* @return the library handle, maybe 0 if not found.
* @throws IllegalArgumentException in case case <code>libraryHandle</code> is unknown.
*/
public long lookupSymbol(long libraryHandle, String symbolName) throws IllegalArgumentException;

/**
* Security checks are implicit by previous call of
* {@link #openLibraryLocal(String, boolean)} or {@link #openLibraryGlobal(String, boolean)}
* retrieving the <code>librarHandle</code>.
*
* @param libraryHandle a library handle previously retrieved via {@link #openLibraryLocal(String, boolean)} or {@link #openLibraryGlobal(String, boolean)}.
* @throws IllegalArgumentException in case case <code>libraryHandle</code> is unknown.
*/
public void closeLibrary(long libraryHandle) throws IllegalArgumentException;

/**
* Returns a string containing the last error.
* Maybe called for debuging purposed if any method fails.
* @return error string, maybe null. A null or non-null value has no semantics.
*/
public String getLastError();
}
27 changes: 1 addition & 26 deletions src/java/com/jogamp/common/os/NativeLibrary.java
Expand Up @@ -76,10 +76,6 @@ public final class NativeLibrary implements DynamicLookupHelper {
private static final DynamicLinker dynLink;
private static final String[] prefixes;
private static final String[] suffixes;
/** TODO: Hide all lookup methods - Then make protected method accessible ..
private static final Method dynLinkLookupLocal;
private static final Method dynLinkLookupGlobal;
*/

static {
// Instantiate dynamic linker implementation
Expand Down Expand Up @@ -114,23 +110,6 @@ public final class NativeLibrary implements DynamicLookupHelper {
suffixes = new String[] { ".so" };
break;
}

/** TODO: Hide all lookup methods - Then make protected method accessible ..
// public long lookupSymbol(long libraryHandle, String symbolName);
// public long lookupSymbolGlobal(String symbolName);
final Method[] dlLookups = AccessController.doPrivileged(new PrivilegedAction<Method[]>() {
public Method[] run() {
final Method[] ms = new Method[2];
ms[0] = ReflectionUtil.getMethod(dynLink.getClass(), "lookupSymbol", Long.class, String.class);
ms[0].setAccessible(true);
ms[1] = ReflectionUtil.getMethod(dynLink.getClass(), "lookupSymbolGlobal", String.class);
ms[0].setAccessible(true);
return ms;
}
} );
dynLinkLookupLocal = dlLookups[0];
dynLinkLookupGlobal = dlLookups[1];
*/
}

// Platform-specific representation for the handle to the open
Expand Down Expand Up @@ -258,7 +237,6 @@ public final long dynamicLookupFunction(String funcName) {
throw new RuntimeException("Library is not open");
}
return dynLink.lookupSymbol(libraryHandle, funcName);
// TODO: return ( (Long) ReflectionUtil.callMethod(dynLink, dynLinkLookupLocal, Long.valueOf(libraryHandle), funcName) ).longValue();
}

@Override
Expand All @@ -267,19 +245,16 @@ public final boolean isFunctionAvailable(String funcName) {
throw new RuntimeException("Library is not open");
}
return 0 != dynLink.lookupSymbol(libraryHandle, funcName);
// TODO return 0 != ( (Long) ReflectionUtil.callMethod(dynLink, dynLinkLookupLocal, Long.valueOf(libraryHandle), funcName) ).longValue();
}

/** Looks up the given function name in all loaded libraries. */
public static final long dynamicLookupFunctionGlobal(String funcName) {
return dynLink.lookupSymbolGlobal(funcName);
// TODO return ( (Long) ReflectionUtil.callMethod(dynLink, dynLinkLookupGlobal, funcName) ).longValue();
}

/** Looks up the given function name in all loaded libraries. */
public static final boolean isFunctionAvailableGlobal(String funcName) {
return 0 != dynLink.lookupSymbolGlobal(funcName);
// TODO return 0 != ( (Long) ReflectionUtil.callMethod(dynLink, dynLinkLookupGlobal, funcName) ).longValue();
}

/** Retrieves the low-level library handle from this NativeLibrary
Expand All @@ -300,7 +275,7 @@ public final void close() {
if (DEBUG) {
System.err.println("NativeLibrary.close(): closing " + this);
}
if (libraryHandle == 0) {
if ( 0 == libraryHandle ) {
throw new RuntimeException("Library already closed");
}
long handle = libraryHandle;
Expand Down
11 changes: 11 additions & 0 deletions src/java/com/jogamp/common/util/SecurityUtil.java
Expand Up @@ -141,6 +141,17 @@ public static final void checkLinkPermission(String libName) throws SecurityExce
}
}

/**
* Throws an {@link SecurityException} if an installed {@link SecurityManager}
* does not permit to dynamically link to all libraries.
*/
public static final void checkAllLinkPermission() throws SecurityException {
if( null != securityManager ) {
securityManager.checkPermission(allLinkPermission);
}
}
private static final RuntimePermission allLinkPermission = new RuntimePermission("loadLibrary.*");

/**
* @param clz
* @return
Expand Down
19 changes: 16 additions & 3 deletions src/java/jogamp/common/os/BionicDynamicLinkerImpl.java
Expand Up @@ -55,7 +55,13 @@ public final long openLibraryLocal(String pathname, boolean debug) throws Securi
// having to dlsym all entry points. System.loadLibrary() uses
// RTLD_LOCAL visibility so can't be used for this purpose.
SecurityUtil.checkLinkPermission(pathname);
return dlopen(pathname, RTLD_LAZY | RTLD_LOCAL);
final long handle = dlopen(pathname, RTLD_LAZY | RTLD_LOCAL);
if( 0 != handle ) {
incrLibRefCount(handle, pathname);
} else if ( DEBUG || debug ) {
System.err.println("dlopen \""+pathname+"\" local failed, error: "+dlerror());
}
return handle;
}

@Override
Expand All @@ -68,11 +74,18 @@ public final long openLibraryGlobal(String pathname, boolean debug) throws Secur
// having to dlsym all entry points. System.loadLibrary() uses
// RTLD_LOCAL visibility so can't be used for this purpose.
SecurityUtil.checkLinkPermission(pathname);
return dlopen(pathname, RTLD_LAZY | RTLD_GLOBAL);
final long handle = dlopen(pathname, RTLD_LAZY | RTLD_GLOBAL);
if( 0 != handle ) {
incrLibRefCount(handle, pathname);
} else if ( DEBUG || debug ) {
System.err.println("dlopen \""+pathname+"\" global failed, error: "+dlerror());
}
return handle;
}

@Override
public final long lookupSymbolGlobal(String symbolName) {
public final long lookupSymbolGlobal(String symbolName) throws SecurityException {
SecurityUtil.checkAllLinkPermission();
final long addr = dlsym(RTLD_DEFAULT, symbolName);
if(DEBUG_LOOKUP) {
System.err.println("DynamicLinkerImpl.lookupSymbolGlobal("+symbolName+") -> 0x"+Long.toHexString(addr));
Expand Down
19 changes: 16 additions & 3 deletions src/java/jogamp/common/os/MacOSXDynamicLinkerImpl.java
Expand Up @@ -53,7 +53,13 @@ public final long openLibraryLocal(String pathname, boolean debug) throws Securi
// having to dlsym all entry points. System.loadLibrary() uses
// RTLD_LOCAL visibility so can't be used for this purpose.
SecurityUtil.checkLinkPermission(pathname);
return dlopen(pathname, RTLD_LAZY | RTLD_LOCAL);
final long handle = dlopen(pathname, RTLD_LAZY | RTLD_LOCAL);
if( 0 != handle ) {
incrLibRefCount(handle, pathname);
} else if ( DEBUG || debug ) {
System.err.println("dlopen \""+pathname+"\" local failed, error: "+dlerror());
}
return handle;
}

@Override
Expand All @@ -66,11 +72,18 @@ public final long openLibraryGlobal(String pathname, boolean debug) throws Secur
// having to dlsym all entry points. System.loadLibrary() uses
// RTLD_LOCAL visibility so can't be used for this purpose.
SecurityUtil.checkLinkPermission(pathname);
return dlopen(pathname, RTLD_LAZY | RTLD_GLOBAL);
final long handle = dlopen(pathname, RTLD_LAZY | RTLD_GLOBAL);
if( 0 != handle ) {
incrLibRefCount(handle, pathname);
} else if ( DEBUG || debug ) {
System.err.println("dlopen \""+pathname+"\" global failed, error: "+dlerror());
}
return handle;
}

@Override
public final long lookupSymbolGlobal(String symbolName) {
public final long lookupSymbolGlobal(String symbolName) throws SecurityException {
SecurityUtil.checkAllLinkPermission();
final long addr = dlsym(RTLD_DEFAULT, symbolName);
if(DEBUG_LOOKUP) {
System.err.println("DynamicLinkerImpl.lookupSymbolGlobal("+symbolName+") -> 0x"+Long.toHexString(addr));
Expand Down

0 comments on commit eb84281

Please sign in to comment.