diff --git a/Ghidra/Debug/Debugger-agent-gdb/src/main/java/agent/gdb/pty/linux/LinuxPty.java b/Ghidra/Debug/Debugger-agent-gdb/src/main/java/agent/gdb/pty/linux/LinuxPty.java index 562c4eadaa..fd920a1d4f 100644 --- a/Ghidra/Debug/Debugger-agent-gdb/src/main/java/agent/gdb/pty/linux/LinuxPty.java +++ b/Ghidra/Debug/Debugger-agent-gdb/src/main/java/agent/gdb/pty/linux/LinuxPty.java @@ -17,7 +17,7 @@ package agent.gdb.pty.linux; import java.io.IOException; -import com.sun.jna.Memory; +import com.sun.jna.*; import com.sun.jna.ptr.IntByReference; import agent.gdb.pty.Pty; @@ -27,6 +27,13 @@ public class LinuxPty implements Pty { static final PosixC LIB_POSIX = PosixC.INSTANCE; + static void checkErr(int result) { + if (result < 0) { + int errno = Native.getLastError(); + throw new LastErrorException("[" + errno + "] " + LIB_POSIX.strerror(errno)); + } + } + private final int aparent; private final int achild; //private final String name; @@ -40,7 +47,7 @@ public class LinuxPty implements Pty { IntByReference p = new IntByReference(); IntByReference c = new IntByReference(); Memory n = new Memory(1024); - Util.INSTANCE.openpty(p, c, n, null, null); + checkErr(Util.INSTANCE.openpty(p, c, n, null, null)); return new LinuxPty(p.getValue(), c.getValue(), n.getString(0)); } @@ -48,7 +55,6 @@ public class LinuxPty implements Pty { Msg.debug(this, "New Pty: " + name + " at (" + aparent + "," + achild + ")"); this.aparent = aparent; this.achild = achild; - //this.name = name; this.parent = new LinuxPtyParent(aparent); this.child = new LinuxPtyChild(achild, name); diff --git a/Ghidra/Debug/Debugger-agent-gdb/src/main/java/agent/gdb/pty/linux/PosixC.java b/Ghidra/Debug/Debugger-agent-gdb/src/main/java/agent/gdb/pty/linux/PosixC.java index c823029d5a..32890a55d7 100644 --- a/Ghidra/Debug/Debugger-agent-gdb/src/main/java/agent/gdb/pty/linux/PosixC.java +++ b/Ghidra/Debug/Debugger-agent-gdb/src/main/java/agent/gdb/pty/linux/PosixC.java @@ -27,6 +27,8 @@ import com.sun.jna.platform.linux.LibC; public interface PosixC extends LibC { PosixC INSTANCE = Native.load("c", PosixC.class); + String strerror(int errnum); + int close(int fd) throws LastErrorException; int read(int fd, Pointer buf, int len) throws LastErrorException; diff --git a/Ghidra/Debug/Debugger-agent-gdb/src/main/java/agent/gdb/pty/linux/Util.java b/Ghidra/Debug/Debugger-agent-gdb/src/main/java/agent/gdb/pty/linux/Util.java index 5ac94ac5f1..c8f0b44d29 100644 --- a/Ghidra/Debug/Debugger-agent-gdb/src/main/java/agent/gdb/pty/linux/Util.java +++ b/Ghidra/Debug/Debugger-agent-gdb/src/main/java/agent/gdb/pty/linux/Util.java @@ -20,20 +20,27 @@ import com.sun.jna.ptr.IntByReference; /** * The interface for linking to {@code openpty} via jna + * + *

+ * See the UNIX manual pages */ public interface Util extends Library { Util INSTANCE = Native.load("util", Util.class); /** - * See the Linux manual pages + * NOTE: We cannot use {@link LastErrorException} here, because the idiom it applies is not + * correct for errno on UNIX. See https://man7.org/linux/man-pages/man3/errno.3.html, in + * particular: * - * @param amaster (purposefully undocumented here) - * @param aslave (purposefully undocumented here) - * @param name (purposefully undocumented here) - * @param termp (purposefully undocumented here) - * @param winp (purposefully undocumented here) - * @return (purposefully undocumented here) + *

The value in errno is significant only when the return value of the call + * indicated an error (i.e., -1 from most system calls; -1 or NULL from most library functions); + * a function that succeeds is allowed to change errno.
+ * + * This actually happens on our test setup when invoking the native {@code openpty} from a + * Docker container. It returns 0, but sets errno. JNA will incorrectly interpret this as + * failure. Thus, callers to this function must check the return value and handle the error + * manually. */ - int openpty(IntByReference amaster, IntByReference aslave, Pointer name, - Pointer termp, Pointer winp) throws LastErrorException; + int openpty(IntByReference amaster, IntByReference aslave, Pointer name, Pointer termp, + Pointer winp); }