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


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

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