Skip to content

Commit

Permalink
Add macroinstructions for call/jmp
Browse files Browse the repository at this point in the history
  • Loading branch information
zyedidia committed Dec 5, 2024
1 parent 9c67604 commit f52d903
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 13 deletions.
78 changes: 78 additions & 0 deletions lfi-verify/amd64/macroinst.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
struct MacroInst {
int size;
int ninstr;
};

static struct MacroInst macroinst_jmp(Verifier* v, uint8_t* buf, size_t size) {
FdInstr i_and, i_jmp;
if (fd_decode(&buf[0], size, 64, 0, &i_and) < 0)
return (struct MacroInst){-1, 0};
if (fd_decode(&buf[i_and.size], size - i_and.size, 64, 0, &i_jmp) < 0)
return (struct MacroInst){-1, 0};
// andq $0xffffffffffffffe0, %rXX
if (FD_TYPE(&i_and) != FDI_AND ||
FD_OP_TYPE(&i_and, 0) != FD_OT_REG ||
FD_OP_TYPE(&i_and, 1) != FD_OT_IMM ||
FD_OP_IMM(&i_and, 1) != 0xffffffffffffffe0)
return (struct MacroInst){-1, 0};

// jmpq *%rXX
if (FD_TYPE(&i_jmp) != FDI_JMP ||
FD_OP_TYPE(&i_jmp, 0) != FD_OT_REG ||
FD_OP_REG(&i_jmp, 0) != FD_OP_REG(&i_and, 0))
return (struct MacroInst){-1, 0};

return (struct MacroInst){i_and.size + i_jmp.size, 2};
}

static struct MacroInst macroinst_call(Verifier* v, uint8_t* buf, size_t size) {
FdInstr i_and, i_call;
if (fd_decode(&buf[0], size, 64, 0, &i_and))
return (struct MacroInst){-1, 0};
if (fd_decode(&buf[i_and.size], size - i_and.size, 64, 0, &i_call))
return (struct MacroInst){-1, 0};
// andq $0xffffffffffffffe0, %rXX
if (FD_TYPE(&i_and) != FDI_AND ||
FD_OP_TYPE(&i_and, 0) != FD_OT_REG ||
FD_OP_TYPE(&i_and, 1) != FD_OT_IMM ||
FD_OP_IMM(&i_and, 1) != 0xffffffffffffffe0)
return (struct MacroInst){-1, 0};

// callq *%rXX
if (FD_TYPE(&i_call) != FDI_CALL ||
FD_OP_TYPE(&i_call, 0) != FD_OT_REG ||
FD_OP_REG(&i_call, 0) != FD_OP_REG(&i_and, 0))
return (struct MacroInst){-1, 0};

return (struct MacroInst){i_and.size + i_call.size, 2};
}

static struct MacroInst macroinst_shxd(Verifier* v, uint8_t* buf, size_t size) {
return (struct MacroInst){-1, 0};
}

static struct MacroInst macroinst_bsx(Verifier* v, uint8_t* buf, size_t size) {
// test %rXX, %rXX
// jz .SKIP
// bsx
// .SKIP:
return (struct MacroInst){-1, 0};
}

typedef struct MacroInst (*MacroFn)(Verifier*, uint8_t*, size_t);

static MacroFn mfns[] = {
macroinst_jmp,
macroinst_call,
macroinst_shxd,
macroinst_bsx,
};

static struct MacroInst macroinst(Verifier* v, uint8_t* buf, size_t size) {
for (size_t i = 0; i < sizeof(mfns) / sizeof(mfns[0]); i++) {
struct MacroInst mi = macroinst_jmp(v, buf, size);
if (mi.size > 0)
return mi;
}
return (struct MacroInst){-1, 0};
}
37 changes: 24 additions & 13 deletions lfi-verify/amd64/verify.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,35 +137,46 @@ static void chkbranch(Verifier* v, FdInstr* instr, size_t bundlesize) {
if (branch && !indirect) {
if (target % bundlesize != 0)
verr(v, instr, "jump target is not bundle-aligned");
} else if (branch && indirect) {
verr(v, instr, "invalid indirect branch");
}
}

#include "macroinst.c"

static size_t vchkbundle(Verifier* v, uint8_t* buf, size_t size, size_t bundlesize) {
size_t count = 0;
size_t ninstr = 0;

while (count < bundlesize && count < size) {
FdInstr instr;
int ret = fd_decode(&buf[count], size - count, 64, 0, &instr);
if (ret < 0) {
verrmin(v, "%lx: unknown instruction", v->addr);
return ninstr;
}
struct MacroInst mi = macroinst(v, &buf[count], size - count);
if (mi.size < 0) {
FdInstr instr;
int ret = fd_decode(&buf[count], size - count, 64, 0, &instr);
if (ret < 0) {
verrmin(v, "%lx: unknown instruction", v->addr);
return ninstr;
}
mi.size = ret;
mi.ninstr = 1;

if (!okmnem(v, &instr))
verr(v, &instr, "illegal instruction");
if (!okmnem(v, &instr))
verr(v, &instr, "illegal instruction");

chkbranch(v, &instr, bundlesize);
chkbranch(v, &instr, bundlesize);
}

if (count + ret > bundlesize) {
if (count + mi.size > bundlesize) {
FdInstr instr;
fd_decode(&buf[count], size - count, 64, 0, &instr);
verr(v, &instr, "instruction spans bundle boundary");
v->abort = true; // not useful to give further errors
return ninstr;
}

v->addr += ret;
count += ret;
ninstr++;
v->addr += mi.size;
count += mi.size;
ninstr += mi.ninstr;
}
return ninstr;
}
Expand Down
2 changes: 2 additions & 0 deletions lfi-verify/test/amd64/fail.s
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,5 @@ jmp foo
nop
foo:
nop
---
jmpq *%rax

0 comments on commit f52d903

Please sign in to comment.