Diff markup
001 001
002 002
003 003
004 004
005 005
006 006
007 007
008 008
009 009
010 010
011 011
012 012
013 013
014 014
015 015
016 016
017 017
018 018
019 #include <hwcore/paging.h> 019 #include <hwcore/paging.h>
020 #include <sos/thread.h> 020 #include <sos/thread.h>
021 #include <sos/assert.h> 021 #include <sos/assert.h>
022 #include <sos/kmalloc.h> 022 #include <sos/kmalloc.h>
023 023
024 #include "uaccess.h" 024 #include "uaccess.h"
025 025
026 026
027 int __uaccess_zero_fool_gcc = 0; 027 int __uaccess_zero_fool_gcc = 0;
028 028
029 029
030 030
031 031
032 032
033 #define KEEP_LABEL(lbl) \ 033 #define KEEP_LABEL(lbl) \
034 ({ if (__uaccess_zero_fool_gcc) goto lbl; }) 034 ({ if (__uaccess_zero_fool_gcc) goto lbl; })
035 035
036 036
037 static sos_ret_t nocheck_user_memcpy(sos_vaddr 037 static sos_ret_t nocheck_user_memcpy(sos_vaddr_t dest,
038 sos_vaddr 038 sos_vaddr_t src,
039 sos_size_ 039 sos_size_t size,
040 sos_bool_ 040 sos_bool_t transfer_from_user)
041 { 041 {
042 __label__ catch_pgflt; 042 __label__ catch_pgflt;
043 char *cptr_dst; 043 char *cptr_dst;
044 const char *cptr_src; 044 const char *cptr_src;
045 sos_size_t transfer_sz; 045 sos_size_t transfer_sz;
046 sos_ret_t retval; 046 sos_ret_t retval;
047 047
048 KEEP_LABEL(catch_pgflt); 048 KEEP_LABEL(catch_pgflt);
049 049
050 if (size <= 0) <<
051 return 0; <<
052 <<
053 retval = sos_thread_prepare_user_space_acces 050 retval = sos_thread_prepare_user_space_access(NULL,
054 051 (sos_vaddr_t) && catch_pgflt);
055 if (SOS_OK != retval) 052 if (SOS_OK != retval)
056 return retval; 053 return retval;
057 054
058 055
059 056
060 057
061 058
062 059
063 for (cptr_dst = (char*)dest, 060 for (cptr_dst = (char*)dest,
064 cptr_src = (const char*)src, 061 cptr_src = (const char*)src,
065 transfer_sz = size ; 062 transfer_sz = size ;
066 transfer_sz > 0 ; 063 transfer_sz > 0 ;
067 cptr_dst++, cptr_src++, transfer_sz--) 064 cptr_dst++, cptr_src++, transfer_sz--)
068 *cptr_dst = *cptr_src; 065 *cptr_dst = *cptr_src;
069 066
070 retval = sos_thread_end_user_space_access(); 067 retval = sos_thread_end_user_space_access();
071 if (SOS_OK != retval) 068 if (SOS_OK != retval)
072 return retval; 069 return retval;
073 070
074 return size; 071 return size;
075 072
076 073
077 catch_pgflt: 074 catch_pgflt:
078 { 075 {
079 struct sos_thread * cur_thr = sos_thread_g 076 struct sos_thread * cur_thr = sos_thread_get_current();
080 sos_uaddr_t faulted_uaddr = cur_thr->fixup 077 sos_uaddr_t faulted_uaddr = cur_thr->fixup_uaccess.faulted_uaddr;
081 078
082 if (transfer_from_user) 079 if (transfer_from_user)
083 { 080 {
084 if ( (faulted_uaddr < src) || (faulted 081 if ( (faulted_uaddr < src) || (faulted_uaddr - size > src) )
085 sos_display_fatal_error("Unexpected 082 sos_display_fatal_error("Unexpected read access in user space");
086 retval = faulted_uaddr - src; 083 retval = faulted_uaddr - src;
087 } 084 }
088 else 085 else
089 { 086 {
090 if ( (faulted_uaddr < dest) || (faulte 087 if ( (faulted_uaddr < dest) || (faulted_uaddr - size > dest) )
091 sos_display_fatal_error("Unexpected 088 sos_display_fatal_error("Unexpected write access in user space");
092 retval = faulted_uaddr - dest; 089 retval = faulted_uaddr - dest;
093 } 090 }
094 091
095 sos_thread_end_user_space_access(); 092 sos_thread_end_user_space_access();
096 return retval; 093 return retval;
097 } 094 }
098 } 095 }
099 096
100 097
101 sos_ret_t sos_memcpy_from_user(sos_vaddr_t ker 098 sos_ret_t sos_memcpy_from_user(sos_vaddr_t kernel_to,
102 sos_uaddr_t use 099 sos_uaddr_t user_from,
103 sos_size_t size 100 sos_size_t size)
104 { 101 {
105 102
106 if (user_from < SOS_PAGING_BASE_USER_ADDRESS 103 if (user_from < SOS_PAGING_BASE_USER_ADDRESS)
107 return -SOS_EPERM; 104 return -SOS_EPERM;
108 105
109 if (user_from > SOS_PAGING_TOP_USER_ADDRESS 106 if (user_from > SOS_PAGING_TOP_USER_ADDRESS - size)
110 return -SOS_EPERM; 107 return -SOS_EPERM;
111 108
112 return nocheck_user_memcpy(kernel_to, user_f 109 return nocheck_user_memcpy(kernel_to, user_from, size, TRUE);
113 } 110 }
114 111
115 112
116 sos_ret_t sos_memdup_from_user(sos_vaddr_t * k <<
117 sos_size_t leng <<
118 sos_ui32_t kmal <<
119 { <<
120 sos_ret_t retval; <<
121 <<
122 if (length <= 0) <<
123 return -SOS_EINVAL; <<
124 <<
125 *kernel_to = sos_kmalloc(length, kmalloc_fla <<
126 if (NULL == (void*) *kernel_to) <<
127 return -SOS_ENOMEM; <<
128 <<
129 retval = sos_memcpy_from_user(*kernel_to, fr <<
130 if ((sos_ret_t)length != retval) <<
131 { <<
132 sos_kfree((sos_vaddr_t)*kernel_to); <<
133 *kernel_to = (sos_vaddr_t) NULL; <<
134 retval = -SOS_EFAULT; <<
135 } <<
136 else <<
137 retval = SOS_OK; <<
138 <<
139 return retval; <<
140 } <<
141 <<
142 <<
143 sos_ret_t sos_memcpy_to_user(sos_uaddr_t user_ 113 sos_ret_t sos_memcpy_to_user(sos_uaddr_t user_to,
144 sos_vaddr_t kerne 114 sos_vaddr_t kernel_from,
145 sos_size_t size) 115 sos_size_t size)
146 { 116 {
147 117
148 if (user_to < SOS_PAGING_BASE_USER_ADDRESS) 118 if (user_to < SOS_PAGING_BASE_USER_ADDRESS)
149 return -SOS_EPERM; 119 return -SOS_EPERM;
150 120
151 if (user_to > SOS_PAGING_TOP_USER_ADDRESS - 121 if (user_to > SOS_PAGING_TOP_USER_ADDRESS - size)
152 return -SOS_EPERM; 122 return -SOS_EPERM;
153 123
154 return nocheck_user_memcpy(user_to, kernel_f 124 return nocheck_user_memcpy(user_to, kernel_from, size, FALSE);
155 } 125 }
156 126
157 127
158 sos_ret_t sos_strnlen_from_user(sos_uaddr_t us 128 sos_ret_t sos_strnlen_from_user(sos_uaddr_t user_str, sos_size_t max_len)
159 { 129 {
160 __label__ catch_pgflt; 130 __label__ catch_pgflt;
161 const char *sc; 131 const char *sc;
162 sos_ret_t retval; 132 sos_ret_t retval;
163 133
164 KEEP_LABEL(catch_pgflt); 134 KEEP_LABEL(catch_pgflt);
165 135
166 if (max_len <= 0) <<
167 return 0; <<
168 <<
169 136
170 if (user_str < SOS_PAGING_BASE_USER_ADDRESS) 137 if (user_str < SOS_PAGING_BASE_USER_ADDRESS)
171 return -SOS_EPERM; 138 return -SOS_EPERM;
172 139
173 140
174 if ( (max_len < 1) || (max_len > SOS_PAGING_ 141 if ( (max_len < 1) || (max_len > SOS_PAGING_USER_SPACE_SIZE) )
175 return -SOS_EINVAL; 142 return -SOS_EINVAL;
176 143
177 retval = sos_thread_prepare_user_space_acces 144 retval = sos_thread_prepare_user_space_access(NULL,
178 145 (sos_vaddr_t) && catch_pgflt);
179 if (SOS_OK != retval) 146 if (SOS_OK != retval)
180 return retval; 147 return retval;
181 148
182 149
183 150
184 151
185 152
186 153
187 for (sc = (const char *)user_str; max_len-- 154 for (sc = (const char *)user_str; max_len-- && *sc != '\0'; ++sc)
188 continue; 155 continue;
189 156
190 157
191 retval = sos_thread_end_user_space_access(); 158 retval = sos_thread_end_user_space_access();
192 if (SOS_OK != retval) 159 if (SOS_OK != retval)
193 return retval; 160 return retval;
194 161
195 return ((sos_uaddr_t)sc - user_str); 162 return ((sos_uaddr_t)sc - user_str);
196 163
197 164
198 catch_pgflt: 165 catch_pgflt:
199 { 166 {
200 sos_thread_end_user_space_access(); 167 sos_thread_end_user_space_access();
201 return -SOS_EFAULT; 168 return -SOS_EFAULT;
202 } 169 }
203 } 170 }
204 171
205 172
206 static sos_ret_t nocheck_user_strzcpy(char *ds 173 static sos_ret_t nocheck_user_strzcpy(char *dst, const char *src,
207 sos_size 174 sos_size_t len)
208 { 175 {
209 __label__ catch_pgflt; 176 __label__ catch_pgflt;
210 unsigned int i; 177 unsigned int i;
211 sos_ret_t retval; 178 sos_ret_t retval;
212 179
213 KEEP_LABEL(catch_pgflt); 180 KEEP_LABEL(catch_pgflt);
214 181
215 if (len <= 0) <<
216 return 0; <<
217 <<
218 retval = sos_thread_prepare_user_space_acces 182 retval = sos_thread_prepare_user_space_access(NULL,
219 183 (sos_vaddr_t) && catch_pgflt);
220 if (SOS_OK != retval) 184 if (SOS_OK != retval)
221 return retval; 185 return retval;
222 186
223 187
224 188
225 189
226 190
227 191
228 for (i = 0; i < len; i++) 192 for (i = 0; i < len; i++)
229 { 193 {
230 dst[i] = src[i]; 194 dst[i] = src[i];
231 if(src[i] == '\0') 195 if(src[i] == '\0')
232 break; 196 break;
233 } 197 }
234 198
235 dst[len-1] = '\0'; 199 dst[len-1] = '\0';
236 200
237 retval = sos_thread_end_user_space_access(); 201 retval = sos_thread_end_user_space_access();
238 if (SOS_OK != retval) 202 if (SOS_OK != retval)
239 return retval; 203 return retval;
240 204
241 return SOS_OK; 205 return SOS_OK;
242 206
243 207
244 catch_pgflt: 208 catch_pgflt:
245 { 209 {
246 sos_thread_end_user_space_access(); 210 sos_thread_end_user_space_access();
247 return -SOS_EFAULT; 211 return -SOS_EFAULT;
248 } 212 }
249 } 213 }
250 214
251 215
252 sos_ret_t sos_strzcpy_from_user(char *kernel_t 216 sos_ret_t sos_strzcpy_from_user(char *kernel_to, sos_uaddr_t user_from,
253 sos_size_t max 217 sos_size_t max_len)
254 { 218 {
255 219
256 if ((sos_uaddr_t)user_from < SOS_PAGING_BASE 220 if ((sos_uaddr_t)user_from < SOS_PAGING_BASE_USER_ADDRESS)
257 return -SOS_EPERM; 221 return -SOS_EPERM;
258 222
259 223
260 if ( (max_len < 1) || (max_len > SOS_PAGING_ 224 if ( (max_len < 1) || (max_len > SOS_PAGING_USER_SPACE_SIZE) )
261 return -SOS_EINVAL; 225 return -SOS_EINVAL;
262 226
263 return nocheck_user_strzcpy(kernel_to, (cons 227 return nocheck_user_strzcpy(kernel_to, (const char*)user_from, max_len);
264 } 228 }
265 229
266 230
267 sos_ret_t sos_strzcpy_to_user(sos_uaddr_t user 231 sos_ret_t sos_strzcpy_to_user(sos_uaddr_t user_to, const char *kernel_from,
268 sos_size_t max_l 232 sos_size_t max_len)
269 { 233 {
270 234
271 if ((sos_uaddr_t)user_to < SOS_PAGING_BASE_U 235 if ((sos_uaddr_t)user_to < SOS_PAGING_BASE_USER_ADDRESS)
272 return -SOS_EPERM; 236 return -SOS_EPERM;
273 237
274 238
275 if ( (max_len < 1) || (max_len > SOS_PAGING_ 239 if ( (max_len < 1) || (max_len > SOS_PAGING_USER_SPACE_SIZE) )
276 return -SOS_EINVAL; 240 return -SOS_EINVAL;
277 241
278 return nocheck_user_strzcpy((char*)user_to, 242 return nocheck_user_strzcpy((char*)user_to, kernel_from, max_len);
279 } 243 }
280 244
281 245
282 sos_ret_t sos_strndup_from_user(char ** kernel 246 sos_ret_t sos_strndup_from_user(char ** kernel_to, sos_uaddr_t from_user,
283 sos_size_t max 247 sos_size_t max_len,
284 sos_ui32_t kma 248 sos_ui32_t kmalloc_flags)
285 { 249 {
286 sos_ret_t retval = sos_strnlen_from_user(fro 250 sos_ret_t retval = sos_strnlen_from_user(from_user, max_len);
287 if (retval < 0) 251 if (retval < 0)
288 return retval; 252 return retval;
289 253
290 *kernel_to = (char*)sos_kmalloc(retval + 1, 254 *kernel_to = (char*)sos_kmalloc(retval + 1, kmalloc_flags);
291 if (NULL == *kernel_to) 255 if (NULL == *kernel_to)
292 return -SOS_ENOMEM; 256 return -SOS_ENOMEM;
293 257
294 retval = sos_strzcpy_from_user(*kernel_to, f 258 retval = sos_strzcpy_from_user(*kernel_to, from_user, retval + 1);
295 if (SOS_OK != retval) 259 if (SOS_OK != retval)
296 { 260 {
297 sos_kfree((sos_vaddr_t)*kernel_to); 261 sos_kfree((sos_vaddr_t)*kernel_to);
298 *kernel_to = NULL; 262 *kernel_to = NULL;
299 } 263 }
300 264
301 return retval; 265 return retval;
302 } <<
303 <<
304 <<
305 sos_ret_t sos_memcpy_generic_to(sos_genaddr_t <<
306 sos_vaddr_t ke <<
307 sos_size_t siz <<
308 { <<
309 if (to_addr.is_user) <<
310 return sos_memcpy_to_user(to_addr.addr, ke <<
311 memcpy((void*)to_addr.addr, (const void*)ker <<
312 return size; <<
313 } <<
314 <<
315 <<
316 sos_ret_t sos_memcpy_generic_from(sos_vaddr_t <<
317 sos_genaddr_ <<
318 sos_size_t s <<
319 { <<
320 if (from_addr.is_user) <<
321 return sos_memcpy_from_user(kernel_from, f <<
322 memcpy((void*)kernel_from, (const void*)from <<
323 return size; <<
324 } 266 }