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) and /sos/uaccess.c (Article 7)


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;               << 
028 /**                                               027 /**
029  * Make sure gcc optimizations don't go too fa !! 028  * Helper function to force the MMU to switch to the address space of
030  * code at the given label because 1/ a global !! 029  * the process
031  * source code lines), 2/ it is never "goto"   << 
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   /* Switch to the user's address space */
                                                   >> 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  * Helper macro to restore the MMU configuration prior to
                                                   >> 048  * bindto_user_mm_context()
                                                   >> 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   if (size <= 0)                               << 
051     return 0;                                  << 
052                                                << 
053   retval = sos_thread_prepare_user_space_acces << 
054                                                << 
055   if (SOS_OK != retval)                           062   if (SOS_OK != retval)
056     return retval;                                063     return retval;
057                                                   064 
058   /* Version of memcpy that does not alter the !! 065   memcpy((void*) dest, (void*) src, size);
059      order to be able to abruptedly jump to ca << 
060      inconsistency. That's the reason why we d << 
061      memcpy here: on page fault, it would retu << 
062      the stack frame returning back here again << 
063   for (cptr_dst = (char*)dest,                 << 
064          cptr_src = (const char*)src,          << 
065          transfer_sz = size ;                  << 
066        transfer_sz > 0 ;                       << 
067        cptr_dst++, cptr_src++, transfer_sz--)  << 
068     *cptr_dst = *cptr_src;                     << 
069                                                   066 
070   retval = sos_thread_end_user_space_access(); !! 067   retval = unbindto_user_mm_context();
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                                                << 
076   /* An unresolved page fault occured while ac << 
077  catch_pgflt:                                  << 
078   {                                            << 
079     struct sos_thread * cur_thr = sos_thread_g << 
080     sos_uaddr_t faulted_uaddr = cur_thr->fixup << 
081                                                << 
082     if (transfer_from_user)                    << 
083       {                                        << 
084         if ( (faulted_uaddr < src) || (faulted << 
085           sos_display_fatal_error("Unexpected  << 
086         retval = faulted_uaddr - src;          << 
087       }                                        << 
088     else                                       << 
089       {                                        << 
090         if ( (faulted_uaddr < dest) || (faulte << 
091           sos_display_fatal_error("Unexpected  << 
092         retval = faulted_uaddr - dest;         << 
093       }                                        << 
094                                                << 
095     sos_thread_end_user_space_access();        << 
096     return retval;                             << 
097   }                                            << 
098 }                                                 072 }
099                                                   073 
100                                                   074 
101 sos_ret_t sos_memcpy_from_user(sos_vaddr_t ker    075 sos_ret_t sos_memcpy_from_user(sos_vaddr_t kernel_to,
102                                sos_uaddr_t use    076                                sos_uaddr_t user_from,
103                                sos_size_t size    077                                sos_size_t size)
104 {                                                 078 {
105   /* Make sure user is trying to access user s    079   /* Make sure user is trying to access user space */
106   if (user_from < SOS_PAGING_BASE_USER_ADDRESS    080   if (user_from < SOS_PAGING_BASE_USER_ADDRESS)
107     return -SOS_EPERM;                            081     return -SOS_EPERM;
108                                                   082 
109   if (user_from > SOS_PAGING_TOP_USER_ADDRESS     083   if (user_from > SOS_PAGING_TOP_USER_ADDRESS - size)
110     return -SOS_EPERM;                            084     return -SOS_EPERM;
111                                                   085 
112   return nocheck_user_memcpy(kernel_to, user_f    086   return nocheck_user_memcpy(kernel_to, user_from, size, TRUE);
113 }                                                 087 }
114                                                   088 
115                                                   089 
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 (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_    090 sos_ret_t sos_memcpy_to_user(sos_uaddr_t user_to,
144                              sos_vaddr_t kerne    091                              sos_vaddr_t kernel_from,
145                              sos_size_t size)     092                              sos_size_t size)
146 {                                                 093 {
147   /* Make sure user is trying to access user s    094   /* Make sure user is trying to access user space */
148   if (user_to < SOS_PAGING_BASE_USER_ADDRESS)     095   if (user_to < SOS_PAGING_BASE_USER_ADDRESS)
149     return -SOS_EPERM;                            096     return -SOS_EPERM;
150                                                   097 
151   if (user_to > SOS_PAGING_TOP_USER_ADDRESS -     098   if (user_to > SOS_PAGING_TOP_USER_ADDRESS - size)
152     return -SOS_EPERM;                            099     return -SOS_EPERM;
153                                                   100 
154   return nocheck_user_memcpy(user_to, kernel_f    101   return nocheck_user_memcpy(user_to, kernel_from, size, FALSE);
155 }                                                 102 }
156                                                   103 
157                                                   104 
158 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)
159 {                                                 106 {
160   __label__ catch_pgflt;                       !! 107   sos_ret_t retval, len;
161   const char *sc;                              << 
162   sos_ret_t retval;                            << 
163                                                << 
164   KEEP_LABEL(catch_pgflt);                     << 
165                                                << 
166   if (max_len <= 0)                            << 
167     return 0;                                  << 
168                                                   108 
169   /* Make sure user is trying to access user s    109   /* Make sure user is trying to access user space */
170   if (user_str < SOS_PAGING_BASE_USER_ADDRESS)    110   if (user_str < SOS_PAGING_BASE_USER_ADDRESS)
171     return -SOS_EPERM;                            111     return -SOS_EPERM;
172                                                   112 
173   /* Don't allow invalid max_len */               113   /* Don't allow invalid max_len */
174   if ( (max_len < 1) || (max_len > SOS_PAGING_    114   if ( (max_len < 1) || (max_len > SOS_PAGING_USER_SPACE_SIZE) )
175     return -SOS_EINVAL;                           115     return -SOS_EINVAL;
176                                                   116 
177   retval = sos_thread_prepare_user_space_acces !! 117   retval = bindto_user_mm_context();
178                                                << 
179   if (SOS_OK != retval)                           118   if (SOS_OK != retval)
180     return retval;                                119     return retval;
181                                                   120 
182   /* Version of strnlen that does not alter th !! 121   len = strnlen((const char*)user_str, max_len);
183      order to be able to abruptedly jump to ca << 
184      inconsistency. That's the reason why we d << 
185      strnlen here: on page fault, it would ret << 
186      the stack frame returning back here again << 
187   for (sc = (const char *)user_str; max_len--  << 
188     continue;                                  << 
189                                                   122 
190                                                !! 123   retval = unbindto_user_mm_context();
191   retval = sos_thread_end_user_space_access(); << 
192   if (SOS_OK != retval)                           124   if (SOS_OK != retval)
193     return retval;                                125     return retval;
194                                                   126 
195   return ((sos_uaddr_t)sc - user_str);         !! 127   return len;
196                                                << 
197   /* An unresolved page fault occured while ac << 
198  catch_pgflt:                                  << 
199   {                                            << 
200     sos_thread_end_user_space_access();        << 
201     return -SOS_EFAULT;                        << 
202   }                                            << 
203 }                                                 128 }
204                                                   129 
205                                                   130 
206 static sos_ret_t nocheck_user_strzcpy(char *ds    131 static sos_ret_t nocheck_user_strzcpy(char *dst, const char *src,
207                                       sos_size    132                                       sos_size_t len)
208 {                                                 133 {
209   __label__ catch_pgflt;                       << 
210   unsigned int i;                              << 
211   sos_ret_t retval;                               134   sos_ret_t retval;
212                                                   135 
213   KEEP_LABEL(catch_pgflt);                     !! 136   retval = bindto_user_mm_context();
214                                                << 
215   if (len <= 0)                                << 
216     return 0;                                  << 
217                                                << 
218   retval = sos_thread_prepare_user_space_acces << 
219                                                << 
220   if (SOS_OK != retval)                           137   if (SOS_OK != retval)
221     return retval;                                138     return retval;
222                                                   139 
223   /* Version of strzcpy that does not alter th !! 140   strzcpy(dst, src, len);
224      order to be able to abruptedly jump to ca << 
225      inconsistency. That's the reason why we d << 
226      strzcpy here: on page fault, it would ret << 
227      the stack frame returning back here again << 
228   for (i = 0; i < len; i++)                    << 
229     {                                          << 
230       dst[i] = src[i];                         << 
231       if(src[i] == '\0')                       << 
232         break;                                 << 
233     }                                          << 
234                                                << 
235   dst[len-1] = '\0';                           << 
236                                                   141 
237   retval = sos_thread_end_user_space_access(); !! 142   retval = unbindto_user_mm_context();
238   if (SOS_OK != retval)                           143   if (SOS_OK != retval)
239     return retval;                                144     return retval;
240                                                   145 
241   return SOS_OK;                                  146   return SOS_OK;
242                                                << 
243   /* An unresolved page fault occured while ac << 
244  catch_pgflt:                                  << 
245   {                                            << 
246     sos_thread_end_user_space_access();        << 
247     return -SOS_EFAULT;                        << 
248   }                                            << 
249 }                                                 147 }
250                                                   148 
251                                                   149 
252 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,
253                                 sos_size_t max    151                                 sos_size_t max_len)
254 {                                                 152 {
255   /* Make sure user is trying to access user s    153   /* Make sure user is trying to access user space */
256   if ((sos_uaddr_t)user_from < SOS_PAGING_BASE    154   if ((sos_uaddr_t)user_from < SOS_PAGING_BASE_USER_ADDRESS)
257     return -SOS_EPERM;                            155     return -SOS_EPERM;
258                                                   156 
259   /* Don't allow invalid max_len */               157   /* Don't allow invalid max_len */
260   if ( (max_len < 1) || (max_len > SOS_PAGING_    158   if ( (max_len < 1) || (max_len > SOS_PAGING_USER_SPACE_SIZE) )
261     return -SOS_EINVAL;                           159     return -SOS_EINVAL;
262                                                   160 
263   return nocheck_user_strzcpy(kernel_to, (cons    161   return nocheck_user_strzcpy(kernel_to, (const char*)user_from, max_len);
264 }                                                 162 }
265                                                   163 
266                                                   164 
267 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,
268                               sos_size_t max_l    166                               sos_size_t max_len)
269 {                                                 167 {
270   /* Make sure user is trying to access user s    168   /* Make sure user is trying to access user space */
271   if ((sos_uaddr_t)user_to < SOS_PAGING_BASE_U    169   if ((sos_uaddr_t)user_to < SOS_PAGING_BASE_USER_ADDRESS)
272     return -SOS_EPERM;                            170     return -SOS_EPERM;
273                                                   171 
274   /* Don't allow invalid max_len */               172   /* Don't allow invalid max_len */
275   if ( (max_len < 1) || (max_len > SOS_PAGING_    173   if ( (max_len < 1) || (max_len > SOS_PAGING_USER_SPACE_SIZE) )
276     return -SOS_EINVAL;                           174     return -SOS_EINVAL;
277                                                   175 
278   return nocheck_user_strzcpy((char*)user_to,     176   return nocheck_user_strzcpy((char*)user_to, kernel_from, max_len);
279 }                                                 177 }
280                                                   178 
281                                                   179 
282 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,
283                                 sos_size_t max    181                                 sos_size_t max_len,
284                                 sos_ui32_t kma    182                                 sos_ui32_t kmalloc_flags)
285 {                                                 183 {
286   sos_ret_t retval = sos_strnlen_from_user(fro    184   sos_ret_t retval = sos_strnlen_from_user(from_user, max_len);
287   if (retval < 0)                                 185   if (retval < 0)
288     return retval;                                186     return retval;
289                                                   187 
290   *kernel_to = (char*)sos_kmalloc(retval + 1,     188   *kernel_to = (char*)sos_kmalloc(retval + 1, kmalloc_flags);
291   if (NULL == *kernel_to)                         189   if (NULL == *kernel_to)
292     return -SOS_ENOMEM;                           190     return -SOS_ENOMEM;
293                                                   191 
294   retval = sos_strzcpy_from_user(*kernel_to, f    192   retval = sos_strzcpy_from_user(*kernel_to, from_user, retval + 1);
295   if (SOS_OK != retval)                           193   if (SOS_OK != retval)
296     {                                             194     {
297       sos_kfree((sos_vaddr_t)*kernel_to);         195       sos_kfree((sos_vaddr_t)*kernel_to);
298       *kernel_to = NULL;                          196       *kernel_to = NULL;
299     }                                             197     }
300                                                   198 
301   return retval;                                  199   return retval;
302 }                                                 200 }
                                                      

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