1 /* 2 * User address space access functions. 3 * 4 * Copyright 1997 Andi Kleen <ak@muc.de> 5 * Copyright 1997 Linus Torvalds 6 * Copyright 2002 Andi Kleen <ak@suse.de> 7 */ 8 #include <linux/module.h> 9 #include <asm/uaccess.h> 10 11 /* 12 * Zero Userspace 13 */ 14 15 unsigned long __clear_user(void __user *addr, unsigned long size) 16 { 17 long __d0; 18 might_fault(); 19 /* no memory constraint because it doesn't change any memory gcc knows 20 about */ 21 asm volatile( 22 " testq %[size8],%[size8]\n" 23 " jz 4f\n" 24 "0: movq %[zero],(%[dst])\n" 25 " addq %[eight],%[dst]\n" 26 " decl %%ecx ; jnz 0b\n" 27 "4: movq %[size1],%%rcx\n" 28 " testl %%ecx,%%ecx\n" 29 " jz 2f\n" 30 "1: movb %b[zero],(%[dst])\n" 31 " incq %[dst]\n" 32 " decl %%ecx ; jnz 1b\n" 33 "2:\n" 34 ".section .fixup,\"ax\"\n" 35 "3: lea 0(%[size1],%[size8],8),%[size8]\n" 36 " jmp 2b\n" 37 ".previous\n" 38 _ASM_EXTABLE(0b,3b) 39 _ASM_EXTABLE(1b,2b) 40 : [size8] "=&c"(size), [dst] "=&D" (__d0) 41 : [size1] "r"(size & 7), "[size8]" (size / 8), "[dst]"(addr), 42 [zero] "r" (0UL), [eight] "r" (8UL)); 43 return size; 44 } 45 EXPORT_SYMBOL(__clear_user); 46 47 unsigned long clear_user(void __user *to, unsigned long n) 48 { 49 if (access_ok(VERIFY_WRITE, to, n)) 50 return __clear_user(to, n); 51 return n; 52 } 53 EXPORT_SYMBOL(clear_user); 54 55 /* 56 * Return the size of a string (including the ending 0) 57 * 58 * Return 0 on exception, a value greater than N if too long 59 */ 60 61 long __strnlen_user(const char __user *s, long n) 62 { 63 long res = 0; 64 char c; 65 66 while (1) { 67 if (res>n) 68 return n+1; 69 if (__get_user(c, s)) 70 return 0; 71 if (!c) 72 return res+1; 73 res++; 74 s++; 75 } 76 } 77 EXPORT_SYMBOL(__strnlen_user); 78 79 long strnlen_user(const char __user *s, long n) 80 { 81 if (!access_ok(VERIFY_READ, s, 1)) 82 return 0; 83 return __strnlen_user(s, n); 84 } 85 EXPORT_SYMBOL(strnlen_user); 86 87 long strlen_user(const char __user *s) 88 { 89 long res = 0; 90 char c; 91 92 for (;;) { 93 if (get_user(c, s)) 94 return 0; 95 if (!c) 96 return res+1; 97 res++; 98 s++; 99 } 100 } 101 EXPORT_SYMBOL(strlen_user); 102 103 unsigned long copy_in_user(void __user *to, const void __user *from, unsigned len) 104 { 105 if (access_ok(VERIFY_WRITE, to, len) && access_ok(VERIFY_READ, from, len)) { 106 return copy_user_generic((__force void *)to, (__force void *)from, len); 107 } 108 return len; 109 } 110 EXPORT_SYMBOL(copy_in_user); 111 112 /* 113 * Try to copy last bytes and clear the rest if needed. 114 * Since protection fault in copy_from/to_user is not a normal situation, 115 * it is not necessary to optimize tail handling. 116 */ 117 unsigned long 118 copy_user_handle_tail(char *to, char *from, unsigned len, unsigned zerorest) 119 { 120 char c; 121 unsigned zero_len; 122 123 for (; len; --len) { 124 if (__get_user_nocheck(c, from++, sizeof(char))) 125 break; 126 if (__put_user_nocheck(c, to++, sizeof(char))) 127 break; 128 } 129 130 for (c = 0, zero_len = len; zerorest && zero_len; --zero_len) 131 if (__put_user_nocheck(c, to++, sizeof(char))) 132 break; 133 return len; 134 } 135