Skip to content

Commit 3055220

Browse files
committed
Merge branch 'main' into wlm/action-filter
2 parents ab441dd + cf31931 commit 3055220

File tree

35 files changed

+1145
-75
lines changed

35 files changed

+1145
-75
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
1717
- [Security Manager Replacement] Create initial Java Agent to intercept Socket::connect calls ([#17724](https://github.com/opensearch-project/OpenSearch/pull/17724))
1818
- Add ingestion management APIs for pause, resume and get ingestion state ([#17631](https://github.com/opensearch-project/OpenSearch/pull/17631))
1919
- [Security Manager Replacement] Enhance Java Agent to intercept System::exit ([#17746](https://github.com/opensearch-project/OpenSearch/pull/17746))
20+
- [Security Manager Replacement] Enhance Java Agent to intercept Runtime::halt ([#17757](https://github.com/opensearch-project/OpenSearch/pull/17757))
21+
- Support AutoExpand for SearchReplica ([#17741](https://github.com/opensearch-project/OpenSearch/pull/17741))
22+
- Implement fixed interval refresh task scheduling ([#17777](https://github.com/opensearch-project/OpenSearch/pull/17777))
2023

2124
### Changed
2225
- Migrate BC libs to their FIPS counterparts ([#14912](https://github.com/opensearch-project/OpenSearch/pull/14912))
@@ -36,6 +39,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
3639
- Bump `lycheeverse/lychee-action` from 2.3.0 to 2.4.0 ([#17731](https://github.com/opensearch-project/OpenSearch/pull/17731))
3740
- Bump `com.netflix.nebula.ospackage-base` from 11.11.1 to 11.11.2 ([#17734](https://github.com/opensearch-project/OpenSearch/pull/17734))
3841
- Bump `com.nimbusds:oauth2-oidc-sdk` from 11.21 to 11.23.1 ([#17729](https://github.com/opensearch-project/OpenSearch/pull/17729))
42+
- Bump `com.google.api.grpc:proto-google-common-protos` from 2.52.0 to 2.54.1 ([#17733](https://github.com/opensearch-project/OpenSearch/pull/17733))
3943

4044
### Changed
4145

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

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,10 @@ private static AgentBuilder createAgentBuilder(Instrumentation inst) throws Exce
6464
ClassInjector.UsingUnsafe.ofBootLoader()
6565
.inject(
6666
Map.of(
67-
new TypeDescription.ForLoadedType(StackCallerChainExtractor.class),
68-
ClassFileLocator.ForClassLoader.read(StackCallerChainExtractor.class),
67+
new TypeDescription.ForLoadedType(StackCallerProtectionDomainChainExtractor.class),
68+
ClassFileLocator.ForClassLoader.read(StackCallerProtectionDomainChainExtractor.class),
69+
new TypeDescription.ForLoadedType(StackCallerClassChainExtractor.class),
70+
ClassFileLocator.ForClassLoader.read(StackCallerClassChainExtractor.class),
6971
new TypeDescription.ForLoadedType(AgentPolicy.class),
7072
ClassFileLocator.ForClassLoader.read(AgentPolicy.class)
7173
)
@@ -83,6 +85,12 @@ private static AgentBuilder createAgentBuilder(Instrumentation inst) throws Exce
8385
(b, typeDescription, classLoader, module, pd) -> b.visit(
8486
Advice.to(SystemExitInterceptor.class).on(ElementMatchers.named("exit"))
8587
)
88+
)
89+
.type(ElementMatchers.is(java.lang.Runtime.class))
90+
.transform(
91+
(b, typeDescription, classLoader, module, pd) -> b.visit(
92+
Advice.to(RuntimeHaltInterceptor.class).on(ElementMatchers.named("halt"))
93+
)
8694
);
8795

8896
return agentBuilder;
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* The OpenSearch Contributors require contributions made to
5+
* this file be licensed under the Apache-2.0 license or a
6+
* compatible open source license.
7+
*/
8+
9+
package org.opensearch.javaagent;
10+
11+
import org.opensearch.javaagent.bootstrap.AgentPolicy;
12+
13+
import java.lang.StackWalker.Option;
14+
import java.security.Policy;
15+
import java.util.stream.Stream;
16+
17+
import net.bytebuddy.asm.Advice;
18+
19+
/**
20+
* {@link Runtime#halt} interceptor
21+
*/
22+
public class RuntimeHaltInterceptor {
23+
/**
24+
* RuntimeHaltInterceptor
25+
*/
26+
public RuntimeHaltInterceptor() {}
27+
28+
/**
29+
* Interceptor
30+
* @param code exit code
31+
* @throws Exception exceptions
32+
*/
33+
@Advice.OnMethodEnter
34+
@SuppressWarnings("removal")
35+
public static void intercept(int code) throws Exception {
36+
final Policy policy = AgentPolicy.getPolicy();
37+
if (policy == null) {
38+
return; /* noop */
39+
}
40+
41+
final StackWalker walker = StackWalker.getInstance(Option.RETAIN_CLASS_REFERENCE);
42+
final Class<?> caller = walker.getCallerClass();
43+
final Stream<Class<?>> chain = walker.walk(StackCallerClassChainExtractor.INSTANCE);
44+
45+
if (AgentPolicy.isChainThatCanExit(caller, chain) == false) {
46+
throw new SecurityException("The class " + caller + " is not allowed to call Runtime::halt(" + code + ")");
47+
}
48+
}
49+
}

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
import java.net.UnixDomainSocketAddress;
1919
import java.security.Policy;
2020
import java.security.ProtectionDomain;
21-
import java.util.List;
21+
import java.util.stream.Stream;
2222

2323
import net.bytebuddy.asm.Advice;
2424
import net.bytebuddy.asm.Advice.Origin;
@@ -47,26 +47,26 @@ public static void intercept(@Advice.AllArguments Object[] args, @Origin Method
4747
}
4848

4949
final StackWalker walker = StackWalker.getInstance(Option.RETAIN_CLASS_REFERENCE);
50-
final List<ProtectionDomain> callers = walker.walk(new StackCallerChainExtractor());
50+
final Stream<ProtectionDomain> callers = walker.walk(StackCallerProtectionDomainChainExtractor.INSTANCE);
5151

5252
if (args[0] instanceof InetSocketAddress address) {
5353
if (!AgentPolicy.isTrustedHost(address.getHostString())) {
5454
final String host = address.getHostString() + ":" + address.getPort();
5555

5656
final SocketPermission permission = new SocketPermission(host, "connect,resolve");
57-
for (final ProtectionDomain domain : callers) {
57+
callers.forEach(domain -> {
5858
if (!policy.implies(domain, permission)) {
5959
throw new SecurityException("Denied access to: " + host + ", domain " + domain);
6060
}
61-
}
61+
});
6262
}
6363
} else if (args[0] instanceof UnixDomainSocketAddress address) {
6464
final NetPermission permission = new NetPermission("accessUnixDomainSocket");
65-
for (final ProtectionDomain domain : callers) {
65+
callers.forEach(domain -> {
6666
if (!policy.implies(domain, permission)) {
6767
throw new SecurityException("Denied access to: " + address + ", domain " + domain);
6868
}
69-
}
69+
});
7070
}
7171
}
7272
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* The OpenSearch Contributors require contributions made to
5+
* this file be licensed under the Apache-2.0 license or a
6+
* compatible open source license.
7+
*/
8+
9+
package org.opensearch.javaagent;
10+
11+
import java.lang.StackWalker.StackFrame;
12+
import java.util.function.Function;
13+
import java.util.stream.Stream;
14+
15+
/**
16+
* Stack Caller Class Chain Extractor
17+
*/
18+
public final class StackCallerClassChainExtractor implements Function<Stream<StackFrame>, Stream<Class<?>>> {
19+
/**
20+
* Single instance of stateless class.
21+
*/
22+
public static final StackCallerClassChainExtractor INSTANCE = new StackCallerClassChainExtractor();
23+
24+
/**
25+
* Constructor
26+
*/
27+
private StackCallerClassChainExtractor() {}
28+
29+
/**
30+
* Folds the stack
31+
* @param frames stack frames
32+
*/
33+
@Override
34+
public Stream<Class<?>> apply(Stream<StackFrame> frames) {
35+
return cast(frames);
36+
}
37+
38+
@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();
41+
}
42+
}

libs/agent-sm/agent/src/main/java/org/opensearch/javaagent/StackCallerChainExtractor.java renamed to libs/agent-sm/agent/src/main/java/org/opensearch/javaagent/StackCallerProtectionDomainChainExtractor.java

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,30 +10,32 @@
1010

1111
import java.lang.StackWalker.StackFrame;
1212
import java.security.ProtectionDomain;
13-
import java.util.List;
1413
import java.util.function.Function;
15-
import java.util.stream.Collectors;
1614
import java.util.stream.Stream;
1715

1816
/**
1917
* Stack Caller Chain Extractor
2018
*/
21-
public final class StackCallerChainExtractor implements Function<Stream<StackFrame>, List<ProtectionDomain>> {
19+
public final class StackCallerProtectionDomainChainExtractor implements Function<Stream<StackFrame>, Stream<ProtectionDomain>> {
20+
/**
21+
* Single instance of stateless class.
22+
*/
23+
public static final StackCallerProtectionDomainChainExtractor INSTANCE = new StackCallerProtectionDomainChainExtractor();
24+
2225
/**
2326
* Constructor
2427
*/
25-
public StackCallerChainExtractor() {}
28+
private StackCallerProtectionDomainChainExtractor() {}
2629

2730
/**
2831
* Folds the stack
2932
* @param frames stack frames
3033
*/
3134
@Override
32-
public List<ProtectionDomain> apply(Stream<StackFrame> frames) {
35+
public Stream<ProtectionDomain> apply(Stream<StackFrame> frames) {
3336
return frames.map(StackFrame::getDeclaringClass)
3437
.map(Class::getProtectionDomain)
3538
.filter(pd -> pd.getCodeSource() != null) /* JDK */
36-
.distinct()
37-
.collect(Collectors.toList());
39+
.distinct();
3840
}
3941
}

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

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
import org.opensearch.javaagent.bootstrap.AgentPolicy;
1212

1313
import java.lang.StackWalker.Option;
14+
import java.security.Policy;
15+
import java.util.stream.Stream;
1416

1517
import net.bytebuddy.asm.Advice;
1618

@@ -29,11 +31,18 @@ public SystemExitInterceptor() {}
2931
* @throws Exception exceptions
3032
*/
3133
@Advice.OnMethodEnter()
34+
@SuppressWarnings("removal")
3235
public static void intercept(int code) throws Exception {
36+
final Policy policy = AgentPolicy.getPolicy();
37+
if (policy == null) {
38+
return; /* noop */
39+
}
40+
3341
final StackWalker walker = StackWalker.getInstance(Option.RETAIN_CLASS_REFERENCE);
3442
final Class<?> caller = walker.getCallerClass();
43+
final Stream<Class<?>> chain = walker.walk(StackCallerClassChainExtractor.INSTANCE);
3544

36-
if (!AgentPolicy.isClassThatCanExit(caller.getName())) {
45+
if (AgentPolicy.isChainThatCanExit(caller, chain) == false) {
3746
throw new SecurityException("The class " + caller + " is not allowed to call System::exit(" + code + ")");
3847
}
3948
}
Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,21 @@
1515
import java.security.Policy;
1616
import java.util.Set;
1717

18-
public class SystemExitInterceptorTests {
18+
public class AgentTests {
1919
@SuppressWarnings("removal")
2020
@BeforeClass
2121
public static void setUp() {
2222
AgentPolicy.setPolicy(new Policy() {
23-
}, Set.of(), new String[] { "worker.org.gradle.process.internal.worker.GradleWorkerMain" });
23+
}, Set.of(), (caller, chain) -> caller.getName().equalsIgnoreCase("worker.org.gradle.process.internal.worker.GradleWorkerMain"));
2424
}
2525

2626
@Test(expected = SecurityException.class)
2727
public void testSystemExitIsForbidden() {
2828
System.exit(0);
2929
}
30+
31+
@Test(expected = SecurityException.class)
32+
public void testRuntimeHaltIsForbidden() {
33+
Runtime.getRuntime().halt(0);
34+
}
3035
}

0 commit comments

Comments
 (0)