diff --git a/apps/app_dahdiras.c b/apps/app_dahdiras.c index 4ac5daa3d3..4ecaaa018e 100644 --- a/apps/app_dahdiras.c +++ b/apps/app_dahdiras.c @@ -27,6 +27,7 @@ /*** MODULEINFO dahdi + working_fork ***/ #include "asterisk.h" @@ -48,6 +49,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include #include #include +#ifdef HAVE_CAP +#include +#endif /* HAVE_CAP */ #include "asterisk/lock.h" #include "asterisk/file.h" @@ -92,6 +96,9 @@ static pid_t spawn_ras(struct ast_channel *chan, char *args) int argc = 0; char *stringp=NULL; sigset_t fullset, oldset; +#ifdef HAVE_CAP + cap_t cap; +#endif sigfillset(&fullset); pthread_sigmask(SIG_BLOCK, &fullset, &oldset); @@ -103,6 +110,16 @@ static pid_t spawn_ras(struct ast_channel *chan, char *args) return pid; } +#ifdef HAVE_CAP + cap = cap_from_text("cap_net_admin-eip"); + + if (cap_set_proc(cap)) { + /* Careful with order! Logging cannot happen after we close FDs */ + ast_log(LOG_WARNING, "Unable to remove capabilities.\n"); + } + cap_free(cap); +#endif + /* Restore original signal handlers */ for (x=0;xworking_fork + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") @@ -41,6 +45,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include #include #include +#ifdef HAVE_CAP +#include +#endif /* HAVE_CAP */ #include "asterisk/lock.h" #include "asterisk/file.h" @@ -317,6 +324,15 @@ static int app_exec(struct ast_channel *chan, void *data) if (!pid) { /* child process */ int i; +#ifdef HAVE_CAP + cap_t cap = cap_from_text("cap_net_admin-eip"); + + if (cap_set_proc(cap)) { + /* Careful with order! Logging cannot happen after we close FDs */ + ast_log(LOG_WARNING, "Unable to remove capabilities.\n"); + } + cap_free(cap); +#endif signal(SIGPIPE, SIG_DFL); pthread_sigmask(SIG_UNBLOCK, &fullset, NULL); diff --git a/apps/app_festival.c b/apps/app_festival.c index ab05824f58..5650d983b1 100644 --- a/apps/app_festival.c +++ b/apps/app_festival.c @@ -25,6 +25,10 @@ * \ingroup applications */ +/*** MODULEINFO + working_fork + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") @@ -46,6 +50,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include #include #include +#ifdef HAVE_CAP +#include +#endif /* HAVE_CAP */ #include "asterisk/file.h" #include "asterisk/logger.h" @@ -132,21 +139,33 @@ static int send_waveform_to_fd(char *waveform, int length, int fd) { char c; #endif sigset_t fullset, oldset; +#ifdef HAVE_CAP + cap_t cap; +#endif sigfillset(&fullset); pthread_sigmask(SIG_BLOCK, &fullset, &oldset); - res = fork(); - if (res < 0) - ast_log(LOG_WARNING, "Fork failed\n"); - if (res) { + res = fork(); + if (res < 0) + ast_log(LOG_WARNING, "Fork failed\n"); + if (res) { pthread_sigmask(SIG_SETMASK, &oldset, NULL); - return res; + return res; + } +#ifdef HAVE_CAP + cap = cap_from_text("cap_net_admin-eip"); + + if (cap_set_proc(cap)) { + /* Careful with order! Logging cannot happen after we close FDs */ + ast_log(LOG_WARNING, "Unable to remove capabilities.\n"); + } + cap_free(cap); +#endif + for (x=0;x<256;x++) { + if (x != fd) + close(x); } - for (x=0;x<256;x++) { - if (x != fd) - close(x); - } if (ast_opt_high_priority) ast_set_priority(0); signal(SIGPIPE, SIG_DFL); diff --git a/apps/app_ices.c b/apps/app_ices.c index eb5980f937..40fbfdb398 100644 --- a/apps/app_ices.c +++ b/apps/app_ices.c @@ -25,6 +25,10 @@ * \ingroup applications */ +/*** MODULEINFO + working_fork + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") @@ -37,6 +41,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include #include #include +#ifdef HAVE_CAP +#include +#endif /* HAVE_CAP */ #include "asterisk/lock.h" #include "asterisk/file.h" @@ -65,6 +72,9 @@ static int icesencode(char *filename, int fd) int res; int x; sigset_t fullset, oldset; +#ifdef HAVE_CAP + cap_t cap; +#endif sigfillset(&fullset); pthread_sigmask(SIG_BLOCK, &fullset, &oldset); @@ -81,6 +91,16 @@ static int icesencode(char *filename, int fd) signal(SIGPIPE, SIG_DFL); pthread_sigmask(SIG_UNBLOCK, &fullset, NULL); +#ifdef HAVE_CAP + cap = cap_from_text("cap_net_admin-eip"); + + if (cap_set_proc(cap)) { + /* Careful with order! Logging cannot happen after we close FDs */ + ast_log(LOG_WARNING, "Unable to remove capabilities.\n"); + } + cap_free(cap); +#endif + if (ast_opt_high_priority) ast_set_priority(0); dup2(fd, STDIN_FILENO); diff --git a/apps/app_mp3.c b/apps/app_mp3.c index 55d50f0119..7cacc1e77b 100644 --- a/apps/app_mp3.c +++ b/apps/app_mp3.c @@ -25,6 +25,10 @@ * \ingroup applications */ +/*** MODULEINFO + working_fork + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") @@ -36,6 +40,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include #include #include +#ifdef HAVE_CAP +#include +#endif /* HAVE_CAP */ #include "asterisk/lock.h" #include "asterisk/file.h" @@ -65,6 +72,9 @@ static int mp3play(char *filename, int fd) int res; int x; sigset_t fullset, oldset; +#ifdef HAVE_CAP + cap_t cap; +#endif sigfillset(&fullset); pthread_sigmask(SIG_BLOCK, &fullset, &oldset); @@ -76,6 +86,15 @@ static int mp3play(char *filename, int fd) pthread_sigmask(SIG_SETMASK, &oldset, NULL); return res; } +#ifdef HAVE_CAP + cap = cap_from_text("cap_net_admin-eip"); + + if (cap_set_proc(cap)) { + /* Careful with order! Logging cannot happen after we close FDs */ + ast_log(LOG_WARNING, "Unable to remove capabilities.\n"); + } + cap_free(cap); +#endif if (ast_opt_high_priority) ast_set_priority(0); signal(SIGPIPE, SIG_DFL); @@ -83,8 +102,7 @@ static int mp3play(char *filename, int fd) dup2(fd, STDOUT_FILENO); for (x=STDERR_FILENO + 1;x<256;x++) { - if (x != STDOUT_FILENO) - close(x); + close(x); } /* Execute mpg123, but buffer if it's a net connection */ if (!strncasecmp(filename, "http://", 7)) { diff --git a/apps/app_nbscat.c b/apps/app_nbscat.c index 5f3000404c..d9a2dd4026 100644 --- a/apps/app_nbscat.c +++ b/apps/app_nbscat.c @@ -25,6 +25,10 @@ * \ingroup applications */ +/*** MODULEINFO + working_fork + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") @@ -37,6 +41,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include #include #include +#ifdef HAVE_CAP +#include +#endif /* HAVE_CAP */ #include "asterisk/lock.h" #include "asterisk/file.h" @@ -69,6 +76,9 @@ static int NBScatplay(int fd) int res; int x; sigset_t fullset, oldset; +#ifdef HAVE_CAP + cap_t cap; +#endif sigfillset(&fullset); pthread_sigmask(SIG_BLOCK, &fullset, &oldset); @@ -83,6 +93,15 @@ static int NBScatplay(int fd) signal(SIGPIPE, SIG_DFL); pthread_sigmask(SIG_UNBLOCK, &fullset, NULL); +#ifdef HAVE_CAP + cap = cap_from_text("cap_net_admin-eip"); + + if (cap_set_proc(cap)) { + /* Careful with order! Logging cannot happen after we close FDs */ + ast_log(LOG_WARNING, "Unable to remove capabilities.\n"); + } + cap_free(cap); +#endif if (ast_opt_high_priority) ast_set_priority(0); diff --git a/autoconf/ast_func_fork.m4 b/autoconf/ast_func_fork.m4 index 37bf0c3979..a5c0835ff1 100644 --- a/autoconf/ast_func_fork.m4 +++ b/autoconf/ast_func_fork.m4 @@ -39,6 +39,8 @@ else fi if test "x$ac_cv_func_fork_works" = xyes; then AC_DEFINE(HAVE_WORKING_FORK, 1, [Define to 1 if `fork' works.]) + PBX_WORKING_FORK=1 + AC_SUBST(PBX_WORKING_FORK) fi ])# AST_FUNC_FORK diff --git a/build_tools/menuselect-deps.in b/build_tools/menuselect-deps.in index 2613ea90e5..7442b0485c 100644 --- a/build_tools/menuselect-deps.in +++ b/build_tools/menuselect-deps.in @@ -39,3 +39,4 @@ ISDNNET=@PBX_ISDNNET@ MISDN=@PBX_MISDN@ SUPPSERV=@PBX_SUPPSERV@ GNU_LD=@GNU_LD@ +WORKING_FORK=@PBX_WORKING_FORK@ diff --git a/configure b/configure index fbcc9cff52..e758935176 100755 --- a/configure +++ b/configure @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.ac Revision: 159808 . +# From configure.ac Revision: 164343 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.61 for asterisk 1.4. # @@ -883,6 +883,7 @@ ZAPTEL_DIR PBX_ZAPTEL ALLOCA LIBOBJS +PBX_WORKING_FORK POW_LIB GC_CFLAGS GC_LDFLAGS @@ -12114,6 +12115,8 @@ cat >>confdefs.h <<\_ACEOF #define HAVE_WORKING_FORK 1 _ACEOF + PBX_WORKING_FORK=1 + fi { echo "$as_me:$LINENO: checking for _LARGEFILE_SOURCE value needed for large files" >&5 @@ -32546,6 +32549,7 @@ ZAPTEL_DIR!$ZAPTEL_DIR$ac_delim PBX_ZAPTEL!$PBX_ZAPTEL$ac_delim ALLOCA!$ALLOCA$ac_delim LIBOBJS!$LIBOBJS$ac_delim +PBX_WORKING_FORK!$PBX_WORKING_FORK$ac_delim POW_LIB!$POW_LIB$ac_delim GC_CFLAGS!$GC_CFLAGS$ac_delim GC_LDFLAGS!$GC_LDFLAGS$ac_delim @@ -32572,7 +32576,6 @@ PBX_SPEEX_PREPROCESS!$PBX_SPEEX_PREPROCESS$ac_delim PBX_ZAPTEL_VLDTMF!$PBX_ZAPTEL_VLDTMF$ac_delim EDITLINE_LIB!$EDITLINE_LIB$ac_delim PBX_H323!$PBX_H323$ac_delim -PBX_IXJUSER!$PBX_IXJUSER$ac_delim _ACEOF if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then @@ -32614,6 +32617,7 @@ _ACEOF ac_delim='%!_!# ' for ac_last_try in false false false false false :; do cat >conf$$subs.sed <<_ACEOF +PBX_IXJUSER!$PBX_IXJUSER$ac_delim GTKCONFIG!$GTKCONFIG$ac_delim PBX_GTK!$PBX_GTK$ac_delim GTK_INCLUDE!$GTK_INCLUDE$ac_delim @@ -32626,7 +32630,7 @@ CURL_CONFIG!$CURL_CONFIG$ac_delim LTLIBOBJS!$LTLIBOBJS$ac_delim _ACEOF - if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 10; then + if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 11; then break elif $ac_last_try; then { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 diff --git a/main/asterisk.c b/main/asterisk.c index 492af2d956..52f91ce597 100644 --- a/main/asterisk.c +++ b/main/asterisk.c @@ -818,6 +818,15 @@ int ast_safe_system(const char *s) #endif if (pid == 0) { +#ifdef HAVE_CAP + cap_t cap = cap_from_text("cap_net_admin-eip"); + + if (cap_set_proc(cap)) { + /* Careful with order! Logging cannot happen after we close FDs */ + ast_log(LOG_WARNING, "Unable to remove capabilities.\n"); + } + cap_free(cap); +#endif #ifdef HAVE_WORKING_FORK if (ast_opt_high_priority) ast_set_priority(0); @@ -842,7 +851,7 @@ int ast_safe_system(const char *s) } ast_unreplace_sigchld(); -#else +#else /* !defined(HAVE_WORKING_FORK) && !defined(HAVE_WORKING_VFORK) */ res = -1; #endif @@ -2914,7 +2923,7 @@ int main(int argc, char *argv[]) if (has_cap) { cap_t cap; - cap = cap_from_text("cap_net_admin=ep"); + cap = cap_from_text("cap_net_admin=eip"); if (cap_set_proc(cap)) ast_log(LOG_WARNING, "Unable to install capabilities.\n"); diff --git a/res/res_agi.c b/res/res_agi.c index b39a9a73fe..35b29d52fa 100644 --- a/res/res_agi.c +++ b/res/res_agi.c @@ -23,6 +23,10 @@ * \author Mark Spencer */ +/*** MODULEINFO + working_fork + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") @@ -44,6 +48,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include #include #include +#ifdef HAVE_CAP +#include +#endif /* HAVE_CAP */ #include "asterisk/file.h" #include "asterisk/logger.h" @@ -308,6 +315,16 @@ static enum agi_result launch_script(char *script, char *argv[], int *fds, int * return AGI_RESULT_FAILURE; } if (!pid) { +#ifdef HAVE_CAP + cap_t cap = cap_from_text("cap_net_admin-eip"); + + if (cap_set_proc(cap)) { + /* Careful with order! Logging cannot happen after we close FDs */ + ast_log(LOG_WARNING, "Unable to remove capabilities.\n"); + } + cap_free(cap); +#endif + /* Pass paths to AGI via environmental variables */ setenv("AST_CONFIG_DIR", ast_config_AST_CONFIG_DIR, 1); setenv("AST_CONFIG_FILE", ast_config_AST_CONFIG_FILE, 1); diff --git a/res/res_musiconhold.c b/res/res_musiconhold.c index 6bf2837dcd..a67999d653 100644 --- a/res/res_musiconhold.c +++ b/res/res_musiconhold.c @@ -28,6 +28,7 @@ /*** MODULEINFO win32 dahdi + working_fork ***/ #include "asterisk.h" @@ -51,6 +52,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #ifdef SOLARIS #include #endif +#ifdef HAVE_CAP +#include +#endif /* HAVE_CAP */ #include "asterisk/lock.h" #include "asterisk/file.h" @@ -450,7 +454,15 @@ static int spawn_mp3(struct mohclass *class) return -1; } if (!class->pid) { + /* Child */ int x; +#ifdef HAVE_CAP + cap_t cap; +#endif + if (strcasecmp(class->dir, "nodir") && chdir(class->dir) < 0) { + ast_log(LOG_WARNING, "chdir() failed: %s\n", strerror(errno)); + _exit(1); + } if (ast_opt_high_priority) ast_set_priority(0); @@ -459,6 +471,14 @@ static int spawn_mp3(struct mohclass *class) signal(SIGPIPE, SIG_DFL); pthread_sigmask(SIG_UNBLOCK, &signal_set, NULL); +#ifdef HAVE_CAP + cap = cap_from_text("cap_net_admin-eip"); + + if (cap_set_proc(cap)) { + ast_log(LOG_WARNING, "Unable to remove capabilities.\n"); + } + cap_free(cap); +#endif close(fds[0]); /* Stdout goes to pipe */ dup2(fds[1], STDOUT_FILENO); @@ -468,12 +488,8 @@ static int spawn_mp3(struct mohclass *class) close(x); } } - /* Child */ - if (strcasecmp(class->dir, "nodir") && chdir(class->dir) < 0) { - ast_log(LOG_WARNING, "chdir() failed: %s\n", strerror(errno)); - _exit(1); - } setpgid(0, getpid()); + if (ast_test_flag(class, MOH_CUSTOM)) { execv(argv[0], argv); } else {