1 /* (c) 2007,2008 Andrei Nigmatulin */
2
3 #include "fpm_config.h"
4
5 #include <string.h>
6 #include <sys/time.h>
7 #include <sys/resource.h>
8 #include <stdlib.h>
9 #include <unistd.h>
10 #include <sys/types.h>
11 #include <pwd.h>
12 #include <grp.h>
13
14 #ifdef HAVE_PRCTL
15 #include <sys/prctl.h>
16 #endif
17
18 #ifdef HAVE_PROCCTL
19 #include <sys/procctl.h>
20 #endif
21
22 #ifdef HAVE_SETPFLAGS
23 #include <priv.h>
24 #endif
25
26 #ifdef HAVE_APPARMOR
27 #include <sys/apparmor.h>
28 #endif
29
30 #ifdef HAVE_SYS_ACL_H
31 #include <sys/acl.h>
32 #endif
33
34 #ifdef HAVE_SELINUX
35 #include <selinux/selinux.h>
36 #endif
37
38 #include "fpm.h"
39 #include "fpm_conf.h"
40 #include "fpm_cleanup.h"
41 #include "fpm_clock.h"
42 #include "fpm_stdio.h"
43 #include "fpm_unix.h"
44 #include "fpm_signals.h"
45 #include "zlog.h"
46
47 size_t fpm_pagesize;
48
49
fpm_unix_is_id(const char * name)50 static inline bool fpm_unix_is_id(const char* name)
51 {
52 return strlen(name) == strspn(name, "0123456789");
53 }
54
fpm_unix_get_passwd(struct fpm_worker_pool_s * wp,const char * name,int flags)55 static struct passwd *fpm_unix_get_passwd(struct fpm_worker_pool_s *wp, const char *name, int flags)
56 {
57 struct passwd *pwd = getpwnam(name);
58 if (!pwd) {
59 zlog(flags, "[pool %s] cannot get uid for user '%s'", wp->config->name, name);
60 return NULL;
61 }
62
63 return pwd;
64 }
65
fpm_unix_check_passwd(struct fpm_worker_pool_s * wp,const char * name,int flags)66 static inline bool fpm_unix_check_passwd(struct fpm_worker_pool_s *wp, const char *name, int flags)
67 {
68 return !name || fpm_unix_is_id(name) || fpm_unix_get_passwd(wp, name, flags);
69 }
70
fpm_unix_get_group(struct fpm_worker_pool_s * wp,const char * name,int flags)71 static struct group *fpm_unix_get_group(struct fpm_worker_pool_s *wp, const char *name, int flags)
72 {
73 struct group *group = getgrnam(name);
74 if (!group) {
75 zlog(flags, "[pool %s] cannot get gid for group '%s'", wp->config->name, name);
76 return NULL;
77 }
78
79 return group;
80 }
81
fpm_unix_check_group(struct fpm_worker_pool_s * wp,const char * name,int flags)82 static inline bool fpm_unix_check_group(struct fpm_worker_pool_s *wp, const char *name, int flags)
83 {
84 return !name || fpm_unix_is_id(name) || fpm_unix_get_group(wp, name, flags);
85 }
86
fpm_unix_test_config(struct fpm_worker_pool_s * wp)87 bool fpm_unix_test_config(struct fpm_worker_pool_s *wp)
88 {
89 struct fpm_worker_pool_config_s *config = wp->config;
90 return (
91 fpm_unix_check_passwd(wp, config->user, ZLOG_ERROR) &&
92 fpm_unix_check_group(wp, config->group, ZLOG_ERROR) &&
93 fpm_unix_check_passwd(wp, config->listen_owner, ZLOG_SYSERROR) &&
94 fpm_unix_check_group(wp, config->listen_group, ZLOG_SYSERROR)
95 );
96 }
97
fpm_unix_resolve_socket_permissions(struct fpm_worker_pool_s * wp)98 int fpm_unix_resolve_socket_permissions(struct fpm_worker_pool_s *wp) /* {{{ */
99 {
100 struct fpm_worker_pool_config_s *c = wp->config;
101 #ifdef HAVE_FPM_ACL
102 int n;
103
104 /* uninitialized */
105 wp->socket_acl = NULL;
106 #endif
107 wp->socket_uid = -1;
108 wp->socket_gid = -1;
109 wp->socket_mode = 0660;
110
111 if (!c) {
112 return 0;
113 }
114
115 if (c->listen_mode && *c->listen_mode) {
116 wp->socket_mode = strtoul(c->listen_mode, 0, 8);
117 }
118
119 #ifdef HAVE_FPM_ACL
120 /* count the users and groups configured */
121 n = 0;
122 if (c->listen_acl_users && *c->listen_acl_users) {
123 char *p;
124 n++;
125 for (p=strchr(c->listen_acl_users, ',') ; p ; p=strchr(p+1, ',')) {
126 n++;
127 }
128 }
129 if (c->listen_acl_groups && *c->listen_acl_groups) {
130 char *p;
131 n++;
132 for (p=strchr(c->listen_acl_groups, ',') ; p ; p=strchr(p+1, ',')) {
133 n++;
134 }
135 }
136 /* if ACL configured */
137 if (n) {
138 acl_t acl;
139 acl_entry_t entry;
140 acl_permset_t perm;
141 char *tmp, *p, *end;
142
143 acl = acl_init(n);
144 if (!acl) {
145 zlog(ZLOG_SYSERROR, "[pool %s] cannot allocate ACL", wp->config->name);
146 return -1;
147 }
148 /* Create USER ACL */
149 if (c->listen_acl_users && *c->listen_acl_users) {
150 struct passwd *pwd;
151
152 tmp = estrdup(c->listen_acl_users);
153 for (p=tmp ; p ; p=end) {
154 if ((end = strchr(p, ','))) {
155 *end++ = 0;
156 }
157 pwd = fpm_unix_get_passwd(wp, p, ZLOG_SYSERROR);
158 if (pwd) {
159 zlog(ZLOG_DEBUG, "[pool %s] user '%s' have uid=%d", wp->config->name, p, pwd->pw_uid);
160 } else {
161 acl_free(acl);
162 efree(tmp);
163 return -1;
164 }
165 if (0 > acl_create_entry(&acl, &entry) ||
166 0 > acl_set_tag_type(entry, ACL_USER) ||
167 0 > acl_set_qualifier(entry, &pwd->pw_uid) ||
168 0 > acl_get_permset(entry, &perm) ||
169 0 > acl_clear_perms (perm) ||
170 0 > acl_add_perm (perm, ACL_READ) ||
171 0 > acl_add_perm (perm, ACL_WRITE)) {
172 zlog(ZLOG_SYSERROR, "[pool %s] cannot create ACL for user '%s'", wp->config->name, p);
173 acl_free(acl);
174 efree(tmp);
175 return -1;
176 }
177 }
178 efree(tmp);
179 }
180 /* Create GROUP ACL */
181 if (c->listen_acl_groups && *c->listen_acl_groups) {
182 struct group *grp;
183
184 tmp = estrdup(c->listen_acl_groups);
185 for (p=tmp ; p ; p=end) {
186 if ((end = strchr(p, ','))) {
187 *end++ = 0;
188 }
189 grp = fpm_unix_get_group(wp, p, ZLOG_SYSERROR);
190 if (grp) {
191 zlog(ZLOG_DEBUG, "[pool %s] group '%s' have gid=%d", wp->config->name, p, grp->gr_gid);
192 } else {
193 acl_free(acl);
194 efree(tmp);
195 return -1;
196 }
197 if (0 > acl_create_entry(&acl, &entry) ||
198 0 > acl_set_tag_type(entry, ACL_GROUP) ||
199 0 > acl_set_qualifier(entry, &grp->gr_gid) ||
200 0 > acl_get_permset(entry, &perm) ||
201 0 > acl_clear_perms (perm) ||
202 0 > acl_add_perm (perm, ACL_READ) ||
203 0 > acl_add_perm (perm, ACL_WRITE)) {
204 zlog(ZLOG_SYSERROR, "[pool %s] cannot create ACL for group '%s'", wp->config->name, p);
205 acl_free(acl);
206 efree(tmp);
207 return -1;
208 }
209 }
210 efree(tmp);
211 }
212 if (c->listen_owner && *c->listen_owner) {
213 zlog(ZLOG_WARNING, "[pool %s] ACL set, listen.owner = '%s' is ignored", wp->config->name, c->listen_owner);
214 }
215 if (c->listen_group && *c->listen_group) {
216 zlog(ZLOG_WARNING, "[pool %s] ACL set, listen.group = '%s' is ignored", wp->config->name, c->listen_group);
217 }
218 wp->socket_acl = acl;
219 return 0;
220 }
221 /* When listen.users and listen.groups not configured, continue with standard right */
222 #endif
223
224 if (c->listen_owner && *c->listen_owner) {
225 if (fpm_unix_is_id(c->listen_owner)) {
226 wp->socket_uid = strtoul(c->listen_owner, 0, 10);
227 } else {
228 struct passwd *pwd;
229
230 pwd = fpm_unix_get_passwd(wp, c->listen_owner, ZLOG_SYSERROR);
231 if (!pwd) {
232 return -1;
233 }
234
235 wp->socket_uid = pwd->pw_uid;
236 wp->socket_gid = pwd->pw_gid;
237 }
238 }
239
240 if (c->listen_group && *c->listen_group) {
241 if (fpm_unix_is_id(c->listen_group)) {
242 wp->socket_gid = strtoul(c->listen_group, 0, 10);
243 } else {
244 struct group *grp;
245
246 grp = fpm_unix_get_group(wp, c->listen_group, ZLOG_SYSERROR);
247 if (!grp) {
248 return -1;
249 }
250 wp->socket_gid = grp->gr_gid;
251 }
252 }
253
254 return 0;
255 }
256 /* }}} */
257
fpm_unix_set_socket_permissions(struct fpm_worker_pool_s * wp,const char * path)258 int fpm_unix_set_socket_permissions(struct fpm_worker_pool_s *wp, const char *path) /* {{{ */
259 {
260 #ifdef HAVE_FPM_ACL
261 if (wp->socket_acl) {
262 acl_t aclfile, aclconf;
263 acl_entry_t entryfile, entryconf;
264 int i;
265
266 /* Read the socket ACL */
267 aclconf = wp->socket_acl;
268 aclfile = acl_get_file (path, ACL_TYPE_ACCESS);
269 if (!aclfile) {
270 zlog(ZLOG_SYSERROR, "[pool %s] failed to read the ACL of the socket '%s'", wp->config->name, path);
271 return -1;
272 }
273 /* Copy the new ACL entry from config */
274 for (i=ACL_FIRST_ENTRY ; acl_get_entry(aclconf, i, &entryconf) ; i=ACL_NEXT_ENTRY) {
275 if (0 > acl_create_entry (&aclfile, &entryfile) ||
276 0 > acl_copy_entry(entryfile, entryconf)) {
277 zlog(ZLOG_SYSERROR, "[pool %s] failed to add entry to the ACL of the socket '%s'", wp->config->name, path);
278 acl_free(aclfile);
279 return -1;
280 }
281 }
282 /* Write the socket ACL */
283 if (0 > acl_calc_mask (&aclfile) ||
284 0 > acl_valid (aclfile) ||
285 0 > acl_set_file (path, ACL_TYPE_ACCESS, aclfile)) {
286 zlog(ZLOG_SYSERROR, "[pool %s] failed to write the ACL of the socket '%s'", wp->config->name, path);
287 acl_free(aclfile);
288 return -1;
289 } else {
290 zlog(ZLOG_DEBUG, "[pool %s] ACL of the socket '%s' is set", wp->config->name, path);
291 }
292
293 acl_free(aclfile);
294 return 0;
295 }
296 /* When listen.users and listen.groups not configured, continue with standard right */
297 #endif
298
299 if (wp->socket_uid != -1 || wp->socket_gid != -1) {
300 if (0 > chown(path, wp->socket_uid, wp->socket_gid)) {
301 zlog(ZLOG_SYSERROR, "[pool %s] failed to chown() the socket '%s'", wp->config->name, wp->config->listen_address);
302 return -1;
303 }
304 }
305 return 0;
306 }
307 /* }}} */
308
fpm_unix_free_socket_permissions(struct fpm_worker_pool_s * wp)309 int fpm_unix_free_socket_permissions(struct fpm_worker_pool_s *wp) /* {{{ */
310 {
311 #ifdef HAVE_FPM_ACL
312 if (wp->socket_acl) {
313 return acl_free(wp->socket_acl);
314 }
315 #endif
316 return 0;
317 }
318 /* }}} */
319
fpm_unix_conf_wp(struct fpm_worker_pool_s * wp)320 static int fpm_unix_conf_wp(struct fpm_worker_pool_s *wp) /* {{{ */
321 {
322 struct passwd *pwd;
323 int is_root = !geteuid();
324
325 if (is_root) {
326 if (wp->config->user && *wp->config->user) {
327 if (fpm_unix_is_id(wp->config->user)) {
328 wp->set_uid = strtoul(wp->config->user, 0, 10);
329 pwd = getpwuid(wp->set_uid);
330 if (pwd) {
331 wp->set_gid = pwd->pw_gid;
332 wp->set_user = strdup(pwd->pw_name);
333 }
334 } else {
335 struct passwd *pwd;
336
337 pwd = fpm_unix_get_passwd(wp, wp->config->user, ZLOG_ERROR);
338 if (!pwd) {
339 return -1;
340 }
341
342 wp->set_uid = pwd->pw_uid;
343 wp->set_gid = pwd->pw_gid;
344
345 wp->user = strdup(pwd->pw_name);
346 wp->home = strdup(pwd->pw_dir);
347 }
348 }
349
350 if (wp->config->group && *wp->config->group) {
351 if (fpm_unix_is_id(wp->config->group)) {
352 wp->set_gid = strtoul(wp->config->group, 0, 10);
353 } else {
354 struct group *grp;
355
356 grp = fpm_unix_get_group(wp, wp->config->group, ZLOG_ERROR);
357 if (!grp) {
358 return -1;
359 }
360 wp->set_gid = grp->gr_gid;
361 }
362 }
363
364 if (!fpm_globals.run_as_root) {
365 if (wp->set_uid == 0 || wp->set_gid == 0) {
366 zlog(ZLOG_ERROR, "[pool %s] please specify user and group other than root", wp->config->name);
367 return -1;
368 }
369 }
370 } else { /* not root */
371 if (wp->config->user && *wp->config->user) {
372 zlog(ZLOG_NOTICE, "[pool %s] 'user' directive is ignored when FPM is not running as root", wp->config->name);
373 }
374 if (wp->config->group && *wp->config->group) {
375 zlog(ZLOG_NOTICE, "[pool %s] 'group' directive is ignored when FPM is not running as root", wp->config->name);
376 }
377 if (wp->config->chroot && *wp->config->chroot) {
378 zlog(ZLOG_NOTICE, "[pool %s] 'chroot' directive is ignored when FPM is not running as root", wp->config->name);
379 }
380 if (wp->config->process_priority != 64) {
381 zlog(ZLOG_NOTICE, "[pool %s] 'process.priority' directive is ignored when FPM is not running as root", wp->config->name);
382 }
383
384 /* set up HOME and USER anyway */
385 pwd = getpwuid(getuid());
386 if (pwd) {
387 wp->user = strdup(pwd->pw_name);
388 wp->home = strdup(pwd->pw_dir);
389 }
390 }
391 return 0;
392 }
393 /* }}} */
394
fpm_unix_init_child(struct fpm_worker_pool_s * wp)395 int fpm_unix_init_child(struct fpm_worker_pool_s *wp) /* {{{ */
396 {
397 int is_root = !geteuid();
398 int made_chroot = 0;
399
400 if (wp->config->rlimit_files) {
401 struct rlimit r;
402
403 r.rlim_max = r.rlim_cur = (rlim_t) wp->config->rlimit_files;
404
405 if (0 > setrlimit(RLIMIT_NOFILE, &r)) {
406 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);
407 }
408 }
409
410 if (wp->config->rlimit_core) {
411 struct rlimit r;
412
413 r.rlim_max = r.rlim_cur = wp->config->rlimit_core == -1 ? (rlim_t) RLIM_INFINITY : (rlim_t) wp->config->rlimit_core;
414
415 if (0 > setrlimit(RLIMIT_CORE, &r)) {
416 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);
417 }
418 }
419
420 if (is_root && wp->config->chroot && *wp->config->chroot) {
421 if (0 > chroot(wp->config->chroot)) {
422 zlog(ZLOG_SYSERROR, "[pool %s] failed to chroot(%s)", wp->config->name, wp->config->chroot);
423 return -1;
424 }
425 made_chroot = 1;
426 }
427
428 if (wp->config->chdir && *wp->config->chdir) {
429 if (0 > chdir(wp->config->chdir)) {
430 zlog(ZLOG_SYSERROR, "[pool %s] failed to chdir(%s)", wp->config->name, wp->config->chdir);
431 return -1;
432 }
433 } else if (made_chroot) {
434 if (0 > chdir("/")) {
435 zlog(ZLOG_WARNING, "[pool %s] failed to chdir(/)", wp->config->name);
436 }
437 }
438
439 if (is_root) {
440
441 if (wp->config->process_priority != 64) {
442 if (setpriority(PRIO_PROCESS, 0, wp->config->process_priority) < 0) {
443 zlog(ZLOG_SYSERROR, "[pool %s] Unable to set priority for this new process", wp->config->name);
444 return -1;
445 }
446 }
447
448 if (wp->set_gid) {
449 if (0 > setgid(wp->set_gid)) {
450 zlog(ZLOG_SYSERROR, "[pool %s] failed to setgid(%d)", wp->config->name, wp->set_gid);
451 return -1;
452 }
453 }
454 if (wp->set_uid) {
455 if (0 > initgroups(wp->set_user ? wp->set_user : wp->config->user, wp->set_gid)) {
456 zlog(ZLOG_SYSERROR, "[pool %s] failed to initgroups(%s, %d)", wp->config->name, wp->config->user, wp->set_gid);
457 return -1;
458 }
459 if (0 > setuid(wp->set_uid)) {
460 zlog(ZLOG_SYSERROR, "[pool %s] failed to setuid(%d)", wp->config->name, wp->set_uid);
461 return -1;
462 }
463 }
464 }
465
466 #ifdef HAVE_PRCTL
467 if (wp->config->process_dumpable) {
468 int dumpable = 1;
469 #ifdef HAVE_SELINUX
470 if (security_get_boolean_active("deny_ptrace") == 1) {
471 zlog(ZLOG_SYSERROR, "[pool %s] ptrace is denied", wp->config->name);
472 dumpable = 0;
473 }
474 #endif
475 if (dumpable && 0 > prctl(PR_SET_DUMPABLE, 1, 0, 0, 0)) {
476 zlog(ZLOG_SYSERROR, "[pool %s] failed to prctl(PR_SET_DUMPABLE)", wp->config->name);
477 }
478 }
479 #endif
480
481 #ifdef HAVE_PROCCTL
482 int dumpable = PROC_TRACE_CTL_ENABLE;
483 if (wp->config->process_dumpable && -1 == procctl(P_PID, getpid(), PROC_TRACE_CTL, &dumpable)) {
484 zlog(ZLOG_SYSERROR, "[pool %s] failed to procctl(PROC_TRACE_CTL)", wp->config->name);
485 }
486 #endif
487
488 #ifdef HAVE_SETPFLAGS
489 if (wp->config->process_dumpable && 0 > setpflags(__PROC_PROTECT, 0)) {
490 zlog(ZLOG_SYSERROR, "[pool %s] failed to setpflags(__PROC_PROTECT)", wp->config->name);
491 }
492 #endif
493
494 if (0 > fpm_clock_init()) {
495 return -1;
496 }
497
498 #ifdef HAVE_APPARMOR
499 if (wp->config->apparmor_hat) {
500 char *con, *new_con;
501
502 if (aa_getcon(&con, NULL) == -1) {
503 zlog(ZLOG_SYSERROR, "[pool %s] failed to query apparmor confinement. Please check if \"/proc/*/attr/current\" is read and writeable.", wp->config->name);
504 return -1;
505 }
506
507 new_con = malloc(strlen(con) + strlen(wp->config->apparmor_hat) + 3); // // + 0 Byte
508 if (!new_con) {
509 zlog(ZLOG_SYSERROR, "[pool %s] failed to allocate memory for apparmor hat change.", wp->config->name);
510 free(con);
511 return -1;
512 }
513
514 if (0 > sprintf(new_con, "%s//%s", con, wp->config->apparmor_hat)) {
515 zlog(ZLOG_SYSERROR, "[pool %s] failed to construct apparmor confinement.", wp->config->name);
516 free(con);
517 free(new_con);
518 return -1;
519 }
520
521 if (0 > aa_change_profile(new_con)) {
522 zlog(ZLOG_SYSERROR, "[pool %s] failed to change to new confinement (%s). Please check if \"/proc/*/attr/current\" is read and writeable and \"change_profile -> %s//*\" is allowed.", wp->config->name, new_con, con);
523 free(con);
524 free(new_con);
525 return -1;
526 }
527
528 free(con);
529 free(new_con);
530 }
531 #endif
532
533 return 0;
534 }
535 /* }}} */
536
fpm_unix_init_main(void)537 int fpm_unix_init_main(void)
538 {
539 struct fpm_worker_pool_s *wp;
540 int is_root = !geteuid();
541
542 if (fpm_global_config.rlimit_files) {
543 struct rlimit r;
544
545 r.rlim_max = r.rlim_cur = (rlim_t) fpm_global_config.rlimit_files;
546
547 if (0 > setrlimit(RLIMIT_NOFILE, &r)) {
548 zlog(ZLOG_SYSERROR, "failed to set rlimit_files for this pool. Please check your system limits or decrease rlimit_files. setrlimit(RLIMIT_NOFILE, %d)", fpm_global_config.rlimit_files);
549 return -1;
550 }
551 }
552
553 if (fpm_global_config.rlimit_core) {
554 struct rlimit r;
555
556 r.rlim_max = r.rlim_cur = fpm_global_config.rlimit_core == -1 ? (rlim_t) RLIM_INFINITY : (rlim_t) fpm_global_config.rlimit_core;
557
558 if (0 > setrlimit(RLIMIT_CORE, &r)) {
559 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);
560 return -1;
561 }
562 }
563
564 fpm_pagesize = getpagesize();
565 if (fpm_global_config.daemonize) {
566 /*
567 * If daemonize, the calling process will die soon
568 * and the master process continues to initialize itself.
569 *
570 * The parent process has then to wait for the master
571 * process to initialize to return a consistent exit
572 * value. For this purpose, the master process will
573 * send \"1\" into the pipe if everything went well
574 * and \"0\" otherwise.
575 */
576
577
578 struct timeval tv;
579 fd_set rfds;
580 int ret;
581
582 if (pipe(fpm_globals.send_config_pipe) == -1) {
583 zlog(ZLOG_SYSERROR, "failed to create pipe");
584 return -1;
585 }
586
587 /* then fork */
588 pid_t pid = fork();
589 switch (pid) {
590
591 case -1 : /* error */
592 zlog(ZLOG_SYSERROR, "failed to daemonize");
593 return -1;
594
595 case 0 : /* children */
596 close(fpm_globals.send_config_pipe[0]); /* close the read side of the pipe */
597 break;
598
599 default : /* parent */
600 close(fpm_globals.send_config_pipe[1]); /* close the write side of the pipe */
601
602 /*
603 * wait for 10s before exiting with error
604 * the child is supposed to send 1 or 0 into the pipe to tell the parent
605 * how it goes for it
606 */
607 FD_ZERO(&rfds);
608 FD_SET(fpm_globals.send_config_pipe[0], &rfds);
609
610 tv.tv_sec = 10;
611 tv.tv_usec = 0;
612
613 zlog(ZLOG_DEBUG, "The calling process is waiting for the master process to ping via fd=%d", fpm_globals.send_config_pipe[0]);
614 ret = select(fpm_globals.send_config_pipe[0] + 1, &rfds, NULL, NULL, &tv);
615 if (ret == -1) {
616 zlog(ZLOG_SYSERROR, "failed to select");
617 exit(FPM_EXIT_SOFTWARE);
618 }
619 if (ret) { /* data available */
620 int readval;
621 ret = read(fpm_globals.send_config_pipe[0], &readval, sizeof(readval));
622 if (ret == -1) {
623 zlog(ZLOG_SYSERROR, "failed to read from pipe");
624 exit(FPM_EXIT_SOFTWARE);
625 }
626
627 if (ret == 0) {
628 zlog(ZLOG_ERROR, "no data have been read from pipe");
629 exit(FPM_EXIT_SOFTWARE);
630 } else {
631 if (readval == 1) {
632 zlog(ZLOG_DEBUG, "I received a valid acknowledge from the master process, I can exit without error");
633 fpm_cleanups_run(FPM_CLEANUP_PARENT_EXIT);
634 exit(FPM_EXIT_OK);
635 } else {
636 zlog(ZLOG_DEBUG, "The master process returned an error !");
637 exit(FPM_EXIT_SOFTWARE);
638 }
639 }
640 } else { /* no date sent ! */
641 zlog(ZLOG_ERROR, "the master process didn't send back its status (via the pipe to the calling process)");
642 exit(FPM_EXIT_SOFTWARE);
643 }
644 exit(FPM_EXIT_SOFTWARE);
645 }
646 }
647
648 /* continue as a child */
649 setsid();
650 if (0 > fpm_clock_init()) {
651 return -1;
652 }
653
654 if (fpm_global_config.process_priority != 64) {
655 if (is_root) {
656 if (setpriority(PRIO_PROCESS, 0, fpm_global_config.process_priority) < 0) {
657 zlog(ZLOG_SYSERROR, "Unable to set priority for the master process");
658 return -1;
659 }
660 } else {
661 zlog(ZLOG_NOTICE, "'process.priority' directive is ignored when FPM is not running as root");
662 }
663 }
664
665 fpm_globals.parent_pid = getpid();
666 for (wp = fpm_worker_all_pools; wp; wp = wp->next) {
667 if (0 > fpm_unix_conf_wp(wp)) {
668 return -1;
669 }
670 }
671
672 return 0;
673 }
674