diff --git a/assembly/pom.xml b/assembly/pom.xml index 9656989..954ba88 100644 --- a/assembly/pom.xml +++ b/assembly/pom.xml @@ -26,6 +26,12 @@ org.ps5jb xlet ${xlet.version} + + + * + * + + diff --git a/sdk/src/main/java/org/ps5jb/sdk/core/AbstractPointer.java b/sdk/src/main/java/org/ps5jb/sdk/core/AbstractPointer.java new file mode 100644 index 0000000..a9a5c26 --- /dev/null +++ b/sdk/src/main/java/org/ps5jb/sdk/core/AbstractPointer.java @@ -0,0 +1,386 @@ +package org.ps5jb.sdk.core; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.nio.charset.Charset; + +/** + * Root parent for any class that implements a pointer to a memory. + */ +public abstract class AbstractPointer { + /** + * Wrap the given pointer in a non-null check. Returns the same pointer if it is not NULL. + * + * @param pointer Pointer to verify. + * @param errorMessage Error message assigned to the exception if the pointer is NULL. + * @return Same pointer value if it is not NULL. + * @throws NullPointerException If the input pointer is NULL or points to the address 0. + */ + public static AbstractPointer nonNull(AbstractPointer pointer, String errorMessage) { + if (pointer == null || pointer.addr() == 0) { + throw new NullPointerException(errorMessage); + } + return pointer; + } + + /** + * Check that the pointer operation will result in an overflow. + * + * @param pointer Pointer to verify. + * @param offset Offset at which the pointer operation is started. + * @param size Size of the pointer operation. + * @throws IndexOutOfBoundsException If the operation is out of bounds. + */ + public static void overflow(AbstractPointer pointer, long offset, long size) { + // All overflow checks are disabled when size is unknown + if (pointer.size != null) { + if (offset < 0) { + throw new IndexOutOfBoundsException(Long.toString(offset)); + } + + if (((offset + size) > pointer.size.longValue())) { + throw new IndexOutOfBoundsException(Long.toString(offset + size)); + } + } + } + + /** Native memory address pointed to by this instance. */ + protected long addr; + + /** Size of the memory pointed to by this instance. May be null if the size is unknown. */ + protected Long size; + + /** + * Constructor of a pointer without a known size. + * + * @param addr Memory address of the pointer. + */ + protected AbstractPointer(long addr) { + this(addr, null); + } + + /** + * Constructor of a pointer where the size is known. + * + * @param addr Memory address of the pointer. + * @param size Size of the memory. + */ + protected AbstractPointer(long addr, Long size) { + this.addr = addr; + this.size = size; + } + + /** + * Read 1 byte at the specified offset from the pointer. + * + * @param offset Offset relative to {@link #addr}. + * @return Value read from the memory. + */ + public abstract byte read1(long offset); + + /** + * Read 1 byte from the address pointed to by this pointer instance. + * + * @return Value read from the memory. + */ + public byte read1() { + return read1(0); + } + + /** + * Read 2 bytes at the specified offset from the pointer. + * + * @param offset Offset relative to {@link #addr}. + * @return Value read from the memory. + */ + public abstract short read2(long offset); + + /** + * Read 2 bytes from the address pointed to by this pointer instance. + * + * @return Value read from the memory. + */ + public short read2() { + return read2(0); + } + + /** + * Read 4 bytes at the specified offset from the pointer. + * + * @param offset Offset relative to {@link #addr}. + * @return Value read from the memory. + */ + public abstract int read4(long offset); + + /** + * Read 4 bytes from the address pointed to by this pointer instance. + * + * @return Value read from the memory. + */ + public int read4() { + return read4(0); + } + + /** + * Read 8 bytes at the specified offset from the pointer. + * + * @param offset Offset relative to {@link #addr}. + * @return Value read from the memory. + */ + public abstract long read8(long offset); + + /** + * Read 8 bytes from the address pointed to by this pointer instance. + * + * @return Value read from the memory. + */ + public long read8() { + return read8(0); + } + + /** + * Read the given number of bytes from the address pointed to by this pointer instance. + * + * @param size Number of bytes to read. + * @return Value read from the memory as an array of bytes. + */ + public byte[] read(int size) { + byte[] result = new byte[size]; + read(0, result, 0, size); + return result; + } + + /** + * Read the given number of bytes at the specified offset from the pointer. + * + * @param offset Offset relative to {@link #addr}. + * @param value Buffer to read the value into. + * @param valueOffset Offset in the buffer where to place the read value. + * @param size Number of bytes to read. + * @throws IndexOutOfBoundsException If the buffer is not large enough to hold the value + * of the specified size. + */ + public void read(long offset, byte[] value, int valueOffset, int size) { + // TODO: This can be implemented more efficiently + for (int i = 0; i < size; ++i) { + value[valueOffset + i] = read1(offset + i); + } + } + + /** + * Read the data at the specified offset from the pointer assuming it is a native + * null-terminated string. + * + * @param offset Offset relative to {@link #addr}. + * @param maxLength Maximum number of bytes to read. If null, + * the memory will be read until the null character is encountered. + * @param charset Charset to use to convert the native string into a Java + * string. + * @return Value of the memory as a Java string. + * @throws SdkRuntimeException If the string could not be read, for example + * if the bytes cannot be converted to the target charset. + */ + public String readString(long offset, Integer maxLength, String charset) { + try { + ByteArrayOutputStream buf = new ByteArrayOutputStream(); + try { + long curSize = 0; + byte c = read1(offset); + while (c != 0 && (maxLength == null || maxLength.intValue() > curSize)) { + buf.write(c); + ++curSize; + c = read1(offset + curSize); + } + } finally { + buf.close(); + } + return buf.toString(charset); + } catch (IOException e) { + throw new SdkRuntimeException(e); + } + } + + /** + * Read the current value of the pointer assuming the data is a native + * null-terminated string. The bytes in the native memory are converted to + * Java string using the system default charset. + * + * @param maxLength Maximum number of bytes to read. If null, + * the memory will be read until the null character is encountered. + * @return Value of the memory as a Java string. + */ + public String readString(Integer maxLength) { + return readString(0, maxLength, Charset.defaultCharset().name()); + } + + /** + * Write 1 byte at the specified offset from the pointer. + * + * @param offset Offset relative to {@link #addr}. + * @param value Value to write. + */ + public abstract void write1(long offset, byte value); + + /** + * Write 1 byte to the address pointed to by this pointer instance. + * + * @param value Value to write. + */ + public void write1(byte value) { + write1(0, value); + } + + /** + * Write 2 bytes at the specified offset from the pointer. + * + * @param offset Offset relative to {@link #addr}. + * @param value Value to write. + */ + public abstract void write2(long offset, short value); + + /** + * Write 2 bytes to the address pointed to by this pointer instance. + * + * @param value Value to write. + */ + public void write2(short value) { + write2(0, value); + } + + /** + * Write 4 bytes at the specified offset from the pointer. + * + * @param offset Offset relative to {@link #addr}. + * @param value Value to write. + */ + public abstract void write4(long offset, int value); + + /** + * Write 4 bytes to the address pointed to by this pointer instance. + * + * @param value Value to write. + */ + public void write4(int value) { + write4(0, value); + } + + /** + * Write 8 bytes at the specified offset from the pointer. + * + * @param offset Offset relative to {@link #addr}. + * @param value Value to write. + */ + public abstract void write8(long offset, long value); + + /** + * Write 8 bytes to the address pointed to by this pointer instance. + * + * @param value Value to write. + */ + public void write8(long value) { + write8(0, value); + } + + /** + * Write the given number of bytes to the address pointed to by this pointer instance. + * + * @param value Value to write. + */ + public void write(byte[] value) { + this.write(0, value, 0, value.length); + } + + /** + * Write the given number of bytes at the specified offset from the pointer. + * + * @param offset Offset relative to {@link #addr}. + * @param value Buffer to write. + * @param valueOffset Offset in the buffer from which to start writing. + * @param count Number of bytes to write. + * @throws IndexOutOfBoundsException If the buffer or the native memory + * are not large enough for the given values of offset, + * valueOffset and count. + */ + public void write(long offset, byte[] value, int valueOffset, int count) { + // TODO: This can be implemented more efficiently + for (int i = 0; i < count - valueOffset; ++i) { + write1(this.addr + offset + i, value[valueOffset + i]); + } + } + + /** + * Write a given Java string at the specified offset from the pointer as + * a native null-terminated string. + * + * @param offset Offset relative to {@link #addr}. + * @param string String value to write. + * @param charset Charset to use to convert the native string into a Java + * string. + * @throws SdkRuntimeException If the string could not be written, for example + * if the bytes cannot be converted to the target charset. + * @throws IndexOutOfBoundsException If the write beyond the pointer size occurs. + */ + public void writeString(long offset, String string, String charset) { + byte[] stringBuffer; + try { + stringBuffer = string.getBytes(charset); + } catch (UnsupportedEncodingException e) { + throw new SdkRuntimeException(e); + } + + write(offset, stringBuffer, 0, stringBuffer.length); + write1(offset + stringBuffer.length, (byte) 0); + } + + public void writeString(String string) { + writeString(0, string, Charset.defaultCharset().name()); + } + + /** + * Get the native memory address of this pointer. + * + * @return Native memory address of this pointer. + */ + public long addr() { + return this.addr; + } + + /** + * Get the size of the allocated native memory pointed to by this instance. + * + * @return Size of the memory pointed to by this pointer. May be null if the size is unknown. + */ + public Long size() { + return this.size; + } + + /** + * Compares the address of this pointer with the address of another pointer. + * Note that size does not play a role in equality of two pointers. + * + * @param obj Other pointer to compare this pointer to. + * If this object is not a pointer, the comparison returns false. + * @return True if obj is a pointer and its address is the same + * as this instance's address. + */ + @Override + public boolean equals(Object obj) { + boolean result = false; + if (obj instanceof AbstractPointer) { + // Size is not considered when evaluating equality + result = ((AbstractPointer) obj).addr == this.addr; + } + return result; + } + + /** + * Computes a hashcode for this pointer. + * + * @return This pointer's hashcode. + */ + @Override + public int hashCode() { + return (new Long(this.addr)).hashCode(); + } +} diff --git a/sdk/src/main/java/org/ps5jb/sdk/core/Pointer.java b/sdk/src/main/java/org/ps5jb/sdk/core/Pointer.java index a837a3b..e04f986 100644 --- a/sdk/src/main/java/org/ps5jb/sdk/core/Pointer.java +++ b/sdk/src/main/java/org/ps5jb/sdk/core/Pointer.java @@ -1,7 +1,5 @@ package org.ps5jb.sdk.core; -import java.io.ByteArrayOutputStream; -import java.io.IOException; import java.io.UnsupportedEncodingException; import java.lang.reflect.InvocationTargetException; import java.nio.charset.Charset; @@ -10,9 +8,9 @@ import jdk.internal.misc.Unsafe; /** - * Abstraction over memory pointer operations. + * Abstraction over memory pointer operations in user-space. */ -public class Pointer { +public class Pointer extends AbstractPointer { /** * Helper class to obtain an instance of Unsafe in a thread-safe manner. */ @@ -145,42 +143,6 @@ static Pointer addrOf(Object object) { return Pointer.valueOf(getUnsafe().getLong(val, getLongValueOffset())); } - /** - * Wrap the given pointer in a non-null check. Returns the same pointer if it is not NULL. - * - * @param pointer Pointer to verify. - * @param errorMessage Error message assigned to the exception if the pointer is NULL. - * @return Same pointer value if it is not NULL. - * @throws NullPointerException If the input pointer is NULL or points to the address 0. - */ - public static Pointer nonNull(Pointer pointer, String errorMessage) { - if (pointer == null || pointer.addr() == 0) { - throw new NullPointerException(errorMessage); - } - return pointer; - } - - /** - * Check that the pointer operation will result in an overflow. - * - * @param pointer Pointer to verify. - * @param offset Offset at which the pointer operation is started. - * @param size Size of the pointer operation. - * @throws IndexOutOfBoundsException If the operation is out of bounds. - */ - public static void overflow(Pointer pointer, long offset, long size) { - // All overflow checks are disabled when size is unknown - if (pointer.size != null) { - if (offset < 0) { - throw new IndexOutOfBoundsException(Long.toString(offset)); - } - - if (((offset + size) > pointer.size.longValue())) { - throw new IndexOutOfBoundsException(Long.toString(offset + size)); - } - } - } - /** * Returns a pointer instance equivalent to the given native memory address. * @@ -194,322 +156,82 @@ public static Pointer valueOf(long addr) { /** Static constant for NULL pointer. */ public static final Pointer NULL = new Pointer(0); - /** Native memory address pointed to by this instance. */ - private long addr; - - /** Size of the memory pointed to by this instance. May be null if the size is unknown. */ - private Long size; - - /** - * Constructor of a pointer without a known size. - * - * @param addr Memory address of the pointer. - */ public Pointer(long addr) { - this(addr, null); + super(addr); } - /** - * Constructor of a pointer where the size is known. - * - * @param addr Memory address of the pointer. - * @param size Size of the memory. - */ public Pointer(long addr, Long size) { - this.addr = addr; - this.size = size; + super(addr, size); } - /** - * Read 1 byte at the specified offset from the pointer. - * - * @param offset Offset relative to {@link #addr}. - * @return Value read from the memory. - */ + @Override public byte read1(long offset) { overflow(this, offset, 1); return getUnsafe().getByte(this.addr + offset); } - /** - * Read 1 byte from the address pointed to by this pointer instance. - * - * @return Value read from the memory. - */ - public byte read1() { - return read1(0); - } - - /** - * Read 2 bytes at the specified offset from the pointer. - * - * @param offset Offset relative to {@link #addr}. - * @return Value read from the memory. - */ + @Override public short read2(long offset) { overflow(this, offset, 2); return getUnsafe().getShort(this.addr + offset); } - /** - * Read 2 bytes from the address pointed to by this pointer instance. - * - * @return Value read from the memory. - */ - public short read2() { - return read2(0); - } - - /** - * Read 4 bytes at the specified offset from the pointer. - * - * @param offset Offset relative to {@link #addr}. - * @return Value read from the memory. - */ + @Override public int read4(long offset) { overflow(this, offset, 4); return getUnsafe().getInt(this.addr + offset); } - /** - * Read 4 bytes from the address pointed to by this pointer instance. - * - * @return Value read from the memory. - */ - public int read4() { - return read4(0); - } - - /** - * Read 8 bytes at the specified offset from the pointer. - * - * @param offset Offset relative to {@link #addr}. - * @return Value read from the memory. - */ + @Override public long read8(long offset) { overflow(this, offset, 8); return getUnsafe().getLong(this.addr + offset); } - /** - * Read 8 bytes from the address pointed to by this pointer instance. - * - * @return Value read from the memory. - */ - public long read8() { - return read8(0); - } - - /** - * Read the given number of bytes from the address pointed to by this pointer instance. - * - * @param size Number of bytes to read. - * @return Value read from the memory as an array of bytes. - */ - public byte[] read(int size) { - byte[] result = new byte[size]; - read(0, result, 0, size); - return result; - } - - /** - * Read the given number of bytes at the specified offset from the pointer. - * - * @param offset Offset relative to {@link #addr}. - * @param value Buffer to read the value into. - * @param valueOffset Offset in the buffer where to place the read value. - * @param size Number of bytes to read. - * @throws IndexOutOfBoundsException If the buffer is not large enough to hold the value - * of the specified size. - */ + @Override public void read(long offset, byte[] value, int valueOffset, int size) { overflow(this, offset, size); - for (int i = 0; i < size; ++i) { - value[valueOffset + i] = read1(offset + i); - } - } - /** - * Read the data at the specified offset from the pointer assuming it is a native - * null-terminated string. - * - * @param offset Offset relative to {@link #addr}. - * @param maxLength Maximum number of bytes to read. If null, - * the memory will be read until the null character is encountered. - * @param charset Charset to use to convert the native string into a Java - * string. - * @return Value of the memory as a Java string. - * @throws SdkRuntimeException If the string could not be read, for example - * if the bytes cannot be converted to the target charset. - */ - public String readString(long offset, Integer maxLength, String charset) { - try { - ByteArrayOutputStream buf = new ByteArrayOutputStream(); - try { - long curSize = 0; - byte c = read1(offset); - while (c != 0 && (maxLength == null || maxLength.intValue() > curSize)) { - buf.write(c); - ++curSize; - c = read1(offset + curSize); - } - } finally { - buf.close(); - } - return buf.toString(charset); - } catch (IOException e) { - throw new SdkRuntimeException(e); + // TODO: This can be implemented more efficiently + for (int i = 0; i < size; ++i) { + value[valueOffset + i] = getUnsafe().getByte(this.addr + offset + i); } } - /** - * Read the current value of the pointer assuming the data is a native - * null-terminated string. The bytes in the native memory are converted to - * Java string using the system default charset. - * - * @param maxLength Maximum number of bytes to read. If null, - * the memory will be read until the null character is encountered. - * @return Value of the memory as a Java string. - */ - public String readString(Integer maxLength) { - return readString(0, maxLength, Charset.defaultCharset().name()); - } - - /** - * Write 1 byte at the specified offset from the pointer. - * - * @param offset Offset relative to {@link #addr}. - * @param value Value to write. - */ + @Override public void write1(long offset, byte value) { overflow(this, offset, 1); getUnsafe().putByte(this.addr + offset, value); } - /** - * Write 1 byte to the address pointed to by this pointer instance. - * - * @param value Value to write. - */ - public void write1(byte value) { - write1(0, value); - } - - /** - * Write 2 bytes at the specified offset from the pointer. - * - * @param offset Offset relative to {@link #addr}. - * @param value Value to write. - */ + @Override public void write2(long offset, short value) { overflow(this, offset, 2); getUnsafe().putShort(this.addr + offset, value); } - /** - * Write 2 bytes to the address pointed to by this pointer instance. - * - * @param value Value to write. - */ - public void write2(short value) { - write2(0, value); - } - - /** - * Write 4 bytes at the specified offset from the pointer. - * - * @param offset Offset relative to {@link #addr}. - * @param value Value to write. - */ + @Override public void write4(long offset, int value) { overflow(this, offset, 4); getUnsafe().putInt(this.addr + offset, value); } - /** - * Write 4 bytes to the address pointed to by this pointer instance. - * - * @param value Value to write. - */ - public void write4(int value) { - write4(0, value); - } - - /** - * Write 8 bytes at the specified offset from the pointer. - * - * @param offset Offset relative to {@link #addr}. - * @param value Value to write. - */ + @Override public void write8(long offset, long value) { overflow(this, offset, 8); getUnsafe().putLong(this.addr + offset, value); } - /** - * Write 8 bytes to the address pointed to by this pointer instance. - * - * @param value Value to write. - */ - public void write8(long value) { - write8(0, value); - } - - /** - * Write the given number of bytes to the address pointed to by this pointer instance. - * - * @param value Value to write. - */ - public void write(byte[] value) { - this.write(0, value, 0, value.length); - } - - /** - * Write the given number of bytes at the specified offset from the pointer. - * - * @param offset Offset relative to {@link #addr}. - * @param value Buffer to write. - * @param valueOffset Offset in the buffer from which to start writing. - * @param count Number of bytes to write. - * @throws IndexOutOfBoundsException If the buffer or the native memory - * are not large enough for the given values of offset, - * valueOffset and count. - */ + @Override public void write(long offset, byte[] value, int valueOffset, int count) { overflow(this, offset, count); + + // TODO: This can be implemented more efficiently for (int i = 0; i < count - valueOffset; ++i) { getUnsafe().putByte(this.addr + offset + i, value[valueOffset + i]); } } - /** - * Write a given Java string at the specified offset from the pointer as - * a native null-terminated string. - * - * @param offset Offset relative to {@link #addr}. - * @param string String value to write. - * @param charset Charset to use to convert the native string into a Java - * string. - * @throws SdkRuntimeException If the string could not be written, for example - * if the bytes cannot be converted to the target charset. - * @throws IndexOutOfBoundsException If the write beyond the pointer size occurs. - */ - public void writeString(long offset, String string, String charset) { - byte[] stringBuffer; - try { - stringBuffer = string.getBytes(charset); - } catch (UnsupportedEncodingException e) { - throw new SdkRuntimeException(e); - } - - write(offset, stringBuffer, 0, stringBuffer.length); - write1(offset + stringBuffer.length, (byte) 0); - } - - public void writeString(String string) { - writeString(0, string, Charset.defaultCharset().name()); - } - /** * Copies values in native memory associated with this pointer to a pointer specified by dest. * @@ -536,24 +258,6 @@ public void free() { this.size = null; } - /** - * Get the native memory address of this pointer. - * - * @return Native memory address of this pointer. - */ - public long addr() { - return this.addr; - } - - /** - * Get the size of the allocated native memory pointed to by this instance. - * - * @return Size of the memory pointed to by this pointer. May be null if the size is unknown. - */ - public Long size() { - return this.size; - } - /** * Increment the pointer by a given offset. The delta parameter may be negative. * @@ -565,33 +269,4 @@ public Pointer inc(long delta) { // Size is intentionally left unknown return Pointer.valueOf(this.addr + delta); } - - /** - * Compares the address of this pointer with the address of another pointer. - * Note that size does not play a role in equality of two pointers. - * - * @param obj Other pointer to compare this pointer to. - * If this object is not a pointer, the comparison returns false. - * @return True if obj is a pointer and its address is the same - * as this instance's address. - */ - @Override - public boolean equals(Object obj) { - boolean result = false; - if (obj instanceof Pointer) { - // Size is not considered when evaluating equality - result = ((Pointer) obj).addr == this.addr; - } - return result; - } - - /** - * Computes a hashcode for this pointer. - * - * @return This pointer's hashcode. - */ - @Override - public int hashCode() { - return (new Long(this.addr)).hashCode(); - } } diff --git a/sdk/src/main/java/org/ps5jb/sdk/core/kernel/KernelAccessor.java b/sdk/src/main/java/org/ps5jb/sdk/core/kernel/KernelAccessor.java new file mode 100644 index 0000000..85b80e5 --- /dev/null +++ b/sdk/src/main/java/org/ps5jb/sdk/core/kernel/KernelAccessor.java @@ -0,0 +1,17 @@ +package org.ps5jb.sdk.core.kernel; + +/** + * Interface for accessing Kernel memory. Various exploits able to + * do so should implement this interface. + */ +public interface KernelAccessor { + byte read1(long kernelAddress); + short read2(long kernelAddress); + int read4(long kernelAddress); + long read8(long kernelAddress); + + void write1(long kernelAddress, byte value); + void write2(long kernelAddress, short value); + void write4(long kernelAddress, int value); + void write8(long kernelAddress, long value); +} diff --git a/sdk/src/main/java/org/ps5jb/sdk/core/kernel/KernelAccessorIPv6.java b/sdk/src/main/java/org/ps5jb/sdk/core/kernel/KernelAccessorIPv6.java new file mode 100644 index 0000000..7e72157 --- /dev/null +++ b/sdk/src/main/java/org/ps5jb/sdk/core/kernel/KernelAccessorIPv6.java @@ -0,0 +1,262 @@ +package org.ps5jb.sdk.core.kernel; + +import org.ps5jb.sdk.core.Pointer; +import org.ps5jb.sdk.core.SdkException; +import org.ps5jb.sdk.core.SdkRuntimeException; +import org.ps5jb.sdk.include.UniStd; +import org.ps5jb.sdk.include.inet.in.ProtocolType; +import org.ps5jb.sdk.include.netinet6.in6.OptionIPv6; +import org.ps5jb.sdk.include.sys.Socket; +import org.ps5jb.sdk.include.sys.socket.AddressFamilyType; +import org.ps5jb.sdk.include.sys.socket.SocketType; +import org.ps5jb.sdk.lib.LibKernel; + +/** + * Kernel read/write accessor which uses IPv6 sockets. + * Implementation inspired from SpecterDev. + * Requires an existing kernel accessor on creation. + */ +public class KernelAccessorIPv6 implements KernelAccessor { + private final Pointer master_target_buffer; + private final Pointer slave_buffer; + private final Pointer pipemap_buffer; + private final Pointer krw_qword_store; + + private final int master_sock; + private final int victim_sock; + + private final LibKernel libKernel; + private final Socket socket; + + private final int[] pipe_fd; + private final KernelPointer pipe_addr; + + /** + * Constructor for kernel IPv6 accessor. + * + * @param ofilesAddress Address of "fdt_ofiles" structure from the "proc" structure of the current process. + * @throws SdkException If an error occurs during accessor creation. + */ + public KernelAccessorIPv6(KernelPointer ofilesAddress) throws SdkException { + this.libKernel = new LibKernel(); + this.socket = new Socket(this.libKernel); + + final long sock_opt_size = 0x14; + master_target_buffer = Pointer.calloc(sock_opt_size); + slave_buffer = Pointer.calloc(sock_opt_size); + pipemap_buffer = Pointer.calloc(sock_opt_size); + krw_qword_store = Pointer.calloc(0x8); + + master_sock = socket.createSocket(AddressFamilyType.AF_INET6, SocketType.SOCK_DGRAM, ProtocolType.IPPROTO_UDP); + victim_sock = socket.createSocket(AddressFamilyType.AF_INET6, SocketType.SOCK_DGRAM, ProtocolType.IPPROTO_UDP); + socket.setSocketOptionsIPv6(master_sock, OptionIPv6.IPV6_PKTINFO, master_target_buffer); + socket.setSocketOptionsIPv6(victim_sock, OptionIPv6.IPV6_PKTINFO, slave_buffer); + + // Find sockets and get pktopts-based r/w + KernelPointer master_sock_filedescent_addr = ofilesAddress.inc(master_sock * 0x30L); + KernelPointer victim_sock_filedescent_addr = ofilesAddress.inc(victim_sock * 0x30L); + + KernelPointer master_sock_file_addr = KernelPointer.valueOf(master_sock_filedescent_addr.read8()); + KernelPointer victim_sock_file_addr = KernelPointer.valueOf(victim_sock_filedescent_addr.read8()); + + KernelPointer master_sock_socket_addr = KernelPointer.valueOf(master_sock_file_addr.read8()); + KernelPointer victim_sock_socket_addr = KernelPointer.valueOf(victim_sock_file_addr.read8()); + + KernelPointer master_pcb = KernelPointer.valueOf(master_sock_socket_addr.read8(0x18)); + KernelPointer slave_pcb = KernelPointer.valueOf(victim_sock_socket_addr.read8(0x18)); + + KernelPointer master_pktopts = KernelPointer.valueOf(master_pcb.read8(0x120)); + KernelPointer slave_pktopts = KernelPointer.valueOf(slave_pcb.read8(0x120)); + + master_pktopts.write8(0x10, slave_pktopts.inc(0x10).addr()); + + // Create pipe pair + final UniStd uniStd = new UniStd(this.libKernel); + pipe_fd = uniStd.pipe(); + int pipe_read = pipe_fd[0]; + KernelPointer pipe_filedescent = ofilesAddress.inc(pipe_read * 0x30L); + KernelPointer pipe_file = KernelPointer.valueOf(ipv6_kread8(pipe_filedescent)); + pipe_addr = KernelPointer.valueOf(ipv6_kread8(pipe_file)); + + // Increase refcounts on socket fds which we corrupt + inc_socket_refcount(master_sock, ofilesAddress); + inc_socket_refcount(victim_sock, ofilesAddress); + } + + public int getMasterSock() { + return master_sock; + } + + public int getVictimSock() { + return victim_sock; + } + + /** + * Frees resources in use by this accessor. After calling this method + * this instance should not be used. + */ + public synchronized void free() { + if (master_target_buffer != null) { + master_target_buffer.free(); + } + if (slave_buffer != null) { + slave_buffer.free(); + } + if (pipemap_buffer != null) { + pipemap_buffer.free(); + } + if (krw_qword_store != null) { + krw_qword_store.free(); + } + if (pipe_fd[0] != -1) { + this.libKernel.close(pipe_fd[0]); + } + if (pipe_fd[1] != -1) { + this.libKernel.close(pipe_fd[1]); + } + + libKernel.closeLibrary(); + } + + private void write_to_victim(KernelPointer kernelAddress) throws SdkException { + master_target_buffer.write8(0, kernelAddress.addr()); + master_target_buffer.write8(0x08, 0); + master_target_buffer.write4(0x10, 0); + socket.setSocketOptionsIPv6(master_sock, OptionIPv6.IPV6_PKTINFO, master_target_buffer); + } + + private void ipv6_kread(KernelPointer kernelAddress, Pointer buffer) throws SdkException { + write_to_victim(kernelAddress); + socket.getSocketOptionsIPv6(victim_sock, OptionIPv6.IPV6_PKTINFO, buffer); + } + + private void ipv6_kwrite(KernelPointer kernelAddress, Pointer buffer) throws SdkException { + write_to_victim(kernelAddress); + socket.setSocketOptionsIPv6(victim_sock, OptionIPv6.IPV6_PKTINFO, buffer); + } + + private long ipv6_kread8(KernelPointer kernelAddress) throws SdkException { + ipv6_kread(kernelAddress, slave_buffer); + return slave_buffer.read8(); + } + + private synchronized long copyout(long src, Pointer dest, long length) throws SdkException { + final long value0 = 0x4000000040000000L; + final long value1 = 0x4000000000000000L; + + pipemap_buffer.write8(value0); + pipemap_buffer.write8(0x8, value1); + pipemap_buffer.write4(0x10, 0); + ipv6_kwrite(pipe_addr, pipemap_buffer); + + pipemap_buffer.write8(src); + pipemap_buffer.write8(0x8, 0); + pipemap_buffer.write4(0x10, 0); + ipv6_kwrite(pipe_addr.inc(0x10), pipemap_buffer); + + return this.libKernel.read(pipe_fd[0], dest, length); + } + + private synchronized long copyin(Pointer src, long dest, long length) throws SdkException { + final long value = 0x4000000000000000L; + + pipemap_buffer.write8(0); + pipemap_buffer.write8(0x8, value); + pipemap_buffer.write4(0x10, 0); + ipv6_kwrite(pipe_addr, pipemap_buffer); + + pipemap_buffer.write8(dest); + pipemap_buffer.write8(0x8, 0); + pipemap_buffer.write4(0x10, 0); + ipv6_kwrite(pipe_addr.inc(0x10), pipemap_buffer); + + return this.libKernel.write(pipe_fd[1], src, length); + } + + private void inc_socket_refcount(int target_fd, KernelPointer ofilesAddress) { + KernelPointer filedescent_addr = ofilesAddress.inc(target_fd * 0x30L); + KernelPointer file_addr = KernelPointer.valueOf(filedescent_addr.read8(0x00)); + KernelPointer file_data_addr = KernelPointer.valueOf(file_addr.read8(0x00)); + file_data_addr.write4(0x100); + } + + @Override + public byte read1(long kernelAddress) { + try { + copyout(kernelAddress, krw_qword_store, 0x1); + return krw_qword_store.read1(); + } catch (SdkException e) { + throw new SdkRuntimeException(e); + } + } + + @Override + public short read2(long kernelAddress) { + try { + copyout(kernelAddress, krw_qword_store, 0x2); + return krw_qword_store.read2(); + } catch (SdkException e) { + throw new SdkRuntimeException(e); + } + } + + @Override + public int read4(long kernelAddress) { + try { + copyout(kernelAddress, krw_qword_store, 0x4); + return krw_qword_store.read4(); + } catch (SdkException e) { + throw new SdkRuntimeException(e); + } + } + + @Override + public long read8(long kernelAddress) { + try { + copyout(kernelAddress, krw_qword_store, 0x8); + return krw_qword_store.read8(); + } catch (SdkException e) { + throw new SdkRuntimeException(e); + } + } + + @Override + public void write1(long kernelAddress, byte value) { + try { + krw_qword_store.write1(value); + copyin(krw_qword_store, kernelAddress, 0x1); + } catch (SdkException e) { + throw new SdkRuntimeException(e); + } + } + + @Override + public void write2(long kernelAddress, short value) { + try { + krw_qword_store.write2(value); + copyin(krw_qword_store, kernelAddress, 0x2); + } catch (SdkException e) { + throw new SdkRuntimeException(e); + } + } + + @Override + public void write4(long kernelAddress, int value) { + try { + krw_qword_store.write4(value); + copyin(krw_qword_store, kernelAddress, 0x4); + } catch (SdkException e) { + throw new SdkRuntimeException(e); + } + } + + @Override + public void write8(long kernelAddress, long value) { + try { + krw_qword_store.write8(value); + copyin(krw_qword_store, kernelAddress, 0x8); + } catch (SdkException e) { + throw new SdkRuntimeException(e); + } + } +} diff --git a/sdk/src/main/java/org/ps5jb/sdk/core/kernel/KernelPointer.java b/sdk/src/main/java/org/ps5jb/sdk/core/kernel/KernelPointer.java new file mode 100644 index 0000000..81763a0 --- /dev/null +++ b/sdk/src/main/java/org/ps5jb/sdk/core/kernel/KernelPointer.java @@ -0,0 +1,130 @@ +package org.ps5jb.sdk.core.kernel; + +import org.ps5jb.sdk.core.AbstractPointer; + +/** + * Abstraction over memory pointer operations in kernel-space. + * This class is only usable if a global kernel accessor has been installed + * by calling {@link KernelReadWrite#setAccessor(KernelAccessor)}. + */ +public class KernelPointer extends AbstractPointer { + /** + * Returns a pointer instance equivalent to the given native memory address. + * + * @param addr Address to convert to a Pointer instance. + * @return Pointer instance representing the given native memory address. + */ + public static KernelPointer valueOf(long addr) { + return addr == 0 ? NULL : new KernelPointer(addr); + } + + /** Static constant for NULL pointer. */ + public static final KernelPointer NULL = new KernelPointer(0); + + public KernelPointer(long addr) { + super(addr); + } + + public KernelPointer(long addr, Long size) { + super(addr, size); + } + + @Override + public byte read1(long offset) { + overflow(this, offset, 1); + return KernelReadWrite.getAccessor().read1(this.addr + offset); + } + + @Override + public short read2(long offset) { + overflow(this, offset, 2); + return KernelReadWrite.getAccessor().read2(this.addr + offset); + } + + @Override + public int read4(long offset) { + overflow(this, offset, 4); + return KernelReadWrite.getAccessor().read4(this.addr + offset); + } + + @Override + public long read8(long offset) { + overflow(this, offset, 8); + return KernelReadWrite.getAccessor().read8(this.addr + offset); + } + + @Override + public void read(long offset, byte[] value, int valueOffset, int size) { + overflow(this, offset, size); + + // TODO: This can be implemented more efficiently + final KernelAccessor accessor = KernelReadWrite.getAccessor(); + for (int i = 0; i < size; ++i) { + value[valueOffset + i] = accessor.read1(this.addr + offset + i); + } + } + + @Override + public void write1(long offset, byte value) { + overflow(this, offset, 1); + KernelReadWrite.getAccessor().write1(this.addr + offset, value); + } + + @Override + public void write2(long offset, short value) { + overflow(this, offset, 2); + KernelReadWrite.getAccessor().write2(this.addr + offset, value); + } + + @Override + public void write4(long offset, int value) { + overflow(this, offset, 4); + KernelReadWrite.getAccessor().write4(this.addr + offset, value); + } + + @Override + public void write8(long offset, long value) { + overflow(this, offset, 8); + KernelReadWrite.getAccessor().write8(this.addr + offset, value); + } + + @Override + public void write(long offset, byte[] value, int valueOffset, int count) { + overflow(this, offset, count); + + // TODO: This can be implemented more efficiently + final KernelAccessor accessor = KernelReadWrite.getAccessor(); + for (int i = 0; i < count - valueOffset; ++i) { + accessor.write1(this.addr + offset + i, value[valueOffset + i]); + } + } + + /** + * Copies values in kernel memory associated with this pointer to a pointer specified by dest. + * + * @param dest Pointer to copy the data to. The data will always be copied starting at offset 0 in dest. + * @param offset Offset in this memory to read the data from. + * @param size Size of data to copy. + * @throws IndexOutOfBoundsException If the read or the write beyond one of the two pointers' sizes occurs. + */ + public void copyTo(KernelPointer dest, long offset, int size) { + overflow(this, offset, size); + overflow(dest, 0, size); + + byte[] data = new byte[size]; + read(offset, data, 0, size); + dest.write(0, data, 0, size); + } + + /** + * Increment the pointer by a given offset. The delta parameter may be negative. + * + * @param delta Offset from the current address of this pointer. + * @return New pointer instance whose size is unknown and whose address is the address of + * this pointer shifted by delta bytes. + */ + public KernelPointer inc(long delta) { + // Size is intentionally left unknown + return KernelPointer.valueOf(this.addr + delta); + } +} diff --git a/sdk/src/main/java/org/ps5jb/sdk/core/kernel/KernelReadWrite.java b/sdk/src/main/java/org/ps5jb/sdk/core/kernel/KernelReadWrite.java new file mode 100644 index 0000000..e9643f2 --- /dev/null +++ b/sdk/src/main/java/org/ps5jb/sdk/core/kernel/KernelReadWrite.java @@ -0,0 +1,35 @@ +package org.ps5jb.sdk.core.kernel; + +/** + * Class managing capability of SDK to read/write the kernel memory. + */ +public final class KernelReadWrite { + // Note: is "volatile" enough? Probably better to do synchronized methods. + private static volatile KernelAccessor kernelAccessor; + + /** + * Default constructor + */ + private KernelReadWrite() { + } + + /** + * Register a global instance of a kernel accessor, responsible for + * reading and writing kernel memory. + * + * @param kernelAccessor New accessor instance. + */ + public static void setAccessor(KernelAccessor kernelAccessor) { + KernelReadWrite.kernelAccessor = kernelAccessor; + } + + /** + * Retrieve a global instance of a kernel accessor. May be null + * if none are installed. + * + * @return Instance of a kernel accessor or null. + */ + public static KernelAccessor getAccessor() { + return KernelReadWrite.kernelAccessor; + } +} diff --git a/sdk/src/main/java/org/ps5jb/sdk/core/kernel/package-info.java b/sdk/src/main/java/org/ps5jb/sdk/core/kernel/package-info.java new file mode 100644 index 0000000..1f220c7 --- /dev/null +++ b/sdk/src/main/java/org/ps5jb/sdk/core/kernel/package-info.java @@ -0,0 +1,7 @@ +/** + * This package contains various classes related to Kernel access. + * Normally, any of the classes in this package are only usable if + * a global kernel accessor has been installed using + * {@link org.ps5jb.sdk.core.kernel.KernelReadWrite#setAccessor(org.ps5jb.sdk.core.kernel.KernelAccessor)} + */ +package org.ps5jb.sdk.core.kernel; diff --git a/sdk/src/main/java/org/ps5jb/sdk/include/inet/in/ProtocolType.java b/sdk/src/main/java/org/ps5jb/sdk/include/inet/in/ProtocolType.java new file mode 100644 index 0000000..959cb40 --- /dev/null +++ b/sdk/src/main/java/org/ps5jb/sdk/include/inet/in/ProtocolType.java @@ -0,0 +1,111 @@ +package org.ps5jb.sdk.include.inet.in; + +import org.ps5jb.sdk.res.ErrorMessages; + +/** + * Protocol types. Note that currently not all constants from FreeBSD are mapped. + */ +public final class ProtocolType implements Comparable { + /* Protocols common to RFC 1700, POSIX, and X/Open. */ + + /** dummy for IP. */ + public static final ProtocolType IPPROTO_IP = new ProtocolType(0, "IPPROTO_IP"); + /** control message protocol. */ + public static final ProtocolType IPPROTO_ICMP = new ProtocolType(1, "IPPROTO_ICMP"); + /** tcp. */ + public static final ProtocolType IPPROTO_TCP = new ProtocolType(6, "IPPROTO_TCP"); + /** user datagram protocol. */ + public static final ProtocolType IPPROTO_UDP = new ProtocolType(17, "IPPROTO_UDP"); + + /** IP6 header. */ + public static final ProtocolType IPPROTO_IPV6 = new ProtocolType(41, "IPPROTO_IPV6"); + /** Raw IP packet. */ + public static final ProtocolType IPPROTO_RAW = new ProtocolType(255, "IPPROTO_RAW"); + + /** All possible ProtocolType values. */ + private static final ProtocolType[] values = new ProtocolType[] { + IPPROTO_IP, + IPPROTO_ICMP, + IPPROTO_TCP, + IPPROTO_UDP, + IPPROTO_IPV6, + IPPROTO_RAW + }; + + private int value; + + private String name; + + /** + * Default constructor. This class should not be instantiated manually, + * use provided constants instead. + * + * @param value Numeric value of this instance. + * @param name String representation of the constant. + */ + private ProtocolType(int value, String name) { + this.value = value; + this.name = name; + } + + /** + * Get all possible values for ProtocolType. + * + * @return Array of ProtocolType possible values. + */ + public static ProtocolType[] values() { + return values; + } + + /** + * Convert a numeric value into a ProtocolType constant. + * + * @param value Number to convert + * @return ProtocolType constant corresponding to the given value. + * @throws IllegalArgumentException If value does not correspond to any ProtocolType. + */ + public static ProtocolType valueOf(int value) { + for (ProtocolType protocolType : values) { + if (value == protocolType.value()) { + return protocolType; + } + } + + throw new IllegalArgumentException(ErrorMessages.getClassErrorMessage(ProtocolType.class,"invalidValue", Integer.toString(value))); + } + + /** + * Numeric value of this instance. + * + * @return Numeric value of the instance. + */ + public int value() { + return this.value; + } + + @Override + public int compareTo(Object o) { + return this.value - ((ProtocolType) o).value; + } + + @Override + public boolean equals(Object o) { + boolean result; + if (o instanceof ProtocolType) { + result = value == ((ProtocolType) o).value; + } else { + result = false; + } + return result; + } + + @Override + public int hashCode() { + return value; + } + + @Override + public String toString() { + return name; + } +} diff --git a/sdk/src/main/java/org/ps5jb/sdk/include/inet/in/package-info.java b/sdk/src/main/java/org/ps5jb/sdk/include/inet/in/package-info.java new file mode 100644 index 0000000..1060822 --- /dev/null +++ b/sdk/src/main/java/org/ps5jb/sdk/include/inet/in/package-info.java @@ -0,0 +1,4 @@ +/** + * Contains wrappers around FreeBSD headers inside include/inet/in directory. + */ +package org.ps5jb.sdk.include.inet.in; diff --git a/sdk/src/main/java/org/ps5jb/sdk/include/inet/package-info.java b/sdk/src/main/java/org/ps5jb/sdk/include/inet/package-info.java new file mode 100644 index 0000000..06e7c59 --- /dev/null +++ b/sdk/src/main/java/org/ps5jb/sdk/include/inet/package-info.java @@ -0,0 +1,4 @@ +/** + * Contains wrappers around FreeBSD headers inside include/inet directory. + */ +package org.ps5jb.sdk.include.inet; diff --git a/sdk/src/main/java/org/ps5jb/sdk/include/machine/package-info.java b/sdk/src/main/java/org/ps5jb/sdk/include/machine/package-info.java new file mode 100644 index 0000000..20b69ba --- /dev/null +++ b/sdk/src/main/java/org/ps5jb/sdk/include/machine/package-info.java @@ -0,0 +1,4 @@ +/** + * Contains wrappers around FreeBSD headers inside include/machine directory. + */ +package org.ps5jb.sdk.include.machine; diff --git a/sdk/src/main/java/org/ps5jb/sdk/include/netinet6/in6/OptionIPv6.java b/sdk/src/main/java/org/ps5jb/sdk/include/netinet6/in6/OptionIPv6.java new file mode 100644 index 0000000..d45a3dc --- /dev/null +++ b/sdk/src/main/java/org/ps5jb/sdk/include/netinet6/in6/OptionIPv6.java @@ -0,0 +1,97 @@ +package org.ps5jb.sdk.include.netinet6.in6; + +import org.ps5jb.sdk.res.ErrorMessages; + +/** + * Options for use with getsockopt/setsockopt at the IPV6 level. + * Note that currently not all constants from FreeBSD are mapped. + */ +public final class OptionIPv6 implements Comparable { + /** buf/ip6_opts; set/get IP6 options. */ + public static final OptionIPv6 IPV6_OPTIONS = new OptionIPv6(1, "IPV6_OPTIONS"); + /** in6_pktinfo; send if, src addr. */ + public static final OptionIPv6 IPV6_PKTINFO = new OptionIPv6(46, "IPV6_PKTINFO"); + + /** All possible OptionsIPv6 values. */ + private static final OptionIPv6[] values = new OptionIPv6[] { + IPV6_OPTIONS, + IPV6_PKTINFO + }; + + private int value; + + private String name; + + /** + * Default constructor. This class should not be instantiated manually, + * use provided constants instead. + * + * @param value Numeric value of this instance. + * @param name String representation of the constant. + */ + private OptionIPv6(int value, String name) { + this.value = value; + this.name = name; + } + + /** + * Get all possible values for OptionIPv6. + * + * @return Array of OptionIPv6 possible values. + */ + public static OptionIPv6[] values() { + return values; + } + + /** + * Convert a numeric value into a OptionIPv6 constant. + * + * @param value Number to convert + * @return OptionIPv6 constant corresponding to the given value. + * @throws IllegalArgumentException If value does not correspond to any OptionIPv6. + */ + public static OptionIPv6 valueOf(int value) { + for (OptionIPv6 opt : values) { + if (value == opt.value()) { + return opt; + } + } + + throw new IllegalArgumentException(ErrorMessages.getClassErrorMessage(OptionIPv6.class,"invalidValue", Integer.toString(value))); + } + + /** + * Numeric value of this instance. + * + * @return Numeric value of the instance. + */ + public int value() { + return this.value; + } + + @Override + public int compareTo(Object o) { + return this.value - ((OptionIPv6) o).value; + } + + @Override + public boolean equals(Object o) { + boolean result; + if (o instanceof OptionIPv6) { + result = value == ((OptionIPv6) o).value; + } else { + result = false; + } + return result; + } + + @Override + public int hashCode() { + return value; + } + + @Override + public String toString() { + return name; + } +} diff --git a/sdk/src/main/java/org/ps5jb/sdk/include/netinet6/in6/package-info.java b/sdk/src/main/java/org/ps5jb/sdk/include/netinet6/in6/package-info.java new file mode 100644 index 0000000..bd3b0ef --- /dev/null +++ b/sdk/src/main/java/org/ps5jb/sdk/include/netinet6/in6/package-info.java @@ -0,0 +1,4 @@ +/** + * Contains wrappers around FreeBSD headers inside include/netinet6/in6 directory. + */ +package org.ps5jb.sdk.include.netinet6.in6; diff --git a/sdk/src/main/java/org/ps5jb/sdk/include/netinet6/package-info.java b/sdk/src/main/java/org/ps5jb/sdk/include/netinet6/package-info.java new file mode 100644 index 0000000..2471c1c --- /dev/null +++ b/sdk/src/main/java/org/ps5jb/sdk/include/netinet6/package-info.java @@ -0,0 +1,4 @@ +/** + * Contains wrappers around FreeBSD headers inside include/netinet6 directory. + */ +package org.ps5jb.sdk.include.netinet6; diff --git a/sdk/src/main/java/org/ps5jb/sdk/include/sys/Socket.java b/sdk/src/main/java/org/ps5jb/sdk/include/sys/Socket.java new file mode 100644 index 0000000..c1175ac --- /dev/null +++ b/sdk/src/main/java/org/ps5jb/sdk/include/sys/Socket.java @@ -0,0 +1,60 @@ +package org.ps5jb.sdk.include.sys; + +import org.ps5jb.sdk.core.Pointer; +import org.ps5jb.sdk.core.SdkException; +import org.ps5jb.sdk.include.inet.in.ProtocolType; +import org.ps5jb.sdk.include.netinet6.in6.OptionIPv6; +import org.ps5jb.sdk.include.sys.rtprio.RtPrioType; +import org.ps5jb.sdk.include.sys.socket.AddressFamilyType; +import org.ps5jb.sdk.include.sys.socket.SocketType; +import org.ps5jb.sdk.lib.LibKernel; + +/** + * This class represents include/sys/socket.h from FreeBSD source. + */ +public class Socket { + private final LibKernel libKernel; + private final ErrNo errNo; + + /** + * Constructor. + * + * @param libKernel Instance of the 'libkernel' native library wrapper. + */ + public Socket(LibKernel libKernel) { + this.libKernel = libKernel; + this.errNo = new ErrNo(this.libKernel); + } + + public int createSocket(AddressFamilyType domain, SocketType socketType, ProtocolType protocol) throws SdkException { + int ret = libKernel.socket(domain.value(), socketType.value(), protocol.value()); + if (ret == -1) { + throw errNo.getLastException(getClass(), "createSocket"); + } + return ret; + } + + public void setSocketOptionsIPv6(int socket, OptionIPv6 optionName, Pointer optionValue) throws SdkException { + int ret = libKernel.setsockopt(socket, ProtocolType.IPPROTO_IPV6.value(), optionName.value(), optionValue, optionValue.size()); + if (ret == -1) { + throw errNo.getLastException(getClass(), "setRtPrio"); + } + } + + public Pointer getSocketOptionsIPv6(int socket, OptionIPv6 optionName, Pointer optionValue) throws SdkException { + Pointer optlen = Pointer.calloc(0x4); + try { + optlen.write4(optionValue.size().intValue()); + + int ret = libKernel.getsockopt(socket, ProtocolType.IPPROTO_IPV6.value(), optionName.value(), optionValue, optlen); + if (ret == -1) { + throw errNo.getLastException(getClass(), "setRtPrio"); + } + + int newLen = optlen.read4(); + return (newLen == optionValue.size().intValue()) ? optionValue : new Pointer(optionValue.addr(), new Long(newLen)); + } finally { + optlen.free(); + } + } +} diff --git a/sdk/src/main/java/org/ps5jb/sdk/include/sys/mman/MappingFlag.java b/sdk/src/main/java/org/ps5jb/sdk/include/sys/mman/MappingFlag.java index caeebe1..175e7d9 100644 --- a/sdk/src/main/java/org/ps5jb/sdk/include/sys/mman/MappingFlag.java +++ b/sdk/src/main/java/org/ps5jb/sdk/include/sys/mman/MappingFlag.java @@ -87,9 +87,9 @@ public static MappingFlag[] values() { * @throws IllegalArgumentException If value does not correspond to any MappingFlag. */ public static MappingFlag valueOf(int value) { - for (MappingFlag openFlag : values) { - if (value == openFlag.value()) { - return openFlag; + for (MappingFlag mappingFlag : values) { + if (value == mappingFlag.value()) { + return mappingFlag; } } diff --git a/sdk/src/main/java/org/ps5jb/sdk/include/sys/mman/ProtectionFlag.java b/sdk/src/main/java/org/ps5jb/sdk/include/sys/mman/ProtectionFlag.java index d6616e0..6c5730f 100644 --- a/sdk/src/main/java/org/ps5jb/sdk/include/sys/mman/ProtectionFlag.java +++ b/sdk/src/main/java/org/ps5jb/sdk/include/sys/mman/ProtectionFlag.java @@ -56,9 +56,9 @@ public static ProtectionFlag[] values() { * @throws IllegalArgumentException If value does not correspond to any ProtectionFlag. */ public static ProtectionFlag valueOf(int value) { - for (ProtectionFlag openFlag : values) { - if (value == openFlag.value()) { - return openFlag; + for (ProtectionFlag protectionFlag : values) { + if (value == protectionFlag.value()) { + return protectionFlag; } } diff --git a/sdk/src/main/java/org/ps5jb/sdk/include/sys/pthreadtypes/PThreadType.java b/sdk/src/main/java/org/ps5jb/sdk/include/sys/pthreadtypes/PThreadType.java index b0a1fac..91a8a8f 100644 --- a/sdk/src/main/java/org/ps5jb/sdk/include/sys/pthreadtypes/PThreadType.java +++ b/sdk/src/main/java/org/ps5jb/sdk/include/sys/pthreadtypes/PThreadType.java @@ -9,7 +9,7 @@ public class PThreadType { private Pointer pthread; /** - * DirEnt constructor. + * PThreadType constructor. * * @param pthread Native address of pthread_t structure. */ diff --git a/sdk/src/main/java/org/ps5jb/sdk/include/sys/rtprio/RtPrioType.java b/sdk/src/main/java/org/ps5jb/sdk/include/sys/rtprio/RtPrioType.java index 2cebdeb..ac04fb3 100644 --- a/sdk/src/main/java/org/ps5jb/sdk/include/sys/rtprio/RtPrioType.java +++ b/sdk/src/main/java/org/ps5jb/sdk/include/sys/rtprio/RtPrioType.java @@ -53,7 +53,7 @@ public static RtPrioType[] values() { * * @param value Number to convert * @return RtPrioType constant corresponding to the given value. - * @throws IllegalArgumentException If value does not correspond to any CpuWhichType. + * @throws IllegalArgumentException If value does not correspond to any RtPrioType. */ public static RtPrioType valueOf(short value) { for (RtPrioType rtPrioType : values) { diff --git a/sdk/src/main/java/org/ps5jb/sdk/include/sys/socket/AddressFamilyType.java b/sdk/src/main/java/org/ps5jb/sdk/include/sys/socket/AddressFamilyType.java new file mode 100644 index 0000000..59da839 --- /dev/null +++ b/sdk/src/main/java/org/ps5jb/sdk/include/sys/socket/AddressFamilyType.java @@ -0,0 +1,105 @@ +package org.ps5jb.sdk.include.sys.socket; + +import org.ps5jb.sdk.res.ErrorMessages; + +/** + * Address families. Note that currently not all constants from FreeBSD are mapped. + */ +public final class AddressFamilyType implements Comparable { + /** Unspecified. */ + public static final AddressFamilyType AF_UNSPEC = new AddressFamilyType(0, "AF_UNSPEC"); + /** Standardized name for {@link #AF_LOCAL}. */ + public static final AddressFamilyType AF_UNIX = new AddressFamilyType(1, "AF_UNIX"); + /** Local to host (pipes, portals). */ + public static final AddressFamilyType AF_LOCAL = new AddressFamilyType(AF_UNIX.value, "AF_LOCAL"); + /** Internetwork: UDP, TCP, etc. */ + public static final AddressFamilyType AF_INET = new AddressFamilyType(2, "AF_INET"); + /** IPv6. */ + public static final AddressFamilyType AF_INET6 = new AddressFamilyType(28, "AF_INET6"); + + /** All possible AddressFamilyType values. */ + private static final AddressFamilyType[] values = new AddressFamilyType[] { + AF_UNSPEC, + AF_UNIX, + AF_LOCAL, + AF_INET, + AF_INET6 + }; + + private final int value; + + private final String name; + + /** + * Default constructor. This class should not be instantiated manually, + * use provided constants instead. + * + * @param value Numeric value of this instance. + * @param name String representation of the constant. + */ + private AddressFamilyType(int value, String name) { + this.value = value; + this.name = name; + } + + /** + * Get all possible values for AddressFamilyType. + * + * @return Array of AddressFamilyType possible values. + */ + public static AddressFamilyType[] values() { + return values; + } + + /** + * Convert a numeric value into a AddressFamilyType constant. + * + * @param value Number to convert + * @return AddressFamilyType constant corresponding to the given value. + * @throws IllegalArgumentException If value does not correspond to any AddressFamilyType. + */ + public static AddressFamilyType valueOf(short value) { + for (AddressFamilyType rtPrioType : values) { + if (value == rtPrioType.value()) { + return rtPrioType; + } + } + + throw new IllegalArgumentException(ErrorMessages.getClassErrorMessage(AddressFamilyType.class,"invalidValue", Integer.toString(value))); + } + + /** + * Numeric value of this instance. + * + * @return Numeric value of the instance. + */ + public int value() { + return this.value; + } + + @Override + public int compareTo(Object o) { + return this.value - ((AddressFamilyType) o).value; + } + + @Override + public boolean equals(Object o) { + boolean result; + if (o instanceof AddressFamilyType) { + result = value == ((AddressFamilyType) o).value; + } else { + result = false; + } + return result; + } + + @Override + public int hashCode() { + return value; + } + + @Override + public String toString() { + return name; + } +} diff --git a/sdk/src/main/java/org/ps5jb/sdk/include/sys/socket/SocketType.java b/sdk/src/main/java/org/ps5jb/sdk/include/sys/socket/SocketType.java new file mode 100644 index 0000000..c5f5859 --- /dev/null +++ b/sdk/src/main/java/org/ps5jb/sdk/include/sys/socket/SocketType.java @@ -0,0 +1,105 @@ +package org.ps5jb.sdk.include.sys.socket; + +import org.ps5jb.sdk.res.ErrorMessages; + +/** + * Socket types + */ +public final class SocketType implements Comparable { + /** Stream socket. */ + public static final SocketType SOCK_STREAM = new SocketType(1, "SOCK_STREAM"); + /** Datagram socket. */ + public static final SocketType SOCK_DGRAM = new SocketType(2, "SOCK_DGRAM"); + /** Raw-protocol interface. */ + public static final SocketType SOCK_RAW = new SocketType(3, "SOCK_RAW"); + /** Reliably-delivered message. */ + public static final SocketType SOCK_RDM = new SocketType(4, "SOCK_RDM"); + /** Sequenced packet stream. */ + public static final SocketType SOCK_SEQPACKET = new SocketType(5, "SOCK_SEQPACKET"); + + /** All possible SocketType values. */ + private static final SocketType[] values = new SocketType[] { + SOCK_STREAM, + SOCK_DGRAM, + SOCK_RAW, + SOCK_RDM, + SOCK_SEQPACKET + }; + + private final int value; + + private final String name; + + /** + * Default constructor. This class should not be instantiated manually, + * use provided constants instead. + * + * @param value Numeric value of this instance. + * @param name String representation of the constant. + */ + private SocketType(int value, String name) { + this.value = value; + this.name = name; + } + + /** + * Get all possible values for SocketType. + * + * @return Array of SocketType possible values. + */ + public static SocketType[] values() { + return values; + } + + /** + * Convert a numeric value into a SocketType constant. + * + * @param value Number to convert + * @return SocketType constant corresponding to the given value. + * @throws IllegalArgumentException If value does not correspond to any SocketType. + */ + public static SocketType valueOf(int value) { + for (SocketType socketType : values) { + if (value == socketType.value()) { + return socketType; + } + } + + throw new IllegalArgumentException(ErrorMessages.getClassErrorMessage(SocketType.class,"invalidValue", Integer.toString(value))); + } + + /** + * Numeric value of this instance. + * + * @return Numeric value of the instance. + */ + public int value() { + return this.value; + } + + @Override + public int compareTo(Object o) { + return this.value - ((SocketType) o).value; + } + + @Override + public boolean equals(Object o) { + boolean result; + if (o instanceof SocketType) { + result = value == ((SocketType) o).value; + } else { + result = false; + } + return result; + } + + @Override + public int hashCode() { + return value; + } + + @Override + public String toString() { + return name; + } +} diff --git a/sdk/src/main/java/org/ps5jb/sdk/include/sys/socket/package-info.java b/sdk/src/main/java/org/ps5jb/sdk/include/sys/socket/package-info.java new file mode 100644 index 0000000..8e4d038 --- /dev/null +++ b/sdk/src/main/java/org/ps5jb/sdk/include/sys/socket/package-info.java @@ -0,0 +1,4 @@ +/** + * Contains Java data type wrappers for C types declared in FreeBSD include/sys/socket.h header. + */ +package org.ps5jb.sdk.include.sys.socket; diff --git a/sdk/src/main/java/org/ps5jb/sdk/include/sys/uio/UioReadWrite.java b/sdk/src/main/java/org/ps5jb/sdk/include/sys/uio/UioReadWrite.java index 741861c..ad60fec 100644 --- a/sdk/src/main/java/org/ps5jb/sdk/include/sys/uio/UioReadWrite.java +++ b/sdk/src/main/java/org/ps5jb/sdk/include/sys/uio/UioReadWrite.java @@ -50,9 +50,9 @@ public static UioReadWrite[] values() { * @throws IllegalArgumentException If value does not correspond to any UioReadWrite. */ public static UioReadWrite valueOf(int value) { - for (UioReadWrite segFlag : values) { - if (value == segFlag.value()) { - return segFlag; + for (UioReadWrite urw : values) { + if (value == urw.value()) { + return urw; } } diff --git a/sdk/src/main/java/org/ps5jb/sdk/include/sys/umtx/UmtxOpcodeType.java b/sdk/src/main/java/org/ps5jb/sdk/include/sys/umtx/UmtxOpcodeType.java index df003f5..b18030f 100644 --- a/sdk/src/main/java/org/ps5jb/sdk/include/sys/umtx/UmtxOpcodeType.java +++ b/sdk/src/main/java/org/ps5jb/sdk/include/sys/umtx/UmtxOpcodeType.java @@ -50,9 +50,9 @@ public static UmtxOpcodeType[] values() { * @throws IllegalArgumentException If value does not correspond to any UmtxOpcodeType. */ public static UmtxOpcodeType valueOf(int value) { - for (UmtxOpcodeType priorityType : values) { - if (value == priorityType.value()) { - return priorityType; + for (UmtxOpcodeType opcodeType : values) { + if (value == opcodeType.value()) { + return opcodeType; } } diff --git a/sdk/src/main/java/org/ps5jb/sdk/include/sys/umtx/UmtxShmFlag.java b/sdk/src/main/java/org/ps5jb/sdk/include/sys/umtx/UmtxShmFlag.java index d40f365..ad10109 100644 --- a/sdk/src/main/java/org/ps5jb/sdk/include/sys/umtx/UmtxShmFlag.java +++ b/sdk/src/main/java/org/ps5jb/sdk/include/sys/umtx/UmtxShmFlag.java @@ -65,9 +65,9 @@ public static UmtxShmFlag[] values() { * @throws IllegalArgumentException If value does not correspond to any UmtxShmFlag. */ public static UmtxShmFlag valueOf(long value) { - for (UmtxShmFlag openFlag : values) { - if (value == openFlag.value()) { - return openFlag; + for (UmtxShmFlag shmFlag : values) { + if (value == shmFlag.value()) { + return shmFlag; } } diff --git a/sdk/src/main/java/org/ps5jb/sdk/lib/LibKernel.java b/sdk/src/main/java/org/ps5jb/sdk/lib/LibKernel.java index 6618c26..9044087 100644 --- a/sdk/src/main/java/org/ps5jb/sdk/lib/LibKernel.java +++ b/sdk/src/main/java/org/ps5jb/sdk/lib/LibKernel.java @@ -54,6 +54,9 @@ public class LibKernel extends Library { private Pointer sched_yield; private Pointer sceKernelGetCurrentCpu; private Pointer sceKernelGetProsperoSystemSwVersion; + private Pointer socket; + private Pointer setsockopt; + private Pointer getsockopt; /** * Constructor. @@ -403,6 +406,30 @@ public long write(int fd, Pointer buf, long nbytes) { return call(write, fd, buf.addr(), nbytes); } + public int socket(int domain, int type, int protocol) { + if (socket == null) { + socket = addrOf("socket"); + } + + return (int) call(socket, domain, type, protocol); + } + + public int getsockopt(int s, int level, int optname, Pointer optval, Pointer optlen) { + if (getsockopt == null) { + getsockopt = addrOf("getsockopt"); + } + + return (int) call(getsockopt, s, level, optname, optval.addr(), optlen.addr()); + } + + public int setsockopt(int s, int level, int optname, Pointer optval, long optlen) { + if (setsockopt == null) { + setsockopt = addrOf("setsockopt"); + } + + return (int) call(setsockopt, s, level, optname, optval.addr(), optlen); + } + public int _umtx_op(Pointer obj, int op, long val, Pointer uaddr, Pointer uaddr2) { if (_umtx_op == null) { _umtx_op = addrOf("_umtx_op");