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 7.5)


001 /* Copyright (C) 2005  David Decotigny            001 /* Copyright (C) 2005  David Decotigny
002                                                   002 
003    This program is free software; you can redi    003    This program is free software; you can redistribute it and/or
004    modify it under the terms of the GNU Genera    004    modify it under the terms of the GNU General Public License
005    as published by the Free Software Foundatio    005    as published by the Free Software Foundation; either version 2
006    of the License, or (at your option) any lat    006    of the License, or (at your option) any later version.
007                                                   007    
008    This program is distributed in the hope tha    008    This program is distributed in the hope that it will be useful,
009    but WITHOUT ANY WARRANTY; without even the     009    but WITHOUT ANY WARRANTY; without even the implied warranty of
010    MERCHANTABILITY or FITNESS FOR A PARTICULAR    010    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
011    GNU General Public License for more details    011    GNU General Public License for more details.
012                                                   012    
013    You should have received a copy of the GNU     013    You should have received a copy of the GNU General Public License
014    along with this program; if not, write to t    014    along with this program; if not, write to the Free Software
015    Foundation, Inc., 59 Temple Place - Suite 3    015    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
016    USA.                                           016    USA. 
017 */                                                017 */
018                                                   018 
019 #include <hwcore/paging.h>                        019 #include <hwcore/paging.h>
020 #include <sos/thread.h>                           020 #include <sos/thread.h>
021 #include <sos/assert.h>                           021 #include <sos/assert.h>
022 #include <sos/kmalloc.h>                          022 #include <sos/kmalloc.h>
023                                                   023 
024 #include "uaccess.h"                              024 #include "uaccess.h"
025                                                   025 
026                                                   026 
                                                   >> 027 int __uaccess_zero_fool_gcc = 0;
027 /**                                               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   retval = sos_thread_prepare_user_space_access(NULL,
                                                   >> 051                                                 (sos_vaddr_t) && catch_pgflt);
062   if (SOS_OK != retval)                           052   if (SOS_OK != retval)
063     return retval;                                053     return retval;
064                                                   054 
065   memcpy((void*) dest, (void*) src, size);     !! 055   /* Version of memcpy that does not alter the stack pointer, in
                                                   >> 056      order to be able to abruptedly jump to catch_pgflt without stack
                                                   >> 057      inconsistency. That's the reason why we don't call the normal
                                                   >> 058      memcpy here: on page fault, it would return back in here, with
                                                   >> 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 = unbindto_user_mm_context();         !! 067   retval = sos_thread_end_user_space_access();
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 accessing user space */
                                                   >> 074  catch_pgflt:
                                                   >> 075   {
                                                   >> 076     struct sos_thread * cur_thr = sos_thread_get_current();
                                                   >> 077     sos_uaddr_t faulted_uaddr = cur_thr->fixup_uaccess.faulted_uaddr;
                                                   >> 078 
                                                   >> 079     if (transfer_from_user)
                                                   >> 080       {
                                                   >> 081         if ( (faulted_uaddr < src) || (faulted_uaddr - size > src) )
                                                   >> 082           sos_display_fatal_error("Unexpected read access in user space");
                                                   >> 083         retval = faulted_uaddr - src;
                                                   >> 084       }
                                                   >> 085     else
                                                   >> 086       {
                                                   >> 087         if ( (faulted_uaddr < dest) || (faulted_uaddr - size > dest) )
                                                   >> 088           sos_display_fatal_error("Unexpected write access in user space");
                                                   >> 089         retval = faulted_uaddr - dest;
                                                   >> 090       }
                                                   >> 091 
                                                   >> 092     sos_thread_end_user_space_access();
                                                   >> 093     return retval;
                                                   >> 094   }
072 }                                                 095 }
073                                                   096 
074                                                   097 
075 sos_ret_t sos_memcpy_from_user(sos_vaddr_t ker    098 sos_ret_t sos_memcpy_from_user(sos_vaddr_t kernel_to,
076                                sos_uaddr_t use    099                                sos_uaddr_t user_from,
077                                sos_size_t size    100                                sos_size_t size)
078 {                                                 101 {
079   /* Make sure user is trying to access user s    102   /* Make sure user is trying to access user space */
080   if (user_from < SOS_PAGING_BASE_USER_ADDRESS    103   if (user_from < SOS_PAGING_BASE_USER_ADDRESS)
081     return -SOS_EPERM;                            104     return -SOS_EPERM;
082                                                   105 
083   if (user_from > SOS_PAGING_TOP_USER_ADDRESS     106   if (user_from > SOS_PAGING_TOP_USER_ADDRESS - size)
084     return -SOS_EPERM;                            107     return -SOS_EPERM;
085                                                   108 
086   return nocheck_user_memcpy(kernel_to, user_f    109   return nocheck_user_memcpy(kernel_to, user_from, size, TRUE);
087 }                                                 110 }
088                                                   111 
089                                                   112 
090 sos_ret_t sos_memcpy_to_user(sos_uaddr_t user_    113 sos_ret_t sos_memcpy_to_user(sos_uaddr_t user_to,
091                              sos_vaddr_t kerne    114                              sos_vaddr_t kernel_from,
092                              sos_size_t size)     115                              sos_size_t size)
093 {                                                 116 {
094   /* Make sure user is trying to access user s    117   /* Make sure user is trying to access user space */
095   if (user_to < SOS_PAGING_BASE_USER_ADDRESS)     118   if (user_to < SOS_PAGING_BASE_USER_ADDRESS)
096     return -SOS_EPERM;                            119     return -SOS_EPERM;
097                                                   120 
098   if (user_to > SOS_PAGING_TOP_USER_ADDRESS -     121   if (user_to > SOS_PAGING_TOP_USER_ADDRESS - size)
099     return -SOS_EPERM;                            122     return -SOS_EPERM;
100                                                   123 
101   return nocheck_user_memcpy(user_to, kernel_f    124   return nocheck_user_memcpy(user_to, kernel_from, size, FALSE);
102 }                                                 125 }
103                                                   126 
104                                                   127 
105 sos_ret_t sos_strnlen_from_user(sos_uaddr_t us    128 sos_ret_t sos_strnlen_from_user(sos_uaddr_t user_str, sos_size_t max_len)
106 {                                                 129 {
107   sos_ret_t retval, len;                       !! 130   __label__ catch_pgflt;
                                                   >> 131   const char *sc;
                                                   >> 132   sos_ret_t retval;
                                                   >> 133 
                                                   >> 134   KEEP_LABEL(catch_pgflt);
108                                                   135 
109   /* Make sure user is trying to access user s    136   /* Make sure user is trying to access user space */
110   if (user_str < SOS_PAGING_BASE_USER_ADDRESS)    137   if (user_str < SOS_PAGING_BASE_USER_ADDRESS)
111     return -SOS_EPERM;                            138     return -SOS_EPERM;
112                                                   139 
113   /* Don't allow invalid max_len */               140   /* Don't allow invalid max_len */
114   if ( (max_len < 1) || (max_len > SOS_PAGING_    141   if ( (max_len < 1) || (max_len > SOS_PAGING_USER_SPACE_SIZE) )
115     return -SOS_EINVAL;                           142     return -SOS_EINVAL;
116                                                   143 
117   retval = bindto_user_mm_context();           !! 144   retval = sos_thread_prepare_user_space_access(NULL,
                                                   >> 145                                                 (sos_vaddr_t) && catch_pgflt);
118   if (SOS_OK != retval)                           146   if (SOS_OK != retval)
119     return retval;                                147     return retval;
120                                                   148 
121   len = strnlen((const char*)user_str, max_len !! 149   /* Version of strnlen that does not alter the stack pointer, in
                                                   >> 150      order to be able to abruptedly jump to catch_pgflt without stack
                                                   >> 151      inconsistency. That's the reason why we don't call the normal
                                                   >> 152      strnlen here: on page fault, it would return back in here, with
                                                   >> 153      the stack frame returning back here again */
                                                   >> 154   for (sc = (const char *)user_str; max_len-- && *sc != '\0'; ++sc)
                                                   >> 155     continue;
122                                                   156 
123   retval = unbindto_user_mm_context();         !! 157 
                                                   >> 158   retval = sos_thread_end_user_space_access();
124   if (SOS_OK != retval)                           159   if (SOS_OK != retval)
125     return retval;                                160     return retval;
126                                                   161 
127   return len;                                  !! 162   return ((sos_uaddr_t)sc - user_str);
                                                   >> 163 
                                                   >> 164   /* An unresolved page fault occured while accessing user space */
                                                   >> 165  catch_pgflt:
                                                   >> 166   {
                                                   >> 167     sos_thread_end_user_space_access();
                                                   >> 168     return -SOS_EFAULT;
                                                   >> 169   }
128 }                                                 170 }
129                                                   171 
130                                                   172 
131 static sos_ret_t nocheck_user_strzcpy(char *ds    173 static sos_ret_t nocheck_user_strzcpy(char *dst, const char *src,
132                                       sos_size    174                                       sos_size_t len)
133 {                                                 175 {
                                                   >> 176   __label__ catch_pgflt;
                                                   >> 177   unsigned int i;
134   sos_ret_t retval;                               178   sos_ret_t retval;
135                                                   179 
136   retval = bindto_user_mm_context();           !! 180   KEEP_LABEL(catch_pgflt);
                                                   >> 181 
                                                   >> 182   retval = sos_thread_prepare_user_space_access(NULL,
                                                   >> 183                                                 (sos_vaddr_t) && catch_pgflt);
137   if (SOS_OK != retval)                           184   if (SOS_OK != retval)
138     return retval;                                185     return retval;
139                                                   186 
140   strzcpy(dst, src, len);                      !! 187   /* Version of strzcpy that does not alter the stack pointer, in
                                                   >> 188      order to be able to abruptedly jump to catch_pgflt without stack
                                                   >> 189      inconsistency. That's the reason why we don't call the normal
                                                   >> 190      strzcpy here: on page fault, it would return back in here, with
                                                   >> 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'; 
141                                                   200 
142   retval = unbindto_user_mm_context();         !! 201   retval = sos_thread_end_user_space_access();
143   if (SOS_OK != retval)                           202   if (SOS_OK != retval)
144     return retval;                                203     return retval;
145                                                   204 
146   return SOS_OK;                                  205   return SOS_OK;
                                                   >> 206 
                                                   >> 207   /* An unresolved page fault occured while accessing user space */
                                                   >> 208  catch_pgflt:
                                                   >> 209   {
                                                   >> 210     sos_thread_end_user_space_access();
                                                   >> 211     return -SOS_EFAULT;
                                                   >> 212   }
147 }                                                 213 }
148                                                   214 
149                                                   215 
150 sos_ret_t sos_strzcpy_from_user(char *kernel_t    216 sos_ret_t sos_strzcpy_from_user(char *kernel_to, sos_uaddr_t user_from,
151                                 sos_size_t max    217                                 sos_size_t max_len)
152 {                                                 218 {
153   /* Make sure user is trying to access user s    219   /* Make sure user is trying to access user space */
154   if ((sos_uaddr_t)user_from < SOS_PAGING_BASE    220   if ((sos_uaddr_t)user_from < SOS_PAGING_BASE_USER_ADDRESS)
155     return -SOS_EPERM;                            221     return -SOS_EPERM;
156                                                   222 
157   /* Don't allow invalid max_len */               223   /* Don't allow invalid max_len */
158   if ( (max_len < 1) || (max_len > SOS_PAGING_    224   if ( (max_len < 1) || (max_len > SOS_PAGING_USER_SPACE_SIZE) )
159     return -SOS_EINVAL;                           225     return -SOS_EINVAL;
160                                                   226 
161   return nocheck_user_strzcpy(kernel_to, (cons    227   return nocheck_user_strzcpy(kernel_to, (const char*)user_from, max_len);
162 }                                                 228 }
163                                                   229 
164                                                   230 
165 sos_ret_t sos_strzcpy_to_user(sos_uaddr_t user    231 sos_ret_t sos_strzcpy_to_user(sos_uaddr_t user_to, const char *kernel_from,
166                               sos_size_t max_l    232                               sos_size_t max_len)
167 {                                                 233 {
168   /* Make sure user is trying to access user s    234   /* Make sure user is trying to access user space */
169   if ((sos_uaddr_t)user_to < SOS_PAGING_BASE_U    235   if ((sos_uaddr_t)user_to < SOS_PAGING_BASE_USER_ADDRESS)
170     return -SOS_EPERM;                            236     return -SOS_EPERM;
171                                                   237 
172   /* Don't allow invalid max_len */               238   /* Don't allow invalid max_len */
173   if ( (max_len < 1) || (max_len > SOS_PAGING_    239   if ( (max_len < 1) || (max_len > SOS_PAGING_USER_SPACE_SIZE) )
174     return -SOS_EINVAL;                           240     return -SOS_EINVAL;
175                                                   241 
176   return nocheck_user_strzcpy((char*)user_to,     242   return nocheck_user_strzcpy((char*)user_to, kernel_from, max_len);
177 }                                                 243 }
178                                                   244 
179                                                   245 
180 sos_ret_t sos_strndup_from_user(char ** kernel    246 sos_ret_t sos_strndup_from_user(char ** kernel_to, sos_uaddr_t from_user,
181                                 sos_size_t max    247                                 sos_size_t max_len,
182                                 sos_ui32_t kma    248                                 sos_ui32_t kmalloc_flags)
183 {                                                 249 {
184   sos_ret_t retval = sos_strnlen_from_user(fro    250   sos_ret_t retval = sos_strnlen_from_user(from_user, max_len);
185   if (retval < 0)                                 251   if (retval < 0)
186     return retval;                                252     return retval;
187                                                   253 
188   *kernel_to = (char*)sos_kmalloc(retval + 1,     254   *kernel_to = (char*)sos_kmalloc(retval + 1, kmalloc_flags);
189   if (NULL == *kernel_to)                         255   if (NULL == *kernel_to)
190     return -SOS_ENOMEM;                           256     return -SOS_ENOMEM;
191                                                   257 
192   retval = sos_strzcpy_from_user(*kernel_to, f    258   retval = sos_strzcpy_from_user(*kernel_to, from_user, retval + 1);
193   if (SOS_OK != retval)                           259   if (SOS_OK != retval)
194     {                                             260     {
195       sos_kfree((sos_vaddr_t)*kernel_to);         261       sos_kfree((sos_vaddr_t)*kernel_to);
196       *kernel_to = NULL;                          262       *kernel_to = NULL;
197     }                                             263     }
198                                                   264 
199   return retval;                                  265   return retval;
200 }                                                 266 }
                                                      

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