Commit 7ba68b21 authored by Jordan Niethe's avatar Jordan Niethe Committed by Michael Ellerman
Browse files

powerpc: Add a probe_user_read_inst() function



Introduce a probe_user_read_inst() function to use in cases where
probe_user_read() is used for getting an instruction. This will be
more useful for prefixed instructions.

Signed-off-by: default avatarJordan Niethe <jniethe5@gmail.com>
Reviewed-by: default avatarAlistair Popple <alistair@popple.id.au>
[mpe: Don't write to *inst on error, fold in __user annotations]
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20200506034050.24806-14-jniethe5@gmail.com
parent f8faaffa
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -37,4 +37,7 @@ static inline bool ppc_inst_equal(struct ppc_inst x, struct ppc_inst y)
	return ppc_inst_val(x) == ppc_inst_val(y);
}

int probe_user_read_inst(struct ppc_inst *inst,
			 struct ppc_inst __user *nip);

#endif /* _ASM_POWERPC_INST_H */
+1 −1
Original line number Diff line number Diff line
@@ -16,7 +16,7 @@ CFLAGS_code-patching.o += -DDISABLE_BRANCH_PROFILING
CFLAGS_feature-fixups.o += -DDISABLE_BRANCH_PROFILING
endif

obj-y += alloc.o code-patching.o feature-fixups.o pmem.o
obj-y += alloc.o code-patching.o feature-fixups.o pmem.o inst.o

ifndef CONFIG_KASAN
obj-y	+=	string.o memcmp_$(BITS).o
+20 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 *  Copyright 2020, IBM Corporation.
 */

#include <linux/uaccess.h>
#include <asm/inst.h>

int probe_user_read_inst(struct ppc_inst *inst,
			 struct ppc_inst __user *nip)
{
	unsigned int val;
	int err;

	err = probe_user_read(&val, nip, sizeof(val));
	if (!err)
		*inst = ppc_inst(val);

	return err;
}
+2 −2
Original line number Diff line number Diff line
@@ -282,7 +282,7 @@ static bool bad_stack_expansion(struct pt_regs *regs, unsigned long address,
	 * expand to 1MB without further checks.
	 */
	if (address + 0x100000 < vma->vm_end) {
		unsigned int __user *nip = (unsigned int __user *)regs->nip;
		struct ppc_inst __user *nip = (struct ppc_inst __user *)regs->nip;
		/* get user regs even if this fault is in kernel mode */
		struct pt_regs *uregs = current->thread.regs;
		if (uregs == NULL)
@@ -307,7 +307,7 @@ static bool bad_stack_expansion(struct pt_regs *regs, unsigned long address,
		    access_ok(nip, sizeof(*nip))) {
			struct ppc_inst inst;

			if (!probe_user_read(&inst, nip, sizeof(inst)))
			if (!probe_user_read_inst(&inst, nip))
				return !store_updates_sp(inst);
			*must_retry = true;
		}