From: Hugh Dickins 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) _