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

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