Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f8f2d4bd authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull arm64 fixes from Catalin Marinas:

 - avoid potential stack information leak via the ptrace ABI caused by
   uninitialised variables

 - SWIOTLB DMA API fall-back allocation fix when the SWIOTLB buffer is
   not initialised (all RAM is suitable for 32-bit DMA masks)

 - fix the bad_mode function returning for unhandled exceptions coming
   from user space

 - fix name clash in __page_to_voff()

* tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux:
  arm64: avoid returning from bad_mode
  arm64/ptrace: Reject attempts to set incomplete hardware breakpoint fields
  arm64/ptrace: Avoid uninitialised struct padding in fpr_set()
  arm64/ptrace: Preserve previous registers for short regset write
  arm64/ptrace: Preserve previous registers for short regset write
  arm64/ptrace: Preserve previous registers for short regset write
  arm64: mm: avoid name clash in __page_to_voff()
  arm64: Fix swiotlb fallback allocation
parents 44b4b461 7d9e8f71
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -222,7 +222,7 @@ static inline void *phys_to_virt(phys_addr_t x)
#define _virt_addr_valid(kaddr)	pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
#else
#define __virt_to_pgoff(kaddr)	(((u64)(kaddr) & ~PAGE_OFFSET) / PAGE_SIZE * sizeof(struct page))
#define __page_to_voff(page)	(((u64)(page) & ~VMEMMAP_START) * PAGE_SIZE / sizeof(struct page))
#define __page_to_voff(kaddr)	(((u64)(kaddr) & ~VMEMMAP_START) * PAGE_SIZE / sizeof(struct page))

#define page_to_virt(page)	((void *)((__page_to_voff(page)) | PAGE_OFFSET))
#define virt_to_page(vaddr)	((struct page *)((__virt_to_pgoff(vaddr)) | VMEMMAP_START))
+1 −0
Original line number Diff line number Diff line
@@ -77,6 +77,7 @@ struct user_fpsimd_state {
	__uint128_t	vregs[32];
	__u32		fpsr;
	__u32		fpcr;
	__u32		__reserved[2];
};

struct user_hwdebug_state {
+1 −1
Original line number Diff line number Diff line
@@ -683,7 +683,7 @@ el0_inv:
	mov	x0, sp
	mov	x1, #BAD_SYNC
	mov	x2, x25
	bl	bad_mode
	bl	bad_el0_sync
	b	ret_to_user
ENDPROC(el0_sync)

+11 −5
Original line number Diff line number Diff line
@@ -551,6 +551,8 @@ static int hw_break_set(struct task_struct *target,
	/* (address, ctrl) registers */
	limit = regset->n * regset->size;
	while (count && offset < limit) {
		if (count < PTRACE_HBP_ADDR_SZ)
			return -EINVAL;
		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &addr,
					 offset, offset + PTRACE_HBP_ADDR_SZ);
		if (ret)
@@ -560,6 +562,8 @@ static int hw_break_set(struct task_struct *target,
			return ret;
		offset += PTRACE_HBP_ADDR_SZ;

		if (!count)
			break;
		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &ctrl,
					 offset, offset + PTRACE_HBP_CTRL_SZ);
		if (ret)
@@ -596,7 +600,7 @@ static int gpr_set(struct task_struct *target, const struct user_regset *regset,
		   const void *kbuf, const void __user *ubuf)
{
	int ret;
	struct user_pt_regs newregs;
	struct user_pt_regs newregs = task_pt_regs(target)->user_regs;

	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &newregs, 0, -1);
	if (ret)
@@ -626,7 +630,8 @@ static int fpr_set(struct task_struct *target, const struct user_regset *regset,
		   const void *kbuf, const void __user *ubuf)
{
	int ret;
	struct user_fpsimd_state newstate;
	struct user_fpsimd_state newstate =
		target->thread.fpsimd_state.user_fpsimd;

	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &newstate, 0, -1);
	if (ret)
@@ -650,7 +655,7 @@ static int tls_set(struct task_struct *target, const struct user_regset *regset,
		   const void *kbuf, const void __user *ubuf)
{
	int ret;
	unsigned long tls;
	unsigned long tls = target->thread.tp_value;

	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &tls, 0, -1);
	if (ret)
@@ -676,7 +681,8 @@ static int system_call_set(struct task_struct *target,
			   unsigned int pos, unsigned int count,
			   const void *kbuf, const void __user *ubuf)
{
	int syscallno, ret;
	int syscallno = task_pt_regs(target)->syscallno;
	int ret;

	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &syscallno, 0, -1);
	if (ret)
@@ -948,7 +954,7 @@ static int compat_tls_set(struct task_struct *target,
			  const void __user *ubuf)
{
	int ret;
	compat_ulong_t tls;
	compat_ulong_t tls = target->thread.tp_value;

	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &tls, 0, -1);
	if (ret)
+24 −4
Original line number Diff line number Diff line
@@ -604,17 +604,34 @@ const char *esr_get_class_string(u32 esr)
}

/*
 * bad_mode handles the impossible case in the exception vector.
 * bad_mode handles the impossible case in the exception vector. This is always
 * fatal.
 */
asmlinkage void bad_mode(struct pt_regs *regs, int reason, unsigned int esr)
{
	siginfo_t info;
	void __user *pc = (void __user *)instruction_pointer(regs);
	console_verbose();

	pr_crit("Bad mode in %s handler detected on CPU%d, code 0x%08x -- %s\n",
		handler[reason], smp_processor_id(), esr,
		esr_get_class_string(esr));

	die("Oops - bad mode", regs, 0);
	local_irq_disable();
	panic("bad mode");
}

/*
 * bad_el0_sync handles unexpected, but potentially recoverable synchronous
 * exceptions taken from EL0. Unlike bad_mode, this returns.
 */
asmlinkage void bad_el0_sync(struct pt_regs *regs, int reason, unsigned int esr)
{
	siginfo_t info;
	void __user *pc = (void __user *)instruction_pointer(regs);
	console_verbose();

	pr_crit("Bad EL0 synchronous exception detected on CPU%d, code 0x%08x -- %s\n",
		smp_processor_id(), esr, esr_get_class_string(esr));
	__show_regs(regs);

	info.si_signo = SIGILL;
@@ -622,7 +639,10 @@ asmlinkage void bad_mode(struct pt_regs *regs, int reason, unsigned int esr)
	info.si_code  = ILL_ILLOPC;
	info.si_addr  = pc;

	arm64_notify_die("Oops - bad mode", regs, &info, 0);
	current->thread.fault_address = 0;
	current->thread.fault_code = 0;

	force_sig_info(info.si_signo, &info, current);
}

void __pte_error(const char *file, int line, unsigned long val)
Loading