feat: Use JNA for WinApiProvider, remove natives
ci/woodpecker/push/woodpecker Pipeline was successful Details

This commit is contained in:
Johannes Frohnmeyer 2023-07-28 18:54:31 +02:00
parent 49b97ad38d
commit d074812af3
Signed by: Johannes
GPG Key ID: E76429612C2929F4
9 changed files with 99 additions and 93 deletions

View File

@ -1,25 +1,49 @@
import com.squareup.javapoet.ClassName
import com.squareup.javapoet.ParameterizedTypeName
import com.squareup.javapoet.TypeSpec
import io.gitlab.jfronny.scripts.*
import java.nio.file.Files
import java.util.*
import java.util.function.Supplier
import javax.lang.model.element.Modifier.*
plugins {
id("jfmod") version "1.3-SNAPSHOT"
id("jf.codegen") version "1.3-SNAPSHOT"
id("jfmod") version "1.5-SNAPSHOT"
}
allprojects { group = "io.gitlab.jfronny" }
base.archivesName = "breakme"
// https://fabricmc.net/develop/
val fabricVersion = "0.86.1+1.20.1"
jfMod {
minecraftVersion = "1.20.1"
yarn("build.10")
loaderVersion = "0.14.21"
libJfVersion = "3.10.2"
modrinth {
projectId = "breakme"
requiredDependencies.add("libjf")
optionalDependencies.add("modmenu")
}
curseforge {
projectId = "400842"
requiredDependencies.add("libjf")
optionalDependencies.add("modmenu")
}
}
if (flavour == "") flavour = "modrinth"
dependencies {
modImplementation("io.gitlab.jfronny.libjf:libjf-config-core-v1:${prop("libjf_version")}")
modImplementation("io.gitlab.jfronny.libjf:libjf-config-core-v1:${jfMod.libJfVersion.get()}")
// Dev env
modLocalRuntime("io.gitlab.jfronny.libjf:libjf-devutil:${prop("libjf_version")}")
modLocalRuntime("io.gitlab.jfronny.libjf:libjf-config-ui-tiny-v1:${prop("libjf_version")}")
modLocalRuntime("net.fabricmc.fabric-api:fabric-api:${prop("fabric_version")}")
modLocalRuntime("com.terraformersmc:modmenu:7.0.1")
modLocalRuntime("io.gitlab.jfronny.libjf:libjf-devutil:${jfMod.libJfVersion.get()}")
modLocalRuntime("io.gitlab.jfronny.libjf:libjf-config-ui-tiny-v1:${jfMod.libJfVersion.get()}")
modLocalRuntime("net.fabricmc.fabric-api:fabric-api:$fabricVersion")
modLocalRuntime("com.terraformersmc:modmenu:7.2.1")
}
loom {
@ -41,7 +65,6 @@ val classes = LinkedList(list("io.gitlab.jfronny.breakme.crash.safe"))
if (flavour == "curseforge") {
sourceSets.main.get().java.filter.exclude("**/unsafe/*")
sourceSets.main.get().resources.exclude("**/native/*")
} else {
classes.addAll(list("io.gitlab.jfronny.breakme.crash.unsafe"))
}
@ -50,6 +73,7 @@ sourceSets {
main {
generate(project) {
val providerType = ClassName.get("io.gitlab.jfronny.breakme.crash", "CrashProvider")
val supplierType = ParameterizedTypeName.get(ClassName.get(Supplier::class.java), providerType)
`enum`("io.gitlab.jfronny.breakme.crash", "Method") {
modifiers(PUBLIC)
@ -58,15 +82,15 @@ sourceSets {
for (klazz in classes) {
val name = klazz.simpleName()
enumConstant(name.substring(0, name.length - "Provider".length), TypeSpec.anonymousClassBuilder("new \$T()", klazz).build())
enumConstant(name.substring(0, name.length - "Provider".length), TypeSpec.anonymousClassBuilder("\$T::new", klazz).build())
}
field(providerType, "provider", PRIVATE, FINAL)
field(supplierType, "provider", PRIVATE, FINAL)
constructor {
parameter(providerType, "provider")
parameter(supplierType, "provider")
code {
addStatement("this.provider = provider")
addStatement("this.provider = new \$T<>(provider)", ClassName.get("io.gitlab.jfronny.commons", "LazySupplier"))
}
}
@ -75,7 +99,7 @@ sourceSets {
exception(Exception::class.java)
annotation(Override::class.java)
code {
addStatement("provider.crash()")
addStatement("provider.get().crash()")
}
}
}

View File

@ -1,17 +0,0 @@
# https://fabricmc.net/develop/
minecraft_version=1.20
yarn_mappings=build.1
loader_version=0.14.21
maven_group=io.gitlab.jfronny
archives_base_name=breakme
modrinth_id=breakme
modrinth_required_dependencies=libjf
modrinth_optional_dependencies=modmenu
curseforge_id=400842
curseforge_required_dependencies=libjf
curseforge_optional_dependencies=modmenu
fabric_version=0.83.0+1.20
libjf_version=3.8.0

View File

@ -1,13 +0,0 @@
@echo off
echo Setting up native env
cd "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build"
call vcvarsall x86_x64
cd %~dp0
echo Building natives
cl .\io_gitlab_jfronny_breakme_crash_unsafe_WinApiProvider.cpp /I"jdk\include" /I"jdk\include\win32" -Fenatives.dll -MD -LD
echo Running post-build steps
del .\natives.exp
del .\natives.lib
del .\io_gitlab_jfronny_breakme_breakme_NativeCrash.obj
del ..\resources\native\natives.dll
echo Natives complete

View File

@ -1,18 +0,0 @@
#include <iostream>
#include <Windows.h>
#include <winternl.h>
#include "io_gitlab_jfronny_breakme_crash_unsafe_WinApiProvider.h"
using namespace std;
typedef NTSTATUS(NTAPI *pdef_NtRaiseHardError)(NTSTATUS ErrorStatus, ULONG NumberOfParameters, ULONG UnicodeStringParameterMask OPTIONAL, PULONG_PTR Parameters, ULONG ResponseOption, PULONG Response);
typedef NTSTATUS(NTAPI *pdef_RtlAdjustPrivilege)(ULONG Privilege, BOOLEAN Enable, BOOLEAN CurrentThread, PBOOLEAN Enabled);
JNIEXPORT void JNICALL Java_io_gitlab_jfronny_breakme_crash_unsafe_WinApiProvider_CrashWindows_1Native(JNIEnv* env, jobject thisObject)
{
BOOLEAN bEnabled;
ULONG uResp;
LPVOID lpFuncAddress = GetProcAddress(LoadLibraryA("ntdll.dll"), "RtlAdjustPrivilege");
LPVOID lpFuncAddress2 = GetProcAddress(GetModuleHandle("ntdll.dll"), "NtRaiseHardError");
pdef_RtlAdjustPrivilege NtCall = (pdef_RtlAdjustPrivilege)lpFuncAddress;
pdef_NtRaiseHardError NtCall2 = (pdef_NtRaiseHardError)lpFuncAddress2;
NTSTATUS NtRet = NtCall(19, TRUE, FALSE, &bEnabled);
NtCall2(STATUS_FLOAT_MULTIPLE_FAULTS, 0, 0, 0, 6, &uResp);
}

View File

@ -1,21 +0,0 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class io_gitlab_jfronny_breakme_crash_unsafe_WinApiProvider */
#ifndef _Included_io_gitlab_jfronny_breakme_crash_unsafe_WinApiProvider
#define _Included_io_gitlab_jfronny_breakme_crash_unsafe_WinApiProvider
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: io_gitlab_jfronny_breakme_crash_unsafe_WinApiProvider
* Method: CrashWindows_Native
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_io_gitlab_jfronny_breakme_crash_unsafe_WinApiProvider_CrashWindows_1Native
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,8 +1,10 @@
package io.gitlab.jfronny.breakme;
import io.gitlab.jfronny.breakme.crash.Method;
import io.gitlab.jfronny.commons.log.Logger;
import net.fabricmc.api.ModInitializer;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.Language;
public class BreakMe implements ModInitializer {
public static final String MOD_ID = "breakme";
@ -17,8 +19,10 @@ public class BreakMe implements ModInitializer {
if (BreakMeConfig.event == BreakMeConfig.Cause.All
|| BreakMeConfig.event == BreakMeConfig.Cause.Damage
|| (BreakMeConfig.event == BreakMeConfig.Cause.Death && player.isDead())) {
LOGGER.info("Invoking the crash");
BreakMeConfig.method.crash();
Method method = BreakMeConfig.method;
String name = Language.getInstance().get(MOD_ID + ".jfconfig.enum.Method." + method.name(), method.name());
LOGGER.info("Invoking the crash (using " + name + ")");
method.crash();
}
}
}

View File

@ -7,6 +7,13 @@ import org.lwjgl.PointerBuffer;
public class SegfaultProvider implements CrashProvider {
@Override
public void crash() throws Exception {
BufferUtils.zeroBuffer(PointerBuffer.create(0, 1000));
Impl.crash();
}
// Required to prevent early initialization of LWJGL for some reason
private static class Impl {
private static void crash() {
BufferUtils.zeroBuffer(PointerBuffer.create(0, 1000));
}
}
}

View File

@ -1,16 +1,19 @@
package io.gitlab.jfronny.breakme.crash.unsafe;
import com.sun.jna.*;
import com.sun.jna.platform.win32.*;
import com.sun.jna.win32.StdCallLibrary;
import com.sun.jna.win32.W32APIOptions;
import io.gitlab.jfronny.breakme.BreakMe;
import io.gitlab.jfronny.breakme.crash.CrashProvider;
import java.io.IOException;
import java.util.function.Supplier;
//import java.lang.foreign.*;
//import java.lang.invoke.MethodHandle;
//
//import static java.lang.foreign.ValueLayout.*;
public class WinApiProvider implements CrashProvider {
private native void CrashWindows_Native();
@Override
public void crash() {
// try {
@ -77,12 +80,49 @@ public class WinApiProvider implements CrashProvider {
// return;
// }
try {
// Old implementation using DLL
NativeUtils.loadLibraryFromJar("/native/natives.dll");
this.CrashWindows_Native();
} catch (IOException e) {
BreakMe.LOGGER.error("Could not load windows native", e);
// Old implementation using JNA
NtDll ntdll = Native.load("NtDll", NtDll.class, W32APIOptions.DEFAULT_OPTIONS);
int status = ntdll.RtlAdjustPrivilege(
new WinDef.ULONG(19),
true,
false,
new WinDef.BOOLByReference()
);
if (status != NTStatus.STATUS_SUCCESS) {
BreakMe.LOGGER.error("Got status: " + String.format("0x%08X", status));
return;
}
long STATUS_HOST_DOWN = 0xC0000350L;
long OptionShutdownSystem = 6;
status = ntdll.NtRaiseHardError(
new WinDef.ULONG(STATUS_HOST_DOWN),
null,
null,
null,
new WinDef.ULONG(OptionShutdownSystem),
new WinDef.ULONGByReference()
);
if (status != NTStatus.STATUS_SUCCESS) {
BreakMe.LOGGER.error("Got status: " + String.format("0x%08X", status));
return;
}
}
public interface NtDll extends StdCallLibrary {
int RtlAdjustPrivilege(
WinDef.ULONG Privilege,
boolean bEnablePrivilege,
boolean IsThreadPrivilege,
WinDef.BOOLByReference PreviousValue
);
int NtRaiseHardError(
WinDef.ULONG ErrorStatus,
WinDef.ULONG NumberOfParameters,
WinDef.ULONG UnicodeStringParameterMask,
WinDef.ULONGByReference Parameters,
WinDef.ULONG ValidResponseOption,
WinDef.ULONGByReference Response
);
}
}