Skip to content

Commit 32e3eff

Browse files
authored
Fix StackCallerClassChainExtractor and respectively RuntimeHaltInterceptor, SystemExitInterceptor (#17793)
Signed-off-by: Andriy Redko <[email protected]>
1 parent 5ec96c5 commit 32e3eff

File tree

4 files changed

+22
-18
lines changed

4 files changed

+22
-18
lines changed

libs/agent-sm/agent/src/main/java/org/opensearch/javaagent/RuntimeHaltInterceptor.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
import java.lang.StackWalker.Option;
1414
import java.security.Policy;
15-
import java.util.stream.Stream;
15+
import java.util.Collection;
1616

1717
import net.bytebuddy.asm.Advice;
1818

@@ -40,7 +40,7 @@ public static void intercept(int code) throws Exception {
4040

4141
final StackWalker walker = StackWalker.getInstance(Option.RETAIN_CLASS_REFERENCE);
4242
final Class<?> caller = walker.getCallerClass();
43-
final Stream<Class<?>> chain = walker.walk(StackCallerClassChainExtractor.INSTANCE);
43+
final Collection<Class<?>> chain = walker.walk(StackCallerClassChainExtractor.INSTANCE);
4444

4545
if (AgentPolicy.isChainThatCanExit(caller, chain) == false) {
4646
throw new SecurityException("The class " + caller + " is not allowed to call Runtime::halt(" + code + ")");

libs/agent-sm/agent/src/main/java/org/opensearch/javaagent/StackCallerClassChainExtractor.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,16 @@
99
package org.opensearch.javaagent;
1010

1111
import java.lang.StackWalker.StackFrame;
12+
import java.util.Collection;
13+
import java.util.Set;
1214
import java.util.function.Function;
15+
import java.util.stream.Collectors;
1316
import java.util.stream.Stream;
1417

1518
/**
1619
* Stack Caller Class Chain Extractor
1720
*/
18-
public final class StackCallerClassChainExtractor implements Function<Stream<StackFrame>, Stream<Class<?>>> {
21+
public final class StackCallerClassChainExtractor implements Function<Stream<StackFrame>, Collection<Class<?>>> {
1922
/**
2023
* Single instance of stateless class.
2124
*/
@@ -31,12 +34,12 @@ private StackCallerClassChainExtractor() {}
3134
* @param frames stack frames
3235
*/
3336
@Override
34-
public Stream<Class<?>> apply(Stream<StackFrame> frames) {
37+
public Collection<Class<?>> apply(Stream<StackFrame> frames) {
3538
return cast(frames);
3639
}
3740

3841
@SuppressWarnings("unchecked")
39-
private static <A> Stream<A> cast(Stream<StackFrame> frames) {
40-
return (Stream<A>) frames.map(StackFrame::getDeclaringClass).filter(c -> !c.isHidden()).distinct();
42+
private static <A> Set<A> cast(Stream<StackFrame> frames) {
43+
return (Set<A>) frames.map(StackFrame::getDeclaringClass).filter(c -> !c.isHidden()).collect(Collectors.toSet());
4144
}
4245
}

libs/agent-sm/agent/src/main/java/org/opensearch/javaagent/SystemExitInterceptor.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
import java.lang.StackWalker.Option;
1414
import java.security.Policy;
15-
import java.util.stream.Stream;
15+
import java.util.Collection;
1616

1717
import net.bytebuddy.asm.Advice;
1818

@@ -40,7 +40,7 @@ public static void intercept(int code) throws Exception {
4040

4141
final StackWalker walker = StackWalker.getInstance(Option.RETAIN_CLASS_REFERENCE);
4242
final Class<?> caller = walker.getCallerClass();
43-
final Stream<Class<?>> chain = walker.walk(StackCallerClassChainExtractor.INSTANCE);
43+
final Collection<Class<?>> chain = walker.walk(StackCallerClassChainExtractor.INSTANCE);
4444

4545
if (AgentPolicy.isChainThatCanExit(caller, chain) == false) {
4646
throw new SecurityException("The class " + caller + " is not allowed to call System::exit(" + code + ")");

libs/agent-sm/bootstrap/src/main/java/org/opensearch/javaagent/bootstrap/AgentPolicy.java

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import java.security.Permission;
1414
import java.security.Policy;
1515
import java.security.ProtectionDomain;
16+
import java.util.Collection;
1617
import java.util.Collections;
1718
import java.util.List;
1819
import java.util.Set;
@@ -29,12 +30,12 @@ public class AgentPolicy {
2930
private static final Logger LOGGER = Logger.getLogger(AgentPolicy.class.getName());
3031
private static volatile Policy policy;
3132
private static volatile Set<String> trustedHosts;
32-
private static volatile BiFunction<Class<?>, Stream<Class<?>>, Boolean> classesThatCanExit;
33+
private static volatile BiFunction<Class<?>, Collection<Class<?>>, Boolean> classesThatCanExit;
3334

3435
/**
3536
* None of the classes is allowed to call {@link System#exit} or {@link Runtime#halt}
3637
*/
37-
public static final class NoneCanExit implements BiFunction<Class<?>, Stream<Class<?>>, Boolean> {
38+
public static final class NoneCanExit implements BiFunction<Class<?>, Collection<Class<?>>, Boolean> {
3839
/**
3940
* NoneCanExit
4041
*/
@@ -47,7 +48,7 @@ public NoneCanExit() {}
4748
* @return is class allowed to call {@link System#exit}, {@link Runtime#halt} or not
4849
*/
4950
@Override
50-
public Boolean apply(Class<?> caller, Stream<Class<?>> chain) {
51+
public Boolean apply(Class<?> caller, Collection<Class<?>> chain) {
5152
return true;
5253
}
5354
}
@@ -86,7 +87,7 @@ public Boolean apply(Class<?> caller, Stream<Class<?>> chain) {
8687
/**
8788
* Any caller in the chain is allowed to call {@link System#exit} or {@link Runtime#halt}
8889
*/
89-
public static final class AnyCanExit implements BiFunction<Class<?>, Stream<Class<?>>, Boolean> {
90+
public static final class AnyCanExit implements BiFunction<Class<?>, Collection<Class<?>>, Boolean> {
9091
private final String[] classesThatCanExit;
9192

9293
/**
@@ -104,15 +105,15 @@ public AnyCanExit(final String[] classesThatCanExit) {
104105
* @return is class allowed to call {@link System#exit}, {@link Runtime#halt} or not
105106
*/
106107
@Override
107-
public Boolean apply(Class<?> caller, Stream<Class<?>> chain) {
108-
return chain.anyMatch(clazz -> {
108+
public Boolean apply(Class<?> caller, Collection<Class<?>> chain) {
109+
for (final Class<?> clazz : chain) {
109110
for (final String classThatCanExit : classesThatCanExit) {
110111
if (clazz.getName().matches(classThatCanExit)) {
111112
return true;
112113
}
113114
}
114-
return false;
115-
});
115+
}
116+
return false;
116117
}
117118
}
118119

@@ -135,7 +136,7 @@ public static void setPolicy(Policy policy) {
135136
public static void setPolicy(
136137
Policy policy,
137138
final Set<String> trustedHosts,
138-
final BiFunction<Class<?>, Stream<Class<?>>, Boolean> classesThatCanExit
139+
final BiFunction<Class<?>, Collection<Class<?>>, Boolean> classesThatCanExit
139140
) {
140141
if (AgentPolicy.policy == null) {
141142
AgentPolicy.policy = policy;
@@ -187,7 +188,7 @@ public static boolean isTrustedHost(String hostname) {
187188
* @param chain chain of call classes
188189
* @return is class allowed to call {@link System#exit}, {@link Runtime#halt} or not
189190
*/
190-
public static boolean isChainThatCanExit(Class<?> caller, Stream<Class<?>> chain) {
191+
public static boolean isChainThatCanExit(Class<?> caller, Collection<Class<?>> chain) {
191192
return classesThatCanExit.apply(caller, chain);
192193
}
193194
}

0 commit comments

Comments
 (0)