From f6161c72d1810db34f83d4570906859fc432e506 Mon Sep 17 00:00:00 2001 From: Jennifer Averett Date: Fri, 3 Jan 2003 18:14:09 +0000 Subject: 2003-01-03 Till Straumann * ChangeLog, base_fs.c, getpwent.c, privateenv.c Per PR303, Fix violation of node_access copy syemantics --- cpukit/libcsupport/src/privateenv.c | 106 +++++++++++++++++++++++++++++++----- 1 file changed, 93 insertions(+), 13 deletions(-) (limited to 'cpukit/libcsupport/src/privateenv.c') diff --git a/cpukit/libcsupport/src/privateenv.c b/cpukit/libcsupport/src/privateenv.c index 93dff453c5..d4e5608be1 100644 --- a/cpukit/libcsupport/src/privateenv.c +++ b/cpukit/libcsupport/src/privateenv.c @@ -23,25 +23,75 @@ #include #include +extern Chain_Control rtems_filesystem_mount_table_control; + +#define THE_ROOT_FS_LOC \ + (((rtems_filesystem_mount_table_entry_t*)\ + rtems_filesystem_mount_table_control.first)->mt_fs_root) + +/* cleanup a user environment + * NOTE: this must be called with + * thread dispatching disabled! + */ +static void +free_user_env(rtems_user_env_t *env) +{ + if (env != &rtems_global_user_env +#ifdef HAVE_USERENV_REFCNT + && --env->refcnt <= 0 +#endif + ) { + rtems_filesystem_freenode( &env->current_directory); + rtems_filesystem_freenode( &env->root_directory); + free(env); + } +} + rtems_status_code rtems_libio_set_private_env(void) { - rtems_status_code sc; - rtems_id task_id; + rtems_status_code sc; + rtems_id task_id; + rtems_filesystem_location_info_t loc; sc=rtems_task_ident(RTEMS_SELF,0,&task_id); if (sc != RTEMS_SUCCESSFUL) return sc; /* Only for the first time a malloc is necesary */ - if (rtems_current_user_env==&rtems_global_user_env) { - sc = rtems_task_variable_add(RTEMS_SELF,(void*)&rtems_current_user_env,free); - if (sc != RTEMS_SUCCESSFUL) return sc; - rtems_current_user_env = malloc(sizeof(rtems_user_env_t)); - if (!rtems_current_user_env) + if (rtems_current_user_env==&rtems_global_user_env) { + rtems_user_env_t *tmp = malloc(sizeof(rtems_user_env_t)); + if (!tmp) return RTEMS_NO_MEMORY; + +#ifdef HAVE_USERENV_REFCNT + tmp->refcnt = 1; +#endif + + sc = rtems_task_variable_add(RTEMS_SELF,(void*)&rtems_current_user_env,free_user_env); + if (sc != RTEMS_SUCCESSFUL) { + /* don't use free_user_env because the pathlocs are + * not initialized yet + */ + free(tmp); + return sc; + } + rtems_current_user_env = tmp; }; - /* the side effect desired . chroot("/") */ *rtems_current_user_env = rtems_global_user_env; /* get the global values*/ rtems_current_user_env->task_id=task_id; /* mark the local values*/ + + /* get a clean root */ + rtems_filesystem_root = THE_ROOT_FS_LOC; + + /* Clone the pathlocs. In contrast to most other + * code we must _not_ free the original locs because + * what we are trying to do here is forking off + * clones. + */ + + rtems_filesystem_evaluate_path("/", 0, &loc, 0); + rtems_filesystem_root = loc; + rtems_filesystem_evaluate_path("/", 0, &loc, 0); + rtems_filesystem_current = loc; return RTEMS_SUCCESSFUL; } @@ -51,6 +101,21 @@ rtems_status_code rtems_libio_set_private_env(void) { * Task_id (remote) and RTEMS_SELF(current). */ +/* NOTE: + * + * THIS CODE HAS NO PROTECTION IMPLEMENTED + * + * Tasks who wish to share their environments must + * + * a) assert that no participants are concurrently + * executing + * libio_share_private_env() and/or libio_set_private_env() + * + * b) mutex access to rtems_filesystem_current, rtems_filesytem_root + * while changing any of those (chdir(), chroot()). + */ + +#ifndef HAVE_USERENV_REFCNT rtems_status_code rtems_libio_share_private_env(rtems_id task_id) { rtems_status_code sc; rtems_user_env_t * shared_user_env; @@ -61,21 +126,36 @@ rtems_status_code rtems_libio_share_private_env(rtems_id task_id) { if (rtems_current_user_env->task_id==current_task_id) { /* kill the current user env & task_var*/ - free(rtems_current_user_env); + rtems_user_env_t *tmp = rtems_current_user_env; sc = rtems_task_variable_delete(RTEMS_SELF,(void*)&rtems_current_user_env); if (sc != RTEMS_SUCCESSFUL) return sc; + free_user_env(tmp); }; + /* AT THIS POINT, rtems_current_user_env is DANGLING */ + sc = rtems_task_variable_get(task_id,(void*)&rtems_current_user_env, (void*)&shared_user_env ); - if (sc != RTEMS_SUCCESSFUL) return sc; + if (sc != RTEMS_SUCCESSFUL) + goto bailout; - /* don't free(NULL'ed) at the task_delete. It is a shared var... */ - sc = rtems_task_variable_add(RTEMS_SELF,(void*)&rtems_current_user_env,NULL); - if (sc != RTEMS_SUCCESSFUL) return sc; + sc = rtems_task_variable_add(RTEMS_SELF,(void*)&rtems_current_user_env,free_user_env); + if (sc != RTEMS_SUCCESSFUL) + goto bailout; /* the current_user_env is the same pointer that remote env */ rtems_current_user_env = shared_user_env; + /* increase the reference count */ +#ifdef HAVE_USERENV_REFCNT + rtems_current_user_env->refcnt++; +#endif + return RTEMS_SUCCESSFUL; + +bailout: + /* fallback to the global env */ + rtems_current_user_env = &rtems_global_user_env; + return sc; } +#endif -- cgit v1.2.3