Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Based on arch/arm/mm/extable.c
0004  */
0005 
0006 #include <linux/bitfield.h>
0007 #include <linux/extable.h>
0008 #include <linux/uaccess.h>
0009 
0010 #include <asm/asm-extable.h>
0011 #include <asm/ptrace.h>
0012 
0013 static inline unsigned long
0014 get_ex_fixup(const struct exception_table_entry *ex)
0015 {
0016     return ((unsigned long)&ex->fixup + ex->fixup);
0017 }
0018 
0019 static bool ex_handler_uaccess_err_zero(const struct exception_table_entry *ex,
0020                     struct pt_regs *regs)
0021 {
0022     int reg_err = FIELD_GET(EX_DATA_REG_ERR, ex->data);
0023     int reg_zero = FIELD_GET(EX_DATA_REG_ZERO, ex->data);
0024 
0025     pt_regs_write_reg(regs, reg_err, -EFAULT);
0026     pt_regs_write_reg(regs, reg_zero, 0);
0027 
0028     regs->pc = get_ex_fixup(ex);
0029     return true;
0030 }
0031 
0032 static bool
0033 ex_handler_load_unaligned_zeropad(const struct exception_table_entry *ex,
0034                   struct pt_regs *regs)
0035 {
0036     int reg_data = FIELD_GET(EX_DATA_REG_DATA, ex->data);
0037     int reg_addr = FIELD_GET(EX_DATA_REG_ADDR, ex->data);
0038     unsigned long data, addr, offset;
0039 
0040     addr = pt_regs_read_reg(regs, reg_addr);
0041 
0042     offset = addr & 0x7UL;
0043     addr &= ~0x7UL;
0044 
0045     data = *(unsigned long*)addr;
0046 
0047 #ifndef __AARCH64EB__
0048     data >>= 8 * offset;
0049 #else
0050     data <<= 8 * offset;
0051 #endif
0052 
0053     pt_regs_write_reg(regs, reg_data, data);
0054 
0055     regs->pc = get_ex_fixup(ex);
0056     return true;
0057 }
0058 
0059 bool fixup_exception(struct pt_regs *regs)
0060 {
0061     const struct exception_table_entry *ex;
0062 
0063     ex = search_exception_tables(instruction_pointer(regs));
0064     if (!ex)
0065         return false;
0066 
0067     switch (ex->type) {
0068     case EX_TYPE_BPF:
0069         return ex_handler_bpf(ex, regs);
0070     case EX_TYPE_UACCESS_ERR_ZERO:
0071     case EX_TYPE_KACCESS_ERR_ZERO:
0072         return ex_handler_uaccess_err_zero(ex, regs);
0073     case EX_TYPE_LOAD_UNALIGNED_ZEROPAD:
0074         return ex_handler_load_unaligned_zeropad(ex, regs);
0075     }
0076 
0077     BUG();
0078 }