7#include <sys/resource.h>
20#include <sys/procctl.h>
28#include <sys/apparmor.h>
36#include <selinux/selinux.h>
51static inline bool fpm_unix_is_id(
const char*
name)
58 struct passwd *pwd = getpwnam(
name);
67static inline bool fpm_unix_check_listen_address(
struct fpm_worker_pool_s *wp,
const char *address,
int flags)
73 struct sockaddr_un test_socket;
74 size_t address_length =
strlen(address);
75 size_t socket_length =
sizeof(test_socket.sun_path);
77 if (address_length < socket_length) {
83 "[pool %s] cannot bind to UNIX socket '%s' as path is too long (found length: %zu, "
84 "maximal length: %zu)",
101 struct group *group = getgrnam(
name);
134 wp->socket_acl =
NULL;
151 if (c->listen_acl_users && *c->listen_acl_users) {
158 if (c->listen_acl_groups && *c->listen_acl_groups) {
178 if (c->listen_acl_users && *c->listen_acl_users) {
181 tmp =
estrdup(c->listen_acl_users);
194 if (0 > acl_create_entry(&acl, &entry) ||
195 0 > acl_set_tag_type(entry, ACL_USER) ||
196 0 > acl_set_qualifier(entry, &pwd->pw_uid) ||
197 0 > acl_get_permset(entry, &perm) ||
198 0 > acl_clear_perms (perm) ||
199 0 > acl_add_perm (perm, ACL_READ) ||
200 0 > acl_add_perm (perm, ACL_WRITE)) {
210 if (c->listen_acl_groups && *c->listen_acl_groups) {
213 tmp =
estrdup(c->listen_acl_groups);
226 if (0 > acl_create_entry(&acl, &entry) ||
227 0 > acl_set_tag_type(entry, ACL_GROUP) ||
228 0 > acl_set_qualifier(entry, &grp->gr_gid) ||
229 0 > acl_get_permset(entry, &perm) ||
230 0 > acl_clear_perms (perm) ||
231 0 > acl_add_perm (perm, ACL_READ) ||
232 0 > acl_add_perm (perm, ACL_WRITE)) {
247 wp->socket_acl = acl;
290 if (wp->socket_acl) {
291 acl_t aclfile, aclconf;
292 acl_entry_t entryfile, entryconf;
296 aclconf = wp->socket_acl;
297 aclfile = acl_get_file (path, ACL_TYPE_ACCESS);
303 for (i=ACL_FIRST_ENTRY ; acl_get_entry(aclconf, i, &entryconf) ; i=ACL_NEXT_ENTRY) {
304 if (0 > acl_create_entry (&aclfile, &entryfile) ||
305 0 > acl_copy_entry(entryfile, entryconf)) {
312 if (0 > acl_calc_mask (&aclfile) ||
313 0 > acl_valid (aclfile) ||
314 0 > acl_set_file (path, ACL_TYPE_ACCESS, aclfile)) {
341 if (wp->socket_acl) {
342 return acl_free(wp->socket_acl);
352 int is_root = !geteuid();
361 wp->
set_user = strdup(pwd->pw_name);
374 wp->
user = strdup(pwd->pw_name);
375 wp->
home = strdup(pwd->pw_dir);
410 zlog(
ZLOG_NOTICE,
"[pool %s] 'process.priority' directive is ignored when FPM is not running as root", wp->
config->
name);
414 pwd = getpwuid(getuid());
416 wp->
user = strdup(pwd->pw_name);
417 wp->
home = strdup(pwd->pw_dir);
426 int is_root = !geteuid();
434 if (0 > setrlimit(RLIMIT_NOFILE, &r)) {
444 if (0 > setrlimit(RLIMIT_CORE, &r)) {
462 }
else if (made_chroot) {
463 if (0 >
chdir(
"/")) {
499 if (security_get_boolean_active(
"deny_ptrace") == 1) {
504 if (dumpable && 0 > prctl(PR_SET_DUMPABLE, 1, 0, 0, 0)) {
511 int dumpable = PROC_TRACE_CTL_ENABLE;
528 if (wp->
config->apparmor_hat) {
531 if (aa_getcon(&con,
NULL) == -1) {
532 zlog(
ZLOG_SYSERROR,
"[pool %s] failed to query apparmor confinement. Please check if \"/proc/*/attr/current\" is read and writeable.", wp->
config->
name);
537 new_con = malloc(new_con_length);
544 if (0 >
snprintf(new_con, new_con_length,
"%s//%s", con, wp->
config->apparmor_hat)) {
551 if (0 > aa_change_profile(new_con)) {
552 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);
570 int is_root = !geteuid();
577 if (0 > setrlimit(RLIMIT_NOFILE, &r)) {
578 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);
588 if (0 > setrlimit(RLIMIT_CORE, &r)) {
589 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);
643 zlog(
ZLOG_DEBUG,
"The calling process is waiting for the master process to ping via fd=%d",
fpm_globals.send_config_pipe[0]);
651 ret = read(
fpm_globals.send_config_pipe[0], &readval,
sizeof(readval));
662 zlog(
ZLOG_DEBUG,
"I received a valid acknowledge from the master process, I can exit without error");
671 zlog(
ZLOG_ERROR,
"the master process didn't send back its status (via the pipe to the calling process)");
691 zlog(
ZLOG_NOTICE,
"'process.priority' directive is ignored when FPM is not running as root");
697 if (0 > fpm_unix_conf_wp(wp)) {
chroot(string $directory)
chown(string $filename, string|int $user)
strspn(string $string, string $characters, int $offset=0, ?int $length=null)
strchr(string $haystack, string $needle, bool $before_needle=false)
struct fpm_globals_s fpm_globals
#define FPM_EXIT_SOFTWARE
void fpm_cleanups_run(int type)
@ FPM_CLEANUP_PARENT_EXIT
struct fpm_global_config_s fpm_global_config
int fpm_unix_set_socket_permissions(struct fpm_worker_pool_s *wp, const char *path)
int fpm_unix_free_socket_permissions(struct fpm_worker_pool_s *wp)
int fpm_unix_resolve_socket_permissions(struct fpm_worker_pool_s *wp)
int fpm_unix_init_main(void)
int fpm_unix_init_child(struct fpm_worker_pool_s *wp)
bool fpm_unix_test_config(struct fpm_worker_pool_s *wp)
struct fpm_worker_pool_s * fpm_worker_all_pools
unsigned const char * end
struct fpm_worker_pool_config_s * config
enum fpm_address_domain listen_address_domain
struct fpm_worker_pool_s * next
exit(string|int $status=0)