From: xiaoqian <xiaoqian9@huawei.com> To: <linux@armlinux.org.uk>, <rafael.j.wysocki@intel.com>, <ebiederm@xmission.com>, <rppt@linux.ibm.com>, <pmladek@suse.com>, <bhelgaas@google.com>, <sakari.ailus@linux.intel.com>, <linux-arm-kernel@lists.infradead.org>, <gregkh@linuxfoundation.org> Cc: <linux-kernel@vger.kernel.org>, <stable@vger.kernel.org>, <xiaoqian9@huawei.com> Subject: [PATCH] Subject:alignment:fetch pc-instr before irq_enable Date: Fri, 31 May 2019 11:01:20 +0800 [thread overview] Message-ID: <1559271680-7486-1-git-send-email-xiaoqian9@huawei.com> (raw) When the instruction code under PC address is read through _probe_kernel_read in do_alignment,if the pte page corresponding to the code segment of PC address is reclaimed exactly at this time, the address mapping cannot be reconstructed because page fault_disable() is executed in _probe_kernel_read function,and the failure to obtain the instruction code of PC finally results in the unsuccessful repair operation. Thus we can modify the implementation of reading user-mode PC instruction before local_irq_enable to avoid the above risk. At the same time, adjust the sequence of code processing and optimize the process. Signed-off-by: xiaoqian <xiaoqian9@huawei.com> Cc: stable@vger.kernel.org --- arch/arm/mm/alignment.c | 81 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 55 insertions(+), 26 deletions(-) diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c index e376883ab35b..4124b9ce3c70 100644 --- a/arch/arm/mm/alignment.c +++ b/arch/arm/mm/alignment.c @@ -76,6 +76,11 @@ #define IS_T32(hi16) \ (((hi16) & 0xe000) == 0xe000 && ((hi16) & 0x1800)) +#define INVALID_INSTR_MODE 0 +#define ARM_INSTR_MODE 1 +#define THUMB_INSTR_MODE 2 +#define THUMB2_INSTR_MODE 3 + static unsigned long ai_user; static unsigned long ai_sys; static void *ai_sys_last_pc; @@ -705,6 +710,48 @@ thumb2arm(u16 tinstr) } } +static unsigned int +fetch_usr_pc_instr(struct pt_regs *regs, unsigned long *pc_instrptr) +{ + unsigned int fault; + unsigned long instrptr; + unsigned long instr_mode = INVALID_INSTR_MODE; + + instrptr = instruction_pointer(regs); + + if (thumb_mode(regs)) { + u16 tinstr = 0; + u16 *ptr = (u16 *)(instrptr & ~1); + + fault = probe_kernel_address(ptr, tinstr); + if (!fault) { + tinstr = __mem_to_opcode_thumb16(tinstr); + if (cpu_architecture() >= CPU_ARCH_ARMv7 && + IS_T32(tinstr)) { + /* Thumb-2 32-bit */ + u16 tinstr2 = 0; + + fault = probe_kernel_address(ptr + 1, tinstr2); + if (!fault) { + tinstr2 = __mem_to_opcode_thumb16(tinstr2); + *pc_instrptr = __opcode_thumb32_compose(tinstr, tinstr2); + instr_mode = THUMB2_INSTR_MODE; + } + } else { + *pc_instrptr = thumb2arm(tinstr); + instr_mode = THUMB_INSTR_MODE; + } + } + } else { + fault = probe_kernel_address((void *)instrptr, *pc_instrptr); + if (!fault) { + *pc_instrptr = __mem_to_opcode_arm(*pc_instrptr); + instr_mode = ARM_INSTR_MODE; + } + } + return instr_mode; +} + /* * Convert Thumb-2 32 bit LDM, STM, LDRD, STRD to equivalent instruction * handlable by ARM alignment handler, also find the corresponding handler, @@ -775,42 +822,24 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs) unsigned long instr = 0, instrptr; int (*handler)(unsigned long addr, unsigned long instr, struct pt_regs *regs); unsigned int type; - unsigned int fault; u16 tinstr = 0; int isize = 4; int thumb2_32b = 0; + unsigned long pc_instr_mode; + + pc_instr_mode = fetch_usr_pc_instr(regs, &instr); if (interrupts_enabled(regs)) local_irq_enable(); instrptr = instruction_pointer(regs); - - if (thumb_mode(regs)) { - u16 *ptr = (u16 *)(instrptr & ~1); - fault = probe_kernel_address(ptr, tinstr); - tinstr = __mem_to_opcode_thumb16(tinstr); - if (!fault) { - if (cpu_architecture() >= CPU_ARCH_ARMv7 && - IS_T32(tinstr)) { - /* Thumb-2 32-bit */ - u16 tinst2 = 0; - fault = probe_kernel_address(ptr + 1, tinst2); - tinst2 = __mem_to_opcode_thumb16(tinst2); - instr = __opcode_thumb32_compose(tinstr, tinst2); - thumb2_32b = 1; - } else { - isize = 2; - instr = thumb2arm(tinstr); - } - } - } else { - fault = probe_kernel_address((void *)instrptr, instr); - instr = __mem_to_opcode_arm(instr); - } - - if (fault) { + if (pc_instr_mode == INVALID_INSTR_MODE) { type = TYPE_FAULT; goto bad_or_fault; + } else if (pc_instr_mode == THUMB_INSTR_MODE) { + isize = 2; + } else if (pc_instr_mode == THUMB2_INSTR_MODE) { + thumb2_32b = 1; } if (user_mode(regs)) -- 2.12.3
WARNING: multiple messages have this Message-ID (diff)
From: xiaoqian <xiaoqian9@huawei.com> To: <linux@armlinux.org.uk>, <rafael.j.wysocki@intel.com>, <ebiederm@xmission.com>, <rppt@linux.ibm.com>, <pmladek@suse.com>, <bhelgaas@google.com>, <sakari.ailus@linux.intel.com>, <linux-arm-kernel@lists.infradead.org>, <gregkh@linuxfoundation.org> Cc: xiaoqian9@huawei.com, linux-kernel@vger.kernel.org, stable@vger.kernel.org Subject: [PATCH] Subject:alignment:fetch pc-instr before irq_enable Date: Fri, 31 May 2019 11:01:20 +0800 [thread overview] Message-ID: <1559271680-7486-1-git-send-email-xiaoqian9@huawei.com> (raw) When the instruction code under PC address is read through _probe_kernel_read in do_alignment,if the pte page corresponding to the code segment of PC address is reclaimed exactly at this time, the address mapping cannot be reconstructed because page fault_disable() is executed in _probe_kernel_read function,and the failure to obtain the instruction code of PC finally results in the unsuccessful repair operation. Thus we can modify the implementation of reading user-mode PC instruction before local_irq_enable to avoid the above risk. At the same time, adjust the sequence of code processing and optimize the process. Signed-off-by: xiaoqian <xiaoqian9@huawei.com> Cc: stable@vger.kernel.org --- arch/arm/mm/alignment.c | 81 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 55 insertions(+), 26 deletions(-) diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c index e376883ab35b..4124b9ce3c70 100644 --- a/arch/arm/mm/alignment.c +++ b/arch/arm/mm/alignment.c @@ -76,6 +76,11 @@ #define IS_T32(hi16) \ (((hi16) & 0xe000) == 0xe000 && ((hi16) & 0x1800)) +#define INVALID_INSTR_MODE 0 +#define ARM_INSTR_MODE 1 +#define THUMB_INSTR_MODE 2 +#define THUMB2_INSTR_MODE 3 + static unsigned long ai_user; static unsigned long ai_sys; static void *ai_sys_last_pc; @@ -705,6 +710,48 @@ thumb2arm(u16 tinstr) } } +static unsigned int +fetch_usr_pc_instr(struct pt_regs *regs, unsigned long *pc_instrptr) +{ + unsigned int fault; + unsigned long instrptr; + unsigned long instr_mode = INVALID_INSTR_MODE; + + instrptr = instruction_pointer(regs); + + if (thumb_mode(regs)) { + u16 tinstr = 0; + u16 *ptr = (u16 *)(instrptr & ~1); + + fault = probe_kernel_address(ptr, tinstr); + if (!fault) { + tinstr = __mem_to_opcode_thumb16(tinstr); + if (cpu_architecture() >= CPU_ARCH_ARMv7 && + IS_T32(tinstr)) { + /* Thumb-2 32-bit */ + u16 tinstr2 = 0; + + fault = probe_kernel_address(ptr + 1, tinstr2); + if (!fault) { + tinstr2 = __mem_to_opcode_thumb16(tinstr2); + *pc_instrptr = __opcode_thumb32_compose(tinstr, tinstr2); + instr_mode = THUMB2_INSTR_MODE; + } + } else { + *pc_instrptr = thumb2arm(tinstr); + instr_mode = THUMB_INSTR_MODE; + } + } + } else { + fault = probe_kernel_address((void *)instrptr, *pc_instrptr); + if (!fault) { + *pc_instrptr = __mem_to_opcode_arm(*pc_instrptr); + instr_mode = ARM_INSTR_MODE; + } + } + return instr_mode; +} + /* * Convert Thumb-2 32 bit LDM, STM, LDRD, STRD to equivalent instruction * handlable by ARM alignment handler, also find the corresponding handler, @@ -775,42 +822,24 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs) unsigned long instr = 0, instrptr; int (*handler)(unsigned long addr, unsigned long instr, struct pt_regs *regs); unsigned int type; - unsigned int fault; u16 tinstr = 0; int isize = 4; int thumb2_32b = 0; + unsigned long pc_instr_mode; + + pc_instr_mode = fetch_usr_pc_instr(regs, &instr); if (interrupts_enabled(regs)) local_irq_enable(); instrptr = instruction_pointer(regs); - - if (thumb_mode(regs)) { - u16 *ptr = (u16 *)(instrptr & ~1); - fault = probe_kernel_address(ptr, tinstr); - tinstr = __mem_to_opcode_thumb16(tinstr); - if (!fault) { - if (cpu_architecture() >= CPU_ARCH_ARMv7 && - IS_T32(tinstr)) { - /* Thumb-2 32-bit */ - u16 tinst2 = 0; - fault = probe_kernel_address(ptr + 1, tinst2); - tinst2 = __mem_to_opcode_thumb16(tinst2); - instr = __opcode_thumb32_compose(tinstr, tinst2); - thumb2_32b = 1; - } else { - isize = 2; - instr = thumb2arm(tinstr); - } - } - } else { - fault = probe_kernel_address((void *)instrptr, instr); - instr = __mem_to_opcode_arm(instr); - } - - if (fault) { + if (pc_instr_mode == INVALID_INSTR_MODE) { type = TYPE_FAULT; goto bad_or_fault; + } else if (pc_instr_mode == THUMB_INSTR_MODE) { + isize = 2; + } else if (pc_instr_mode == THUMB2_INSTR_MODE) { + thumb2_32b = 1; } if (user_mode(regs)) -- 2.12.3 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
next reply other threads:[~2019-05-31 3:02 UTC|newest] Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top 2019-05-31 3:01 xiaoqian [this message] 2019-05-31 3:01 ` [PATCH] Subject:alignment:fetch pc-instr before irq_enable xiaoqian
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=1559271680-7486-1-git-send-email-xiaoqian9@huawei.com \ --to=xiaoqian9@huawei.com \ --cc=bhelgaas@google.com \ --cc=ebiederm@xmission.com \ --cc=gregkh@linuxfoundation.org \ --cc=linux-arm-kernel@lists.infradead.org \ --cc=linux-kernel@vger.kernel.org \ --cc=linux@armlinux.org.uk \ --cc=pmladek@suse.com \ --cc=rafael.j.wysocki@intel.com \ --cc=rppt@linux.ibm.com \ --cc=sakari.ailus@linux.intel.com \ --cc=stable@vger.kernel.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.