Back to index

php5  5.3.10
fpm_unix.c
Go to the documentation of this file.
00001 
00002        /* $Id: fpm_unix.c,v 1.25.2.1 2008/12/13 03:18:23 anight Exp $ */
00003        /* (c) 2007,2008 Andrei Nigmatulin */
00004 
00005 #include "fpm_config.h"
00006 
00007 #include <string.h>
00008 #include <sys/time.h>
00009 #include <sys/resource.h>
00010 #include <stdlib.h>
00011 #include <unistd.h>
00012 #include <sys/types.h>
00013 #include <pwd.h>
00014 #include <grp.h>
00015 
00016 #ifdef HAVE_PRCTL
00017 #include <sys/prctl.h>
00018 #endif
00019 
00020 #include "fpm.h"
00021 #include "fpm_conf.h"
00022 #include "fpm_cleanup.h"
00023 #include "fpm_clock.h"
00024 #include "fpm_stdio.h"
00025 #include "fpm_unix.h"
00026 #include "zlog.h"
00027 
00028 size_t fpm_pagesize;
00029 
00030 int fpm_unix_resolve_socket_premissions(struct fpm_worker_pool_s *wp) /* {{{ */
00031 {
00032        struct fpm_worker_pool_config_s *c = wp->config;
00033 
00034        /* uninitialized */
00035        wp->socket_uid = -1;
00036        wp->socket_gid = -1;
00037        wp->socket_mode = 0666;
00038 
00039        if (!c) {
00040               return 0;
00041        }
00042 
00043        if (c->listen_owner && *c->listen_owner) {
00044               struct passwd *pwd;
00045 
00046               pwd = getpwnam(c->listen_owner);
00047               if (!pwd) {
00048                      zlog(ZLOG_SYSERROR, "[pool %s] cannot get uid for user '%s'", wp->config->name, c->listen_owner);
00049                      return -1;
00050               }
00051 
00052               wp->socket_uid = pwd->pw_uid;
00053               wp->socket_gid = pwd->pw_gid;
00054        }
00055 
00056        if (c->listen_group && *c->listen_group) {
00057               struct group *grp;
00058 
00059               grp = getgrnam(c->listen_group);
00060               if (!grp) {
00061                      zlog(ZLOG_SYSERROR, "[pool %s] cannot get gid for group '%s'", wp->config->name, c->listen_group);
00062                      return -1;
00063               }
00064               wp->socket_gid = grp->gr_gid;
00065        }
00066 
00067        if (c->listen_mode && *c->listen_mode) {
00068               wp->socket_mode = strtoul(c->listen_mode, 0, 8);
00069        }
00070        return 0;
00071 }
00072 /* }}} */
00073 
00074 static int fpm_unix_conf_wp(struct fpm_worker_pool_s *wp) /* {{{ */
00075 {
00076        struct passwd *pwd;
00077        int is_root = !geteuid();
00078 
00079        if (is_root) {
00080               if (wp->config->user && *wp->config->user) {
00081                      if (strlen(wp->config->user) == strspn(wp->config->user, "0123456789")) {
00082                             wp->set_uid = strtoul(wp->config->user, 0, 10);
00083                      } else {
00084                             struct passwd *pwd;
00085 
00086                             pwd = getpwnam(wp->config->user);
00087                             if (!pwd) {
00088                                    zlog(ZLOG_ERROR, "[pool %s] cannot get uid for user '%s'", wp->config->name, wp->config->user);
00089                                    return -1;
00090                             }
00091 
00092                             wp->set_uid = pwd->pw_uid;
00093                             wp->set_gid = pwd->pw_gid;
00094 
00095                             wp->user = strdup(pwd->pw_name);
00096                             wp->home = strdup(pwd->pw_dir);
00097                      }
00098               }
00099 
00100               if (wp->config->group && *wp->config->group) {
00101                      if (strlen(wp->config->group) == strspn(wp->config->group, "0123456789")) {
00102                             wp->set_gid = strtoul(wp->config->group, 0, 10);
00103                      } else {
00104                             struct group *grp;
00105 
00106                             grp = getgrnam(wp->config->group);
00107                             if (!grp) {
00108                                    zlog(ZLOG_ERROR, "[pool %s] cannot get gid for group '%s'", wp->config->name, wp->config->group);
00109                                    return -1;
00110                             }
00111                             wp->set_gid = grp->gr_gid;
00112                      }
00113               }
00114 
00115 #ifndef I_REALLY_WANT_ROOT_PHP
00116               if (wp->set_uid == 0 || wp->set_gid == 0) {
00117                      zlog(ZLOG_ERROR, "[pool %s] please specify user and group other than root", wp->config->name);
00118                      return -1;
00119               }
00120 #endif
00121        } else { /* not root */
00122               if (wp->config->user && *wp->config->user) {
00123                      zlog(ZLOG_WARNING, "[pool %s] 'user' directive is ignored when FPM is not running as root", wp->config->name);
00124               }
00125               if (wp->config->group && *wp->config->group) {
00126                      zlog(ZLOG_WARNING, "[pool %s] 'group' directive is ignored when FPM is not running as root", wp->config->name);
00127               }
00128               if (wp->config->chroot && *wp->config->chroot) {
00129                      zlog(ZLOG_WARNING, "[pool %s] 'chroot' directive is ignored when FPM is not running as root", wp->config->name);
00130               }
00131 
00132               /* set up HOME and USER anyway */
00133               pwd = getpwuid(getuid());
00134               if (pwd) {
00135                      wp->user = strdup(pwd->pw_name);
00136                      wp->home = strdup(pwd->pw_dir);
00137               }
00138        }
00139        return 0;
00140 }
00141 /* }}} */
00142 
00143 int fpm_unix_init_child(struct fpm_worker_pool_s *wp) /* {{{ */
00144 {
00145        int is_root = !geteuid();
00146        int made_chroot = 0;
00147 
00148        if (wp->config->rlimit_files) {
00149               struct rlimit r;
00150 
00151               r.rlim_max = r.rlim_cur = (rlim_t) wp->config->rlimit_files;
00152 
00153               if (0 > setrlimit(RLIMIT_NOFILE, &r)) {
00154                      zlog(ZLOG_SYSERROR, "[pool %s] failed to set rlimit_files for this pool. Please check your system limits or decrease rlimit_files. setrlimit(RLIMIT_NOFILE, %d)", wp->config->name, wp->config->rlimit_files);
00155               }
00156        }
00157 
00158        if (wp->config->rlimit_core) {
00159               struct rlimit r;
00160 
00161               r.rlim_max = r.rlim_cur = wp->config->rlimit_core == -1 ? (rlim_t) RLIM_INFINITY : (rlim_t) wp->config->rlimit_core;
00162 
00163               if (0 > setrlimit(RLIMIT_CORE, &r)) {
00164                      zlog(ZLOG_SYSERROR, "[pool %s] failed to set rlimit_core for this pool. Please check your system limits or decrease rlimit_core. setrlimit(RLIMIT_CORE, %d)", wp->config->name, wp->config->rlimit_core);
00165               }
00166        }
00167 
00168        if (is_root && wp->config->chroot && *wp->config->chroot) {
00169               if (0 > chroot(wp->config->chroot)) {
00170                      zlog(ZLOG_SYSERROR, "[pool %s] failed to chroot(%s)",  wp->config->name, wp->config->chroot);
00171                      return -1;
00172               }
00173               made_chroot = 1;
00174        }
00175 
00176        if (wp->config->chdir && *wp->config->chdir) {
00177               if (0 > chdir(wp->config->chdir)) {
00178                      zlog(ZLOG_SYSERROR, "[pool %s] failed to chdir(%s)", wp->config->name, wp->config->chdir);
00179                      return -1;
00180               }
00181        } else if (made_chroot) {
00182               chdir("/");
00183        }
00184 
00185        if (is_root) {
00186               if (wp->set_gid) {
00187                      if (0 > setgid(wp->set_gid)) {
00188                             zlog(ZLOG_SYSERROR, "[pool %s] failed to setgid(%d)", wp->config->name, wp->set_gid);
00189                             return -1;
00190                      }
00191               }
00192               if (wp->set_uid) {
00193                      if (0 > initgroups(wp->config->user, wp->set_gid)) {
00194                             zlog(ZLOG_SYSERROR, "[pool %s] failed to initgroups(%s, %d)", wp->config->name, wp->config->user, wp->set_gid);
00195                             return -1;
00196                      }
00197                      if (0 > setuid(wp->set_uid)) {
00198                             zlog(ZLOG_SYSERROR, "[pool %s] failed to setuid(%d)", wp->config->name, wp->set_uid);
00199                             return -1;
00200                      }
00201               }
00202        }
00203 
00204 #ifdef HAVE_PRCTL
00205        if (0 > prctl(PR_SET_DUMPABLE, 1, 0, 0, 0)) {
00206               zlog(ZLOG_SYSERROR, "[pool %s] failed to prctl(PR_SET_DUMPABLE)", wp->config->name);
00207        }
00208 #endif
00209 
00210        if (0 > fpm_clock_init()) {
00211               return -1;
00212        }
00213        return 0;
00214 }
00215 /* }}} */
00216 
00217 int fpm_unix_init_main() /* {{{ */
00218 {
00219        struct fpm_worker_pool_s *wp;
00220 
00221        if (fpm_global_config.rlimit_files) {
00222               struct rlimit r;
00223 
00224               r.rlim_max = r.rlim_cur = (rlim_t) fpm_global_config.rlimit_files;
00225 
00226               if (0 > setrlimit(RLIMIT_NOFILE, &r)) {
00227                      zlog(ZLOG_SYSERROR, "failed to set rlimit_core for this pool. Please check your system limits or decrease rlimit_files. setrlimit(RLIMIT_NOFILE, %d)", fpm_global_config.rlimit_files);
00228                      return -1;
00229               }
00230        }
00231 
00232        if (fpm_global_config.rlimit_core) {
00233               struct rlimit r;
00234 
00235               r.rlim_max = r.rlim_cur = fpm_global_config.rlimit_core == -1 ? (rlim_t) RLIM_INFINITY : (rlim_t) fpm_global_config.rlimit_core;
00236 
00237               if (0 > setrlimit(RLIMIT_CORE, &r)) {
00238                      zlog(ZLOG_SYSERROR, "failed to set rlimit_core for this pool. Please check your system limits or decrease rlimit_core. setrlimit(RLIMIT_CORE, %d)", fpm_global_config.rlimit_core);
00239                      return -1;
00240               }
00241        }
00242 
00243        fpm_pagesize = getpagesize();
00244        if (fpm_global_config.daemonize) {
00245               switch (fork()) {
00246                      case -1 :
00247                             zlog(ZLOG_SYSERROR, "failed to daemonize");
00248                             return -1;
00249                      case 0 :
00250                             break;
00251                      default :
00252                             fpm_cleanups_run(FPM_CLEANUP_PARENT_EXIT);
00253                             exit(0);
00254               }
00255        }
00256 
00257        setsid();
00258        if (0 > fpm_clock_init()) {
00259               return -1;
00260        }
00261 
00262        fpm_globals.parent_pid = getpid();
00263        for (wp = fpm_worker_all_pools; wp; wp = wp->next) {
00264               if (0 > fpm_unix_conf_wp(wp)) {
00265                      return -1;
00266               }
00267        }
00268 
00269        zlog_set_level(fpm_globals.log_level);
00270        return 0;
00271 }
00272 /* }}} */
00273