Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
8d4a458
Move exec syscall filtering to NativeAccess
rjernst May 23, 2024
d648156
use var handle without offset
rjernst May 23, 2024
ffc033f
address feedback
rjernst May 24, 2024
607ea10
spotless
rjernst May 24, 2024
59c16d0
Merge branch 'main' into native/exec_sandbox
rjernst May 24, 2024
1ce8edc
try syncing job object struct explicitly
rjernst May 28, 2024
bf5cfb4
Merge branch 'main' into native/exec_sandbox
rjernst Jun 4, 2024
082c71a
fix windows to set exec sandbox state
rjernst Jun 4, 2024
4b48c16
Merge branch 'main' into native/exec_sandbox
rjernst Jun 5, 2024
9a3e867
Merge branch 'main' into native/exec_sandbox
rjernst Jun 7, 2024
75b9cbd
add debug for existing path in bwc test
rjernst Jun 7, 2024
ccbbe68
more debugging, who is opening the node lock?
rjernst Jun 8, 2024
1db6ca4
more debug
rjernst Jun 8, 2024
5cbd971
try to wait for cluster to be ready before moving versions
rjernst Jun 10, 2024
b5fbb11
Merge branch 'main' into native/exec_sandbox
rjernst Jun 10, 2024
d7cee93
another try
rjernst Jun 10, 2024
45e8a3b
Merge branch 'main' into native/exec_sandbox
rjernst Jun 11, 2024
b18e03e
Merge branch 'main' into native/exec_sandbox
rjernst Jun 11, 2024
21e13cd
Merge branch 'main' into native/exec_sandbox
rjernst Jun 18, 2024
18adbd5
Merge branch 'main' into native/exec_sandbox
rjernst Jun 19, 2024
12e2fae
Merge branch 'main' into native/exec_sandbox
rjernst Jun 20, 2024
b773880
Merge branch 'main' into native/exec_sandbox
rjernst Jun 20, 2024
d5e8578
Merge branch 'main' into native/exec_sandbox
rjernst Jul 5, 2024
b234bda
Merge branch 'main' into native/exec_sandbox
rjernst Jul 9, 2024
2762c19
remove debugging
rjernst Jul 9, 2024
8797e23
spotless
rjernst Jul 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import com.sun.jna.NativeLong;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import com.sun.jna.Structure.ByReference;
import com.sun.jna.WString;
import com.sun.jna.win32.StdCallLibrary;

Expand Down Expand Up @@ -98,6 +99,38 @@ public long Type() {
}
}

/**
* Basic limit information for a job object
*
* https://msdn.microsoft.com/en-us/library/windows/desktop/ms684147%28v=vs.85%29.aspx
*/
public static class JnaJobObjectBasicLimitInformation extends Structure implements ByReference, JobObjectBasicLimitInformation {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the corresponding classes/functions in org/elasticsearch/bootstrap/JNAKernel32Library.java can be cleaned up too (e.g. class JOBOBJECT_BASIC_LIMIT_INFORMATION)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh good catch, that entire class can be removed.

public byte[] _ignore1 = new byte[16];
public int LimitFlags;
public byte[] _ignore2 = new byte[20];
public int ActiveProcessLimit;
public byte[] _ignore3 = new byte[20];

public JnaJobObjectBasicLimitInformation() {
super(8);
}

@Override
protected List<String> getFieldOrder() {
return List.of("_ignore1", "LimitFlags", "_ignore2", "ActiveProcessLimit", "_ignore3");
}

@Override
public void setLimitFlags(int v) {
LimitFlags = v;
}

@Override
public void setActiveProcessLimit(int v) {
ActiveProcessLimit = v;
}
}

/**
* JNA adaptation of {@link ConsoleCtrlHandler}
*/
Expand Down Expand Up @@ -128,6 +161,20 @@ private interface NativeFunctions extends StdCallLibrary {
int GetShortPathNameW(WString lpszLongPath, char[] lpszShortPath, int cchBuffer);

boolean SetConsoleCtrlHandler(StdCallLibrary.StdCallCallback handler, boolean add);

Pointer CreateJobObjectW(Pointer jobAttributes, String name);

boolean AssignProcessToJobObject(Pointer job, Pointer process);

boolean QueryInformationJobObject(
Pointer job,
int infoClass,
JnaJobObjectBasicLimitInformation info,
int infoLength,
Pointer returnLength
);

boolean SetInformationJobObject(Pointer job, int infoClass, JnaJobObjectBasicLimitInformation info, int infoLength);
}

private final NativeFunctions functions;
Expand Down Expand Up @@ -197,4 +244,42 @@ public boolean SetConsoleCtrlHandler(ConsoleCtrlHandler handler, boolean add) {
consoleCtrlHandlerCallback = new NativeHandlerCallback(handler);
return functions.SetConsoleCtrlHandler(consoleCtrlHandlerCallback, true);
}

@Override
public Handle CreateJobObjectW() {
return new JnaHandle(functions.CreateJobObjectW(null, null));
}

@Override
public boolean AssignProcessToJobObject(Handle job, Handle process) {
assert job instanceof JnaHandle;
assert process instanceof JnaHandle;
var jnaJob = (JnaHandle) job;
var jnaProcess = (JnaHandle) process;
return functions.AssignProcessToJobObject(jnaJob.pointer, jnaProcess.pointer);
}

@Override
public JobObjectBasicLimitInformation newJobObjectBasicLimitInformation() {
return new JnaJobObjectBasicLimitInformation();
}

@Override
public boolean QueryInformationJobObject(Handle job, int infoClass, JobObjectBasicLimitInformation info) {
assert job instanceof JnaHandle;
assert info instanceof JnaJobObjectBasicLimitInformation;
var jnaJob = (JnaHandle) job;
var jnaInfo = (JnaJobObjectBasicLimitInformation) info;
var ret = functions.QueryInformationJobObject(jnaJob.pointer, infoClass, jnaInfo, jnaInfo.size(), null);
return ret;
}

@Override
public boolean SetInformationJobObject(Handle job, int infoClass, JobObjectBasicLimitInformation info) {
assert job instanceof JnaHandle;
assert info instanceof JnaJobObjectBasicLimitInformation;
var jnaJob = (JnaHandle) job;
var jnaInfo = (JnaJobObjectBasicLimitInformation) info;
return functions.SetInformationJobObject(jnaJob.pointer, infoClass, jnaInfo, jnaInfo.size());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

package org.elasticsearch.nativeaccess.jna;

import com.sun.jna.Library;
import com.sun.jna.Memory;
import com.sun.jna.Native;
import com.sun.jna.NativeLong;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;

import org.elasticsearch.nativeaccess.lib.LinuxCLibrary;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;

class JnaLinuxCLibrary implements LinuxCLibrary {

@Structure.FieldOrder({ "len", "filter" })
public static final class JnaSockFProg extends Structure implements Structure.ByReference, SockFProg {
public short len; // number of filters
public Pointer filter; // filters

JnaSockFProg(SockFilter filters[]) {
len = (short) filters.length;
// serialize struct sock_filter * explicitly, its less confusing than the JNA magic we would need
Memory filter = new Memory(len * 8);
ByteBuffer bbuf = filter.getByteBuffer(0, len * 8);
bbuf.order(ByteOrder.nativeOrder()); // little endian
for (SockFilter f : filters) {
bbuf.putShort(f.code());
bbuf.put(f.jt());
bbuf.put(f.jf());
bbuf.putInt(f.k());
}
this.filter = filter;
}

@Override
public long address() {
return Pointer.nativeValue(getPointer());
}
}

private interface NativeFunctions extends Library {

/**
* maps to prctl(2)
*/
int prctl(int option, NativeLong arg2, NativeLong arg3, NativeLong arg4, NativeLong arg5);

/**
* used to call seccomp(2), its too new...
* this is the only way, DON'T use it on some other architecture unless you know wtf you are doing
*/
NativeLong syscall(NativeLong number, Object... args);
}

private final NativeFunctions functions;

JnaLinuxCLibrary() {
try {
this.functions = Native.load("c", NativeFunctions.class);
} catch (UnsatisfiedLinkError e) {
throw new UnsupportedOperationException(
"seccomp unavailable: could not link methods. requires kernel 3.5+ "
+ "with CONFIG_SECCOMP and CONFIG_SECCOMP_FILTER compiled in"
);
}
}

@Override
public SockFProg newSockFProg(SockFilter[] filters) {
var prog = new JnaSockFProg(filters);
prog.write();
return prog;
}

@Override
public int prctl(int option, long arg2, long arg3, long arg4, long arg5) {
return functions.prctl(option, new NativeLong(arg2), new NativeLong(arg3), new NativeLong(arg4), new NativeLong(arg5));
}

@Override
public long syscall(long number, int operation, int flags, long address) {
return functions.syscall(new NativeLong(number), operation, flags, address).longValue();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

package org.elasticsearch.nativeaccess.jna;

import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.PointerByReference;

import org.elasticsearch.nativeaccess.lib.MacCLibrary;

class JnaMacCLibrary implements MacCLibrary {
static class JnaErrorReference implements ErrorReference {
final PointerByReference ref = new PointerByReference();

@Override
public String toString() {
return ref.getValue().getString(0);
}
}

private interface NativeFunctions extends Library {
int sandbox_init(String profile, long flags, PointerByReference errorbuf);

void sandbox_free_error(Pointer errorbuf);
}

private final NativeFunctions functions;

JnaMacCLibrary() {
this.functions = Native.load("c", NativeFunctions.class);
}

@Override
public ErrorReference newErrorReference() {
return new JnaErrorReference();
}

@Override
public int sandbox_init(String profile, long flags, ErrorReference errorbuf) {
assert errorbuf instanceof JnaErrorReference;
var jnaErrorbuf = (JnaErrorReference) errorbuf;
return functions.sandbox_init(profile, flags, jnaErrorbuf.ref);
}

@Override
public void sandbox_free_error(ErrorReference errorbuf) {
assert errorbuf instanceof JnaErrorReference;
var jnaErrorbuf = (JnaErrorReference) errorbuf;
functions.sandbox_free_error(jnaErrorbuf.ref.getValue());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

import org.elasticsearch.nativeaccess.lib.JavaLibrary;
import org.elasticsearch.nativeaccess.lib.Kernel32Library;
import org.elasticsearch.nativeaccess.lib.LinuxCLibrary;
import org.elasticsearch.nativeaccess.lib.MacCLibrary;
import org.elasticsearch.nativeaccess.lib.NativeLibrary;
import org.elasticsearch.nativeaccess.lib.NativeLibraryProvider;
import org.elasticsearch.nativeaccess.lib.PosixCLibrary;
Expand All @@ -30,6 +32,10 @@ public JnaNativeLibraryProvider() {
JnaJavaLibrary::new,
PosixCLibrary.class,
JnaPosixCLibrary::new,
LinuxCLibrary.class,
JnaLinuxCLibrary::new,
MacCLibrary.class,
JnaMacCLibrary::new,
Kernel32Library.class,
JnaKernel32Library::new,
SystemdLibrary.class,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,63 @@ public long rlim_cur() {
public long rlim_max() {
return rlim_max.longValue();
}

@Override
public void rlim_cur(long v) {
rlim_cur.setValue(v);
}

@Override
public void rlim_max(long v) {
rlim_max.setValue(v);
}
}

public static class JnaFStore extends Structure implements Structure.ByReference, FStore {

public int fst_flags = 0;
public int fst_posmode = 0;
public NativeLong fst_offset = new NativeLong(0);
public NativeLong fst_length = new NativeLong(0);
public NativeLong fst_bytesalloc = new NativeLong(0);

@Override
public void set_flags(int flags) {
this.fst_flags = flags;
}

@Override
public void set_posmode(int posmode) {
this.fst_posmode = posmode;
}

@Override
public void set_offset(long offset) {
fst_offset.setValue(offset);
}

@Override
public void set_length(long length) {
fst_length.setValue(length);
}

@Override
public long bytesalloc() {
return fst_bytesalloc.longValue();
}
}

private interface NativeFunctions extends Library {
int geteuid();

int getrlimit(int resource, JnaRLimit rlimit);

int setrlimit(int resource, JnaRLimit rlimit);

int mlockall(int flags);

int fcntl(int fd, int cmd, JnaFStore fst);

String strerror(int errno);
}

Expand All @@ -74,11 +122,30 @@ public int getrlimit(int resource, RLimit rlimit) {
return functions.getrlimit(resource, jnaRlimit);
}

@Override
public int setrlimit(int resource, RLimit rlimit) {
assert rlimit instanceof JnaRLimit;
var jnaRlimit = (JnaRLimit) rlimit;
return functions.setrlimit(resource, jnaRlimit);
}

@Override
public int mlockall(int flags) {
return functions.mlockall(flags);
}

@Override
public FStore newFStore() {
return new JnaFStore();
}

@Override
public int fcntl(int fd, int cmd, FStore fst) {
assert fst instanceof JnaFStore;
var jnaFst = (JnaFStore) fst;
return functions.fcntl(fd, cmd, jnaFst);
}

@Override
public String strerror(int errno) {
return functions.strerror(errno);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ abstract class AbstractNativeAccess implements NativeAccess {
private final JavaLibrary javaLib;
private final Zstd zstd;
protected boolean isMemoryLocked = false;
protected ExecSandboxState execSandboxState = ExecSandboxState.NONE;

protected AbstractNativeAccess(String name, NativeLibraryProvider libraryProvider) {
this.name = name;
Expand Down Expand Up @@ -53,4 +54,9 @@ public CloseableByteBuffer newBuffer(int len) {
public boolean isMemoryLocked() {
return isMemoryLocked;
}

@Override
public ExecSandboxState getExecSandboxState() {
return execSandboxState;
}
}
Loading