Message ID | 20200506034050.24806-17-jniethe5@gmail.com (mailing list archive) |
---|---|
State | Accepted |
Commit | 5249385ad7f0ac178433f0ae9cc5b64612c8ff77 |
Headers | show |
Series | Initial Prefixed Instruction support | expand |
Context | Check | Description |
---|---|---|
snowpatch_ozlabs/apply_patch | success | Successfully applied on branch powerpc/merge (1bc92fe3175eb26ff37e580c0383d7a9abe06835) |
snowpatch_ozlabs/checkpatch | success | total: 0 errors, 0 warnings, 0 checks, 35 lines checked |
snowpatch_ozlabs/needsstable | success | Patch has no Fixes tags |
Jordan Niethe <jniethe5@gmail.com> writes: > Define specific __get_user_instr() and __get_user_instr_inatomic() > macros for reading instructions from user space. At least for fix_alignment() we could be coming from the kernel, not sure about the other cases. I can tweak the change log. > diff --git a/arch/powerpc/include/asm/uaccess.h b/arch/powerpc/include/asm/uaccess.h > index 2f500debae21..c0a35e4586a5 100644 > --- a/arch/powerpc/include/asm/uaccess.h > +++ b/arch/powerpc/include/asm/uaccess.h > @@ -105,6 +105,11 @@ static inline int __access_ok(unsigned long addr, unsigned long size, > #define __put_user_inatomic(x, ptr) \ > __put_user_nosleep((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr))) > > +#define __get_user_instr(x, ptr) \ > + __get_user_nocheck((x).val, (u32 *)(ptr), sizeof(u32), true) > + > +#define __get_user_instr_inatomic(x, ptr) \ > + __get_user_nosleep((x).val, (u32 *)(ptr), sizeof(u32)) I'm not super keen on adding new __ versions, which lack the access_ok() check, but I guess we have to. > diff --git a/arch/powerpc/kernel/vecemu.c b/arch/powerpc/kernel/vecemu.c > index 3dd70eeb10c5..60ed5aea8d4e 100644 > --- a/arch/powerpc/kernel/vecemu.c > +++ b/arch/powerpc/kernel/vecemu.c > @@ -266,7 +266,7 @@ int emulate_altivec(struct pt_regs *regs) > unsigned int va, vb, vc, vd; > vector128 *vrs; > > - if (get_user(instr.val, (unsigned int __user *)regs->nip)) > + if (__get_user_instr(instr, (void __user *)regs->nip)) > return -EFAULT; That drops the access_ok() check, which is not OK, at least without a reasonable justification. Given it's regs->nip I guess it should be safe, but it should still be called out. Or preferably switched to __get_user() in a precursor patch. cheers
On Thu, May 14, 2020 at 12:17 AM Michael Ellerman <mpe@ellerman.id.au> wrote: > > Jordan Niethe <jniethe5@gmail.com> writes: > > Define specific __get_user_instr() and __get_user_instr_inatomic() > > macros for reading instructions from user space. > > At least for fix_alignment() we could be coming from the kernel, not > sure about the other cases. > > I can tweak the change log. > > > diff --git a/arch/powerpc/include/asm/uaccess.h b/arch/powerpc/include/asm/uaccess.h > > index 2f500debae21..c0a35e4586a5 100644 > > --- a/arch/powerpc/include/asm/uaccess.h > > +++ b/arch/powerpc/include/asm/uaccess.h > > @@ -105,6 +105,11 @@ static inline int __access_ok(unsigned long addr, unsigned long size, > > #define __put_user_inatomic(x, ptr) \ > > __put_user_nosleep((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr))) > > > > +#define __get_user_instr(x, ptr) \ > > + __get_user_nocheck((x).val, (u32 *)(ptr), sizeof(u32), true) > > + > > +#define __get_user_instr_inatomic(x, ptr) \ > > + __get_user_nosleep((x).val, (u32 *)(ptr), sizeof(u32)) > > I'm not super keen on adding new __ versions, which lack the access_ok() > check, but I guess we have to. > > > diff --git a/arch/powerpc/kernel/vecemu.c b/arch/powerpc/kernel/vecemu.c > > index 3dd70eeb10c5..60ed5aea8d4e 100644 > > --- a/arch/powerpc/kernel/vecemu.c > > +++ b/arch/powerpc/kernel/vecemu.c > > @@ -266,7 +266,7 @@ int emulate_altivec(struct pt_regs *regs) > > unsigned int va, vb, vc, vd; > > vector128 *vrs; > > > > - if (get_user(instr.val, (unsigned int __user *)regs->nip)) > > + if (__get_user_instr(instr, (void __user *)regs->nip)) > > return -EFAULT; > > That drops the access_ok() check, which is not OK, at least without a > reasonable justification. > > Given it's regs->nip I guess it should be safe, but it should still be > called out. Or preferably switched to __get_user() in a precursor patch. Or should I add a get_user_instr() that includes the check? > > cheers
Hi mpe, could you please take this. arch/powerpc/include/asm/uaccess.h | 3 +++ arch/powerpc/kernel/vecemu.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/include/asm/uaccess.h b/arch/powerpc/include/asm/uaccess.h --- a/arch/powerpc/include/asm/uaccess.h +++ b/arch/powerpc/include/asm/uaccess.h @@ -105,6 +105,9 @@ static inline int __access_ok(unsigned long addr, unsigned long size, #define __put_user_inatomic(x, ptr) \ __put_user_nosleep((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr))) +#define get_user_instr(x, ptr) \ + get_user((x).val, (u32 *)(ptr)) + #define __get_user_instr(x, ptr) \ __get_user_nocheck((x).val, (u32 *)(ptr), sizeof(u32), true) diff --git a/arch/powerpc/kernel/vecemu.c b/arch/powerpc/kernel/vecemu.c index 60ed5aea8d4e..ae632569446f 100644 --- a/arch/powerpc/kernel/vecemu.c +++ b/arch/powerpc/kernel/vecemu.c @@ -266,7 +266,7 @@ int emulate_altivec(struct pt_regs *regs) unsigned int va, vb, vc, vd; vector128 *vrs; - if (__get_user_instr(instr, (void __user *)regs->nip)) + if (get_user_instr(instr, (void __user *)regs->nip)) return -EFAULT; word = ppc_inst_val(instr);
diff --git a/arch/powerpc/include/asm/uaccess.h b/arch/powerpc/include/asm/uaccess.h index 2f500debae21..c0a35e4586a5 100644 --- a/arch/powerpc/include/asm/uaccess.h +++ b/arch/powerpc/include/asm/uaccess.h @@ -105,6 +105,11 @@ static inline int __access_ok(unsigned long addr, unsigned long size, #define __put_user_inatomic(x, ptr) \ __put_user_nosleep((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr))) +#define __get_user_instr(x, ptr) \ + __get_user_nocheck((x).val, (u32 *)(ptr), sizeof(u32), true) + +#define __get_user_instr_inatomic(x, ptr) \ + __get_user_nosleep((x).val, (u32 *)(ptr), sizeof(u32)) extern long __put_user_bad(void); /* diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c index 9e66e6c62354..b8f56052c6fe 100644 --- a/arch/powerpc/kernel/align.c +++ b/arch/powerpc/kernel/align.c @@ -304,7 +304,7 @@ int fix_alignment(struct pt_regs *regs) */ CHECK_FULL_REGS(regs); - if (unlikely(__get_user(instr.val, (unsigned int __user *)regs->nip))) + if (unlikely(__get_user_instr(instr, (void __user *)regs->nip))) return -EFAULT; if ((regs->msr & MSR_LE) != (MSR_KERNEL & MSR_LE)) { /* We don't handle PPC little-endian any more... */ diff --git a/arch/powerpc/kernel/hw_breakpoint.c b/arch/powerpc/kernel/hw_breakpoint.c index 2db9a7ac7bcb..423603c92c0f 100644 --- a/arch/powerpc/kernel/hw_breakpoint.c +++ b/arch/powerpc/kernel/hw_breakpoint.c @@ -249,7 +249,7 @@ static bool stepping_handler(struct pt_regs *regs, struct perf_event *bp, struct instruction_op op; unsigned long addr = info->address; - if (__get_user_inatomic(instr.val, (unsigned int *)regs->nip)) + if (__get_user_instr_inatomic(instr, (void __user *)regs->nip)) goto fail; ret = analyse_instr(&op, regs, instr); diff --git a/arch/powerpc/kernel/vecemu.c b/arch/powerpc/kernel/vecemu.c index 3dd70eeb10c5..60ed5aea8d4e 100644 --- a/arch/powerpc/kernel/vecemu.c +++ b/arch/powerpc/kernel/vecemu.c @@ -266,7 +266,7 @@ int emulate_altivec(struct pt_regs *regs) unsigned int va, vb, vc, vd; vector128 *vrs; - if (get_user(instr.val, (unsigned int __user *)regs->nip)) + if (__get_user_instr(instr, (void __user *)regs->nip)) return -EFAULT; word = ppc_inst_val(instr);