Skip to content

Commit 4422bad

Browse files
authored
Set coredump filter for Elasticsearch (#137300) (#137445)
When a linux process dies and the core process memory is dumped, which parts of the memory to output are controlled by the coredump filter. By default the JVM dumps anonymous memory (ie heap and direct memory) and file-backed memory (ie mmaps), and private huge pages. However, the default of dumping file-backed memory for Elasticsearch is problematic; these can be enormous, and they also aren't very useful since the indices will likely be available when investigating the crash. This commit sets the coredump filter when running on Linux to omit file-backed memory from coredumps. Although the JVM has diagnostic VM options for controlling the filter, they end up causing the filter to be inherited, which is from the server CLI, another Java process, which has the file-backed memory bits set. Instead of using the JVM options we set it via the special proc filesystem.
1 parent 3d91087 commit 4422bad

File tree

3 files changed

+75
-2
lines changed

3 files changed

+75
-2
lines changed
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the "Elastic License
4+
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
5+
* Public License v 1"; you may not use this file except in compliance with, at
6+
* your election, the "Elastic License 2.0", the "GNU Affero General Public
7+
* License v3.0 only", or the "Server Side Public License, v 1".
8+
*/
9+
10+
package org.elasticsearch.packaging.test;
11+
12+
import org.elasticsearch.packaging.util.Platforms;
13+
import org.elasticsearch.packaging.util.ProcessInfo;
14+
import org.junit.BeforeClass;
15+
16+
import java.util.List;
17+
18+
import static com.carrotsearch.randomizedtesting.RandomizedTest.assumeTrue;
19+
import static org.hamcrest.Matchers.equalTo;
20+
21+
// tests for how the linux distro interacts with the OS
22+
public class LinuxSystemTests extends PackagingTestCase {
23+
24+
@BeforeClass
25+
public static void ensureLinux() {
26+
assumeTrue(Platforms.LINUX);
27+
}
28+
29+
public void test10Install() throws Exception {
30+
install();
31+
}
32+
33+
public void test20CoredumpFilter() throws Exception {
34+
startElasticsearch();
35+
36+
// find the Elasticsearch process
37+
int esPid = -1;
38+
List<ProcessInfo> procs = ProcessInfo.getProcessInfo(sh, "java");
39+
for (ProcessInfo proc : procs) {
40+
if (proc.commandLine().contains("org.elasticsearch.bootstrap.Elasticsearch")) {
41+
esPid = proc.pid();
42+
}
43+
}
44+
if (esPid == -1) {
45+
fail("Could not find Elasticsearch process, existing processes:\n" + procs);
46+
}
47+
48+
// check the coredump filter was set correctly
49+
String coredumpFilter = sh.run("cat /proc/" + esPid + "/coredump_filter").stdout().trim();
50+
assertThat(coredumpFilter, equalTo("00000023"));
51+
}
52+
53+
}

qa/packaging/src/test/java/org/elasticsearch/packaging/util/ProcessInfo.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
* works in Linux containers. At the moment that isn't a problem, because we only publish Docker images
2323
* for Linux.
2424
*/
25-
public record ProcessInfo(int pid, int uid, int gid, String username, String group) {
25+
public record ProcessInfo(int pid, int uid, int gid, String username, String group, String commandLine) {
2626

2727
/**
2828
* Fetches process information about <code>command</code>, using <code>sh</code> to execute commands.
@@ -53,7 +53,9 @@ public static List<ProcessInfo> getProcessInfo(Shell sh, String command) {
5353
final String username = sh.run("getent passwd " + uid + " | cut -f1 -d:").stdout().trim();
5454
final String group = sh.run("getent group " + gid + " | cut -f1 -d:").stdout().trim();
5555

56-
infos.add(new ProcessInfo(pid, uid, gid, username, group));
56+
final String commandLine = sh.run("cat /proc/" + pid + "/cmdline").stdout().trim();
57+
58+
infos.add(new ProcessInfo(pid, uid, gid, username, group, commandLine));
5759
}
5860
return Collections.unmodifiableList(infos);
5961
}

server/src/main/java/org/elasticsearch/bootstrap/Elasticsearch.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,10 @@ static void initializeNatives(final Path tmpFile, final boolean mlockAll, final
484484
}
485485
}
486486

487+
if (IOUtils.LINUX) {
488+
setCoredumpFilter();
489+
}
490+
487491
// init lucene random seed. it will use /dev/urandom where available:
488492
StringHelper.randomId();
489493
}
@@ -598,6 +602,20 @@ static Map<String, Set<String>> findPluginsWithNativeAccess(Map<String, Policy>
598602
return pluginsWithNativeAccess;
599603
}
600604

605+
@SuppressForbidden(reason = "access proc filesystem")
606+
private static void setCoredumpFilter() {
607+
// The coredump filter determines which types of memory are added to core dumps. By default, Java
608+
// includes memory mapped files, bits 2 and 3. Here we disable those bits. Note that the VM
609+
// has special options to disable these, but the filter is then inherited from the parent process
610+
// which is the server CLI, which is also a JVM so it has these bits set. Thus, we set it explicitly.
611+
// See https://man7.org/linux/man-pages/man5/core.5.html for more info on the relevant bits of the filter
612+
try {
613+
Files.writeString(Path.of("/proc/self/coredump_filter"), "0x23");
614+
} catch (IOException e) {
615+
throw new RuntimeException("Could not set coredump filter", e);
616+
}
617+
}
618+
601619
// -- instance
602620

603621
private static volatile Elasticsearch INSTANCE;

0 commit comments

Comments
 (0)