patch-2.4.0-test7 linux/include/asm-arm/uaccess.h
Next file: linux/include/asm-arm/unaligned.h
Previous file: linux/include/asm-arm/termios.h
Back to the patch index
Back to the overall index
- Lines: 116
- Date:
Sun Aug 13 09:54:15 2000
- Orig file:
v2.4.0-test6/linux/include/asm-arm/uaccess.h
- Orig date:
Fri Oct 22 13:21:53 1999
diff -u --recursive --new-file v2.4.0-test6/linux/include/asm-arm/uaccess.h linux/include/asm-arm/uaccess.h
@@ -46,7 +46,14 @@
/*
* Single-value transfer routines. They automatically use the right
- * size if we just have the right pointer type.
+ * size if we just have the right pointer type. Note that the functions
+ * which read from user space (*get_*) need to take care not to leak
+ * kernel data even if the calling code is buggy and fails to check
+ * the return value. This means zeroing out the destination variable
+ * or buffer on error. Normally this is done out of line by the
+ * fixup code, but there are a few places where it intrudes on the
+ * main code path. When we only write to user space, there is no
+ * problem.
*
* The "__xxx" versions of the user access functions do not verify the
* address space - it must have been done previously with a separate
@@ -54,24 +61,27 @@
*
* The "xxx_ret" versions return constant specified in the third
* argument if something bad happens.
+ *
+ * The "xxx_error" versions set the third argument to EFAULT if an
+ * error occurs, and leave it unchanged on success. Note that these
+ * versions are void (ie, don't return a value as such).
*/
#define get_user(x,p) __get_user_check((x),(p),sizeof(*(p)))
#define __get_user(x,p) __get_user_nocheck((x),(p),sizeof(*(p)))
+#define __get_user_error(x,p,e) __get_user_nocheck_error((x),(p),sizeof(*(p)),(e))
#define get_user_ret(x,p,r) ({ if (get_user(x,p)) return r; })
#define __get_user_ret(x,p,r) ({ if (__get_user(x,p)) return r; })
#define put_user(x,p) __put_user_check((__typeof(*(p)))(x),(p),sizeof(*(p)))
#define __put_user(x,p) __put_user_nocheck((__typeof(*(p)))(x),(p),sizeof(*(p)))
+#define __put_user_error(x,p,e) __put_user_nocheck_error((x),(p),sizeof(*(p)),(e))
#define put_user_ret(x,p,r) ({ if (put_user(x,p)) return r; })
#define __put_user_ret(x,p,r) ({ if (__put_user(x,p)) return r; })
static __inline__ unsigned long copy_from_user(void *to, const void *from, unsigned long n)
{
- char *end = (char *)to + n;
- if (access_ok(VERIFY_READ, from, n)) {
+ if (access_ok(VERIFY_READ, from, n))
__do_copy_from_user(to, from, n);
- if (n) memset(end - n, 0, n);
- }
return n;
}
@@ -147,26 +157,38 @@
({ \
long __gu_err = -EFAULT, __gu_val = 0; \
const __typeof__(*(ptr)) *__gu_addr = (ptr); \
- if (access_ok(VERIFY_READ,__gu_addr,size)) \
+ if (access_ok(VERIFY_READ,__gu_addr,size)) { \
+ __gu_err = 0; \
__get_user_size(__gu_val,__gu_addr,(size),__gu_err); \
+ } \
(x) = (__typeof__(*(ptr)))__gu_val; \
__gu_err; \
})
#define __get_user_nocheck(x,ptr,size) \
({ \
- long __gu_err = 0, __gu_val = 0; \
+ long __gu_err = 0, __gu_val; \
__get_user_size(__gu_val,(ptr),(size),__gu_err); \
(x) = (__typeof__(*(ptr)))__gu_val; \
__gu_err; \
})
+#define __get_user_nocheck_error(x,ptr,size,err) \
+({ \
+ long __gu_val; \
+ __get_user_size(__gu_val,(ptr),(size),(err)); \
+ (x) = (__typeof__(*(ptr)))__gu_val; \
+ (void) 0; \
+})
+
#define __put_user_check(x,ptr,size) \
({ \
long __pu_err = -EFAULT; \
__typeof__(*(ptr)) *__pu_addr = (ptr); \
- if (access_ok(VERIFY_WRITE,__pu_addr,size)) \
+ if (access_ok(VERIFY_WRITE,__pu_addr,size)) { \
+ __pu_err = 0; \
__put_user_size((x),__pu_addr,(size),__pu_err); \
+ } \
__pu_err; \
})
@@ -177,11 +199,16 @@
__pu_err; \
})
+#define __put_user_nocheck_error(x,ptr,size,err) \
+({ \
+ __put_user_size((x),(ptr),(size),err); \
+ (void) 0; \
+})
+
extern long __get_user_bad(void);
#define __get_user_size(x,ptr,size,retval) \
do { \
- retval = 0; \
switch (size) { \
case 1: __get_user_asm_byte(x,ptr,retval); break; \
case 2: __get_user_asm_half(x,ptr,retval); break; \
@@ -194,7 +221,6 @@
#define __put_user_size(x,ptr,size,retval) \
do { \
- retval = 0; \
switch (size) { \
case 1: __put_user_asm_byte(x,ptr,retval); break; \
case 2: __put_user_asm_half(x,ptr,retval); break; \
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)