Commit message: halfway revert hack/configure changes - switch order of daemon_init/drop_privileges
CVE: CVE-2017-12847
CWE: CWE-665
Vulnerability description: Nagios Core before 4.3.3 creates a nagios.lock PID file after dropping privileges to a non-root account, which might allow local users to kill arbitrary processes by leveraging access to this non-root account for nagios.lock modification before a root script executes a "kill `cat /pathname/nagios.lock`" command.

Project: nagioscore
File: nagios.c

static int nagios_core_worker(const char *path)
{
	int sd, ret;
	char response[128];

	is_worker = 1;

	set_loadctl_defaults();

	sd = nsock_unix(path, NSOCK_TCP | NSOCK_CONNECT);
	if (sd < 0) {
		printf("Failed to connect to query socket '%s': %s: %s\n",
			   path, nsock_strerror(sd), strerror(errno));
		return 1;
	}

	ret = nsock_printf_nul(sd, "@wproc register name=Core Worker %ld;pid=%ld", (long)getpid(), (long)getpid());
	if (ret < 0) {
		printf("Failed to register as worker.\n");
		return 1;
	}

	ret = read(sd, response, 3);
	if (ret != 3) {
		printf("Failed to read response from wproc manager\n");
		return 1;
	}
	if (memcmp(response, "OK", 3)) {
		read(sd, response + 3, sizeof(response) - 4);
		response[sizeof(response) - 2] = 0;
		printf("Failed to register with wproc manager: %s\n", response);
		return 1;
	}

	enter_worker(sd, start_cmd);
	return 0;
}

Project: nagioscore
File: nagios.c

static void set_loadctl_defaults(void)
{
	struct rlimit rlim;

	/* Workers need to up 'em, master needs to know 'em */
	getrlimit(RLIMIT_NOFILE, &rlim);
	rlim.rlim_cur = rlim.rlim_max;
	setrlimit(RLIMIT_NOFILE, &rlim);
	loadctl.nofile_limit = rlim.rlim_max;
#ifdef RLIMIT_NPROC
	getrlimit(RLIMIT_NPROC, &rlim);
	rlim.rlim_cur = rlim.rlim_max;
	setrlimit(RLIMIT_NPROC, &rlim);
	loadctl.nproc_limit = rlim.rlim_max;
#else
	loadctl.nproc_limit = loadctl.nofile_limit / 2;
#endif

	/*
	 * things may have been configured already. Otherwise we
	 * set some sort of sane defaults here
	 */
	if (!loadctl.jobs_max) {
		loadctl.jobs_max = loadctl.nproc_limit - 100;
		if (!is_worker && loadctl.jobs_max > (loadctl.nofile_limit - 50) * wproc_num_workers_online) {
			loadctl.jobs_max = (loadctl.nofile_limit - 50) * wproc_num_workers_online;
		}
	}

	if (!loadctl.jobs_limit)
		loadctl.jobs_limit = loadctl.jobs_max;

	if (!loadctl.backoff_limit)
		loadctl.backoff_limit = online_cpus() * 2.5;
	if (!loadctl.rampup_limit)
		loadctl.rampup_limit = online_cpus() * 0.8;
	if (!loadctl.backoff_change)
		loadctl.backoff_change = loadctl.jobs_limit * 0.3;
	if (!loadctl.rampup_change)
		loadctl.rampup_change = loadctl.backoff_change * 0.25;
	if (!loadctl.check_interval)
		loadctl.check_interval = 60;
	if (!loadctl.jobs_min)
		loadctl.jobs_min = online_cpus() * 20; /* pessimistic */
}

Project: nagioscore
File: nagios.c

static int test_configured_paths(void)
{
	FILE *fp;
	nagios_macros *mac;

	mac = get_global_macros();

	fp = fopen(log_file, "a+");
	if (!fp) {
		/*
		 * we do some variable trashing here so logit() can
		 * open the old logfile (if any), in case we got a
		 * restart command or a SIGHUP
		 */
		char *value_absolute = log_file;
		log_file = mac->x[MACRO_LOGFILE];
		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Failed to open logfile '%s' for writing: %s\n", value_absolute, strerror(errno));
		return ERROR;
		}

	fclose(fp);

	/* save the macro */
	mac->x[MACRO_LOGFILE] = log_file;
	return OK;
}

Project: nagioscore
File: nagios.c

static int test_path_access(const char *program, int mode)
{
	char *envpath, *p, *colon;
	int ret, our_errno = 1500; /* outside errno range */

	if (program[0] == '/' || !(envpath = getenv("PATH")))
		return access(program, mode);

	if (!(envpath = strdup(envpath))) {
		errno = ENOMEM;
		return -1;
	}

	for (p = envpath; p; p = colon + 1) {
		char *path;

		colon = strchr(p, ':');
		if (colon)
			*colon = 0;
		asprintf(&path, "%s/%s", p, program);
		ret = access(path, mode);
		free(path);
		if (!ret)
			break;

		if (ret < 0) {
			if (errno == ENOENT)
				continue;
			if (our_errno > errno)
				our_errno = errno;
		}
		if (!colon)
			break;
	}

	free(envpath);

	if (!ret)
		errno = 0;
	else
		errno = our_errno;

	return ret;
}