Skip to content

Instantly share code, notes, and snippets.

@legionus
Last active August 8, 2024 10:30
Show Gist options
  • Save legionus/e990834da836da0e5d7330876e50469e to your computer and use it in GitHub Desktop.
Save legionus/e990834da836da0e5d7330876e50469e to your computer and use it in GitHub Desktop.
diff --git a/arch/x86/coco/tdx/tdx.c b/arch/x86/coco/tdx/tdx.c
index 5b3421a89998..992cc3f19f52 100644
--- a/arch/x86/coco/tdx/tdx.c
+++ b/arch/x86/coco/tdx/tdx.c
@@ -494,16 +494,44 @@ static int decode_insn_struct(struct insn *insn, struct pt_regs *regs)
char buffer[MAX_INSN_SIZE];
if (user_mode(regs)) {
- int nr_copied = insn_fetch_from_user(regs, buffer);
+ int not_copied, nr_copied, size;
+ unsigned long ip, offset;
+ char *dst, __user *src;
+
+ if (insn_get_effective_ip(regs, &ip))
+ return -EFAULT;
+
+ offset = offset_in_page(ip);
+ src = (char __user *)ip;
+
+ dst = buffer;
+ size = MAX_INSN_SIZE;
+ nr_copied = 0;
+
+ if (unlikely(offset + size > PAGE_SIZE)) {
+ size = PAGE_SIZE - offset;
+
+ not_copied = copy_from_user(dst, src, size);
+ nr_copied = size - not_copied;
+
+ if (nr_copied <= 0)
+ nr_copied = 0;
+ else if (insn_decode_from_regs(insn, regs, buffer, nr_copied))
+ goto decoded;
+
+ size = MAX_INSN_SIZE - nr_copied;
+ dst += nr_copied;
+ src += nr_copied;
+ }
+
+ not_copied = copy_from_user(dst, src, size);
+ nr_copied += size - not_copied;
if (nr_copied <= 0)
return -EFAULT;
if (!insn_decode_from_regs(insn, regs, buffer, nr_copied))
return -EINVAL;
-
- if (!insn->immediate.got)
- return -EINVAL;
} else {
if (copy_from_kernel_nofault(buffer, (void *)regs->ip, MAX_INSN_SIZE))
return -EFAULT;
@@ -511,6 +539,10 @@ static int decode_insn_struct(struct insn *insn, struct pt_regs *regs)
if (insn_decode(insn, buffer, MAX_INSN_SIZE, INSN_MODE_64))
return -EINVAL;
}
+decoded:
+ if (!insn->immediate.got)
+ return -EINVAL;
+
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment