extable.c 1.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include <linux/err.h>
  3. #include <linux/mm.h>
  4. #include <asm/current.h>
  5. #include <asm/traps.h>
  6. #include <asm/vdso.h>
  7. struct vdso_exception_table_entry {
  8. int insn, fixup;
  9. };
  10. bool fixup_vdso_exception(struct pt_regs *regs, int trapnr,
  11. unsigned long error_code, unsigned long fault_addr)
  12. {
  13. const struct vdso_image *image = current->mm->context.vdso_image;
  14. const struct vdso_exception_table_entry *extable;
  15. unsigned int nr_entries, i;
  16. unsigned long base;
  17. /*
  18. * Do not attempt to fixup #DB or #BP. It's impossible to identify
  19. * whether or not a #DB/#BP originated from within an SGX enclave and
  20. * SGX enclaves are currently the only use case for vDSO fixup.
  21. */
  22. if (trapnr == X86_TRAP_DB || trapnr == X86_TRAP_BP)
  23. return false;
  24. if (!current->mm->context.vdso)
  25. return false;
  26. base = (unsigned long)current->mm->context.vdso + image->extable_base;
  27. nr_entries = image->extable_len / (sizeof(*extable));
  28. extable = image->extable;
  29. for (i = 0; i < nr_entries; i++) {
  30. if (regs->ip == base + extable[i].insn) {
  31. regs->ip = base + extable[i].fixup;
  32. regs->di = trapnr;
  33. regs->si = error_code;
  34. regs->dx = fault_addr;
  35. return true;
  36. }
  37. }
  38. return false;
  39. }