]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
FS-8195 Compatibility with Solaris 11 process privileges
authorStanislav Sinyagin <ssinyagin@k-open.com>
Tue, 22 Sep 2015 09:01:07 +0000 (09:01 +0000)
committerStanislav Sinyagin <ssinyagin@k-open.com>
Sat, 3 Oct 2015 01:52:37 +0000 (01:52 +0000)
Now the daemon manages its privileges correctly, so that -rp, -u,
-g and -lp can be supported, also in a Solaris zone.

Also fixed a problem that switch_log_printf() was used before the
logger was initialized, so the messages were sent to nowhere.

configure.ac
src/include/switch_core.h
src/switch.c
src/switch_core.c

index becdd41f2c4920b2c13a9a510137497ef7e64bb8..fba37d76516507e74bf1f4847859b424a76bfe7e 100644 (file)
@@ -834,6 +834,12 @@ AC_HEADER_DIRENT
 AC_HEADER_STDC
 AC_CHECK_HEADERS([sys/types.h sys/resource.h sched.h wchar.h sys/filio.h sys/ioctl.h sys/prctl.h sys/select.h netdb.h execinfo.h sys/time.h])
 
+# Solaris 11 privilege management
+AS_CASE([$host],
+  [*-*-solaris2.11], [AC_CHECK_HEADER([priv.h], [AC_DEFINE([SOLARIS_PRIVILEGES],[1],[Solaris 11 privilege management])])]
+)
+
+
 if test x"$ac_cv_header_wchar_h" = xyes; then
   HAVE_WCHAR_H_DEFINE=1
 else
index 75172cff6e345d6effcb44b17cf4ba7dee7f09a0..f6472be2f342749656b457f386b5dff017ff491a 100644 (file)
@@ -2243,6 +2243,12 @@ SWITCH_DECLARE(switch_core_flag_t) switch_core_flags(void);
 */
 SWITCH_DECLARE(switch_status_t) switch_core_management_exec(char *relative_oid, switch_management_action_t action, char *data, switch_size_t datalen);
 
+/*! 
+  \brief Switch on the privilege awareness for the process and request required privileges
+  \return 0 on success
+*/
+                                                               
+SWITCH_DECLARE(int32_t) switch_core_set_process_privileges(void);
 
 /*! 
   \brief Set the maximum priority the process can obtain
index bd8c73ae917d66f96432bb7fa847191f02c5ddd0..942b5cd7635f1951771c81f968e489d36d99db27 100644 (file)
@@ -1089,6 +1089,10 @@ int main(int argc, char *argv[])
                reincarnate_protect(reincarnate_reexec ? argv : NULL);
 #endif
 
+       if (switch_core_set_process_privileges() < 0) {
+               return 255;
+       }
+       
        switch (priority) {
        case 2:
                set_realtime_priority();
index e0c800e2bf9a63bc795c3b2f4496bd24a8ef5ac1..7e79a92f42e8d792e35745c897c6e1f46c53d7ec 100644 (file)
@@ -53,7 +53,9 @@
 #ifdef HAVE_SYS_PRCTL_H
 #include <sys/prctl.h>
 #endif
-
+#ifdef SOLARIS_PRIVILEGES
+#include <priv.h>
+#endif
 
 SWITCH_DECLARE_DATA switch_directories SWITCH_GLOBAL_dirs = { 0 };
 SWITCH_DECLARE_DATA switch_filenames SWITCH_GLOBAL_filenames = { 0 };
@@ -888,20 +890,54 @@ SWITCH_DECLARE(void) switch_core_set_globals(void)
 }
 
 
-SWITCH_DECLARE(int32_t) set_low_priority(void)
+SWITCH_DECLARE(int32_t) switch_core_set_process_privileges(void)
 {
+#ifdef SOLARIS_PRIVILEGES
+       priv_set_t *basicset;
+       
+       /* make the process privilege-aware */
+       setpflags(PRIV_AWARE, 1);
 
+       /* reset the privileges to basic */
+       basicset = priv_str_to_set("basic", ",", NULL);
+       if (setppriv(PRIV_SET, PRIV_EFFECTIVE, basicset) != 0) {
+               fprintf(stderr, "ERROR: Failed to acquire basic privileges (%s)\n", strerror(errno));
+       }
+       
+       /* we need high-resolution clock, and this requires a non-basic privilege */
+       if (priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_PROC_CLOCK_HIGHRES, NULL) < 0) {
+               fprintf(stderr, "ERROR: Failed to acquire proc_clock_highres privilege (%s)\n", strerror(errno));
+               return -1;
+       }
 
+       /* need this for setrlimit */
+       if (priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_SYS_RESOURCE, NULL) < 0) {
+               fprintf(stderr, "ERROR: Failed to acquire sys_resource privilege (%s)\n", strerror(errno));
+               return -1;
+       }
+       
+       /* we need to read directories belonging to other uid */
+       if (priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_FILE_DAC_SEARCH, NULL) < 0) {
+               fprintf(stderr, "ERROR: Failed to acquire file_dac_search privilege (%s)\n", strerror(errno));
+               return -1;
+       }
+#endif
+       return 0;
+}
+
+SWITCH_DECLARE(int32_t) set_low_priority(void)
+{
 #ifdef WIN32
        SetPriorityClass(GetCurrentProcess(), BELOW_NORMAL_PRIORITY_CLASS);
 #else
-#ifdef USE_SCHED_SETSCHEDULER
+#if defined(USE_SCHED_SETSCHEDULER) && ! defined(SOLARIS_PRIVILEGES)
        /*
         * Try to use a normal scheduler
         */
        struct sched_param sched = { 0 };
        sched.sched_priority = 0;
-       if (sched_setscheduler(0, SCHED_OTHER, &sched)) {
+       if (sched_setscheduler(0, SCHED_OTHER, &sched) < 0) {
+               fprintf(stderr, "ERROR: Failed to set SCHED_OTHER scheduler (%s)\n", strerror(errno));
                return -1;
        }
 #endif
@@ -911,12 +947,12 @@ SWITCH_DECLARE(int32_t) set_low_priority(void)
         * setpriority() works on FreeBSD (6.2), nice() doesn't
         */
        if (setpriority(PRIO_PROCESS, getpid(), 19) < 0) {
-               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not set nice level\n");
+               fprintf(stderr, "ERROR: Could not set nice level\n");
                return -1;
        }
 #else
        if (nice(19) != 19) {
-               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not set nice level\n");
+               fprintf(stderr, "ERROR: Could not set nice level\n");
                return -1;
        }
 #endif
@@ -937,32 +973,60 @@ SWITCH_DECLARE(int32_t) set_realtime_priority(void)
         */
        struct sched_param sched = { 0 };
        sched.sched_priority = SWITCH_PRI_LOW;
-       if (sched_setscheduler(0, SCHED_FIFO, &sched)) {
+#endif
+
+#ifdef SOLARIS_PRIVILEGES
+       /* request the privileges to elevate the priority */
+       if (priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_PROC_PRIOCNTL, NULL) < 0) {
+               fprintf(stderr, "WARN: Failed to acquire proc_priocntl privilege (%s)\n", strerror(errno));
+       } else {
+               if (sched_setscheduler(0, SCHED_FIFO, &sched) < 0) {
+                       fprintf(stderr, "ERROR: Failed to set SCHED_FIFO scheduler (%s)\n", strerror(errno));
+               } else {
+                       return 0;
+               }
+       }
+               
+       if (priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_PROC_PRIOUP, NULL) < 0) {
+               fprintf(stderr, "ERROR: Failed to acquire proc_prioup privilege (%s)\n", strerror(errno));
+               return -1;
+       } else {
+               if (setpriority(PRIO_PROCESS, 0, -10) < 0) {
+                       fprintf(stderr, "ERROR: Could not set nice level\n");
+                       return -1;
+               }
+       }
+       return 0;
+#else
+
+#ifdef USE_SCHED_SETSCHEDULER
+       if (sched_setscheduler(0, SCHED_FIFO, &sched) < 0) {
+               fprintf(stderr, "ERROR: Failed to set SCHED_FIFO scheduler (%s)\n", strerror(errno));
                sched.sched_priority = 0;
-               if (sched_setscheduler(0, SCHED_OTHER, &sched)) {
+               if (sched_setscheduler(0, SCHED_OTHER, &sched) < 0 ) {
+                       fprintf(stderr, "ERROR: Failed to set SCHED_OTHER scheduler (%s)\n", strerror(errno));
                        return -1;
                }
        }
 #endif
 
-       
-
 #ifdef HAVE_SETPRIORITY
        /*
         * setpriority() works on FreeBSD (6.2), nice() doesn't
         */
        if (setpriority(PRIO_PROCESS, getpid(), -10) < 0) {
-               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not set nice level\n");
+               fprintf(stderr, "ERROR: Could not set nice level\n");
                return -1;
        }
 #else
        if (nice(-10) != -10) {
-               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not set nice level\n");
+               fprintf(stderr, "ERROR: Could not set nice level\n");
                return -1;
        }
 #endif
 #endif
        return 0;
+#endif
 }
 
 SWITCH_DECLARE(uint32_t) switch_core_cpu_count(void)
@@ -1006,7 +1070,7 @@ SWITCH_DECLARE(int32_t) change_user_group(const char *user, const char *group)
                 */
                runas_pw = getpwnam(user);
                if (!runas_pw) {
-                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Unknown user \"%s\"\n", user);
+                       fprintf(stderr, "ERROR: Unknown user \"%s\"\n", user);
                        return -1;
                }
                runas_uid = runas_pw->pw_uid;
@@ -1020,7 +1084,7 @@ SWITCH_DECLARE(int32_t) change_user_group(const char *user, const char *group)
                 */
                gr = getgrnam(group);
                if (!gr) {
-                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Unknown group \"%s\"\n", group);
+                       fprintf(stderr, "ERROR: Unknown group \"%s\"\n", group);
                        return -1;
                }
                runas_gid = gr->gr_gid;
@@ -1032,6 +1096,13 @@ SWITCH_DECLARE(int32_t) change_user_group(const char *user, const char *group)
        }
 
        if (runas_uid) {
+#ifdef SOLARIS_PRIVILEGES
+               /* request the privilege to set the UID */
+               if (priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_PROC_SETID, NULL) < 0) {
+                       fprintf(stderr, "ERROR: Failed to acquire proc_setid privilege (%s)\n", strerror(errno));
+                       return -1;
+               }
+#endif
 #ifdef HAVE_SETGROUPS
                /*
                 * Drop all group memberships prior to changing anything
@@ -1039,7 +1110,7 @@ SWITCH_DECLARE(int32_t) change_user_group(const char *user, const char *group)
                 * (which is not what we want...)
                 */
                if (setgroups(0, NULL) < 0) {
-                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to drop group access list\n");
+                       fprintf(stderr, "ERROR: Failed to drop group access list\n");
                        return -1;
                }
 #endif
@@ -1049,7 +1120,7 @@ SWITCH_DECLARE(int32_t) change_user_group(const char *user, const char *group)
                         * (without loading the user's other groups)
                         */
                        if (setgid(runas_gid) < 0) {
-                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to change gid!\n");
+                               fprintf(stderr, "ERROR: Failed to change gid!\n");
                                return -1;
                        }
                } else {
@@ -1057,7 +1128,7 @@ SWITCH_DECLARE(int32_t) change_user_group(const char *user, const char *group)
                         * No group has been passed, use the user's primary group in this case
                         */
                        if (setgid(runas_pw->pw_gid) < 0) {
-                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to change gid!\n");
+                               fprintf(stderr, "ERROR: Failed to change gid!\n");
                                return -1;
                        }
 #ifdef HAVE_INITGROUPS
@@ -1066,7 +1137,7 @@ SWITCH_DECLARE(int32_t) change_user_group(const char *user, const char *group)
                         * (This can be really useful for fine-grained access control)
                         */
                        if (initgroups(runas_pw->pw_name, runas_pw->pw_gid) < 0) {
-                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to set group access list for user\n");
+                               fprintf(stderr, "ERROR: Failed to set group access list for user\n");
                                return -1;
                        }
 #endif
@@ -1076,12 +1147,12 @@ SWITCH_DECLARE(int32_t) change_user_group(const char *user, const char *group)
                 * Finally drop all privileges by switching to the new userid
                 */
                if (setuid(runas_uid) < 0) {
-                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to change uid!\n");
+                       fprintf(stderr, "ERROR: Failed to change uid!\n");
                        return -1;
                }
 #ifdef HAVE_SYS_PRCTL_H
                if (prctl(PR_SET_DUMPABLE, 1) < 0) {
-                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to enable core dumps!\n");
+                       fprintf(stderr, "ERROR: Failed to enable core dumps!\n");
                        return -1;
                }
 #endif