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.
  • Loading branch information
rrva committed Nov 4, 2022
1 parent f56b909 commit 578774e
Show file tree
Hide file tree
Showing 5 changed files with 196 additions and 2 deletions.
5 changes: 5 additions & 0 deletions sdk/trace-shaded-deps/build.gradle.kts
Expand Up @@ -26,3 +26,8 @@ tasks {
into("build/extracted/shadow")
}
}

tasks.withType<Test>().configureEach {
// JcToolsSecurityManagerTest interferes with JcToolsTest
setForkEvery(1)
}
Expand Up @@ -25,8 +25,9 @@ public final class JcTools {
public static <T> Queue<T> newFixedSizeQueue(int capacity) {
try {
return new MpscArrayQueue<>(capacity);
} catch (java.lang.NoClassDefFoundError e) {
// Happens when modules such as jdk.unsupported are disabled in a custom JRE distribution
} catch (java.lang.NoClassDefFoundError | java.lang.ExceptionInInitializerError e) {
// Happens when modules such as jdk.unsupported are disabled in a custom JRE distribution,
// or a security manager preventing access to Unsafe is installed.
return new ArrayBlockingQueue<>(capacity);
}
}
Expand Down
@@ -0,0 +1,36 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.sdk.trace.internal;

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

import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledOnJre;
import org.junit.jupiter.api.condition.JRE;

public class JcToolsSecurityManagerTest {

@Test
@EnabledOnJre({JRE.JAVA_8, JRE.JAVA_11, JRE.JAVA_17})
void newFixedSizeQueue_SunMiscProhibited() {
assertThat(System.getSecurityManager()).isNull();
SunMiscProhibitedSecurityManager testingSecurityManager =
new SunMiscProhibitedSecurityManager();
try {
System.setSecurityManager(testingSecurityManager);
Queue<Object> queue =
AccessController.doPrivileged(
(PrivilegedAction<Queue<Object>>) () -> JcTools.newFixedSizeQueue(10));
assertThat(queue).isInstanceOf(ArrayBlockingQueue.class);
} 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,0 +1,41 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.sdk.trace.internal;

import static org.assertj.core.api.Assertions.assertThatNoException;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

import java.security.AccessControlException;
import org.junit.jupiter.api.Test;

class SunMiscProhibitedSecurityManagerTest {

@Test
public void checkPackageAccess_ProhibitsSunMisc() {
SunMiscProhibitedSecurityManager sm = new SunMiscProhibitedSecurityManager();
assertThatThrownBy(() -> sm.checkPackageAccess("sun.misc"))
.isInstanceOf(AccessControlException.class)
.hasMessage(
"access denied (\"java.lang.RuntimePermission\" \"accessClassInPackage.sun.misc\")");
}

@Test
public void checkPackageAccess_ProhibitsSunMiscRuntimePermission() {
SunMiscProhibitedSecurityManager sm = new SunMiscProhibitedSecurityManager();

assertThatThrownBy(
() -> sm.checkPermission(new RuntimePermission("accessClassInPackage.sun.misc")))
.isInstanceOf(AccessControlException.class)
.hasMessage(
"access denied (\"java.lang.RuntimePermission\" \"accessClassInPackage.sun.misc\")");
}

@Test
public void checkPackageAccess_AllowsOtherPackage() {
SunMiscProhibitedSecurityManager sm = new SunMiscProhibitedSecurityManager();
assertThatNoException().isThrownBy(() -> sm.checkPackageAccess("io.opentelemetry.sdk"));
}
}

0 comments on commit 578774e

Please sign in to comment.