]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Lose the CAP_NET_ADMIN at every fork, instead of at startup. Otherwise, if
authorTilghman Lesher <tilghman@meg.abyt.es>
Thu, 29 Jan 2009 22:54:29 +0000 (22:54 +0000)
committerTilghman Lesher <tilghman@meg.abyt.es>
Thu, 29 Jan 2009 22:54:29 +0000 (22:54 +0000)
Asterisk runs as a non-root user and the administrator does a 'restart now',
Asterisk loses the ability to set QOS on packets.
(closes issue #14004)
 Reported by: nemo
 Patches:
       20090105__bug14004.diff.txt uploaded by Corydon76 (license 14)
 Tested by: Corydon76

git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.4@172438 65c4cc65-6c06-0410-ace0-fbb531ad65f3

12 files changed:
apps/app_dahdiras.c
apps/app_externalivr.c
apps/app_festival.c
apps/app_ices.c
apps/app_mp3.c
apps/app_nbscat.c
autoconf/ast_func_fork.m4
build_tools/menuselect-deps.in
configure
main/asterisk.c
res/res_agi.c
res/res_musiconhold.c

index 4ac5daa3d33ed6d0956825c4f4c71c0c6cb219a9..4ecaaa018efd29a559f182073561594e8769979d 100644 (file)
@@ -27,6 +27,7 @@
 
 /*** MODULEINFO
        <depend>dahdi</depend>
+       <depend>working_fork</depend>
  ***/
 
 #include "asterisk.h"
@@ -48,6 +49,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include <errno.h>
 #include <stdio.h>
 #include <fcntl.h>
+#ifdef HAVE_CAP
+#include <sys/capability.h>
+#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;x<NSIG;x++)
                signal(x, SIG_DFL);
index 8004fecd143ee875681d44b12719e6c90b90c4bb..42fd469c314f6057269420f069f10ffc71aa2ba7 100644 (file)
  * \ingroup applications
  */
 
+/*** MODULEINFO
+       <depend>working_fork</depend>
+ ***/
+
 #include "asterisk.h"
 
 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
@@ -41,6 +45,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include <unistd.h>
 #include <errno.h>
 #include <signal.h>
+#ifdef HAVE_CAP
+#include <sys/capability.h>
+#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);
index ab05824f58da4b04c2122c58a36eadb6e79ec14e..5650d983b1bd173331178e7e94021f02c0fc4dac 100644 (file)
  * \ingroup applications
  */
 
+/*** MODULEINFO
+       <depend>working_fork</depend>
+ ***/
+
 #include "asterisk.h"
 
 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
@@ -46,6 +50,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include <fcntl.h>
 #include <ctype.h>
 #include <errno.h>
+#ifdef HAVE_CAP
+#include <sys/capability.h>
+#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);
index eb5980f937f47f567c9db77e2aff9cb3794b76a1..40fbfdb398a65ec4ca8168b111aef27e2c74419c 100644 (file)
  * \ingroup applications
  */
  
+/*** MODULEINFO
+       <depend>working_fork</depend>
+ ***/
+
 #include "asterisk.h"
 
 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
@@ -37,6 +41,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include <fcntl.h>
 #include <sys/time.h>
 #include <errno.h>
+#ifdef HAVE_CAP
+#include <sys/capability.h>
+#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);
index 55d50f01190d64cc6d3aef6f89490ff62f93906a..7cacc1e77bd8208f8ce9abf1f78b56dc8288e7ae 100644 (file)
  * \ingroup applications
  */
  
+/*** MODULEINFO
+       <depend>working_fork</depend>
+ ***/
+
 #include "asterisk.h"
 
 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
@@ -36,6 +40,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include <unistd.h>
 #include <fcntl.h>
 #include <sys/time.h>
+#ifdef HAVE_CAP
+#include <sys/capability.h>
+#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)) {
index 5f3000404c9a8608cc31d572afcccbab43aa8072..d9a2dd4026f7bf43cd77304e0f65c2ac573b3cf3 100644 (file)
  * \ingroup applications
  */
  
+/*** MODULEINFO
+       <depend>working_fork</depend>
+ ***/
+
 #include "asterisk.h"
 
 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
@@ -37,6 +41,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include <fcntl.h>
 #include <sys/time.h>
 #include <sys/socket.h>
+#ifdef HAVE_CAP
+#include <sys/capability.h>
+#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);
 
index 37bf0c397911f3b01697c3c5a16f84bbbb6ecdff..a5c0835ff132c5f5a719c2001c12ba7b650101e6 100644 (file)
@@ -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
 
index 2613ea90e5b7d6260963af4107c194a15ccbd7b6..7442b0485c9ea2f663ad37a59c737d8263973f77 100644 (file)
@@ -39,3 +39,4 @@ ISDNNET=@PBX_ISDNNET@
 MISDN=@PBX_MISDN@
 SUPPSERV=@PBX_SUPPSERV@
 GNU_LD=@GNU_LD@
+WORKING_FORK=@PBX_WORKING_FORK@
index fbcc9cff521b778eb07fab3b81f1dd378e533189..e758935176038df268b7ffe332b2ca6027456f1d 100755 (executable)
--- 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
index 492af2d9564f2996e1037ce56563d3bc4fba0f75..52f91ce597649ddd31fda49033d971f2b5499f02 100644 (file)
@@ -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");
index b39a9a73fea1426163fe33f931cc4cb43aa683cd..35b29d52fac339c06f017880c39157216db70f3f 100644 (file)
  * \author Mark Spencer <markster@digium.com> 
  */
 
+/*** MODULEINFO
+       <depend>working_fork</depend>
+ ***/
+
 #include "asterisk.h"
 
 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
@@ -44,6 +48,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include <fcntl.h>
 #include <errno.h>
 #include <sys/wait.h>
+#ifdef HAVE_CAP
+#include <sys/capability.h>
+#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);
index 6bf2837dcdeb805654fb6df740b582dc2c2e1a94..a67999d653ea7cb2643b6a9fae0854a15ece4047 100644 (file)
@@ -28,6 +28,7 @@
 /*** MODULEINFO
        <conflict>win32</conflict>
        <use>dahdi</use>
+       <depend>working_fork</depend>
  ***/
 
 #include "asterisk.h"
@@ -51,6 +52,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #ifdef SOLARIS
 #include <thread.h>
 #endif
+#ifdef HAVE_CAP
+#include <sys/capability.h>
+#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 {