xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] x86: polish __{get,put}_user_{,no}check()
@ 2017-05-02 13:23 Jan Beulich
  2017-05-02 14:28 ` Andrew Cooper
  2017-05-04  8:52 ` Julien Grall
  0 siblings, 2 replies; 7+ messages in thread
From: Jan Beulich @ 2017-05-02 13:23 UTC (permalink / raw)
  To: xen-devel; +Cc: Andrew Cooper, Julien Grall

[-- Attachment #1: Type: text/plain, Size: 3287 bytes --]

The primary purpose is correcting a latent bug in __get_user_check()
(the macro has no active user at present): The access_ok() check should
be before the actual access, or else any PV guest could initiate MMIO
reads with side effects.

Clean up all four macros at once:
- all arguments evaluated exactly once
- build the "check" flavor using the "nocheck" ones, instead of open
  coding them
- "int" is wide enough for error codes
- name local variables without using underscores as prefixes
- avoid pointless parentheses
- add blanks after commas separating parameters or arguments
- consistently use tabs for indentation

Signed-off-by: Jan Beulich <jbeulich@suse.com>
---
This corrects the code which would have resulted in an XSA on Xen 4.2
and older, if those were still security supported. For that reason I at
least want to explore whether this is a change we want to take for 4.9.

--- a/xen/include/asm-x86/uaccess.h
+++ b/xen/include/asm-x86/uaccess.h
@@ -104,37 +104,35 @@ extern void __put_user_bad(void);
 #define __put_user(x,ptr) \
   __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
 
-#define __put_user_nocheck(x,ptr,size)				\
-({								\
-	long __pu_err;						\
-	__put_user_size((x),(ptr),(size),__pu_err,-EFAULT);	\
-	__pu_err;						\
+#define __put_user_nocheck(x, ptr, size)				\
+({									\
+	int err_; 							\
+	__put_user_size(x, ptr, size, err_, -EFAULT);			\
+	err_;								\
 })
 
-#define __put_user_check(x,ptr,size)					\
+#define __put_user_check(x, ptr, size)					\
 ({									\
-	long __pu_err = -EFAULT;					\
-	__typeof__(*(ptr)) __user *__pu_addr = (ptr);			\
-	if (access_ok(__pu_addr,size))					\
-		__put_user_size((x),__pu_addr,(size),__pu_err,-EFAULT);	\
-	__pu_err;							\
+	__typeof__(*(ptr)) __user *ptr_ = (ptr);			\
+	__typeof__(size) size_ = (size);				\
+	access_ok(ptr_, size_) ? __put_user_nocheck(x, ptr_, size_)	\
+			       : -EFAULT;				\
 })							
 
-#define __get_user_nocheck(x,ptr,size)                          \
-({                                                              \
-	long __gu_err;                                          \
-	__get_user_size((x),(ptr),(size),__gu_err,-EFAULT);     \
-	__gu_err;                                               \
+#define __get_user_nocheck(x, ptr, size)				\
+({									\
+	int err_; 							\
+	__get_user_size(x, ptr, size, err_, -EFAULT);			\
+	err_;								\
 })
 
-#define __get_user_check(x,ptr,size)                            \
-({                                                              \
-	long __gu_err;                                          \
-	__typeof__(*(ptr)) __user *__gu_addr = (ptr);           \
-	__get_user_size((x),__gu_addr,(size),__gu_err,-EFAULT); \
-	if (!access_ok(__gu_addr,size)) __gu_err = -EFAULT;     \
-	__gu_err;                                               \
-})							
+#define __get_user_check(x, ptr, size)					\
+({									\
+	__typeof__(*(ptr)) __user *ptr_ = (ptr);			\
+	__typeof__(size) size_ = (size);				\
+	access_ok(ptr_, size_) ? __get_user_nocheck(x, ptr_, size_)	\
+			       : -EFAULT;				\
+})
 
 struct __large_struct { unsigned long buf[100]; };
 #define __m(x) (*(const struct __large_struct *)(x))




[-- Attachment #2: x86-get-put-user.patch --]
[-- Type: text/plain, Size: 3326 bytes --]

x86: polish __{get,put}_user_{,no}check()

The primary purpose is correcting a latent bug in __get_user_check()
(the macro has no active user at present): The access_ok() check should
be before the actual access, or else any PV guest could initiate MMIO
reads with side effects.

Clean up all four macros at once:
- all arguments evaluated exactly once
- build the "check" flavor using the "nocheck" ones, instead of open
  coding them
- "int" is wide enough for error codes
- name local variables without using underscores as prefixes
- avoid pointless parentheses
- add blanks after commas separating parameters or arguments
- consistently use tabs for indentation

Signed-off-by: Jan Beulich <jbeulich@suse.com>
---
This corrects the code which would have resulted in an XSA on Xen 4.2
and older, if those were still security supported. For that reason I at
least want to explore whether this is a change we want to take for 4.9.

--- a/xen/include/asm-x86/uaccess.h
+++ b/xen/include/asm-x86/uaccess.h
@@ -104,37 +104,35 @@ extern void __put_user_bad(void);
 #define __put_user(x,ptr) \
   __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
 
-#define __put_user_nocheck(x,ptr,size)				\
-({								\
-	long __pu_err;						\
-	__put_user_size((x),(ptr),(size),__pu_err,-EFAULT);	\
-	__pu_err;						\
+#define __put_user_nocheck(x, ptr, size)				\
+({									\
+	int err_; 							\
+	__put_user_size(x, ptr, size, err_, -EFAULT);			\
+	err_;								\
 })
 
-#define __put_user_check(x,ptr,size)					\
+#define __put_user_check(x, ptr, size)					\
 ({									\
-	long __pu_err = -EFAULT;					\
-	__typeof__(*(ptr)) __user *__pu_addr = (ptr);			\
-	if (access_ok(__pu_addr,size))					\
-		__put_user_size((x),__pu_addr,(size),__pu_err,-EFAULT);	\
-	__pu_err;							\
+	__typeof__(*(ptr)) __user *ptr_ = (ptr);			\
+	__typeof__(size) size_ = (size);				\
+	access_ok(ptr_, size_) ? __put_user_nocheck(x, ptr_, size_)	\
+			       : -EFAULT;				\
 })							
 
-#define __get_user_nocheck(x,ptr,size)                          \
-({                                                              \
-	long __gu_err;                                          \
-	__get_user_size((x),(ptr),(size),__gu_err,-EFAULT);     \
-	__gu_err;                                               \
+#define __get_user_nocheck(x, ptr, size)				\
+({									\
+	int err_; 							\
+	__get_user_size(x, ptr, size, err_, -EFAULT);			\
+	err_;								\
 })
 
-#define __get_user_check(x,ptr,size)                            \
-({                                                              \
-	long __gu_err;                                          \
-	__typeof__(*(ptr)) __user *__gu_addr = (ptr);           \
-	__get_user_size((x),__gu_addr,(size),__gu_err,-EFAULT); \
-	if (!access_ok(__gu_addr,size)) __gu_err = -EFAULT;     \
-	__gu_err;                                               \
-})							
+#define __get_user_check(x, ptr, size)					\
+({									\
+	__typeof__(*(ptr)) __user *ptr_ = (ptr);			\
+	__typeof__(size) size_ = (size);				\
+	access_ok(ptr_, size_) ? __get_user_nocheck(x, ptr_, size_)	\
+			       : -EFAULT;				\
+})
 
 struct __large_struct { unsigned long buf[100]; };
 #define __m(x) (*(const struct __large_struct *)(x))

[-- Attachment #3: Type: text/plain, Size: 127 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2017-05-04 17:53 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-05-02 13:23 [PATCH] x86: polish __{get,put}_user_{,no}check() Jan Beulich
2017-05-02 14:28 ` Andrew Cooper
2017-05-02 14:40   ` Jan Beulich
2017-05-03 19:05     ` Andrew Cooper
2017-05-04  8:52 ` Julien Grall
2017-05-04 17:52   ` Andrew Cooper
2017-05-04 17:53     ` Julien Grall

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).