Ticket #303: privateenv.patch

File privateenv.patch, 12.2 KB (added by strauman, on Dec 3, 2006 at 1:31:12 PM)

privateenv.patch

Line 
1Index: base_fs.c
2===================================================================
3RCS file: /afs/slac/g/spear/cvsrep/rtems/src/c/src/lib/libc/base_fs.c,v
4retrieving revision 1.1.1.1
5diff -c -r1.1.1.1 base_fs.c
6*** base_fs.c   14 Dec 2001 22:52:31 -0000      1.1.1.1
7--- base_fs.c   26 Oct 2002 02:45:15 -0000
8***************
9*** 49,54 ****
10--- 49,55 ----
11    int                                   status;
12    rtems_filesystem_mount_table_entry_t *entry;
13    rtems_filesystem_mount_table_t       *mt;
14+   rtems_filesystem_location_info_t            loc;
15   
16    /*
17     *  Set the default umask to "022".
18***************
19*** 75,82 ****
20      rtems_fatal_error_occurred( 0xABCD0002 );
21 
22    rtems_filesystem_link_counts = 0;
23    rtems_filesystem_root        = entry->mt_fs_root;
24!   rtems_filesystem_current     = rtems_filesystem_root;
25 
26 
27    /*
28--- 76,113 ----
29      rtems_fatal_error_occurred( 0xABCD0002 );
30 
31    rtems_filesystem_link_counts = 0;
32+
33+   /* setup the 'current' and 'root' directories
34+    *
35+    * NOTE: cloning the pathlocs is not strictly
36+    *       necessary. Since we implicitely let
37+    *       all threads that don't call
38+    *       libio_set_private_env() share the same
39+    *       (initial) 'root' and 'current' locs,
40+    *       we (also implicitely) assume that the
41+    *       root filesystem doesn't care about
42+    *       reference counts.
43+    *       I just inserted the code snippet below
44+    *       to remind everybody of the fact by
45+    *       making it more explicit...
46+    *       Ideally, every thread would have to
47+    *       call either share_private_env() or
48+    *       set_private_env() - but then: that's
49+    *       gonna hit performance.
50+    *
51+    *       Till Straumann, 10/25/2002
52+    */
53    rtems_filesystem_root        = entry->mt_fs_root;
54!   /* Clone the root pathloc */
55!   rtems_filesystem_evaluate_path("/", 0, &loc, 0);
56!   rtems_filesystem_root        = loc;
57!   /* One more clone for the current node */
58!   rtems_filesystem_evaluate_path("/", 0, &loc, 0);
59!   rtems_filesystem_current     = loc;
60!
61!   /* Note: the global_env's refcnt doesn't matter
62!    * as the global env is never released
63!    */
64 
65 
66    /*
67Index: getgrent.c
68===================================================================
69RCS file: /afs/slac/g/spear/cvsrep/rtems/src/c/src/lib/libc/getgrent.c,v
70retrieving revision 1.1.1.1
71diff -c -r1.1.1.1 getgrent.c
72*** getgrent.c  14 Dec 2001 22:52:31 -0000      1.1.1.1
73--- getgrent.c  8 Nov 2002 02:10:43 -0000
74***************
75*** 50,63 ****
76  )
77  {
78    FILE *fp;
79-   rtems_user_env_t * aux=rtems_current_user_env; /* save */
80 
81    init_etc_passwd_group();
82-   rtems_current_user_env=&rtems_global_user_env; /* set root */
83 
84    if ((fp = fopen ("/etc/group", "r")) == NULL) {
85      errno = EINVAL;
86-     rtems_current_user_env=aux; /* restore */
87      return -1;
88    }
89 
90--- 50,60 ----
91***************
92*** 72,84 ****
93      if (!strcmp (groupname, name)) {
94        fclose (fp);
95        *result = grp;
96-       rtems_current_user_env=aux; /* restore */
97        return 0;
98      }
99    }
100    fclose (fp);
101    errno = EINVAL;
102-   rtems_current_user_env=aux; /* restore */
103    return -1;
104  }
105 
106--- 69,79 ----
107***************
108*** 104,118 ****
109  )
110  {
111    FILE *fp;
112-   rtems_user_env_t * aux=rtems_current_user_env; /* save */
113 
114 
115    init_etc_passwd_group();
116-   rtems_current_user_env=&rtems_global_user_env; /* set root */
117 
118    if ((fp = fopen ("/etc/group", "r")) == NULL) {
119      errno = EINVAL;
120-     rtems_current_user_env=aux; /* restore */
121      return -1;
122    }
123 
124--- 99,110 ----
125***************
126*** 128,140 ****
127      if (gid == gr_group.gr_gid) {
128        fclose (fp);
129        *result = grp;
130-       rtems_current_user_env=aux; /* restore */
131        return 0;
132      }
133    }
134    fclose (fp);
135    errno = EINVAL;
136-   rtems_current_user_env=aux; /* restore */
137    return -1;
138  }
139 
140--- 120,130 ----
141***************
142*** 174,188 ****
143  void
144  setgrent ()
145  {
146-   rtems_user_env_t * aux=rtems_current_user_env; /* save */
147    init_etc_passwd_group();
148-   rtems_current_user_env=&rtems_global_user_env; /* set root */
149 
150    if (group_fp != NULL)
151      fclose (group_fp);
152 
153    group_fp = fopen ("/etc/group", "r");
154-   rtems_current_user_env=aux; /* restore */
155  }
156 
157  void
158--- 164,175 ----
159Index: getpwent.c
160===================================================================
161RCS file: /afs/slac/g/spear/cvsrep/rtems/src/c/src/lib/libc/getpwent.c,v
162retrieving revision 1.1.1.1
163diff -c -r1.1.1.1 getpwent.c
164*** getpwent.c  14 Dec 2001 22:52:31 -0000      1.1.1.1
165--- getpwent.c  8 Nov 2002 02:11:09 -0000
166***************
167*** 97,110 ****
168  )
169  {
170    FILE *fp;
171-   rtems_user_env_t * aux=rtems_current_user_env; /* save */
172 
173    init_etc_passwd_group();
174-   rtems_current_user_env=&rtems_global_user_env; /* set root */
175 
176    if ((fp = fopen ("/etc/passwd", "r")) == NULL) {
177      errno = EINVAL;
178-     rtems_current_user_env=aux; /* restore */
179      return -1;
180    }
181 
182--- 97,107 ----
183***************
184*** 123,135 ****
185      if (!strcmp (logname, name)) {
186        fclose (fp);
187        *result = pwd;
188-       rtems_current_user_env=aux; /* restore */
189        return 0;
190      }
191    }
192    fclose (fp);
193    errno = EINVAL;
194-     rtems_current_user_env=aux; /* restore */
195    return -1;
196  }
197 
198--- 120,130 ----
199***************
200*** 155,168 ****
201  )
202  {
203    FILE *fp;
204-   rtems_user_env_t * aux=rtems_current_user_env; /* save */
205 
206    init_etc_passwd_group();
207-   rtems_current_user_env=&rtems_global_user_env; /* set root */
208 
209    if ((fp = fopen ("/etc/passwd", "r")) == NULL) {
210      errno = EINVAL;
211-     rtems_current_user_env=aux; /* restore */
212      return -1;
213    }
214 
215--- 150,160 ----
216***************
217*** 181,193 ****
218      if (uid == pwd->pw_uid) {
219        fclose (fp);
220        *result = pwd;
221-       rtems_current_user_env=aux; /* restore */
222        return 0;
223      }
224    }
225    fclose (fp);
226    errno = EINVAL;
227-   rtems_current_user_env=aux; /* restore */
228    return -1;
229  }
230 
231--- 173,183 ----
232***************
233*** 230,244 ****
234 
235  void setpwent( void )
236  {
237-   rtems_user_env_t * aux=rtems_current_user_env; /* save */
238    init_etc_passwd_group();
239-   rtems_current_user_env=&rtems_global_user_env; /* set root */
240 
241    if (passwd_fp != NULL)
242      fclose (passwd_fp);
243 
244    passwd_fp = fopen ("/etc/passwd", "r");
245-   rtems_current_user_env=aux; /* restore */
246  }
247 
248  void endpwent( void )
249--- 220,231 ----
250Index: privateenv.c
251===================================================================
252RCS file: /afs/slac/g/spear/cvsrep/rtems/src/c/src/lib/libc/privateenv.c,v
253retrieving revision 1.1.1.2
254diff -c -r1.1.1.2 privateenv.c
255*** privateenv.c        7 Mar 2002 01:53:51 -0000       1.1.1.2
256--- privateenv.c        8 Nov 2002 02:19:14 -0000
257***************
258*** 23,47 ****
259  #include <rtems/libio.h>
260  #include <rtems/libio_.h>
261 
262  rtems_status_code rtems_libio_set_private_env(void) {
263!   rtems_status_code sc;
264!   rtems_id          task_id;
265 
266    sc=rtems_task_ident(RTEMS_SELF,0,&task_id);
267    if (sc != RTEMS_SUCCESSFUL) return sc;
268 
269    /* Only for the first time a malloc is necesary */
270!   if (rtems_current_user_env==&rtems_global_user_env) {
271!    sc = rtems_task_variable_add(RTEMS_SELF,(void*)&rtems_current_user_env,free);
272!    if (sc != RTEMS_SUCCESSFUL) return sc;
273!    rtems_current_user_env = malloc(sizeof(rtems_user_env_t));
274!    if (!rtems_current_user_env)
275       return RTEMS_NO_MEMORY;
276    };
277 
278-   /* the side effect desired . chroot("/") */
279    *rtems_current_user_env = rtems_global_user_env; /* get the global values*/
280    rtems_current_user_env->task_id=task_id;         /* mark the local values*/
281 
282    return RTEMS_SUCCESSFUL;
283  }
284--- 23,97 ----
285  #include <rtems/libio.h>
286  #include <rtems/libio_.h>
287 
288+ extern Chain_Control rtems_filesystem_mount_table_control;
289+
290+ #define THE_ROOT_FS_LOC \
291+       (((rtems_filesystem_mount_table_entry_t*)\
292+          rtems_filesystem_mount_table_control.first)->mt_fs_root)
293+
294+ /* cleanup a user environment
295+  * NOTE: this must be called with
296+  *       thread dispatching disabled!
297+  */
298+ static void
299+ free_user_env(rtems_user_env_t *env)
300+ {
301+       if (env != &rtems_global_user_env
302+ #ifdef HAVE_USERENV_REFCNT
303+               && --env->refcnt <= 0
304+ #endif
305+               ) {
306+               rtems_filesystem_freenode( &env->current_directory);
307+               rtems_filesystem_freenode( &env->root_directory);
308+               free(env);
309+       }
310+ }
311+
312  rtems_status_code rtems_libio_set_private_env(void) {
313!   rtems_status_code                                   sc;
314!   rtems_id                                            task_id;
315!   rtems_filesystem_location_info_t            loc;
316 
317    sc=rtems_task_ident(RTEMS_SELF,0,&task_id);
318    if (sc != RTEMS_SUCCESSFUL) return sc;
319 
320    /* Only for the first time a malloc is necesary */
321!   if (rtems_current_user_env==&rtems_global_user_env) {
322!    rtems_user_env_t   *tmp = malloc(sizeof(rtems_user_env_t));
323!    if (!tmp)
324       return RTEMS_NO_MEMORY;
325+
326+ #ifdef HAVE_USERENV_REFCNT
327+    tmp->refcnt = 1;
328+ #endif
329+
330+    sc = rtems_task_variable_add(RTEMS_SELF,(void*)&rtems_current_user_env,free_user_env);
331+    if (sc != RTEMS_SUCCESSFUL) {
332+        /* don't use free_user_env because the pathlocs are
333+         * not initialized yet
334+         */
335+      free(tmp);
336+      return sc;
337+    }
338+    rtems_current_user_env = tmp;
339    };
340 
341    *rtems_current_user_env = rtems_global_user_env; /* get the global values*/
342    rtems_current_user_env->task_id=task_id;         /* mark the local values*/
343+   
344+   /* get a clean root */
345+   rtems_filesystem_root    = THE_ROOT_FS_LOC;
346+
347+   /* Clone the pathlocs. In contrast to most other
348+    * code we must _not_ free the original locs because
349+    * what we are trying to do here is forking off
350+    * clones.
351+    */
352+
353+   rtems_filesystem_evaluate_path("/", 0, &loc, 0);
354+   rtems_filesystem_root    = loc;
355+   rtems_filesystem_evaluate_path("/", 0, &loc, 0);
356+   rtems_filesystem_current = loc;
357 
358    return RTEMS_SUCCESSFUL;
359  }
360***************
361*** 51,56 ****
362--- 101,121 ----
363   *   Task_id (remote) and RTEMS_SELF(current).
364   */
365 
366+ /* NOTE:
367+  *
368+  * THIS CODE HAS NO PROTECTION IMPLEMENTED
369+  *
370+  * Tasks who wish to share their environments must
371+  *
372+  *  a) assert that no participants are concurrently
373+  *     executing
374+  *     libio_share_private_env() and/or libio_set_private_env()
375+  *
376+  *  b) mutex access to rtems_filesystem_current, rtems_filesytem_root
377+  *     while changing any of those (chdir(), chroot()).
378+  */
379+
380+ #ifndef HAVE_USERENV_REFCNT
381  rtems_status_code rtems_libio_share_private_env(rtems_id task_id) {
382    rtems_status_code  sc;
383    rtems_user_env_t * shared_user_env;
384***************
385*** 61,81 ****
386 
387    if (rtems_current_user_env->task_id==current_task_id) {
388     /* kill the current user env & task_var*/   
389!    free(rtems_current_user_env);       
390     sc = rtems_task_variable_delete(RTEMS_SELF,(void*)&rtems_current_user_env);
391     if (sc != RTEMS_SUCCESSFUL) return sc;
392    };
393 
394    sc = rtems_task_variable_get(task_id,(void*)&rtems_current_user_env,
395                                       (void*)&shared_user_env       );
396!   if (sc != RTEMS_SUCCESSFUL) return sc;
397 
398!   /* don't free(NULL'ed) at the task_delete. It is a shared var... */   
399!   sc = rtems_task_variable_add(RTEMS_SELF,(void*)&rtems_current_user_env,NULL);
400!   if (sc != RTEMS_SUCCESSFUL) return sc;
401   
402    /* the current_user_env is the same pointer that remote env */
403    rtems_current_user_env = shared_user_env;
404 
405    return RTEMS_SUCCESSFUL;
406  }
407--- 126,161 ----
408 
409    if (rtems_current_user_env->task_id==current_task_id) {
410     /* kill the current user env & task_var*/   
411!       rtems_user_env_t        *tmp = rtems_current_user_env;
412     sc = rtems_task_variable_delete(RTEMS_SELF,(void*)&rtems_current_user_env);
413     if (sc != RTEMS_SUCCESSFUL) return sc;
414+    free_user_env(tmp);         
415    };
416 
417+   /* AT THIS POINT, rtems_current_user_env is DANGLING */
418+
419    sc = rtems_task_variable_get(task_id,(void*)&rtems_current_user_env,
420                                       (void*)&shared_user_env       );
421!   if (sc != RTEMS_SUCCESSFUL)
422!     goto bailout;
423 
424!   sc = rtems_task_variable_add(RTEMS_SELF,(void*)&rtems_current_user_env,free_user_env);
425!   if (sc != RTEMS_SUCCESSFUL)
426!     goto bailout;
427   
428    /* the current_user_env is the same pointer that remote env */
429    rtems_current_user_env = shared_user_env;
430 
431+   /* increase the reference count */
432+ #ifdef HAVE_USERENV_REFCNT
433+   rtems_current_user_env->refcnt++;
434+ #endif
435+
436    return RTEMS_SUCCESSFUL;
437+
438+ bailout:
439+   /* fallback to the global env */
440+   rtems_current_user_env = &rtems_global_user_env;
441+   return sc;
442  }
443+ #endif