mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2026-09-21 23:54:25 +08:00
2003-01-03 Till Straumann <strauman@slac.stanford.edu>
* ChangeLog, base_fs.c, getpwent.c, privateenv.c Per PR303, Fix violation of node_access copy syemantics
This commit is contained in:
@@ -49,6 +49,7 @@ void rtems_filesystem_initialize( void )
|
||||
int status;
|
||||
rtems_filesystem_mount_table_entry_t *entry;
|
||||
rtems_filesystem_mount_table_t *mt;
|
||||
rtems_filesystem_location_info_t loc;
|
||||
|
||||
/*
|
||||
* Set the default umask to "022".
|
||||
@@ -75,8 +76,38 @@ void rtems_filesystem_initialize( void )
|
||||
rtems_fatal_error_occurred( 0xABCD0002 );
|
||||
|
||||
rtems_filesystem_link_counts = 0;
|
||||
|
||||
/* setup the 'current' and 'root' directories
|
||||
*
|
||||
* NOTE: cloning the pathlocs is not strictly
|
||||
* necessary. Since we implicitely let
|
||||
* all threads that don't call
|
||||
* libio_set_private_env() share the same
|
||||
* (initial) 'root' and 'current' locs,
|
||||
* we (also implicitely) assume that the
|
||||
* root filesystem doesn't care about
|
||||
* reference counts.
|
||||
* I just inserted the code snippet below
|
||||
* to remind everybody of the fact by
|
||||
* making it more explicit...
|
||||
* Ideally, every thread would have to
|
||||
* call either share_private_env() or
|
||||
* set_private_env() - but then: that's
|
||||
* gonna hit performance.
|
||||
*
|
||||
* Till Straumann, 10/25/2002
|
||||
*/
|
||||
rtems_filesystem_root = entry->mt_fs_root;
|
||||
rtems_filesystem_current = rtems_filesystem_root;
|
||||
/* Clone the root pathloc */
|
||||
rtems_filesystem_evaluate_path("/", 0, &loc, 0);
|
||||
rtems_filesystem_root = loc;
|
||||
/* One more clone for the current node */
|
||||
rtems_filesystem_evaluate_path("/", 0, &loc, 0);
|
||||
rtems_filesystem_current = loc;
|
||||
|
||||
/* Note: the global_env's refcnt doesn't matter
|
||||
* as the global env is never released
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
|
||||
@@ -185,21 +185,17 @@ static int getpw_r(
|
||||
{
|
||||
FILE *fp;
|
||||
int match;
|
||||
rtems_user_env_t * aux=rtems_current_user_env; /* save */
|
||||
|
||||
init_etc_passwd_group();
|
||||
rtems_current_user_env=&rtems_global_user_env; /* set root */
|
||||
|
||||
if ((fp = fopen("/etc/passwd", "r")) == NULL) {
|
||||
errno = EINVAL;
|
||||
rtems_current_user_env=aux; /* restore */
|
||||
return -1;
|
||||
}
|
||||
for(;;) {
|
||||
if (!scanpw(fp, pwd, buffer, bufsize)) {
|
||||
errno = EINVAL;
|
||||
fclose(fp);
|
||||
rtems_current_user_env=aux; /* restore */
|
||||
return -1;
|
||||
}
|
||||
if (name) {
|
||||
@@ -211,13 +207,11 @@ static int getpw_r(
|
||||
if (match) {
|
||||
fclose(fp);
|
||||
*result = pwd;
|
||||
rtems_current_user_env=aux; /* restore */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
errno = EINVAL;
|
||||
rtems_current_user_env=aux; /* restore */
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -276,14 +270,11 @@ struct passwd *getpwent()
|
||||
|
||||
void setpwent(void)
|
||||
{
|
||||
rtems_user_env_t * aux=rtems_current_user_env; /* save */
|
||||
init_etc_passwd_group();
|
||||
rtems_current_user_env=&rtems_global_user_env; /* set root */
|
||||
|
||||
if (passwd_fp != NULL)
|
||||
fclose(passwd_fp);
|
||||
passwd_fp = fopen("/etc/passwd", "r");
|
||||
rtems_current_user_env=aux; /* restore */
|
||||
}
|
||||
|
||||
void endpwent(void)
|
||||
@@ -353,21 +344,17 @@ static int getgr_r(
|
||||
{
|
||||
FILE *fp;
|
||||
int match;
|
||||
rtems_user_env_t * aux=rtems_current_user_env; /* save */
|
||||
|
||||
init_etc_passwd_group();
|
||||
rtems_current_user_env=&rtems_global_user_env; /* set root */
|
||||
|
||||
if ((fp = fopen("/etc/group", "r")) == NULL) {
|
||||
errno = EINVAL;
|
||||
rtems_current_user_env=aux; /* restore */
|
||||
return -1;
|
||||
}
|
||||
for(;;) {
|
||||
if (!scangr(fp, grp, buffer, bufsize)) {
|
||||
errno = EINVAL;
|
||||
fclose(fp);
|
||||
rtems_current_user_env=aux; /* restore */
|
||||
return -1;
|
||||
}
|
||||
if (name) {
|
||||
@@ -379,13 +366,11 @@ static int getgr_r(
|
||||
if (match) {
|
||||
fclose(fp);
|
||||
*result = grp;
|
||||
rtems_current_user_env=aux; /* restore */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
errno = EINVAL;
|
||||
rtems_current_user_env=aux; /* restore */
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -444,14 +429,11 @@ struct group *getgrent()
|
||||
|
||||
void setgrent(void)
|
||||
{
|
||||
rtems_user_env_t * aux=rtems_current_user_env; /* save */
|
||||
init_etc_passwd_group();
|
||||
rtems_current_user_env=&rtems_global_user_env; /* set root */
|
||||
|
||||
if (group_fp != NULL)
|
||||
fclose(group_fp);
|
||||
group_fp = fopen("/etc/group", "r");
|
||||
rtems_current_user_env=aux; /* restore */
|
||||
}
|
||||
|
||||
void endgrent(void)
|
||||
|
||||
@@ -23,25 +23,75 @@
|
||||
#include <rtems/libio.h>
|
||||
#include <rtems/libio_.h>
|
||||
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user