Skip to content

Commit

Permalink
Allow SDK to run in environments prohibiting use of sun.misc.Unsafe
Browse files Browse the repository at this point in the history
Some applications run under strict java.security permissions
which do not allow access to sun.misc.Unsafe.

BatchSpanProcessor uses Unsafe via jctools, but has a fallback to
ArrayBlockingQueue. Extending that fallback rule to cover
java security exceptions as well.

Since the entire java security manager is marked for deprecation
in future java versions, I went with string-matching on the
root cause message, which removes deprecation warnings when building
with newer java but still does the job in those versions which use
java.security policies.
  • Loading branch information
rrva committed Nov 1, 2022
1 parent f56b909 commit d5fdd43
Show file tree
Hide file tree
Showing 3 changed files with 149 additions and 0 deletions.
Expand Up @@ -28,9 +28,28 @@ public static <T> Queue<T> newFixedSizeQueue(int capacity) {
} catch (java.lang.NoClassDefFoundError e) {
// Happens when modules such as jdk.unsupported are disabled in a custom JRE distribution
return new ArrayBlockingQueue<>(capacity);
} catch (java.lang.ExceptionInInitializerError e) {
if (isSunMiscAccessProhibited(e)) {
return new ArrayBlockingQueue<>(capacity);
} else {
throw e;
}
}
}

private static boolean isSunMiscAccessProhibited(Throwable t) {
String rootCause = rootCause(t).getMessage();
return rootCause != null && rootCause.contains("accessClassInPackage.sun.misc");
}

private static Throwable rootCause(Throwable throwable) {
Throwable c = throwable;
while (c.getCause() != null && c.getCause() != c) {
c = c.getCause();
}
return c;
}

/**
* Returns the capacity of the {@link Queue}. We cast to the implementation so callers do not need
* to use the shaded classes.
Expand Down
Expand Up @@ -7,10 +7,13 @@

import static org.assertj.core.api.Assertions.assertThat;

import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;
import org.jctools.queues.MpscArrayQueue;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
Expand Down Expand Up @@ -106,4 +109,20 @@ void capacity_ArrayBlockingQueue() {
// Assert
assertThat(queueSize).isEqualTo(10);
}

@Test
void newFixedSizeQueue_works_with_sunMisc_prohibited() {
Assertions.assertNull(System.getSecurityManager());
SunMiscProhibitedSecurityManager testingSecurityManager =
new SunMiscProhibitedSecurityManager();
try {
System.setSecurityManager(testingSecurityManager);
Queue<Object> queue =
AccessController.doPrivileged(
(PrivilegedAction<Queue<Object>>) () -> JcTools.newFixedSizeQueue(10));
Assertions.assertNotNull(queue);
} finally {
System.setSecurityManager(null);
}
}
}
@@ -0,0 +1,111 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.sdk.trace.internal;

import java.io.FileDescriptor;
import java.net.InetAddress;
import java.security.AccessControlException;
import java.security.Permission;

/**
* A security manager which disallows access to classes in sun.misc Running the tests with a
* standard security manager is too invasive
*/
public class SunMiscProhibitedSecurityManager extends SecurityManager {

public SunMiscProhibitedSecurityManager() {}

@Override
protected Class<?>[] getClassContext() {
return super.getClassContext();
}

@Override
public void checkPermission(Permission perm) {
if (perm.getName().equals("accessClassInPackage.sun.misc")) {
throw new AccessControlException("access denied " + perm, perm);
}
}

@Override
public void checkPermission(Permission perm, Object context) {}

@Override
public void checkCreateClassLoader() {}

@Override
public void checkAccess(Thread t) {}

@Override
public void checkAccess(ThreadGroup g) {}

@Override
public void checkExit(int status) {}

@Override
public void checkExec(String cmd) {}

@Override
public void checkLink(String lib) {}

@Override
public void checkRead(FileDescriptor fd) {}

@Override
public void checkRead(String file) {}

@Override
public void checkRead(String file, Object context) {}

@Override
public void checkWrite(FileDescriptor fd) {}

@Override
public void checkWrite(String file) {}

@Override
public void checkDelete(String file) {}

@Override
public void checkConnect(String host, int port) {}

@Override
public void checkConnect(String host, int port, Object context) {}

@Override
public void checkListen(int port) {}

@Override
public void checkAccept(String host, int port) {}

@Override
public void checkMulticast(InetAddress maddr) {}

@Override
public void checkPropertiesAccess() {}

@Override
public void checkPropertyAccess(String key) {}

@Override
public void checkPrintJobAccess() {}

@Override
public void checkPackageAccess(String pkg) {
if (pkg.equals("sun.misc")) {
super.checkPackageAccess(pkg);
}
}

@Override
public void checkPackageDefinition(String pkg) {}

@Override
public void checkSetFactory() {}

@Override
public void checkSecurityAccess(String target) {}
}

0 comments on commit d5fdd43

Please sign in to comment.