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


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

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