On Thu, Mar 26, 2015 at 11:33:53AM -0700, Dave Hansen wrote: > > From: Dave Hansen <dave.han...@linux.intel.com> > > user_atomic_cmpxchg_inatomic() actually looks at sizeof(*ptr) to > figure out how many bytes to copy. If we run it on a 64-bit > kernel with a 64-bit pointer, it will copy a 64-bit bounds > directory entry. That's fine, except when we have 32-bit > programs with 32-bit bounds directory entries and we only *want* > 32-bits. > > This patch breaks the cmpxchg operation out in to its own > function and performs the 32-bit type swizzling in there. > > Note, the "64-bit" version of this code _would_ work on a > 32-bit-only kernel. The issue this patch addresses is only for > when the kernel's 'long' is mismatched from the size of the > bounds directory entry of the process we are working on. > > The new helper modifies 'actual_old_val' or returns an error. > But gcc doesn't know this, so it warns about 'actual_old_val' > being unused. Shut it up with an uninitialized_var(). > > Signed-off-by: Dave Hansen <dave.han...@linux.intel.com> > --- > > b/arch/x86/mm/mpx.c | 41 ++++++++++++++++++++++++++++++++++++----- > 1 file changed, 36 insertions(+), 5 deletions(-) > > diff -puN arch/x86/mm/mpx.c~mpx-variable-sized-userspace-pokes > arch/x86/mm/mpx.c > --- a/arch/x86/mm/mpx.c~mpx-variable-sized-userspace-pokes 2015-03-26 > 11:27:33.927520821 -0700 > +++ b/arch/x86/mm/mpx.c 2015-03-26 11:27:33.931521001 -0700 > @@ -421,6 +421,35 @@ int mpx_disable_management(struct task_s > return 0; > } > > +static int mpx_cmpxchg_bd_entry(struct mm_struct *mm, > + unsigned long *actual_old_val_ptr, long __user *bd_entry_addr, > + unsigned long expected_old_val, unsigned long new_bd_entry) > +{ > + int ret; > + /* > + * user_atomic_cmpxchg_inatomic() actually uses sizeof() > + * the pointer thatt we pass to it to figure out how much > + * data to cmpxchg. We have to be careful here not to > + * pass a pointer to a 64-bit data type when we only want > + * a 32-bit copy. > + */ > + if (is_64bit_mm(mm)) { > + ret = user_atomic_cmpxchg_inatomic(actual_old_val_ptr, > + bd_entry_addr, expected_old_val, new_bd_entry); > + } else { > + u32 uninitialized_var(actual_old_val_32); > + u32 expected_old_val_32 = expected_old_val; > + u32 new_bd_entry_32 = new_bd_entry; > + u32 __user *bd_entry_32 = (u32 __user *)bd_entry_addr; > + ret = user_atomic_cmpxchg_inatomic(&actual_old_val_32, > + bd_entry_32, expected_old_val_32, > + new_bd_entry_32);
Hmm, I would've added a user_atomic_cmpxchg_inatomic_size() macro which calls __user_atomic_cmpxchg_inatomic(). -- Regards/Gruss, Boris. ECO tip #101: Trim your mails when you reply. -- -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/