From: Hugh Dickins <hugh@veritas.com>

4G/4G get_user_size and put_user_size are still not quite right in the
KERNEL_DS case: Manfred found the original memcpys wrong, we fixed them
to direct_copys then __direct_copys; now use by kdb's md command proves
we shouldn't assume success 0, but return the actual residue; and to
perfectly imitate non-4G/4G behaviour, I suppose get_user_size should
even memset to 0 in the KERNEL_DS case of residue.



 mm/usercopy.c |   18 ++++++++----------
 1 files changed, 8 insertions(+), 10 deletions(-)

diff -puN mm/usercopy.c~4g4g-KERNEL_DS-usercopy-fix mm/usercopy.c
--- 25/mm/usercopy.c~4g4g-KERNEL_DS-usercopy-fix	2003-11-02 11:51:12.000000000 -0800
+++ 25-akpm/mm/usercopy.c	2003-11-02 11:51:12.000000000 -0800
@@ -191,11 +191,10 @@ int get_user_size(unsigned int size, voi
 {
 	int ret;
 
-	if (unlikely(segment_eq(get_fs(), KERNEL_DS))) {
-		__direct_copy_from_user(val, ptr, size);
-		return 0;
-	}
-	ret = rw_vm((unsigned long)ptr, val, size, 0);
+	if (unlikely(segment_eq(get_fs(), KERNEL_DS)))
+		ret = __direct_copy_from_user(val, ptr, size);
+	else
+		ret = rw_vm((unsigned long)ptr, val, size, 0);
 	if (ret)
 		/*
 		 * Zero the rest:
@@ -211,11 +210,10 @@ int get_user_size(unsigned int size, voi
  */
 int put_user_size(unsigned int size, const void *val, void *ptr)
 {
-	if (unlikely(segment_eq(get_fs(), KERNEL_DS))) {
-		__direct_copy_to_user(ptr, val, size);
-		return 0;
-	}
-	return rw_vm((unsigned long)ptr, (void *)val, size, 1);
+	if (unlikely(segment_eq(get_fs(), KERNEL_DS)))
+		return __direct_copy_to_user(ptr, val, size);
+	else
+		return rw_vm((unsigned long)ptr, (void *)val, size, 1);
 }
 
 int copy_str_fromuser_size(unsigned int size, void *val, const void *ptr)

_