Skip to content

Commit 012cf65

Browse files
committed
Test with --sun-misc-unsafe-memory-access=deny
1 parent 28cd73b commit 012cf65

File tree

15 files changed

+248
-4
lines changed

15 files changed

+248
-4
lines changed

.github/workflows/build.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ jobs:
3232
- 11
3333
- 17
3434
- 21
35+
# keeping 23 around for now because its new enough to support --sun-misc-unsafe-memory-access=deny
36+
# but old enough to support -Djava.security.manager which is used to work around an issue with
37+
# the protobuf test-only dependency
38+
- 23
3539
- 24 # renovate: datasource=java-version
3640
# Collect coverage on latest LTS
3741
include:
@@ -49,6 +53,8 @@ jobs:
4953
test-java-version: 17
5054
- os: macos-13
5155
test-java-version: 21
56+
- os: macos-13
57+
test-java-version: 23
5258
- os: macos-13
5359
test-java-version: 24 # renovate: datasource=java-version
5460
steps:
@@ -70,11 +76,13 @@ jobs:
7076

7177
- name: Set up gradle
7278
uses: gradle/actions/setup-gradle@ed408507eac070d1f99cc633dbcf757c94c7933a # v4.4.3
79+
7380
- name: Build
7481
run: >
7582
./gradlew build
7683
${{ matrix.coverage && 'jacocoTestReport' || '' }}
7784
-PtestJavaVersion=${{ matrix.test-java-version }}
85+
${{ matrix.test-java-version == 23 && '-PdenyUnsafe=true' || '' }}
7886
"-Porg.gradle.java.installations.paths=${{ steps.setup-java-test.outputs.path }}"
7987
"-Porg.gradle.java.installations.auto-download=false"
8088
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)