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; <<
028 027
029 !! 028
030 !! 029
031 <<
032 030
033 #define KEEP_LABEL(lbl) \ !! 031 static sos_ret_t bindto_user_mm_context()
034 ({ if (__uaccess_zero_fool_gcc) goto lbl; }) !! 032 {
>> 033 struct sos_thread * current_thread;
>> 034 struct sos_mm_context * process_mm_ctxt;
>> 035
>> 036 current_thread = sos_thread_get_current();
>> 037 SOS_ASSERT_FATAL(NULL != current_thread->process);
>> 038
>> 039
>> 040 process_mm_ctxt
>> 041 = sos_process_get_mm_context(current_thread->process);
>> 042 return sos_thread_change_current_mm_context(process_mm_ctxt);
>> 043 }
>> 044
>> 045
>> 046
>> 047
>> 048
>> 049
>> 050 #define unbindto_user_mm_context() \
>> 051 sos_thread_change_current_mm_context(NULL)
035 052
036 053
037 static sos_ret_t nocheck_user_memcpy(sos_vaddr 054 static sos_ret_t nocheck_user_memcpy(sos_vaddr_t dest,
038 sos_vaddr 055 sos_vaddr_t src,
039 sos_size_ 056 sos_size_t size,
040 sos_bool_ 057 sos_bool_t transfer_from_user)
041 { 058 {
042 __label__ catch_pgflt; <<
043 char *cptr_dst; <<
044 const char *cptr_src; <<
045 sos_size_t transfer_sz; <<
046 sos_ret_t retval; 059 sos_ret_t retval;
047 060
048 KEEP_LABEL(catch_pgflt); !! 061 retval = bindto_user_mm_context();
049 <<
050 retval = sos_thread_prepare_user_space_acces <<
051 <<
052 if (SOS_OK != retval) 062 if (SOS_OK != retval)
053 return retval; 063 return retval;
054 064
055 !! 065 memcpy((void*) dest, (void*) src, size);
056 <<
057 <<
058 <<
059 <<
060 for (cptr_dst = (char*)dest, <<
061 cptr_src = (const char*)src, <<
062 transfer_sz = size ; <<
063 transfer_sz > 0 ; <<
064 cptr_dst++, cptr_src++, transfer_sz--) <<
065 *cptr_dst = *cptr_src; <<
066 066
067 retval = sos_thread_end_user_space_access(); !! 067 retval = unbindto_user_mm_context();
068 if (SOS_OK != retval) 068 if (SOS_OK != retval)
069 return retval; 069 return retval;
070 070
071 return size; 071 return size;
072 <<
073 <<
074 catch_pgflt: <<
075 { <<
076 struct sos_thread * cur_thr = sos_thread_g <<
077 sos_uaddr_t faulted_uaddr = cur_thr->fixup <<
078 <<
079 if (transfer_from_user) <<
080 { <<
081 if ( (faulted_uaddr < src) || (faulted <<
082 sos_display_fatal_error("Unexpected <<
083 retval = faulted_uaddr - src; <<
084 } <<
085 else <<
086 { <<
087 if ( (faulted_uaddr < dest) || (faulte <<
088 sos_display_fatal_error("Unexpected <<
089 retval = faulted_uaddr - dest; <<
090 } <<
091 <<
092 sos_thread_end_user_space_access(); <<
093 return retval; <<
094 } <<
095 } 072 }
096 073
097 074
098 sos_ret_t sos_memcpy_from_user(sos_vaddr_t ker 075 sos_ret_t sos_memcpy_from_user(sos_vaddr_t kernel_to,
099 sos_uaddr_t use 076 sos_uaddr_t user_from,
100 sos_size_t size 077 sos_size_t size)
101 { 078 {
102 079
103 if (user_from < SOS_PAGING_BASE_USER_ADDRESS 080 if (user_from < SOS_PAGING_BASE_USER_ADDRESS)
104 return -SOS_EPERM; 081 return -SOS_EPERM;
105 082
106 if (user_from > SOS_PAGING_TOP_USER_ADDRESS 083 if (user_from > SOS_PAGING_TOP_USER_ADDRESS - size)
107 return -SOS_EPERM; 084 return -SOS_EPERM;
108 085
109 return nocheck_user_memcpy(kernel_to, user_f 086 return nocheck_user_memcpy(kernel_to, user_from, size, TRUE);
110 } 087 }
111 088
112 089
113 sos_ret_t sos_memcpy_to_user(sos_uaddr_t user_ 090 sos_ret_t sos_memcpy_to_user(sos_uaddr_t user_to,
114 sos_vaddr_t kerne 091 sos_vaddr_t kernel_from,
115 sos_size_t size) 092 sos_size_t size)
116 { 093 {
117 094
118 if (user_to < SOS_PAGING_BASE_USER_ADDRESS) 095 if (user_to < SOS_PAGING_BASE_USER_ADDRESS)
119 return -SOS_EPERM; 096 return -SOS_EPERM;
120 097
121 if (user_to > SOS_PAGING_TOP_USER_ADDRESS - 098 if (user_to > SOS_PAGING_TOP_USER_ADDRESS - size)
122 return -SOS_EPERM; 099 return -SOS_EPERM;
123 100
124 return nocheck_user_memcpy(user_to, kernel_f 101 return nocheck_user_memcpy(user_to, kernel_from, size, FALSE);
125 } 102 }
126 103
127 104
128 sos_ret_t sos_strnlen_from_user(sos_uaddr_t us 105 sos_ret_t sos_strnlen_from_user(sos_uaddr_t user_str, sos_size_t max_len)
129 { 106 {
130 __label__ catch_pgflt; !! 107 sos_ret_t retval, len;
131 const char *sc; <<
132 sos_ret_t retval; <<
133 <<
134 KEEP_LABEL(catch_pgflt); <<
135 108
136 109
137 if (user_str < SOS_PAGING_BASE_USER_ADDRESS) 110 if (user_str < SOS_PAGING_BASE_USER_ADDRESS)
138 return -SOS_EPERM; 111 return -SOS_EPERM;
139 112
140 113
141 if ( (max_len < 1) || (max_len > SOS_PAGING_ 114 if ( (max_len < 1) || (max_len > SOS_PAGING_USER_SPACE_SIZE) )
142 return -SOS_EINVAL; 115 return -SOS_EINVAL;
143 116
144 retval = sos_thread_prepare_user_space_acces !! 117 retval = bindto_user_mm_context();
145 <<
146 if (SOS_OK != retval) 118 if (SOS_OK != retval)
147 return retval; 119 return retval;
148 120
149 !! 121 len = strnlen((const char*)user_str, max_len);
150 <<
151 <<
152 <<
153 <<
154 for (sc = (const char *)user_str; max_len-- <<
155 continue; <<
156 122
157 !! 123 retval = unbindto_user_mm_context();
158 retval = sos_thread_end_user_space_access(); <<
159 if (SOS_OK != retval) 124 if (SOS_OK != retval)
160 return retval; 125 return retval;
161 126
162 return ((sos_uaddr_t)sc - user_str); !! 127 return len;
163 <<
164 <<
165 catch_pgflt: <<
166 { <<
167 sos_thread_end_user_space_access(); <<
168 return -SOS_EFAULT; <<
169 } <<
170 } 128 }
171 129
172 130
173 static sos_ret_t nocheck_user_strzcpy(char *ds 131 static sos_ret_t nocheck_user_strzcpy(char *dst, const char *src,
174 sos_size 132 sos_size_t len)
175 { 133 {
176 __label__ catch_pgflt; <<
177 unsigned int i; <<
178 sos_ret_t retval; 134 sos_ret_t retval;
179 135
180 KEEP_LABEL(catch_pgflt); !! 136 retval = bindto_user_mm_context();
181 <<
182 retval = sos_thread_prepare_user_space_acces <<
183 <<
184 if (SOS_OK != retval) 137 if (SOS_OK != retval)
185 return retval; 138 return retval;
186 139
187 !! 140 strzcpy(dst, src, len);
188 <<
189 <<
190 <<
191 <<
192 for (i = 0; i < len; i++) <<
193 { <<
194 dst[i] = src[i]; <<
195 if(src[i] == '\0') <<
196 break; <<
197 } <<
198 <<
199 dst[len-1] = '\0'; <<
200 141
201 retval = sos_thread_end_user_space_access(); !! 142 retval = unbindto_user_mm_context();
202 if (SOS_OK != retval) 143 if (SOS_OK != retval)
203 return retval; 144 return retval;
204 145
205 return SOS_OK; 146 return SOS_OK;
206 <<
207 <<
208 catch_pgflt: <<
209 { <<
210 sos_thread_end_user_space_access(); <<
211 return -SOS_EFAULT; <<
212 } <<
213 } 147 }
214 148
215 149
216 sos_ret_t sos_strzcpy_from_user(char *kernel_t 150 sos_ret_t sos_strzcpy_from_user(char *kernel_to, sos_uaddr_t user_from,
217 sos_size_t max 151 sos_size_t max_len)
218 { 152 {
219 153
220 if ((sos_uaddr_t)user_from < SOS_PAGING_BASE 154 if ((sos_uaddr_t)user_from < SOS_PAGING_BASE_USER_ADDRESS)
221 return -SOS_EPERM; 155 return -SOS_EPERM;
222 156
223 157
224 if ( (max_len < 1) || (max_len > SOS_PAGING_ 158 if ( (max_len < 1) || (max_len > SOS_PAGING_USER_SPACE_SIZE) )
225 return -SOS_EINVAL; 159 return -SOS_EINVAL;
226 160
227 return nocheck_user_strzcpy(kernel_to, (cons 161 return nocheck_user_strzcpy(kernel_to, (const char*)user_from, max_len);
228 } 162 }
229 163
230 164
231 sos_ret_t sos_strzcpy_to_user(sos_uaddr_t user 165 sos_ret_t sos_strzcpy_to_user(sos_uaddr_t user_to, const char *kernel_from,
232 sos_size_t max_l 166 sos_size_t max_len)
233 { 167 {
234 168
235 if ((sos_uaddr_t)user_to < SOS_PAGING_BASE_U 169 if ((sos_uaddr_t)user_to < SOS_PAGING_BASE_USER_ADDRESS)
236 return -SOS_EPERM; 170 return -SOS_EPERM;
237 171
238 172
239 if ( (max_len < 1) || (max_len > SOS_PAGING_ 173 if ( (max_len < 1) || (max_len > SOS_PAGING_USER_SPACE_SIZE) )
240 return -SOS_EINVAL; 174 return -SOS_EINVAL;
241 175
242 return nocheck_user_strzcpy((char*)user_to, 176 return nocheck_user_strzcpy((char*)user_to, kernel_from, max_len);
243 } 177 }
244 178
245 179
246 sos_ret_t sos_strndup_from_user(char ** kernel 180 sos_ret_t sos_strndup_from_user(char ** kernel_to, sos_uaddr_t from_user,
247 sos_size_t max 181 sos_size_t max_len,
248 sos_ui32_t kma 182 sos_ui32_t kmalloc_flags)
249 { 183 {
250 sos_ret_t retval = sos_strnlen_from_user(fro 184 sos_ret_t retval = sos_strnlen_from_user(from_user, max_len);
251 if (retval < 0) 185 if (retval < 0)
252 return retval; 186 return retval;
253 187
254 *kernel_to = (char*)sos_kmalloc(retval + 1, 188 *kernel_to = (char*)sos_kmalloc(retval + 1, kmalloc_flags);
255 if (NULL == *kernel_to) 189 if (NULL == *kernel_to)
256 return -SOS_ENOMEM; 190 return -SOS_ENOMEM;
257 191
258 retval = sos_strzcpy_from_user(*kernel_to, f 192 retval = sos_strzcpy_from_user(*kernel_to, from_user, retval + 1);
259 if (SOS_OK != retval) 193 if (SOS_OK != retval)
260 { 194 {
261 sos_kfree((sos_vaddr_t)*kernel_to); 195 sos_kfree((sos_vaddr_t)*kernel_to);
262 *kernel_to = NULL; 196 *kernel_to = NULL;
263 } 197 }
264 198
265 return retval; 199 return retval;
266 } 200 }