Skip to content

Commit 0272582

Browse files
committed
Test with --sun-misc-unsafe-memory-access=deny
1 parent 567e737 commit 0272582

File tree

14 files changed

+234
-4
lines changed

14 files changed

+234
-4
lines changed

.github/workflows/build.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,13 @@ jobs:
7070

7171
- name: Set up gradle
7272
uses: gradle/actions/setup-gradle@ed408507eac070d1f99cc633dbcf757c94c7933a # v4.4.3
73+
7374
- name: Build
7475
run: >
7576
./gradlew build
7677
${{ matrix.coverage && 'jacocoTestReport' || '' }}
7778
-PtestJavaVersion=${{ matrix.test-java-version }}
79+
${{ matrix.test-java-version == 23 && '-PdenyUnsafe=true' || '' }}
7880
"-Porg.gradle.java.installations.paths=${{ steps.setup-java-test.outputs.path }}"
7981
"-Porg.gradle.java.installations.auto-download=false"
8082
env:

buildSrc/src/main/kotlin/otel.java-conventions.gradle.kts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ dependencyCheck {
7070
}
7171

7272
val testJavaVersion = gradle.startParameter.projectProperties.get("testJavaVersion")?.let(JavaVersion::toVersion)
73+
val denyUnsafe = gradle.startParameter.projectProperties.get("denyUnsafe")?.toBoolean() ?: false
7374

7475
tasks {
7576
withType<JavaCompile>().configureEach {
@@ -114,6 +115,11 @@ tasks {
114115
)
115116
}
116117

118+
// Add JVM arguments when denyUnsafe property is set
119+
if (denyUnsafe) {
120+
jvmArgs("--sun-misc-unsafe-memory-access=deny")
121+
}
122+
117123
val defaultMaxRetries = if (System.getenv().containsKey("CI")) 2 else 0
118124
val maxTestRetries = gradle.startParameter.projectProperties["maxTestRetries"]?.toInt() ?: defaultMaxRetries
119125

exporters/common/build.gradle.kts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,15 @@ testing {
7676
}
7777

7878
tasks {
79+
withType<Test>().configureEach {
80+
val denyUnsafe = gradle.startParameter.projectProperties.get("denyUnsafe")?.toBoolean() ?: false
81+
if (denyUnsafe) {
82+
// Use a custom Security Manager to force proper fallback from protobuf under --sun-misc-unsafe-memory-access=deny
83+
// Workaround for https://github.com/protocolbuffers/protobuf/issues/20760
84+
// Note: protobuf is only a test dependency, so this issue does not affect users
85+
jvmArgs("-Djava.security.manager=io.opentelemetry.exporter.internal.unsafe.ProtobufWorkaroundSecurityManager")
86+
}
87+
}
7988
check {
8089
dependsOn(testing.suites)
8190
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.exporter.internal.unsafe;
7+
8+
import java.security.Permission;
9+
10+
public class ProtobufWorkaroundSecurityManager extends SecurityManager {
11+
12+
@Override
13+
public void checkPermission(Permission perm) {
14+
// Block access to sun.misc.Unsafe fields
15+
if (perm instanceof java.lang.reflect.ReflectPermission) {
16+
if ("suppressAccessChecks".equals(perm.getName())) {
17+
// Get the stack trace to see what's trying to access
18+
StackTraceElement[] stack = Thread.currentThread().getStackTrace();
19+
for (StackTraceElement element : stack) {
20+
if (element.getClassName().contains("UnsafeUtil")
21+
&& element.getMethodName().contains("getUnsafe")) {
22+
throw new SecurityException("Access to sun.misc.Unsafe denied");
23+
}
24+
}
25+
}
26+
}
27+
// Allow everything else
28+
}
29+
30+
@Override
31+
public void checkPermission(Permission perm, Object context) {
32+
checkPermission(perm);
33+
}
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.exporter.internal.unsafe;
7+
8+
import java.security.Permission;
9+
10+
public class ProtobufWorkaroundSecurityManager extends SecurityManager {
11+
12+
@Override
13+
public void checkPermission(Permission perm) {
14+
// Block access to sun.misc.Unsafe fields
15+
if (perm instanceof java.lang.reflect.ReflectPermission) {
16+
if ("suppressAccessChecks".equals(perm.getName())) {
17+
// Get the stack trace to see what's trying to access
18+
StackTraceElement[] stack = Thread.currentThread().getStackTrace();
19+
for (StackTraceElement element : stack) {
20+
if (element.getClassName().contains("UnsafeUtil")
21+
&& element.getMethodName().contains("getUnsafe")) {
22+
throw new SecurityException("Access to sun.misc.Unsafe denied");
23+
}
24+
}
25+
}
26+
}
27+
// Allow everything else
28+
}
29+
30+
@Override
31+
public void checkPermission(Permission perm, Object context) {
32+
checkPermission(perm);
33+
}
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.exporter.internal.unsafe;
7+
8+
import java.security.Permission;
9+
10+
public class ProtobufWorkaroundSecurityManager extends SecurityManager {
11+
12+
@Override
13+
public void checkPermission(Permission perm) {
14+
// Block access to sun.misc.Unsafe fields
15+
if (perm instanceof java.lang.reflect.ReflectPermission) {
16+
if ("suppressAccessChecks".equals(perm.getName())) {
17+
// Get the stack trace to see what's trying to access
18+
StackTraceElement[] stack = Thread.currentThread().getStackTrace();
19+
for (StackTraceElement element : stack) {
20+
if (element.getClassName().contains("UnsafeUtil")
21+
&& element.getMethodName().contains("getUnsafe")) {
22+
throw new SecurityException("Access to sun.misc.Unsafe denied");
23+
}
24+
}
25+
}
26+
}
27+
// Allow everything else
28+
}
29+
30+
@Override
31+
public void checkPermission(Permission perm, Object context) {
32+
checkPermission(perm);
33+
}
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.exporter.internal.unsafe;
7+
8+
import java.security.Permission;
9+
10+
public class ProtobufWorkaroundSecurityManager extends SecurityManager {
11+
12+
@Override
13+
public void checkPermission(Permission perm) {
14+
// Block access to sun.misc.Unsafe fields
15+
if (perm instanceof java.lang.reflect.ReflectPermission) {
16+
if ("suppressAccessChecks".equals(perm.getName())) {
17+
// Get the stack trace to see what's trying to access
18+
StackTraceElement[] stack = Thread.currentThread().getStackTrace();
19+
for (StackTraceElement element : stack) {
20+
if (element.getClassName().contains("UnsafeUtil")
21+
&& element.getMethodName().contains("getUnsafe")) {
22+
throw new SecurityException("Access to sun.misc.Unsafe denied");
23+
}
24+
}
25+
}
26+
}
27+
// Allow everything else
28+
}
29+
30+
@Override
31+
public void checkPermission(Permission perm, Object context) {
32+
checkPermission(perm);
33+
}
34+
}

exporters/otlp/common/build.gradle.kts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,16 @@ dependencies {
4141
jmhImplementation("io.grpc:grpc-netty")
4242
}
4343

44+
tasks.withType<Test>().configureEach {
45+
val denyUnsafe = gradle.startParameter.projectProperties.get("denyUnsafe")?.toBoolean() ?: false
46+
if (denyUnsafe) {
47+
// Use a custom Security Manager to force proper fallback from protobuf under --sun-misc-unsafe-memory-access=deny
48+
// Workaround for https://github.com/protocolbuffers/protobuf/issues/20760
49+
// Note: protobuf is only a test dependency, so this issue does not affect users
50+
jvmArgs("-Djava.security.manager=io.opentelemetry.exporter.internal.otlp.unsafe.ProtobufWorkaroundSecurityManager")
51+
}
52+
}
53+
4454
testing {
4555
suites {
4656
register<JvmTestSuite>("testIncubating") {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.exporter.internal.otlp.unsafe;
7+
8+
import java.security.Permission;
9+
10+
public class ProtobufWorkaroundSecurityManager extends SecurityManager {
11+
12+
@Override
13+
public void checkPermission(Permission perm) {
14+
// Block access to sun.misc.Unsafe fields
15+
if (perm instanceof java.lang.reflect.ReflectPermission) {
16+
if ("suppressAccessChecks".equals(perm.getName())) {
17+
// Get the stack trace to see what's trying to access
18+
StackTraceElement[] stack = Thread.currentThread().getStackTrace();
19+
for (StackTraceElement element : stack) {
20+
if (element.getClassName().contains("UnsafeUtil")
21+
&& element.getMethodName().contains("getUnsafe")) {
22+
throw new SecurityException("Access to sun.misc.Unsafe denied");
23+
}
24+
}
25+
}
26+
}
27+
// Allow everything else
28+
}
29+
30+
@Override
31+
public void checkPermission(Permission perm, Object context) {
32+
checkPermission(perm);
33+
}
34+
}

exporters/prometheus/build.gradle.kts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,14 @@ dependencies {
3434
}
3535

3636
tasks {
37+
named<Test>("test") {
38+
val denyUnsafe = gradle.startParameter.projectProperties.get("denyUnsafe")?.toBoolean() ?: false
39+
if (denyUnsafe) {
40+
// These tests use Armeria which uses Unsafe via JCTools
41+
jvmArgs("--sun-misc-unsafe-memory-access=allow")
42+
}
43+
}
44+
3745
check {
3846
dependsOn(testing.suites)
3947
}

0 commit comments

Comments
 (0)