From 965cb15c69ced7becc7102ec1ee07156fad3beb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20H=C3=BCbinette=20=28Hubbe=29?= <hubbe@hubbe.net> Date: Mon, 6 Apr 1998 13:38:52 -0700 Subject: [PATCH] changed to not use malloc and other dangerous functions after fork() Rev: src/signal_handler.c:1.42 --- src/signal_handler.c | 529 +++++++++++++++++++++++++------------------ 1 file changed, 313 insertions(+), 216 deletions(-) diff --git a/src/signal_handler.c b/src/signal_handler.c index 48f4add28d..b696c2587e 100644 --- a/src/signal_handler.c +++ b/src/signal_handler.c @@ -22,7 +22,7 @@ #include "builtin_functions.h" #include <signal.h> -RCSID("$Id: signal_handler.c,v 1.41 1998/03/28 15:03:31 grubba Exp $"); +RCSID("$Id: signal_handler.c,v 1.42 1998/04/06 20:38:52 hubbe Exp $"); #ifdef HAVE_PASSWD_H # include <passwd.h> @@ -68,6 +68,8 @@ RCSID("$Id: signal_handler.c,v 1.41 1998/03/28 15:03:31 grubba Exp $"); #define SIGNAL_BUFFER 16384 #define WAIT_BUFFER 4096 +extern int fd_from_object(struct object *o); + static struct svalue signal_callbacks[MAX_SIGNALS]; static unsigned char sigbuf[SIGNAL_BUFFER]; @@ -578,20 +580,25 @@ static HANDLE get_inheritable_handle(struct mapping *optional, { if(tmp->type == T_OBJECT) { - apply(tmp->u.object,"query_fd",0); - if(sp[-1].type == T_INT) - { - if(!(fd_query_properties(sp[-1].u.integer, 0) & fd_INTERPROCESSABLE)) - { - void create_proxy_pipe(struct object *o, int for_reading); + INT32 fd=fd_from_object(tmp->u.object); - create_proxy_pipe(tmp->u.object, for_reading); - apply(sp[-1].u.object, "query_fd", 0); - } + if(fd == -1) + error("File for %s is not open.\n",name); + + if(!(fd_query_properties(fd, 0) & fd_INTERPROCESSABLE)) + { + void create_proxy_pipe(struct object *o, int for_reading); - - if(!DuplicateHandle(GetCurrentProcess(), - (HANDLE)da_handle[sp[-1].u.integer], + create_proxy_pipe(tmp->u.object, for_reading); + fd=fd_from_object(sp[-1].u.object); + + if(fd == -1) + error("Proxy thread creation failed for %s.\n",name); + } + + + if(!DuplicateHandle(GetCurrentProcess(), + (HANDLE)da_handle[fd], GetCurrentProcess(), &ret, NULL, @@ -599,7 +606,6 @@ static HANDLE get_inheritable_handle(struct mapping *optional, DUPLICATE_SAME_ACCESS)) /* This could cause handle-leaks */ error("Failed to duplicate handle %d.\n",GetLastError()); - } } } pop_n_elems(sp-save_stack); @@ -607,58 +613,47 @@ static HANDLE get_inheritable_handle(struct mapping *optional, } #endif -#ifdef HAVE_GETPWENT -#ifndef HAVE_GETPWNAM -struct passwd *getpwnam(char *name) +#ifndef __NT__ + +struct perishables { - struct passwd *pw; - THREADS_ALLOW_UID(); - setpwent(); - while(pw=getpwent()) - if(strcmp(pw->pw_name,name)) - break; - endpwent(); - THREADS_DISALLOW_UID(); - return pw; -} -#define HAVE_GETPWNAM + char **env; + char **argv; + struct pike_string *nice_s; + struct pike_string *cwd_s; + struct pike_string *stdin_s; + struct pike_string *stdout_s; + struct pike_string *stderr_s; +#ifdef HAVE_SETGROUPS + gid_t *wanted_gids; + struct array *wanted_gids_array; + int num_wanted_gids; #endif +}; -#ifndef HAVE_GETPWUID -struct passwd *getpwiod(int uid) +static void free_perishables(struct perishables *storage) { - struct passwd *pw; - THREADS_ALLOW_UID(); - setpwent(); - while(pw=getpwent()) - if(pw->pw_uid == uid) - break; - endpwent(); - THREADS_DISALLOW_UID(); - return 0; -} -#define HAVE_GETPWUID -#endif + if(storage->env) free((char *)storage->env); + + if(storage->argv) free((char *)storage->argv); + if(storage->nice_s) free_string(storage->nice_s); + if(storage->cwd_s) free_string(storage->cwd_s); + if(storage->stdin_s) free_string(storage->stdin_s); + if(storage->stdout_s) free_string(storage->stdout_s); + if(storage->stderr_s) free_string(storage->stderr_s); + +#ifdef HAVE_SETGROUPS + if(storage->wanted_gids) free((char *)storage->wanted_gids); + + if(storage->wanted_gids_array) free_array(storage->wanted_gids_array); + #endif -#ifdef HAVE_GETGRENT -#ifndef HAVE_GETGRNAM -struct group *getgrnam(char *name) -{ - struct group *gr; - THREADS_ALLOW_UID(); - setgrent(); - while(pw=getgrent()) - if(strcmp(gr->gr_name,name)) - break; - endgrent(); - THREADS_DISALLOW_UID(); - return gr; } -#define HAVE_GETGRNAM -#endif + #endif + /* * create_process(string *arguments, mapping optional_data); * @@ -828,7 +823,234 @@ void f_create_process(INT32 args) } #else /* __NT__ */ { + struct svalue *stack_save=sp-args; + ONERROR err; + struct passwd *pw=0; + struct perishables storage; + int do_initgroups=1; + int wanted_uid; + int wanted_gid; + int gid_request=0; pid_t pid; + + storage.env=0; + storage.argv=0; + MAKE_CONSTANT_SHARED_STRING(storage.nice_s, "nice"); + MAKE_CONSTANT_SHARED_STRING(storage.cwd_s, "cwd"); + MAKE_CONSTANT_SHARED_STRING(storage.stdin_s, "stdin"); + MAKE_CONSTANT_SHARED_STRING(storage.stdout_s, "stdout"); + MAKE_CONSTANT_SHARED_STRING(storage.stderr_s, "stderr"); + +#ifdef HAVE_SETGROUPS + storage.wanted_gids=0; + storage.wanted_gids_array=0; +#endif + + SET_ONERROR(err, free_perishables, &storage); + +#ifdef HAVE_GETEUID + wanted_uid=geteuid(); +#else + wanted_uid=getgid(); +#endif + +#ifdef HAVE_GETGID + wanted_gid=getegid(); +#else + wanted_gid=getgid(); +#endif + + if(optional) + { + if((tmp=simple_mapping_string_lookup(optional, "gid"))) + { + switch(tmp->type) + { + case T_INT: + wanted_gid=tmp->u.integer; + gid_request=1; + break; + +#if defined(HAVE_GETGRNAM) || defined(HAVE_GETGRENT) + case T_STRING: + { + extern void f_getgrnam(INT32); + push_svalue(tmp); + f_getgrnam(1); + if(!sp[-1].type!=T_ARRAY) + error("No such group.\n"); + if(sp[-1].u.array->item[2].type!=T_INT) + error("Getpwuid failed!\n"); + wanted_gid=sp[-1].u.array->item[2].u.integer; + pop_stack(); + gid_request=1; + } +#endif + + default: + error("Invalid argument for gid.\n"); + } + } + + if((tmp=simple_mapping_string_lookup(optional, "uid"))) + { + switch(tmp->type) + { + case T_INT: + wanted_uid=tmp->u.integer; +#if defined(HAVE_GETPWUID) || defined(HAVE_GETPWENT) + if(!gid_request) + { + extern void f_getpwent(INT32); + push_int(gid_request); + f_getpwent(1); + + if(sp[-1].type==T_ARRAY) + { + if(sp[-1].u.array->item[3].type!=T_INT) + error("Getpwuid failed!\n"); + wanted_gid=sp[-1].u.array->item[3].u.integer; + } + pop_stack(); + } +#endif + break; + +#if defined(HAVE_GETPWNAM) || defined(HAVE_GETPWENT) + case T_STRING: + { + extern void f_getpwnam(INT32); + push_svalue(tmp); + f_getpwnam(1); + if(sp[-1].type != T_ARRAY) + error("No such user.\n"); + if(sp[-1].u.array->item[2].type!=T_INT || + sp[-1].u.array->item[3].type!=T_INT) + error("Getpwnam failed!\n"); + wanted_uid=sp[-1].u.array->item[2].u.integer; + if(!gid_request) + wanted_gid=sp[-1].u.array->item[3].u.integer; + pop_stack(); + break; + } +#endif + + default: + error("Invalid argument for uid.\n"); + } + } + + if((tmp=simple_mapping_string_lookup(optional, "setgroups"))) + { +#ifdef HAVE_SETGROUPS + if(tmp->type != T_ARRAY) + { + storage.wanted_gids_array=tmp->u.array; + for(e=0;e<storage.wanted_gids_array->size;e++) + if(storage.wanted_gids_array->item[e].type != T_INT) + error("Invalid type for setgroups.\n"); + storage.wanted_gids_array->refs++; + do_initgroups=0; + }else{ + error("Invalid type for setgroups.\n"); + } +#else + error("Setgroups is not available.\n"); +#endif + } + + + if((tmp=simple_mapping_string_lookup(optional, "env"))) + { + if(tmp->type == T_MAPPING) + { + struct mapping *m=tmp->u.mapping; + struct array *i,*v; + int ptr=0; + i=mapping_indices(m); + v=mapping_values(m); + + storage.env=(char **)xalloc((1+m_sizeof(m)) * sizeof(char *)); + for(e=0;e<i->size;e++) + { + if(ITEM(i)[e].type == T_STRING && + ITEM(v)[e].type == T_STRING) + { + check_stack(3); + push_string(ITEM(i)[e].u.string); + push_string(make_shared_string("=")); + push_string(ITEM(v)[e].u.string); + f_add(3); + storage.env[ptr++]=sp[-1].u.string->str; + } + } + storage.env[ptr++]=0; + free_array(i); + free_array(v); + } + } + + if((tmp=simple_mapping_string_lookup(optional, "noinitgroups"))) + if(!IS_ZERO(tmp)) + do_initgroups=0; + } + +#ifdef HAVE_SETGROUPS + +#ifdef HAVE_GETGRENT + if(wanted_uid != getuid() && do_initgroups) + { + extern void f_get_groups_for_user(INT32); + push_int(wanted_uid); + f_get_groups_for_user(1); + if(sp[-1].type == T_ARRAY) + { + storage.wanted_gids_array=sp[-1].u.array; + sp--; + } + } +#endif + + if(storage.wanted_gids_array) + { + int e; + storage.wanted_gids=(gid_t *)xalloc(sizeof(gid_t) * storage.wanted_gids_array->size); + for(e=0;e<storage.wanted_gids_array->size;e++) + { + switch(storage.wanted_gids_array->item[e].type) + { + case T_INT: + storage.wanted_gids[e]=storage.wanted_gids_array->item[e].u.integer; + break; + +#if defined(HAVE_GETGRENT) || defined(HAVE_GETGRNAM) + case T_STRING: + { + extern void f_getgrnam(INT32); + ref_push_string(storage.wanted_gids_array->item[e].u.string); + f_getgrnam(2); + if(sp[-1].type != T_ARRAY) + error("No such group.\n"); + + storage.wanted_gids[e]=sp[-1].u.array->item[2].u.integer; + pop_stack(); + break; + } +#endif + + default: + error("Gids must be integers or strings only.\n"); + } + } + storage.num_wanted_gids=storage.wanted_gids_array->size; + free_array(storage.wanted_gids_array); + storage.wanted_gids_array=0; + do_initgroups=0; + } +#endif /* HAVE_SETGROUPS */ + + storage.argv=(char **)xalloc((1+cmd->size) * sizeof(char *)); + THREADS_ALLOW_UID(); #if defined(HAVE_FORK1) && defined(_REENTRANT) pid=fork1(); @@ -839,6 +1061,10 @@ void f_create_process(INT32 args) if(pid==-1) error("Failed to start process.\n"); if(pid) { + UNSET_ONERROR(err); + free_perishables(&storage); + pop_n_elems(sp - stack_save); + if(!signal_evaluator_callback) { signal_evaluator_callback=add_to_callback(&evaluator_callbacks, @@ -851,19 +1077,13 @@ void f_create_process(INT32 args) push_int(pid); mapping_insert(pid_mapping,sp-1, sp-2); pop_n_elems(2); + push_int(0); }else{ - int wanted_uid; - int wanted_gid; - int gid_request=0; - int do_initgroups=1; - struct passwd *pw=0; ONERROR oe; - char **argv; #ifdef DECLARE_ENVIRON extern char **environ; #endif - char **env; extern void my_set_close_on_exec(int,int); extern void do_set_close_on_exec(void); @@ -874,26 +1094,11 @@ void f_create_process(INT32 args) num_threads=1; #endif call_callback(&fork_child_callback, 0); - - - argv=(char **)xalloc((1+cmd->size) * sizeof(char *)); - - for(e=0;e<cmd->size;e++) - argv[e]=ITEM(cmd)[e].u.string->str; - - argv[e]=0; -#ifdef HAVE_GETEUID - wanted_uid=geteuid(); -#else - wanted_uid=getgid(); -#endif + for(e=0;e<cmd->size;e++) storage.argv[e]=ITEM(cmd)[e].u.string->str; + storage.argv[e]=0; -#ifdef HAVE_GETGID - wanted_gid=getegid(); -#else - wanted_gid=getgid(); -#endif + if(storage.env) environ=storage.env; #ifdef HAVE_SETEUID seteuid(0); @@ -908,95 +1113,13 @@ void f_create_process(INT32 args) int toclose[3]; int fd; - if((tmp=simple_mapping_string_lookup(optional, "gid"))) - { - switch(tmp->type) - { - case T_INT: - wanted_gid=tmp->u.integer; - gid_request=1; - break; - -#ifdef HAVE_GETGRNAM - case T_STRING: - { - struct group *gr=getgrnam(tmp->u.string->str); - if(!gr) exit(77); - wanted_gid=tmp->u.integer; - gid_request=1; - } -#endif - - default: - exit(64); - } - } - - if((tmp=simple_mapping_string_lookup(optional, "uid"))) - { - switch(tmp->type) - { - case T_INT: - wanted_uid=tmp->u.integer; -#ifdef HAVE_GETPWUID - if(!gid_request) - { - pw=getpwuid(wanted_uid); - if(pw) wanted_gid=pw->pw_gid; - } -#endif - break; - -#ifdef HAVE_GETPWNAM - case T_STRING: - pw=getpwnam(tmp->u.string->str); - if(!pw) exit(77); - wanted_uid=pw->pw_uid; - if(!gid_request) - wanted_gid=pw->pw_gid; - break; -#endif - - default: - exit(64); - } - } - - if((tmp=simple_mapping_string_lookup(optional, "noinitgroups"))) - if(!IS_ZERO(tmp)) - do_initgroups=0; - - if((tmp=simple_mapping_string_lookup(optional, "setgroups"))) - { -#ifdef HAVE_SETGROUPS - if(tmp->type != T_ARRAY) - { - int e; - gid_t *g=(gid_t *)xalloc(sizeof(gid_t) * tmp->u.array->size); - for(e=0;e<tmp->u.array->size;e++) - { - if(tmp->u.array->item[e].type != T_INT) exit(64); - g[e]=tmp->u.array->item[e].u.integer; - } - if(!setgroups(tmp->u.array->size, g)) exit(77); - do_initgroups=0; - }else{ - exit(64); - } -#else - exit(69); -#endif - } - - - if((tmp=simple_mapping_string_lookup(optional, "cwd"))) + if((tmp=low_mapping_string_lookup(optional, storage.cwd_s))) if(tmp->type == T_STRING) if(chdir(tmp->u.string->str)) exit(69); - #ifdef HAVE_NICE - if ((tmp=simple_mapping_string_lookup(optional, "nice"))) { + if ((tmp=low_mapping_string_lookup(optional, storage.nice_s))) { if (tmp->type == T_INT) { int n = nice(0); int nn = tmp->u.integer; @@ -1010,61 +1133,23 @@ void f_create_process(INT32 args) } #endif /* HAVE_NICE */ - - if((tmp=simple_mapping_string_lookup(optional, "env"))) - { - if(tmp->type == T_MAPPING) - { - struct mapping *m=tmp->u.mapping; - struct array *i,*v; - int ptr=0; - i=mapping_indices(m); - v=mapping_values(m); - - env=(char **)xalloc((1+m_sizeof(m)) * sizeof(char *)); - for(e=0;e<i->size;e++) - { - if(ITEM(i)[e].type == T_STRING && - ITEM(v)[e].type == T_STRING) - { - check_stack(3); - push_string(ITEM(i)[e].u.string); - push_string(make_shared_string("=")); - push_string(ITEM(v)[e].u.string); - f_add(3); - env[ptr++]=sp[-1].u.string->str; - } - } - env[ptr++]=0; - free_array(i); - free_array(v); - environ=env; - } - } - for(fd=0;fd<3;fd++) { - char *fdname; + struct pike_string *fdname; switch(fd) { - case 0: fdname="stdin"; break; - case 1: fdname="stdout"; break; - default: fdname="stderr"; break; + case 0: fdname=storage.stdin_s; break; + case 1: fdname=storage.stdout_s; break; + default: fdname=storage.stderr_s; break; } - if((tmp=simple_mapping_string_lookup(optional, fdname))) + if((tmp=low_mapping_string_lookup(optional, fdname))) { if(tmp->type == T_OBJECT) { - apply(tmp->u.object,"query_fd",0); - if(sp[-1].type == T_INT) - { - if(sp[-1].u.integer != fd) - { - dup2(toclose[fd]=sp[-1].u.integer, fd); - } - } - pop_stack(); + INT32 f=fd_from_object(tmp->u.object); + if(f != -1 && fd!=f) + dup2(toclose[fd]=f, fd); } } } @@ -1099,6 +1184,16 @@ void f_create_process(INT32 args) } #endif +#ifdef HAVE_SETGROUPS + if(storage.wanted_gids) + { + if(setgroups(storage.num_wanted_gids, storage.wanted_gids)) + { + exit(77); + } + } +#endif + #ifdef HAVE_SETUID #ifdef HAVE_GETUID @@ -1147,15 +1242,12 @@ void f_create_process(INT32 args) #endif /* HAVE_SETRESUID */ #endif /* HAVE_SETEUID */ - my_set_close_on_exec(0,0); - my_set_close_on_exec(1,0); - my_set_close_on_exec(2,0); do_set_close_on_exec(); set_close_on_exec(0,0); set_close_on_exec(1,0); set_close_on_exec(2,0); - execvp(argv[0],argv); + execvp(storage.argv[0],storage.argv); exit(69); } } @@ -1171,6 +1263,11 @@ void f_fork(INT32 args) pid_t pid; pop_n_elems(args); +#ifdef _REENTRANT + if(num_threads >1) + error("You cannot use fork in a multithreaded application.\n"); +#endif + THREADS_ALLOW_UID(); #if defined(HAVE_FORK1) && defined(_REENTRANT) pid=fork1(); -- GitLab