SimpleOS

LXR

Navigation



Site hébergé par : enix

The LXR Cross Referencer for SOS

source navigation ]
diff markup ]
identifier search ]
general search ]
 
 
Article:1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ] [ 6.5 ] [ 7 ] [ 7.5 ] [ 8 ] [ 9 ] [ 9.5 ]

Diff markup

Differences between /sos/uaccess.c (Article 9.5) and /sos/uaccess.c (Article 7.5)


001 /* Copyright (C) 2005  David Decotigny            001 /* Copyright (C) 2005  David Decotigny
002                                                   002 
003    This program is free software; you can redi    003    This program is free software; you can redistribute it and/or
004    modify it under the terms of the GNU Genera    004    modify it under the terms of the GNU General Public License
005    as published by the Free Software Foundatio    005    as published by the Free Software Foundation; either version 2
006    of the License, or (at your option) any lat    006    of the License, or (at your option) any later version.
007                                                   007    
008    This program is distributed in the hope tha    008    This program is distributed in the hope that it will be useful,
009    but WITHOUT ANY WARRANTY; without even the     009    but WITHOUT ANY WARRANTY; without even the implied warranty of
010    MERCHANTABILITY or FITNESS FOR A PARTICULAR    010    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
011    GNU General Public License for more details    011    GNU General Public License for more details.
012                                                   012    
013    You should have received a copy of the GNU     013    You should have received a copy of the GNU General Public License
014    along with this program; if not, write to t    014    along with this program; if not, write to the Free Software
015    Foundation, Inc., 59 Temple Place - Suite 3    015    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
016    USA.                                           016    USA. 
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  * Make sure gcc optimizations don't go too fa    029  * Make sure gcc optimizations don't go too far and don't suppress the
030  * code at the given label because 1/ a global    030  * code at the given label because 1/ a global return is "above" (wrt
031  * source code lines), 2/ it is never "goto"      031  * source code lines), 2/ it is never "goto"
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   /* Version of memcpy that does not alter the    055   /* Version of memcpy that does not alter the stack pointer, in
059      order to be able to abruptedly jump to ca    056      order to be able to abruptedly jump to catch_pgflt without stack
060      inconsistency. That's the reason why we d    057      inconsistency. That's the reason why we don't call the normal
061      memcpy here: on page fault, it would retu    058      memcpy here: on page fault, it would return back in here, with
062      the stack frame returning back here again    059      the stack frame returning back here again */
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   /* An unresolved page fault occured while ac    073   /* An unresolved page fault occured while accessing user space */
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   /* Make sure user is trying to access user s    102   /* Make sure user is trying to access user space */
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   /* Make sure user is trying to access user s    117   /* Make sure user is trying to access user space */
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   /* Make sure user is trying to access user s    136   /* Make sure user is trying to access user space */
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   /* Don't allow invalid max_len */               140   /* Don't allow invalid max_len */
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   /* Version of strnlen that does not alter th    149   /* Version of strnlen that does not alter the stack pointer, in
183      order to be able to abruptedly jump to ca    150      order to be able to abruptedly jump to catch_pgflt without stack
184      inconsistency. That's the reason why we d    151      inconsistency. That's the reason why we don't call the normal
185      strnlen here: on page fault, it would ret    152      strnlen here: on page fault, it would return back in here, with
186      the stack frame returning back here again    153      the stack frame returning back here again */
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   /* An unresolved page fault occured while ac    164   /* An unresolved page fault occured while accessing user space */
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   /* Version of strzcpy that does not alter th    187   /* Version of strzcpy that does not alter the stack pointer, in
224      order to be able to abruptedly jump to ca    188      order to be able to abruptedly jump to catch_pgflt without stack
225      inconsistency. That's the reason why we d    189      inconsistency. That's the reason why we don't call the normal
226      strzcpy here: on page fault, it would ret    190      strzcpy here: on page fault, it would return back in here, with
227      the stack frame returning back here again    191      the stack frame returning back here again */
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   /* An unresolved page fault occured while ac    207   /* An unresolved page fault occured while accessing user space */
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   /* Make sure user is trying to access user s    219   /* Make sure user is trying to access user space */
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   /* Don't allow invalid max_len */               223   /* Don't allow invalid max_len */
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   /* Make sure user is trying to access user s    234   /* Make sure user is trying to access user space */
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   /* Don't allow invalid max_len */               238   /* Don't allow invalid max_len */
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 }
                                                      

source navigation ] diff markup ] identifier search ] general search ]