Skip to content
Snippets Groups Projects
Commit 3fd75078 authored by deuce's avatar deuce
Browse files

Check the current real and effective IDs (user and group) before calling

setre?id() since new systems apparently hang on that call when the IDs
are already what you want.  Further, use a single mutex to protect both
do_setuid() and do_seteuid().

The symptoms:
When you connect to the BBS, the user prompt would repeat quickly three
times then drop carrier on you.  Nothing you entered ever showed up.
--OR--
You seem to connect to the BBS, but you never see any output.

This was only easily reproduced when starting the system as a non-root
user.

This has been confirmed on FC3, FC4, and Debian etch.


The cause:
output_thread or input_thread called thread_up() which called do_seteuid()
which hung in setregid().  Since do_seteuid() is holding a mutex at this
point, when the other *put_thread calls thread_up(), it waits forever for
the mutex.  If output_thread starts first, this results in getchr()
returning ^C every time it's called since input_thread_running is false.


Question for DigitalMan:
Should output_thread/input_thread post a semaphore when they're up to prevent
SMP systems from getting far enough into answer() to call IO stuff before the
corresponding thread is running?  A timed semaphore wait in main.cpp then
could be used (you wouldn't want to block forever in case this happens again).
parent c7a0de8b
No related branches found
No related tags found
No related merge requests found
......@@ -256,38 +256,42 @@ static int lprintf(int level, char *fmt, ...)
}
#ifdef __unix__
static pthread_mutex_t setid_mutex;
static BOOL setid_mutex_initialized;
/**********************************************************
* Change uid of the calling process to the user if specified
* **********************************************************/
static BOOL do_seteuid(BOOL to_new)
{
BOOL result=FALSE;
static pthread_mutex_t mutex;
static BOOL mutex_initialized;
if(new_uid_name[0]==0) /* not set? */
return(TRUE); /* do nothing */
if(!mutex_initialized) {
pthread_mutex_init(&mutex,NULL);
mutex_initialized=TRUE;
if(!setid_mutex_initialized) {
pthread_mutex_init(&setid_mutex,NULL);
setid_mutex_initialized=TRUE;
}
pthread_mutex_lock(&mutex);
pthread_mutex_lock(&setid_mutex);
if(to_new)
if(!setregid(-1,new_gid) && !setreuid(-1,new_uid))
if(to_new) {
if(((new_gid==getegid() && new_gid==getgid()) || setregid(-1,new_gid)==0)
&& ((new_uid==geteuid() && new_uid==getuid()) || setreuid(-1,new_uid)==0))
result=TRUE;
else
result=FALSE;
else
if(!setregid(-1,old_gid) && !setreuid(-1,old_uid))
}
else {
if(((old_gid==getegid() && old_gid==getgid()) || setregid(-1,old_gid)==0)
&& ((old_uid==geteuid() && old_uid==getuid()) || setreuid(-1,old_uid)==0))
result=TRUE;
else
result=FALSE;
}
pthread_mutex_unlock(&mutex);
pthread_mutex_unlock(&setid_mutex);
if(!result) {
lputs(LOG_ERR,"!seteuid FAILED");
......@@ -306,6 +310,14 @@ BOOL do_setuid(BOOL force)
if(!force)
return(do_seteuid(TRUE));
#endif
if(!setid_mutex_initialized) {
pthread_mutex_init(&setid_mutex,NULL);
setid_mutex_initialized=TRUE;
}
pthread_mutex_lock(&setid_mutex);
setregid(-1,old_gid);
setreuid(-1,old_uid);
if(setregid(new_gid,new_gid))
......@@ -321,6 +333,9 @@ BOOL do_setuid(BOOL force)
lputs(LOG_ERR,strerror(errno));
result=FALSE;
}
pthread_mutex_unlock(&setid_mutex);
if(force && (!result))
exit(1);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment