9b2267b5ba9d0640512a41e139a4a36caa43730dBob Halley/*
6431922cb25fb3d9815677cfbfba83db95b4e401Tinderbox User * Copyright (C) 1999-2002, 2004-2011, 2013-2017 Internet Systems Consortium, Inc. ("ISC")
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence *
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * This Source Code Form is subject to the terms of the Mozilla Public
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * License, v. 2.0. If a copy of the MPL was not distributed with this
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9b2267b5ba9d0640512a41e139a4a36caa43730dBob Halley */
9b2267b5ba9d0640512a41e139a4a36caa43730dBob Halley
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein/*! \file */
9c3531d72aeaad6c5f01efe6a1c82023e1379e4dDavid Lawrence
9b2267b5ba9d0640512a41e139a4a36caa43730dBob Halley#include <config.h>
a3a11c4f3fc9ba972802b811c4d95a9884d6ff4aMichael Sawyer#include <stdarg.h>
9b2267b5ba9d0640512a41e139a4a36caa43730dBob Halley
5d98cf67b32d785aca1a72ea1dc4d559fab39208Mark Andrews#include <sys/types.h> /* dev_t FreeBSD 2.1 */
9ee5efde7df57cbe70fb9b32c9d898e8ef7eca1eBob Halley#include <sys/stat.h>
f02c22d58ac88777655e0b407b22b07864d39184Evan Hunt#ifdef HAVE_UNAME
f02c22d58ac88777655e0b407b22b07864d39184Evan Hunt#include <sys/utsname.h>
f02c22d58ac88777655e0b407b22b07864d39184Evan Hunt#endif
9b2267b5ba9d0640512a41e139a4a36caa43730dBob Halley
2dfd6bca9aa6d9279b4278d6fa18ea5f63ba0ec9Bob Halley#include <ctype.h>
9b2267b5ba9d0640512a41e139a4a36caa43730dBob Halley#include <errno.h>
2aa67e804d85f4d88153368ce65ce4df7b5390e6Bob Halley#include <fcntl.h>
de8661e517ed679cfaa12e47eb9a8e23829ed320David Lawrence#include <grp.h> /* Required for initgroups() on IRIX. */
2dfd6bca9aa6d9279b4278d6fa18ea5f63ba0ec9Bob Halley#include <pwd.h>
de8661e517ed679cfaa12e47eb9a8e23829ed320David Lawrence#include <stdio.h>
de8661e517ed679cfaa12e47eb9a8e23829ed320David Lawrence#include <stdlib.h>
90c4900d5cf1a1b556ae4c1de6338b2e7475ee55Mark Andrews#include <signal.h>
de8661e517ed679cfaa12e47eb9a8e23829ed320David Lawrence#include <syslog.h>
764808211e952f1617aaa609281da66d80120c0dMark Andrews#ifdef HAVE_TZSET
764808211e952f1617aaa609281da66d80120c0dMark Andrews#include <time.h>
764808211e952f1617aaa609281da66d80120c0dMark Andrews#endif
de8661e517ed679cfaa12e47eb9a8e23829ed320David Lawrence#include <unistd.h>
9b2267b5ba9d0640512a41e139a4a36caa43730dBob Halley
cf300e03de3df3ff422db922520bf07c686c86daMark Andrews#include <isc/buffer.h>
76477bd0e0a8f150f06f45c347d286b782cfa679Brian Wellington#include <isc/file.h>
108490a7f8529aff50a0ac7897580b59a73d9845David Lawrence#include <isc/print.h>
6d54a6fc180acaf8772c9447cb925b31f39c7158Mark Andrews#include <isc/resource.h>
a3a11c4f3fc9ba972802b811c4d95a9884d6ff4aMichael Sawyer#include <isc/result.h>
4b87939256ede703385e9cab92d3c58d03c31098Mark Andrews#include <isc/strerror.h>
108490a7f8529aff50a0ac7897580b59a73d9845David Lawrence#include <isc/string.h>
9b2267b5ba9d0640512a41e139a4a36caa43730dBob Halley
52254f75267c734acf1f1fb982b6a3be05e93507Mark Andrews#include <named/globals.h>
9b2267b5ba9d0640512a41e139a4a36caa43730dBob Halley#include <named/main.h>
9b2267b5ba9d0640512a41e139a4a36caa43730dBob Halley#include <named/os.h>
f754fa97bc698cc251d227173a95e4d39a88ac01Mark Andrews#ifdef HAVE_LIBSCF
f754fa97bc698cc251d227173a95e4d39a88ac01Mark Andrews#include <named/ns_smf_globals.h>
f754fa97bc698cc251d227173a95e4d39a88ac01Mark Andrews#endif
9b2267b5ba9d0640512a41e139a4a36caa43730dBob Halley
9ee5efde7df57cbe70fb9b32c9d898e8ef7eca1eBob Halleystatic char *pidfile = NULL;
7ae96d882326357448f8f440c52f47ac1b1fa455Evan Huntstatic char *lockfile = NULL;
c52ae25dd70636c673d4a299859137a1c8ba611aMark Andrewsstatic int devnullfd = -1;
47d837a49967a6a1b290024f5efb0669276013b1Mukund Sivaramanstatic int singletonfd = -1;
51e0ad287f1b345f0c3316f0633aab14d0e8bb65Brian Wellington
ee80f4506479e189ca1320eb87ac89188c5a7848Mark Andrews#ifndef ISC_FACILITY
ee80f4506479e189ca1320eb87ac89188c5a7848Mark Andrews#define ISC_FACILITY LOG_DAEMON
ee80f4506479e189ca1320eb87ac89188c5a7848Mark Andrews#endif
ee80f4506479e189ca1320eb87ac89188c5a7848Mark Andrews
51e0ad287f1b345f0c3316f0633aab14d0e8bb65Brian Wellington/*
1d8cbe855fc355b80802dcf29f4ac24bebdd1193Brian Wellington * If there's no <linux/capability.h>, we don't care about <sys/prctl.h>
51e0ad287f1b345f0c3316f0633aab14d0e8bb65Brian Wellington */
51e0ad287f1b345f0c3316f0633aab14d0e8bb65Brian Wellington#ifndef HAVE_LINUX_CAPABILITY_H
f8727bd90366af835f551da1b5e1fdfcd2d3d01fBrian Wellington#undef HAVE_SYS_PRCTL_H
51e0ad287f1b345f0c3316f0633aab14d0e8bb65Brian Wellington#endif
51e0ad287f1b345f0c3316f0633aab14d0e8bb65Brian Wellington
51e0ad287f1b345f0c3316f0633aab14d0e8bb65Brian Wellington/*
51e0ad287f1b345f0c3316f0633aab14d0e8bb65Brian Wellington * Linux defines:
5d98cf67b32d785aca1a72ea1dc4d559fab39208Mark Andrews * (T) HAVE_LINUXTHREADS
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt * (C) HAVE_SYS_CAPABILITY_H (or HAVE_LINUX_CAPABILITY_H)
5d98cf67b32d785aca1a72ea1dc4d559fab39208Mark Andrews * (P) HAVE_SYS_PRCTL_H
51e0ad287f1b345f0c3316f0633aab14d0e8bb65Brian Wellington * The possible cases are:
5d98cf67b32d785aca1a72ea1dc4d559fab39208Mark Andrews * none: setuid() normally
5d98cf67b32d785aca1a72ea1dc4d559fab39208Mark Andrews * T: no setuid()
5d98cf67b32d785aca1a72ea1dc4d559fab39208Mark Andrews * C: setuid() normally, drop caps (keep CAP_SETUID)
5d98cf67b32d785aca1a72ea1dc4d559fab39208Mark Andrews * T+C: no setuid(), drop caps (don't keep CAP_SETUID)
5d98cf67b32d785aca1a72ea1dc4d559fab39208Mark Andrews * T+C+P: setuid() early, drop caps (keep CAP_SETUID)
5d98cf67b32d785aca1a72ea1dc4d559fab39208Mark Andrews * C+P: setuid() normally, drop caps (keep CAP_SETUID)
51e0ad287f1b345f0c3316f0633aab14d0e8bb65Brian Wellington * P: not possible
51e0ad287f1b345f0c3316f0633aab14d0e8bb65Brian Wellington * T+P: not possible
51e0ad287f1b345f0c3316f0633aab14d0e8bb65Brian Wellington *
51e0ad287f1b345f0c3316f0633aab14d0e8bb65Brian Wellington * if (C)
5d98cf67b32d785aca1a72ea1dc4d559fab39208Mark Andrews * caps = BIND_SERVICE + CHROOT + SETGID
5d98cf67b32d785aca1a72ea1dc4d559fab39208Mark Andrews * if ((T && C && P) || !T)
5d98cf67b32d785aca1a72ea1dc4d559fab39208Mark Andrews * caps += SETUID
5d98cf67b32d785aca1a72ea1dc4d559fab39208Mark Andrews * endif
5d98cf67b32d785aca1a72ea1dc4d559fab39208Mark Andrews * capset(caps)
51e0ad287f1b345f0c3316f0633aab14d0e8bb65Brian Wellington * endif
51e0ad287f1b345f0c3316f0633aab14d0e8bb65Brian Wellington * if (T && C && P && -u)
5d98cf67b32d785aca1a72ea1dc4d559fab39208Mark Andrews * setuid()
51e0ad287f1b345f0c3316f0633aab14d0e8bb65Brian Wellington * else if (T && -u)
5d98cf67b32d785aca1a72ea1dc4d559fab39208Mark Andrews * fail
51e0ad287f1b345f0c3316f0633aab14d0e8bb65Brian Wellington * --> start threads
51e0ad287f1b345f0c3316f0633aab14d0e8bb65Brian Wellington * if (!T && -u)
5d98cf67b32d785aca1a72ea1dc4d559fab39208Mark Andrews * setuid()
51e0ad287f1b345f0c3316f0633aab14d0e8bb65Brian Wellington * if (C && (P || !-u))
5d98cf67b32d785aca1a72ea1dc4d559fab39208Mark Andrews * caps = BIND_SERVICE
5d98cf67b32d785aca1a72ea1dc4d559fab39208Mark Andrews * capset(caps)
51e0ad287f1b345f0c3316f0633aab14d0e8bb65Brian Wellington * endif
51e0ad287f1b345f0c3316f0633aab14d0e8bb65Brian Wellington *
51e0ad287f1b345f0c3316f0633aab14d0e8bb65Brian Wellington * It will be nice when Linux threads work properly with setuid().
51e0ad287f1b345f0c3316f0633aab14d0e8bb65Brian Wellington */
51e0ad287f1b345f0c3316f0633aab14d0e8bb65Brian Wellington
9ee5efde7df57cbe70fb9b32c9d898e8ef7eca1eBob Halley#ifdef HAVE_LINUXTHREADS
9ee5efde7df57cbe70fb9b32c9d898e8ef7eca1eBob Halleystatic pid_t mainpid = 0;
9ee5efde7df57cbe70fb9b32c9d898e8ef7eca1eBob Halley#endif
9b2267b5ba9d0640512a41e139a4a36caa43730dBob Halley
4e5388b45908ce8b8b35825ca6f16c1d236643baBrian Wellingtonstatic struct passwd *runas_pw = NULL;
c336121fb5a5c1b9cb9b2cd4cea50f0788270505Brian Wellingtonstatic isc_boolean_t done_setuid = ISC_FALSE;
2c329da87c5c886e7f4468c69a9e6323121068cbMark Andrewsstatic int dfd[2] = { -1, -1 };
202991557a4b7e8d3df7725d84f0fcae90dbaee6David Lawrence
9b2267b5ba9d0640512a41e139a4a36caa43730dBob Halley#ifdef HAVE_LINUX_CAPABILITY_H
2dfd6bca9aa6d9279b4278d6fa18ea5f63ba0ec9Bob Halley
51e0ad287f1b345f0c3316f0633aab14d0e8bb65Brian Wellingtonstatic isc_boolean_t non_root = ISC_FALSE;
51e0ad287f1b345f0c3316f0633aab14d0e8bb65Brian Wellingtonstatic isc_boolean_t non_root_caps = ISC_FALSE;
51e0ad287f1b345f0c3316f0633aab14d0e8bb65Brian Wellington
dc2a0aa7aaa8b85398ae183c7274c0eeec5009afMark Andrews#ifdef HAVE_SYS_CAPABILITY_H
dc2a0aa7aaa8b85398ae183c7274c0eeec5009afMark Andrews#include <sys/capability.h>
dc2a0aa7aaa8b85398ae183c7274c0eeec5009afMark Andrews#else
7433a204d32673e9f6747172f202272cc5bfe27cMark Andrews#ifdef HAVE_LINUX_TYPES_H
7433a204d32673e9f6747172f202272cc5bfe27cMark Andrews#include <linux/types.h>
7433a204d32673e9f6747172f202272cc5bfe27cMark Andrews#endif
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein/*%
077daa21229ffaedda79588fa70fbaeae19ae998Bob Halley * We define _LINUX_FS_H to prevent it from being included. We don't need
077daa21229ffaedda79588fa70fbaeae19ae998Bob Halley * anything from it, and the files it includes cause warnings with 2.2
077daa21229ffaedda79588fa70fbaeae19ae998Bob Halley * kernels, and compilation failures (due to conflicts between <linux/string.h>
077daa21229ffaedda79588fa70fbaeae19ae998Bob Halley * and <string.h>) on 2.3 kernels.
077daa21229ffaedda79588fa70fbaeae19ae998Bob Halley */
077daa21229ffaedda79588fa70fbaeae19ae998Bob Halley#define _LINUX_FS_H
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt#include <linux/capability.h>
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt#include <syscall.h>
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt#ifndef SYS_capset
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt#ifndef __NR_capset
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt#include <asm/unistd.h> /* Slackware 4.0 needs this. */
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt#endif /* __NR_capset */
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt#define SYS_capset __NR_capset
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt#endif /* SYS_capset */
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt#endif /* HAVE_SYS_CAPABILITY_H */
9b2267b5ba9d0640512a41e139a4a36caa43730dBob Halley
f8727bd90366af835f551da1b5e1fdfcd2d3d01fBrian Wellington#ifdef HAVE_SYS_PRCTL_H
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence#include <sys/prctl.h> /* Required for prctl(). */
d1e4b08844175357a925ddd6dcfa750cccd2b116Brian Wellington
d1e4b08844175357a925ddd6dcfa750cccd2b116Brian Wellington/*
1d8cbe855fc355b80802dcf29f4ac24bebdd1193Brian Wellington * If the value of PR_SET_KEEPCAPS is not in <sys/prctl.h>, define it
d1e4b08844175357a925ddd6dcfa750cccd2b116Brian Wellington * here. This allows setuid() to work on systems running a new enough
d1e4b08844175357a925ddd6dcfa750cccd2b116Brian Wellington * kernel but with /usr/include/linux pointing to "standard" kernel
d1e4b08844175357a925ddd6dcfa750cccd2b116Brian Wellington * headers.
d1e4b08844175357a925ddd6dcfa750cccd2b116Brian Wellington */
da76a8046e01e1c1c2e6f75772afb2c4f202cc25Brian Wellington#ifndef PR_SET_KEEPCAPS
da76a8046e01e1c1c2e6f75772afb2c4f202cc25Brian Wellington#define PR_SET_KEEPCAPS 8
134ba0e08a0ae9a564a8d8628fc633377d3fc239Bob Halley#endif
d1e4b08844175357a925ddd6dcfa750cccd2b116Brian Wellington
f8727bd90366af835f551da1b5e1fdfcd2d3d01fBrian Wellington#endif /* HAVE_SYS_PRCTL_H */
134ba0e08a0ae9a564a8d8628fc633377d3fc239Bob Halley
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt#ifdef HAVE_LIBCAP
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt#define SETCAPS_FUNC "cap_set_proc "
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt#else
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunttypedef unsigned int cap_t;
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt#define SETCAPS_FUNC "syscall(capset) "
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt#endif /* HAVE_LIBCAP */
9b2267b5ba9d0640512a41e139a4a36caa43730dBob Halley
9b2267b5ba9d0640512a41e139a4a36caa43730dBob Halleystatic void
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Huntlinux_setcaps(cap_t caps) {
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt#ifndef HAVE_LIBCAP
9b2267b5ba9d0640512a41e139a4a36caa43730dBob Halley struct __user_cap_header_struct caphead;
9b2267b5ba9d0640512a41e139a4a36caa43730dBob Halley struct __user_cap_data_struct cap;
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt#endif
4b87939256ede703385e9cab92d3c58d03c31098Mark Andrews char strbuf[ISC_STRERRORSIZE];
9b2267b5ba9d0640512a41e139a4a36caa43730dBob Halley
77771185071bf74d53378f1a3099a04d2af5153eBrian Wellington if ((getuid() != 0 && !non_root_caps) || non_root)
9b2267b5ba9d0640512a41e139a4a36caa43730dBob Halley return;
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt#ifndef HAVE_LIBCAP
2f734e0a7e518c89c2b2b179714b8885b7626b3aAndreas Gustafsson memset(&caphead, 0, sizeof(caphead));
9b2267b5ba9d0640512a41e139a4a36caa43730dBob Halley caphead.version = _LINUX_CAPABILITY_VERSION;
9b2267b5ba9d0640512a41e139a4a36caa43730dBob Halley caphead.pid = 0;
2f734e0a7e518c89c2b2b179714b8885b7626b3aAndreas Gustafsson memset(&cap, 0, sizeof(cap));
9b2267b5ba9d0640512a41e139a4a36caa43730dBob Halley cap.effective = caps;
9b2267b5ba9d0640512a41e139a4a36caa43730dBob Halley cap.permitted = caps;
bb99a72b219ad4f1daa80c636883ab485174c9a6Mark Andrews cap.inheritable = 0;
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt#endif
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt#ifdef HAVE_LIBCAP
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt if (cap_set_proc(caps) < 0) {
dc2a0aa7aaa8b85398ae183c7274c0eeec5009afMark Andrews#else
dc2a0aa7aaa8b85398ae183c7274c0eeec5009afMark Andrews if (syscall(SYS_capset, &caphead, &cap) < 0) {
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt#endif
dc2a0aa7aaa8b85398ae183c7274c0eeec5009afMark Andrews isc__strerror(errno, strbuf, sizeof(strbuf));
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt ns_main_earlyfatal(SETCAPS_FUNC "failed: %s:"
dc2a0aa7aaa8b85398ae183c7274c0eeec5009afMark Andrews " please ensure that the capset kernel"
dc2a0aa7aaa8b85398ae183c7274c0eeec5009afMark Andrews " module is loaded. see insmod(8)",
dc2a0aa7aaa8b85398ae183c7274c0eeec5009afMark Andrews strbuf);
dc2a0aa7aaa8b85398ae183c7274c0eeec5009afMark Andrews }
9b2267b5ba9d0640512a41e139a4a36caa43730dBob Halley}
2dfd6bca9aa6d9279b4278d6fa18ea5f63ba0ec9Bob Halley
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt#ifdef HAVE_LIBCAP
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt#define SET_CAP(flag) \
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt do { \
88674be66567d3c7db91e717cd5972655e2e2488Mark Andrews cap_flag_value_t curval; \
51143259789034ac19e12984a8390b9f86ab368cMark Andrews capval = (flag); \
ef4eed2a2a8897bd4e5b19dd94f638e0861ebda5Mark Andrews err = cap_get_flag(curcaps, capval, CAP_PERMITTED, &curval); \
88674be66567d3c7db91e717cd5972655e2e2488Mark Andrews if (err != -1 && curval) { \
88674be66567d3c7db91e717cd5972655e2e2488Mark Andrews err = cap_set_flag(caps, CAP_EFFECTIVE, 1, &capval, CAP_SET); \
88674be66567d3c7db91e717cd5972655e2e2488Mark Andrews if (err == -1) { \
88674be66567d3c7db91e717cd5972655e2e2488Mark Andrews isc__strerror(errno, strbuf, sizeof(strbuf)); \
88674be66567d3c7db91e717cd5972655e2e2488Mark Andrews ns_main_earlyfatal("cap_set_proc failed: %s", strbuf); \
88674be66567d3c7db91e717cd5972655e2e2488Mark Andrews } \
88674be66567d3c7db91e717cd5972655e2e2488Mark Andrews \
88674be66567d3c7db91e717cd5972655e2e2488Mark Andrews err = cap_set_flag(caps, CAP_PERMITTED, 1, &capval, CAP_SET); \
88674be66567d3c7db91e717cd5972655e2e2488Mark Andrews if (err == -1) { \
88674be66567d3c7db91e717cd5972655e2e2488Mark Andrews isc__strerror(errno, strbuf, sizeof(strbuf)); \
88674be66567d3c7db91e717cd5972655e2e2488Mark Andrews ns_main_earlyfatal("cap_set_proc failed: %s", strbuf); \
88674be66567d3c7db91e717cd5972655e2e2488Mark Andrews } \
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt } \
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt } while (0)
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt#define INIT_CAP \
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt do { \
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt caps = cap_init(); \
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt if (caps == NULL) { \
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt isc__strerror(errno, strbuf, sizeof(strbuf)); \
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt ns_main_earlyfatal("cap_init failed: %s", strbuf); \
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt } \
ef4eed2a2a8897bd4e5b19dd94f638e0861ebda5Mark Andrews curcaps = cap_get_proc(); \
ef4eed2a2a8897bd4e5b19dd94f638e0861ebda5Mark Andrews if (curcaps == NULL) { \
ef4eed2a2a8897bd4e5b19dd94f638e0861ebda5Mark Andrews isc__strerror(errno, strbuf, sizeof(strbuf)); \
ef4eed2a2a8897bd4e5b19dd94f638e0861ebda5Mark Andrews ns_main_earlyfatal("cap_get_proc failed: %s", strbuf); \
ef4eed2a2a8897bd4e5b19dd94f638e0861ebda5Mark Andrews } \
ef4eed2a2a8897bd4e5b19dd94f638e0861ebda5Mark Andrews } while (0)
ef4eed2a2a8897bd4e5b19dd94f638e0861ebda5Mark Andrews#define FREE_CAP \
ef4eed2a2a8897bd4e5b19dd94f638e0861ebda5Mark Andrews { \
ef4eed2a2a8897bd4e5b19dd94f638e0861ebda5Mark Andrews cap_free(caps); \
ef4eed2a2a8897bd4e5b19dd94f638e0861ebda5Mark Andrews cap_free(curcaps); \
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt } while (0)
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt#else
ef4eed2a2a8897bd4e5b19dd94f638e0861ebda5Mark Andrews#define SET_CAP(flag) do { caps |= (1 << (flag)); } while (0)
ef4eed2a2a8897bd4e5b19dd94f638e0861ebda5Mark Andrews#define INIT_CAP do { caps = 0; } while (0)
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt#endif /* HAVE_LIBCAP */
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt
2dfd6bca9aa6d9279b4278d6fa18ea5f63ba0ec9Bob Halleystatic void
2dfd6bca9aa6d9279b4278d6fa18ea5f63ba0ec9Bob Halleylinux_initialprivs(void) {
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt cap_t caps;
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt#ifdef HAVE_LIBCAP
ef4eed2a2a8897bd4e5b19dd94f638e0861ebda5Mark Andrews cap_t curcaps;
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt cap_value_t capval;
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt char strbuf[ISC_STRERRORSIZE];
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt int err;
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt#endif
2dfd6bca9aa6d9279b4278d6fa18ea5f63ba0ec9Bob Halley
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein /*%
134ba0e08a0ae9a564a8d8628fc633377d3fc239Bob Halley * We don't need most privileges, so we drop them right away.
134ba0e08a0ae9a564a8d8628fc633377d3fc239Bob Halley * Later on linux_minprivs() will be called, which will drop our
134ba0e08a0ae9a564a8d8628fc633377d3fc239Bob Halley * capabilities to the minimum needed to run the server.
2dfd6bca9aa6d9279b4278d6fa18ea5f63ba0ec9Bob Halley */
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt INIT_CAP;
134ba0e08a0ae9a564a8d8628fc633377d3fc239Bob Halley
134ba0e08a0ae9a564a8d8628fc633377d3fc239Bob Halley /*
134ba0e08a0ae9a564a8d8628fc633377d3fc239Bob Halley * We need to be able to bind() to privileged ports, notably port 53!
134ba0e08a0ae9a564a8d8628fc633377d3fc239Bob Halley */
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt SET_CAP(CAP_NET_BIND_SERVICE);
134ba0e08a0ae9a564a8d8628fc633377d3fc239Bob Halley
134ba0e08a0ae9a564a8d8628fc633377d3fc239Bob Halley /*
134ba0e08a0ae9a564a8d8628fc633377d3fc239Bob Halley * We need chroot() initially too.
134ba0e08a0ae9a564a8d8628fc633377d3fc239Bob Halley */
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt SET_CAP(CAP_SYS_CHROOT);
134ba0e08a0ae9a564a8d8628fc633377d3fc239Bob Halley
f8727bd90366af835f551da1b5e1fdfcd2d3d01fBrian Wellington#if defined(HAVE_SYS_PRCTL_H) || !defined(HAVE_LINUXTHREADS)
134ba0e08a0ae9a564a8d8628fc633377d3fc239Bob Halley /*
51e0ad287f1b345f0c3316f0633aab14d0e8bb65Brian Wellington * We can setuid() only if either the kernel supports keeping
51e0ad287f1b345f0c3316f0633aab14d0e8bb65Brian Wellington * capabilities after setuid() (which we don't know until we've
51e0ad287f1b345f0c3316f0633aab14d0e8bb65Brian Wellington * tried) or we're not using threads. If either of these is
51e0ad287f1b345f0c3316f0633aab14d0e8bb65Brian Wellington * true, we want the setuid capability.
134ba0e08a0ae9a564a8d8628fc633377d3fc239Bob Halley */
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt SET_CAP(CAP_SETUID);
134ba0e08a0ae9a564a8d8628fc633377d3fc239Bob Halley#endif
134ba0e08a0ae9a564a8d8628fc633377d3fc239Bob Halley
71954c957132c35ddf5f9e4dcc98c057b265b6d8Brian Wellington /*
71954c957132c35ddf5f9e4dcc98c057b265b6d8Brian Wellington * Since we call initgroups, we need this.
71954c957132c35ddf5f9e4dcc98c057b265b6d8Brian Wellington */
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt SET_CAP(CAP_SETGID);
71954c957132c35ddf5f9e4dcc98c057b265b6d8Brian Wellington
d119051ef75d5a88d28c13fb0a7c6d6757a4e9b5Brian Wellington /*
d119051ef75d5a88d28c13fb0a7c6d6757a4e9b5Brian Wellington * Without this, we run into problems reading a configuration file
d119051ef75d5a88d28c13fb0a7c6d6757a4e9b5Brian Wellington * owned by a non-root user and non-world-readable on startup.
d119051ef75d5a88d28c13fb0a7c6d6757a4e9b5Brian Wellington */
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt SET_CAP(CAP_DAC_READ_SEARCH);
d119051ef75d5a88d28c13fb0a7c6d6757a4e9b5Brian Wellington
5e4b7294d88ab58371d8c98e05ea80086dcb67cdBob Halley /*
5e4b7294d88ab58371d8c98e05ea80086dcb67cdBob Halley * XXX We might want to add CAP_SYS_RESOURCE, though it's not
5e4b7294d88ab58371d8c98e05ea80086dcb67cdBob Halley * clear it would work right given the way linuxthreads work.
108490a7f8529aff50a0ac7897580b59a73d9845David Lawrence * XXXDCL But since we need to be able to set the maximum number
108490a7f8529aff50a0ac7897580b59a73d9845David Lawrence * of files, the stack size, data size, and core dump size to
108490a7f8529aff50a0ac7897580b59a73d9845David Lawrence * support named.conf options, this is now being added to test.
5e4b7294d88ab58371d8c98e05ea80086dcb67cdBob Halley */
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt SET_CAP(CAP_SYS_RESOURCE);
134ba0e08a0ae9a564a8d8628fc633377d3fc239Bob Halley
a4463732ad7935992a101b3d19f0a41120b85458Mark Andrews /*
a4463732ad7935992a101b3d19f0a41120b85458Mark Andrews * We need to be able to set the ownership of the containing
a4463732ad7935992a101b3d19f0a41120b85458Mark Andrews * directory of the pid file when we create it.
a4463732ad7935992a101b3d19f0a41120b85458Mark Andrews */
a4463732ad7935992a101b3d19f0a41120b85458Mark Andrews SET_CAP(CAP_CHOWN);
a4463732ad7935992a101b3d19f0a41120b85458Mark Andrews
2dfd6bca9aa6d9279b4278d6fa18ea5f63ba0ec9Bob Halley linux_setcaps(caps);
ef4eed2a2a8897bd4e5b19dd94f638e0861ebda5Mark Andrews
ef4eed2a2a8897bd4e5b19dd94f638e0861ebda5Mark Andrews#ifdef HAVE_LIBCAP
ef4eed2a2a8897bd4e5b19dd94f638e0861ebda5Mark Andrews FREE_CAP;
ef4eed2a2a8897bd4e5b19dd94f638e0861ebda5Mark Andrews#endif
2dfd6bca9aa6d9279b4278d6fa18ea5f63ba0ec9Bob Halley}
2dfd6bca9aa6d9279b4278d6fa18ea5f63ba0ec9Bob Halley
2dfd6bca9aa6d9279b4278d6fa18ea5f63ba0ec9Bob Halleystatic void
2dfd6bca9aa6d9279b4278d6fa18ea5f63ba0ec9Bob Halleylinux_minprivs(void) {
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt cap_t caps;
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt#ifdef HAVE_LIBCAP
ef4eed2a2a8897bd4e5b19dd94f638e0861ebda5Mark Andrews cap_t curcaps;
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt cap_value_t capval;
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt char strbuf[ISC_STRERRORSIZE];
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt int err;
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt#endif
2dfd6bca9aa6d9279b4278d6fa18ea5f63ba0ec9Bob Halley
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt INIT_CAP;
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein /*%
134ba0e08a0ae9a564a8d8628fc633377d3fc239Bob Halley * Drop all privileges except the ability to bind() to privileged
5e4b7294d88ab58371d8c98e05ea80086dcb67cdBob Halley * ports.
134ba0e08a0ae9a564a8d8628fc633377d3fc239Bob Halley *
134ba0e08a0ae9a564a8d8628fc633377d3fc239Bob Halley * It's important that we drop CAP_SYS_CHROOT. If we didn't, it
134ba0e08a0ae9a564a8d8628fc633377d3fc239Bob Halley * chroot() could be used to escape from the chrooted area.
2dfd6bca9aa6d9279b4278d6fa18ea5f63ba0ec9Bob Halley */
2dfd6bca9aa6d9279b4278d6fa18ea5f63ba0ec9Bob Halley
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt SET_CAP(CAP_NET_BIND_SERVICE);
2dfd6bca9aa6d9279b4278d6fa18ea5f63ba0ec9Bob Halley
8fd925169f3d690f6c50c17d711adc9695407528Mark Andrews /*
8fd925169f3d690f6c50c17d711adc9695407528Mark Andrews * XXX We might want to add CAP_SYS_RESOURCE, though it's not
8fd925169f3d690f6c50c17d711adc9695407528Mark Andrews * clear it would work right given the way linuxthreads work.
8fd925169f3d690f6c50c17d711adc9695407528Mark Andrews * XXXDCL But since we need to be able to set the maximum number
8fd925169f3d690f6c50c17d711adc9695407528Mark Andrews * of files, the stack size, data size, and core dump size to
8fd925169f3d690f6c50c17d711adc9695407528Mark Andrews * support named.conf options, this is now being added to test.
8fd925169f3d690f6c50c17d711adc9695407528Mark Andrews */
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt SET_CAP(CAP_SYS_RESOURCE);
8fd925169f3d690f6c50c17d711adc9695407528Mark Andrews
2dfd6bca9aa6d9279b4278d6fa18ea5f63ba0ec9Bob Halley linux_setcaps(caps);
ef4eed2a2a8897bd4e5b19dd94f638e0861ebda5Mark Andrews
ef4eed2a2a8897bd4e5b19dd94f638e0861ebda5Mark Andrews#ifdef HAVE_LIBCAP
ef4eed2a2a8897bd4e5b19dd94f638e0861ebda5Mark Andrews FREE_CAP;
ef4eed2a2a8897bd4e5b19dd94f638e0861ebda5Mark Andrews#endif
2dfd6bca9aa6d9279b4278d6fa18ea5f63ba0ec9Bob Halley}
2dfd6bca9aa6d9279b4278d6fa18ea5f63ba0ec9Bob Halley
f8727bd90366af835f551da1b5e1fdfcd2d3d01fBrian Wellington#ifdef HAVE_SYS_PRCTL_H
134ba0e08a0ae9a564a8d8628fc633377d3fc239Bob Halleystatic void
134ba0e08a0ae9a564a8d8628fc633377d3fc239Bob Halleylinux_keepcaps(void) {
4b87939256ede703385e9cab92d3c58d03c31098Mark Andrews char strbuf[ISC_STRERRORSIZE];
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein /*%
134ba0e08a0ae9a564a8d8628fc633377d3fc239Bob Halley * Ask the kernel to allow us to keep our capabilities after we
134ba0e08a0ae9a564a8d8628fc633377d3fc239Bob Halley * setuid().
134ba0e08a0ae9a564a8d8628fc633377d3fc239Bob Halley */
134ba0e08a0ae9a564a8d8628fc633377d3fc239Bob Halley
134ba0e08a0ae9a564a8d8628fc633377d3fc239Bob Halley if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) < 0) {
4b87939256ede703385e9cab92d3c58d03c31098Mark Andrews if (errno != EINVAL) {
4b87939256ede703385e9cab92d3c58d03c31098Mark Andrews isc__strerror(errno, strbuf, sizeof(strbuf));
4b87939256ede703385e9cab92d3c58d03c31098Mark Andrews ns_main_earlyfatal("prctl() failed: %s", strbuf);
4b87939256ede703385e9cab92d3c58d03c31098Mark Andrews }
77771185071bf74d53378f1a3099a04d2af5153eBrian Wellington } else {
134ba0e08a0ae9a564a8d8628fc633377d3fc239Bob Halley non_root_caps = ISC_TRUE;
77771185071bf74d53378f1a3099a04d2af5153eBrian Wellington if (getuid() != 0)
77771185071bf74d53378f1a3099a04d2af5153eBrian Wellington non_root = ISC_TRUE;
77771185071bf74d53378f1a3099a04d2af5153eBrian Wellington }
134ba0e08a0ae9a564a8d8628fc633377d3fc239Bob Halley}
134ba0e08a0ae9a564a8d8628fc633377d3fc239Bob Halley#endif
134ba0e08a0ae9a564a8d8628fc633377d3fc239Bob Halley
2dfd6bca9aa6d9279b4278d6fa18ea5f63ba0ec9Bob Halley#endif /* HAVE_LINUX_CAPABILITY_H */
2dfd6bca9aa6d9279b4278d6fa18ea5f63ba0ec9Bob Halley
9b2267b5ba9d0640512a41e139a4a36caa43730dBob Halley
1fc4929aa610263a2362afed516d7dc8e689397dBob Halleystatic void
663841abe0bb1cc8040e552597ef721c35b799e5Brian Wellingtonsetup_syslog(const char *progname) {
1fc4929aa610263a2362afed516d7dc8e689397dBob Halley int options;
1fc4929aa610263a2362afed516d7dc8e689397dBob Halley
1fc4929aa610263a2362afed516d7dc8e689397dBob Halley options = LOG_PID;
1fc4929aa610263a2362afed516d7dc8e689397dBob Halley#ifdef LOG_NDELAY
1fc4929aa610263a2362afed516d7dc8e689397dBob Halley options |= LOG_NDELAY;
1fc4929aa610263a2362afed516d7dc8e689397dBob Halley#endif
ee80f4506479e189ca1320eb87ac89188c5a7848Mark Andrews openlog(isc_file_basename(progname), options, ISC_FACILITY);
1fc4929aa610263a2362afed516d7dc8e689397dBob Halley}
9b2267b5ba9d0640512a41e139a4a36caa43730dBob Halley
2dfd6bca9aa6d9279b4278d6fa18ea5f63ba0ec9Bob Halleyvoid
663841abe0bb1cc8040e552597ef721c35b799e5Brian Wellingtonns_os_init(const char *progname) {
663841abe0bb1cc8040e552597ef721c35b799e5Brian Wellington setup_syslog(progname);
9b2267b5ba9d0640512a41e139a4a36caa43730dBob Halley#ifdef HAVE_LINUX_CAPABILITY_H
2dfd6bca9aa6d9279b4278d6fa18ea5f63ba0ec9Bob Halley linux_initialprivs();
9b2267b5ba9d0640512a41e139a4a36caa43730dBob Halley#endif
9ee5efde7df57cbe70fb9b32c9d898e8ef7eca1eBob Halley#ifdef HAVE_LINUXTHREADS
9ee5efde7df57cbe70fb9b32c9d898e8ef7eca1eBob Halley mainpid = getpid();
9ee5efde7df57cbe70fb9b32c9d898e8ef7eca1eBob Halley#endif
90c4900d5cf1a1b556ae4c1de6338b2e7475ee55Mark Andrews#ifdef SIGXFSZ
90c4900d5cf1a1b556ae4c1de6338b2e7475ee55Mark Andrews signal(SIGXFSZ, SIG_IGN);
90c4900d5cf1a1b556ae4c1de6338b2e7475ee55Mark Andrews#endif
9b2267b5ba9d0640512a41e139a4a36caa43730dBob Halley}
9b2267b5ba9d0640512a41e139a4a36caa43730dBob Halley
2dfd6bca9aa6d9279b4278d6fa18ea5f63ba0ec9Bob Halleyvoid
2aa67e804d85f4d88153368ce65ce4df7b5390e6Bob Halleyns_os_daemonize(void) {
2aa67e804d85f4d88153368ce65ce4df7b5390e6Bob Halley pid_t pid;
4b87939256ede703385e9cab92d3c58d03c31098Mark Andrews char strbuf[ISC_STRERRORSIZE];
2aa67e804d85f4d88153368ce65ce4df7b5390e6Bob Halley
2c329da87c5c886e7f4468c69a9e6323121068cbMark Andrews if (pipe(dfd) == -1) {
2c329da87c5c886e7f4468c69a9e6323121068cbMark Andrews isc__strerror(errno, strbuf, sizeof(strbuf));
2c329da87c5c886e7f4468c69a9e6323121068cbMark Andrews ns_main_earlyfatal("pipe(): %s", strbuf);
2c329da87c5c886e7f4468c69a9e6323121068cbMark Andrews }
2c329da87c5c886e7f4468c69a9e6323121068cbMark Andrews
2aa67e804d85f4d88153368ce65ce4df7b5390e6Bob Halley pid = fork();
4b87939256ede703385e9cab92d3c58d03c31098Mark Andrews if (pid == -1) {
4b87939256ede703385e9cab92d3c58d03c31098Mark Andrews isc__strerror(errno, strbuf, sizeof(strbuf));
4b87939256ede703385e9cab92d3c58d03c31098Mark Andrews ns_main_earlyfatal("fork(): %s", strbuf);
4b87939256ede703385e9cab92d3c58d03c31098Mark Andrews }
2c329da87c5c886e7f4468c69a9e6323121068cbMark Andrews if (pid != 0) {
2c329da87c5c886e7f4468c69a9e6323121068cbMark Andrews int n;
2c329da87c5c886e7f4468c69a9e6323121068cbMark Andrews /*
2c329da87c5c886e7f4468c69a9e6323121068cbMark Andrews * Wait for the child to finish loading for the first time.
2c329da87c5c886e7f4468c69a9e6323121068cbMark Andrews * This would be so much simpler if fork() worked once we
2f012d936b5ccdf6520c96a4de23721dc58a2221Automatic Updater * were multi-threaded.
2c329da87c5c886e7f4468c69a9e6323121068cbMark Andrews */
2c329da87c5c886e7f4468c69a9e6323121068cbMark Andrews (void)close(dfd[1]);
2c329da87c5c886e7f4468c69a9e6323121068cbMark Andrews do {
2c329da87c5c886e7f4468c69a9e6323121068cbMark Andrews char buf;
2c329da87c5c886e7f4468c69a9e6323121068cbMark Andrews n = read(dfd[0], &buf, 1);
2c329da87c5c886e7f4468c69a9e6323121068cbMark Andrews if (n == 1)
2c329da87c5c886e7f4468c69a9e6323121068cbMark Andrews _exit(0);
2c329da87c5c886e7f4468c69a9e6323121068cbMark Andrews } while (n == -1 && errno == EINTR);
2c329da87c5c886e7f4468c69a9e6323121068cbMark Andrews _exit(1);
2c329da87c5c886e7f4468c69a9e6323121068cbMark Andrews }
2c329da87c5c886e7f4468c69a9e6323121068cbMark Andrews (void)close(dfd[0]);
2aa67e804d85f4d88153368ce65ce4df7b5390e6Bob Halley
2aa67e804d85f4d88153368ce65ce4df7b5390e6Bob Halley /*
2aa67e804d85f4d88153368ce65ce4df7b5390e6Bob Halley * We're the child.
2aa67e804d85f4d88153368ce65ce4df7b5390e6Bob Halley */
2aa67e804d85f4d88153368ce65ce4df7b5390e6Bob Halley
9ee5efde7df57cbe70fb9b32c9d898e8ef7eca1eBob Halley#ifdef HAVE_LINUXTHREADS
9ee5efde7df57cbe70fb9b32c9d898e8ef7eca1eBob Halley mainpid = getpid();
9ee5efde7df57cbe70fb9b32c9d898e8ef7eca1eBob Halley#endif
9ee5efde7df57cbe70fb9b32c9d898e8ef7eca1eBob Halley
5d98cf67b32d785aca1a72ea1dc4d559fab39208Mark Andrews if (setsid() == -1) {
4b87939256ede703385e9cab92d3c58d03c31098Mark Andrews isc__strerror(errno, strbuf, sizeof(strbuf));
4b87939256ede703385e9cab92d3c58d03c31098Mark Andrews ns_main_earlyfatal("setsid(): %s", strbuf);
4b87939256ede703385e9cab92d3c58d03c31098Mark Andrews }
2aa67e804d85f4d88153368ce65ce4df7b5390e6Bob Halley
2aa67e804d85f4d88153368ce65ce4df7b5390e6Bob Halley /*
2aa67e804d85f4d88153368ce65ce4df7b5390e6Bob Halley * Try to set stdin, stdout, and stderr to /dev/null, but press
2aa67e804d85f4d88153368ce65ce4df7b5390e6Bob Halley * on even if it fails.
15197aefa1659e98ea1c48e2cbae631136a072b7Michael Graff *
15197aefa1659e98ea1c48e2cbae631136a072b7Michael Graff * XXXMLG The close() calls here are unneeded on all but NetBSD, but
15197aefa1659e98ea1c48e2cbae631136a072b7Michael Graff * are harmless to include everywhere. dup2() is supposed to close
15197aefa1659e98ea1c48e2cbae631136a072b7Michael Graff * the FD if it is in use, but unproven-pthreads-0.16 is broken
15197aefa1659e98ea1c48e2cbae631136a072b7Michael Graff * and will end up closing the wrong FD. This will be fixed eventually,
15197aefa1659e98ea1c48e2cbae631136a072b7Michael Graff * and these calls will be removed.
2aa67e804d85f4d88153368ce65ce4df7b5390e6Bob Halley */
c52ae25dd70636c673d4a299859137a1c8ba611aMark Andrews if (devnullfd != -1) {
c52ae25dd70636c673d4a299859137a1c8ba611aMark Andrews if (devnullfd != STDIN_FILENO) {
c52ae25dd70636c673d4a299859137a1c8ba611aMark Andrews (void)close(STDIN_FILENO);
c52ae25dd70636c673d4a299859137a1c8ba611aMark Andrews (void)dup2(devnullfd, STDIN_FILENO);
c52ae25dd70636c673d4a299859137a1c8ba611aMark Andrews }
c52ae25dd70636c673d4a299859137a1c8ba611aMark Andrews if (devnullfd != STDOUT_FILENO) {
c52ae25dd70636c673d4a299859137a1c8ba611aMark Andrews (void)close(STDOUT_FILENO);
c52ae25dd70636c673d4a299859137a1c8ba611aMark Andrews (void)dup2(devnullfd, STDOUT_FILENO);
c52ae25dd70636c673d4a299859137a1c8ba611aMark Andrews }
52254f75267c734acf1f1fb982b6a3be05e93507Mark Andrews if (devnullfd != STDERR_FILENO && !ns_g_keepstderr) {
c52ae25dd70636c673d4a299859137a1c8ba611aMark Andrews (void)close(STDERR_FILENO);
c52ae25dd70636c673d4a299859137a1c8ba611aMark Andrews (void)dup2(devnullfd, STDERR_FILENO);
c52ae25dd70636c673d4a299859137a1c8ba611aMark Andrews }
c52ae25dd70636c673d4a299859137a1c8ba611aMark Andrews }
c52ae25dd70636c673d4a299859137a1c8ba611aMark Andrews}
c52ae25dd70636c673d4a299859137a1c8ba611aMark Andrews
2c329da87c5c886e7f4468c69a9e6323121068cbMark Andrewsvoid
2c329da87c5c886e7f4468c69a9e6323121068cbMark Andrewsns_os_started(void) {
2c329da87c5c886e7f4468c69a9e6323121068cbMark Andrews char buf = 0;
2c329da87c5c886e7f4468c69a9e6323121068cbMark Andrews
2c329da87c5c886e7f4468c69a9e6323121068cbMark Andrews /*
dfa3ca995c99e66ab56e98da79e386bcdb23c43aMark Andrews * Signal to the parent that we started successfully.
2c329da87c5c886e7f4468c69a9e6323121068cbMark Andrews */
2c329da87c5c886e7f4468c69a9e6323121068cbMark Andrews if (dfd[0] != -1 && dfd[1] != -1) {
dfa3ca995c99e66ab56e98da79e386bcdb23c43aMark Andrews if (write(dfd[1], &buf, 1) != 1)
dfa3ca995c99e66ab56e98da79e386bcdb23c43aMark Andrews ns_main_earlyfatal("unable to signal parent that we "
dfa3ca995c99e66ab56e98da79e386bcdb23c43aMark Andrews "otherwise started successfully.");
2c329da87c5c886e7f4468c69a9e6323121068cbMark Andrews close(dfd[1]);
2c329da87c5c886e7f4468c69a9e6323121068cbMark Andrews dfd[0] = dfd[1] = -1;
2c329da87c5c886e7f4468c69a9e6323121068cbMark Andrews }
2c329da87c5c886e7f4468c69a9e6323121068cbMark Andrews}
2c329da87c5c886e7f4468c69a9e6323121068cbMark Andrews
c52ae25dd70636c673d4a299859137a1c8ba611aMark Andrewsvoid
c52ae25dd70636c673d4a299859137a1c8ba611aMark Andrewsns_os_opendevnull(void) {
c52ae25dd70636c673d4a299859137a1c8ba611aMark Andrews devnullfd = open("/dev/null", O_RDWR, 0);
c52ae25dd70636c673d4a299859137a1c8ba611aMark Andrews}
c52ae25dd70636c673d4a299859137a1c8ba611aMark Andrews
c52ae25dd70636c673d4a299859137a1c8ba611aMark Andrewsvoid
c52ae25dd70636c673d4a299859137a1c8ba611aMark Andrewsns_os_closedevnull(void) {
c52ae25dd70636c673d4a299859137a1c8ba611aMark Andrews if (devnullfd != STDIN_FILENO &&
c52ae25dd70636c673d4a299859137a1c8ba611aMark Andrews devnullfd != STDOUT_FILENO &&
c52ae25dd70636c673d4a299859137a1c8ba611aMark Andrews devnullfd != STDERR_FILENO) {
c52ae25dd70636c673d4a299859137a1c8ba611aMark Andrews close(devnullfd);
c52ae25dd70636c673d4a299859137a1c8ba611aMark Andrews devnullfd = -1;
2aa67e804d85f4d88153368ce65ce4df7b5390e6Bob Halley }
2aa67e804d85f4d88153368ce65ce4df7b5390e6Bob Halley}
2aa67e804d85f4d88153368ce65ce4df7b5390e6Bob Halley
2dfd6bca9aa6d9279b4278d6fa18ea5f63ba0ec9Bob Halleystatic isc_boolean_t
2dfd6bca9aa6d9279b4278d6fa18ea5f63ba0ec9Bob Halleyall_digits(const char *s) {
2dfd6bca9aa6d9279b4278d6fa18ea5f63ba0ec9Bob Halley if (*s == '\0')
2dfd6bca9aa6d9279b4278d6fa18ea5f63ba0ec9Bob Halley return (ISC_FALSE);
2dfd6bca9aa6d9279b4278d6fa18ea5f63ba0ec9Bob Halley while (*s != '\0') {
e63f7c6f556aef66ff81fb128605f9eadf1ddcd9Mark Andrews if (!isdigit((*s)&0xff))
2dfd6bca9aa6d9279b4278d6fa18ea5f63ba0ec9Bob Halley return (ISC_FALSE);
2dfd6bca9aa6d9279b4278d6fa18ea5f63ba0ec9Bob Halley s++;
2dfd6bca9aa6d9279b4278d6fa18ea5f63ba0ec9Bob Halley }
2dfd6bca9aa6d9279b4278d6fa18ea5f63ba0ec9Bob Halley return (ISC_TRUE);
2dfd6bca9aa6d9279b4278d6fa18ea5f63ba0ec9Bob Halley}
2dfd6bca9aa6d9279b4278d6fa18ea5f63ba0ec9Bob Halley
2dfd6bca9aa6d9279b4278d6fa18ea5f63ba0ec9Bob Halleyvoid
2dfd6bca9aa6d9279b4278d6fa18ea5f63ba0ec9Bob Halleyns_os_chroot(const char *root) {
4b87939256ede703385e9cab92d3c58d03c31098Mark Andrews char strbuf[ISC_STRERRORSIZE];
f754fa97bc698cc251d227173a95e4d39a88ac01Mark Andrews#ifdef HAVE_LIBSCF
f754fa97bc698cc251d227173a95e4d39a88ac01Mark Andrews ns_smf_chroot = 0;
f754fa97bc698cc251d227173a95e4d39a88ac01Mark Andrews#endif
2dfd6bca9aa6d9279b4278d6fa18ea5f63ba0ec9Bob Halley if (root != NULL) {
9935447b51456f598b45246d0114b8006049244dMark Andrews#ifdef HAVE_CHROOT
4b87939256ede703385e9cab92d3c58d03c31098Mark Andrews if (chroot(root) < 0) {
4b87939256ede703385e9cab92d3c58d03c31098Mark Andrews isc__strerror(errno, strbuf, sizeof(strbuf));
4b87939256ede703385e9cab92d3c58d03c31098Mark Andrews ns_main_earlyfatal("chroot(): %s", strbuf);
4b87939256ede703385e9cab92d3c58d03c31098Mark Andrews }
9935447b51456f598b45246d0114b8006049244dMark Andrews#else
9935447b51456f598b45246d0114b8006049244dMark Andrews ns_main_earlyfatal("chroot(): disabled");
9935447b51456f598b45246d0114b8006049244dMark Andrews#endif
4b87939256ede703385e9cab92d3c58d03c31098Mark Andrews if (chdir("/") < 0) {
4b87939256ede703385e9cab92d3c58d03c31098Mark Andrews isc__strerror(errno, strbuf, sizeof(strbuf));
4b87939256ede703385e9cab92d3c58d03c31098Mark Andrews ns_main_earlyfatal("chdir(/): %s", strbuf);
4b87939256ede703385e9cab92d3c58d03c31098Mark Andrews }
f754fa97bc698cc251d227173a95e4d39a88ac01Mark Andrews#ifdef HAVE_LIBSCF
f754fa97bc698cc251d227173a95e4d39a88ac01Mark Andrews /* Set ns_smf_chroot flag on successful chroot. */
f754fa97bc698cc251d227173a95e4d39a88ac01Mark Andrews ns_smf_chroot = 1;
f754fa97bc698cc251d227173a95e4d39a88ac01Mark Andrews#endif
2dfd6bca9aa6d9279b4278d6fa18ea5f63ba0ec9Bob Halley }
2dfd6bca9aa6d9279b4278d6fa18ea5f63ba0ec9Bob Halley}
2dfd6bca9aa6d9279b4278d6fa18ea5f63ba0ec9Bob Halley
2dfd6bca9aa6d9279b4278d6fa18ea5f63ba0ec9Bob Halleyvoid
202991557a4b7e8d3df7725d84f0fcae90dbaee6David Lawrencens_os_inituserinfo(const char *username) {
4b87939256ede703385e9cab92d3c58d03c31098Mark Andrews char strbuf[ISC_STRERRORSIZE];
c336121fb5a5c1b9cb9b2cd4cea50f0788270505Brian Wellington if (username == NULL)
2dfd6bca9aa6d9279b4278d6fa18ea5f63ba0ec9Bob Halley return;
2dfd6bca9aa6d9279b4278d6fa18ea5f63ba0ec9Bob Halley
2dfd6bca9aa6d9279b4278d6fa18ea5f63ba0ec9Bob Halley if (all_digits(username))
4e5388b45908ce8b8b35825ca6f16c1d236643baBrian Wellington runas_pw = getpwuid((uid_t)atoi(username));
2dfd6bca9aa6d9279b4278d6fa18ea5f63ba0ec9Bob Halley else
4e5388b45908ce8b8b35825ca6f16c1d236643baBrian Wellington runas_pw = getpwnam(username);
2dfd6bca9aa6d9279b4278d6fa18ea5f63ba0ec9Bob Halley endpwent();
202991557a4b7e8d3df7725d84f0fcae90dbaee6David Lawrence
4e5388b45908ce8b8b35825ca6f16c1d236643baBrian Wellington if (runas_pw == NULL)
2dfd6bca9aa6d9279b4278d6fa18ea5f63ba0ec9Bob Halley ns_main_earlyfatal("user '%s' unknown", username);
71954c957132c35ddf5f9e4dcc98c057b265b6d8Brian Wellington
71954c957132c35ddf5f9e4dcc98c057b265b6d8Brian Wellington if (getuid() == 0) {
4b87939256ede703385e9cab92d3c58d03c31098Mark Andrews if (initgroups(runas_pw->pw_name, runas_pw->pw_gid) < 0) {
4b87939256ede703385e9cab92d3c58d03c31098Mark Andrews isc__strerror(errno, strbuf, sizeof(strbuf));
4b87939256ede703385e9cab92d3c58d03c31098Mark Andrews ns_main_earlyfatal("initgroups(): %s", strbuf);
4b87939256ede703385e9cab92d3c58d03c31098Mark Andrews }
71954c957132c35ddf5f9e4dcc98c057b265b6d8Brian Wellington }
71954c957132c35ddf5f9e4dcc98c057b265b6d8Brian Wellington
202991557a4b7e8d3df7725d84f0fcae90dbaee6David Lawrence}
202991557a4b7e8d3df7725d84f0fcae90dbaee6David Lawrence
202991557a4b7e8d3df7725d84f0fcae90dbaee6David Lawrencevoid
202991557a4b7e8d3df7725d84f0fcae90dbaee6David Lawrencens_os_changeuser(void) {
4b87939256ede703385e9cab92d3c58d03c31098Mark Andrews char strbuf[ISC_STRERRORSIZE];
c336121fb5a5c1b9cb9b2cd4cea50f0788270505Brian Wellington if (runas_pw == NULL || done_setuid)
c6ab6ca3fd5f0bca400aac931f616722bbb19109Andreas Gustafsson return;
c6ab6ca3fd5f0bca400aac931f616722bbb19109Andreas Gustafsson
c336121fb5a5c1b9cb9b2cd4cea50f0788270505Brian Wellington done_setuid = ISC_TRUE;
c336121fb5a5c1b9cb9b2cd4cea50f0788270505Brian Wellington
c6ab6ca3fd5f0bca400aac931f616722bbb19109Andreas Gustafsson#ifdef HAVE_LINUXTHREADS
51e0ad287f1b345f0c3316f0633aab14d0e8bb65Brian Wellington#ifdef HAVE_LINUX_CAPABILITY_H
c6ab6ca3fd5f0bca400aac931f616722bbb19109Andreas Gustafsson if (!non_root_caps)
31a71adf14d106260127079f6ea26bea600163e9Mark Andrews ns_main_earlyfatal("-u with Linux threads not supported: "
31a71adf14d106260127079f6ea26bea600163e9Mark Andrews "requires kernel support for "
31a71adf14d106260127079f6ea26bea600163e9Mark Andrews "prctl(PR_SET_KEEPCAPS)");
31a71adf14d106260127079f6ea26bea600163e9Mark Andrews#else
31a71adf14d106260127079f6ea26bea600163e9Mark Andrews ns_main_earlyfatal("-u with Linux threads not supported: "
31a71adf14d106260127079f6ea26bea600163e9Mark Andrews "no capabilities support or capabilities "
31a71adf14d106260127079f6ea26bea600163e9Mark Andrews "disabled at build time");
51e0ad287f1b345f0c3316f0633aab14d0e8bb65Brian Wellington#endif
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence#endif
c6ab6ca3fd5f0bca400aac931f616722bbb19109Andreas Gustafsson
4b87939256ede703385e9cab92d3c58d03c31098Mark Andrews if (setgid(runas_pw->pw_gid) < 0) {
4b87939256ede703385e9cab92d3c58d03c31098Mark Andrews isc__strerror(errno, strbuf, sizeof(strbuf));
4b87939256ede703385e9cab92d3c58d03c31098Mark Andrews ns_main_earlyfatal("setgid(): %s", strbuf);
4b87939256ede703385e9cab92d3c58d03c31098Mark Andrews }
4e5388b45908ce8b8b35825ca6f16c1d236643baBrian Wellington
4b87939256ede703385e9cab92d3c58d03c31098Mark Andrews if (setuid(runas_pw->pw_uid) < 0) {
4b87939256ede703385e9cab92d3c58d03c31098Mark Andrews isc__strerror(errno, strbuf, sizeof(strbuf));
4b87939256ede703385e9cab92d3c58d03c31098Mark Andrews ns_main_earlyfatal("setuid(): %s", strbuf);
4b87939256ede703385e9cab92d3c58d03c31098Mark Andrews }
51e0ad287f1b345f0c3316f0633aab14d0e8bb65Brian Wellington
d53520b78d4a8726396efdbaa71f86f687a6f308Mark Andrews#if defined(HAVE_SYS_PRCTL_H) && defined(PR_SET_DUMPABLE)
d53520b78d4a8726396efdbaa71f86f687a6f308Mark Andrews /*
d53520b78d4a8726396efdbaa71f86f687a6f308Mark Andrews * Restore the ability of named to drop core after the setuid()
d53520b78d4a8726396efdbaa71f86f687a6f308Mark Andrews * call has disabled it.
d53520b78d4a8726396efdbaa71f86f687a6f308Mark Andrews */
f61a7c87bf36b189d8f04ea4c8ab3ec55778355cMark Andrews if (prctl(PR_SET_DUMPABLE,1,0,0,0) < 0) {
f61a7c87bf36b189d8f04ea4c8ab3ec55778355cMark Andrews isc__strerror(errno, strbuf, sizeof(strbuf));
f61a7c87bf36b189d8f04ea4c8ab3ec55778355cMark Andrews ns_main_earlywarning("prctl(PR_SET_DUMPABLE) failed: %s",
f61a7c87bf36b189d8f04ea4c8ab3ec55778355cMark Andrews strbuf);
f61a7c87bf36b189d8f04ea4c8ab3ec55778355cMark Andrews }
f61a7c87bf36b189d8f04ea4c8ab3ec55778355cMark Andrews#endif
f61a7c87bf36b189d8f04ea4c8ab3ec55778355cMark Andrews#if defined(HAVE_LINUX_CAPABILITY_H) && !defined(HAVE_LINUXTHREADS)
f61a7c87bf36b189d8f04ea4c8ab3ec55778355cMark Andrews linux_minprivs();
d53520b78d4a8726396efdbaa71f86f687a6f308Mark Andrews#endif
2dfd6bca9aa6d9279b4278d6fa18ea5f63ba0ec9Bob Halley}
9ee5efde7df57cbe70fb9b32c9d898e8ef7eca1eBob Halley
214b53880b6d77359f60feccb91bd2589059300aEvan Huntuid_t
214b53880b6d77359f60feccb91bd2589059300aEvan Huntns_os_uid(void) {
214b53880b6d77359f60feccb91bd2589059300aEvan Hunt if (runas_pw == NULL)
214b53880b6d77359f60feccb91bd2589059300aEvan Hunt return (0);
214b53880b6d77359f60feccb91bd2589059300aEvan Hunt return (runas_pw->pw_uid);
214b53880b6d77359f60feccb91bd2589059300aEvan Hunt}
214b53880b6d77359f60feccb91bd2589059300aEvan Hunt
6d54a6fc180acaf8772c9447cb925b31f39c7158Mark Andrewsvoid
b454c0319685041db3f3e8fd7671e1b364fd20c5Evan Huntns_os_adjustnofile(void) {
6d54a6fc180acaf8772c9447cb925b31f39c7158Mark Andrews#ifdef HAVE_LINUXTHREADS
6d54a6fc180acaf8772c9447cb925b31f39c7158Mark Andrews isc_result_t result;
6d54a6fc180acaf8772c9447cb925b31f39c7158Mark Andrews isc_resourcevalue_t newvalue;
6d54a6fc180acaf8772c9447cb925b31f39c7158Mark Andrews
6d54a6fc180acaf8772c9447cb925b31f39c7158Mark Andrews /*
6d54a6fc180acaf8772c9447cb925b31f39c7158Mark Andrews * Linux: max number of open files specified by one thread doesn't seem
6d54a6fc180acaf8772c9447cb925b31f39c7158Mark Andrews * to apply to other threads on Linux.
6d54a6fc180acaf8772c9447cb925b31f39c7158Mark Andrews */
6d54a6fc180acaf8772c9447cb925b31f39c7158Mark Andrews newvalue = ISC_RESOURCE_UNLIMITED;
6d54a6fc180acaf8772c9447cb925b31f39c7158Mark Andrews
6d54a6fc180acaf8772c9447cb925b31f39c7158Mark Andrews result = isc_resource_setlimit(isc_resource_openfiles, newvalue);
6d54a6fc180acaf8772c9447cb925b31f39c7158Mark Andrews if (result != ISC_R_SUCCESS)
6d54a6fc180acaf8772c9447cb925b31f39c7158Mark Andrews ns_main_earlywarning("couldn't adjust limit on open files");
be40453080750077f1161c70f03c5f6921a27961Automatic Updater#endif
6d54a6fc180acaf8772c9447cb925b31f39c7158Mark Andrews}
6d54a6fc180acaf8772c9447cb925b31f39c7158Mark Andrews
134ba0e08a0ae9a564a8d8628fc633377d3fc239Bob Halleyvoid
202991557a4b7e8d3df7725d84f0fcae90dbaee6David Lawrencens_os_minprivs(void) {
f8727bd90366af835f551da1b5e1fdfcd2d3d01fBrian Wellington#ifdef HAVE_SYS_PRCTL_H
c6ab6ca3fd5f0bca400aac931f616722bbb19109Andreas Gustafsson linux_keepcaps();
134ba0e08a0ae9a564a8d8628fc633377d3fc239Bob Halley#endif
202991557a4b7e8d3df7725d84f0fcae90dbaee6David Lawrence
51e0ad287f1b345f0c3316f0633aab14d0e8bb65Brian Wellington#ifdef HAVE_LINUXTHREADS
51e0ad287f1b345f0c3316f0633aab14d0e8bb65Brian Wellington ns_os_changeuser(); /* Call setuid() before threads are started */
51e0ad287f1b345f0c3316f0633aab14d0e8bb65Brian Wellington#endif
202991557a4b7e8d3df7725d84f0fcae90dbaee6David Lawrence
51e0ad287f1b345f0c3316f0633aab14d0e8bb65Brian Wellington#if defined(HAVE_LINUX_CAPABILITY_H) && defined(HAVE_LINUXTHREADS)
51e0ad287f1b345f0c3316f0633aab14d0e8bb65Brian Wellington linux_minprivs();
51e0ad287f1b345f0c3316f0633aab14d0e8bb65Brian Wellington#endif
134ba0e08a0ae9a564a8d8628fc633377d3fc239Bob Halley}
134ba0e08a0ae9a564a8d8628fc633377d3fc239Bob Halley
9ee5efde7df57cbe70fb9b32c9d898e8ef7eca1eBob Halleystatic int
3a875400473e5c06199272a1292ed84646990e2fEvan Huntsafe_open(const char *filename, mode_t mode, isc_boolean_t append) {
a3a11c4f3fc9ba972802b811c4d95a9884d6ff4aMichael Sawyer int fd;
5d98cf67b32d785aca1a72ea1dc4d559fab39208Mark Andrews struct stat sb;
9ee5efde7df57cbe70fb9b32c9d898e8ef7eca1eBob Halley
5d98cf67b32d785aca1a72ea1dc4d559fab39208Mark Andrews if (stat(filename, &sb) == -1) {
5d98cf67b32d785aca1a72ea1dc4d559fab39208Mark Andrews if (errno != ENOENT)
9ee5efde7df57cbe70fb9b32c9d898e8ef7eca1eBob Halley return (-1);
5d98cf67b32d785aca1a72ea1dc4d559fab39208Mark Andrews } else if ((sb.st_mode & S_IFREG) == 0) {
c9e698df1b2f3731577eaf9598ed3845eac67e1bBrian Wellington errno = EOPNOTSUPP;
9ee5efde7df57cbe70fb9b32c9d898e8ef7eca1eBob Halley return (-1);
c9e698df1b2f3731577eaf9598ed3845eac67e1bBrian Wellington }
9ee5efde7df57cbe70fb9b32c9d898e8ef7eca1eBob Halley
a3a11c4f3fc9ba972802b811c4d95a9884d6ff4aMichael Sawyer if (append)
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt fd = open(filename, O_WRONLY|O_CREAT|O_APPEND, mode);
a3a11c4f3fc9ba972802b811c4d95a9884d6ff4aMichael Sawyer else {
e502b133d630bda0ee64c1e2ce6729d96750d8abMark Andrews if (unlink(filename) < 0 && errno != ENOENT)
e502b133d630bda0ee64c1e2ce6729d96750d8abMark Andrews return (-1);
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt fd = open(filename, O_WRONLY|O_CREAT|O_EXCL, mode);
a3a11c4f3fc9ba972802b811c4d95a9884d6ff4aMichael Sawyer }
a3a11c4f3fc9ba972802b811c4d95a9884d6ff4aMichael Sawyer return (fd);
9ee5efde7df57cbe70fb9b32c9d898e8ef7eca1eBob Halley}
9ee5efde7df57cbe70fb9b32c9d898e8ef7eca1eBob Halley
9ee5efde7df57cbe70fb9b32c9d898e8ef7eca1eBob Halleystatic void
9ee5efde7df57cbe70fb9b32c9d898e8ef7eca1eBob Halleycleanup_pidfile(void) {
e502b133d630bda0ee64c1e2ce6729d96750d8abMark Andrews int n;
a3a11c4f3fc9ba972802b811c4d95a9884d6ff4aMichael Sawyer if (pidfile != NULL) {
e502b133d630bda0ee64c1e2ce6729d96750d8abMark Andrews n = unlink(pidfile);
e502b133d630bda0ee64c1e2ce6729d96750d8abMark Andrews if (n == -1 && errno != ENOENT)
e502b133d630bda0ee64c1e2ce6729d96750d8abMark Andrews ns_main_earlywarning("unlink '%s': failed", pidfile);
a3a11c4f3fc9ba972802b811c4d95a9884d6ff4aMichael Sawyer free(pidfile);
a3a11c4f3fc9ba972802b811c4d95a9884d6ff4aMichael Sawyer }
9ee5efde7df57cbe70fb9b32c9d898e8ef7eca1eBob Halley pidfile = NULL;
9ee5efde7df57cbe70fb9b32c9d898e8ef7eca1eBob Halley}
9ee5efde7df57cbe70fb9b32c9d898e8ef7eca1eBob Halley
7ae96d882326357448f8f440c52f47ac1b1fa455Evan Huntstatic void
7ae96d882326357448f8f440c52f47ac1b1fa455Evan Huntcleanup_lockfile(void) {
7ae96d882326357448f8f440c52f47ac1b1fa455Evan Hunt if (singletonfd != -1) {
7ae96d882326357448f8f440c52f47ac1b1fa455Evan Hunt close(singletonfd);
7ae96d882326357448f8f440c52f47ac1b1fa455Evan Hunt singletonfd = -1;
7ae96d882326357448f8f440c52f47ac1b1fa455Evan Hunt }
7ae96d882326357448f8f440c52f47ac1b1fa455Evan Hunt
7ae96d882326357448f8f440c52f47ac1b1fa455Evan Hunt if (lockfile != NULL) {
7ae96d882326357448f8f440c52f47ac1b1fa455Evan Hunt int n = unlink(lockfile);
7ae96d882326357448f8f440c52f47ac1b1fa455Evan Hunt if (n == -1 && errno != ENOENT)
7ae96d882326357448f8f440c52f47ac1b1fa455Evan Hunt ns_main_earlywarning("unlink '%s': failed", lockfile);
7ae96d882326357448f8f440c52f47ac1b1fa455Evan Hunt free(lockfile);
7ae96d882326357448f8f440c52f47ac1b1fa455Evan Hunt lockfile = NULL;
7ae96d882326357448f8f440c52f47ac1b1fa455Evan Hunt }
7ae96d882326357448f8f440c52f47ac1b1fa455Evan Hunt}
7ae96d882326357448f8f440c52f47ac1b1fa455Evan Hunt
7ae96d882326357448f8f440c52f47ac1b1fa455Evan Hunt/*
7ae96d882326357448f8f440c52f47ac1b1fa455Evan Hunt * Ensure that a directory exists.
7ae96d882326357448f8f440c52f47ac1b1fa455Evan Hunt * NOTE: This function overwrites the '/' characters in 'filename' with
7ae96d882326357448f8f440c52f47ac1b1fa455Evan Hunt * nulls. The caller should copy the filename to a fresh buffer first.
7ae96d882326357448f8f440c52f47ac1b1fa455Evan Hunt */
598da901aba066208ab57ef5a44661f00f6c7dc6Mark Andrewsstatic int
598da901aba066208ab57ef5a44661f00f6c7dc6Mark Andrewsmkdirpath(char *filename, void (*report)(const char *, ...)) {
598da901aba066208ab57ef5a44661f00f6c7dc6Mark Andrews char *slash = strrchr(filename, '/');
598da901aba066208ab57ef5a44661f00f6c7dc6Mark Andrews char strbuf[ISC_STRERRORSIZE];
598da901aba066208ab57ef5a44661f00f6c7dc6Mark Andrews unsigned int mode;
598da901aba066208ab57ef5a44661f00f6c7dc6Mark Andrews
598da901aba066208ab57ef5a44661f00f6c7dc6Mark Andrews if (slash != NULL && slash != filename) {
598da901aba066208ab57ef5a44661f00f6c7dc6Mark Andrews struct stat sb;
598da901aba066208ab57ef5a44661f00f6c7dc6Mark Andrews *slash = '\0';
598da901aba066208ab57ef5a44661f00f6c7dc6Mark Andrews
598da901aba066208ab57ef5a44661f00f6c7dc6Mark Andrews if (stat(filename, &sb) == -1) {
598da901aba066208ab57ef5a44661f00f6c7dc6Mark Andrews if (errno != ENOENT) {
598da901aba066208ab57ef5a44661f00f6c7dc6Mark Andrews isc__strerror(errno, strbuf, sizeof(strbuf));
598da901aba066208ab57ef5a44661f00f6c7dc6Mark Andrews (*report)("couldn't stat '%s': %s", filename,
598da901aba066208ab57ef5a44661f00f6c7dc6Mark Andrews strbuf);
598da901aba066208ab57ef5a44661f00f6c7dc6Mark Andrews goto error;
598da901aba066208ab57ef5a44661f00f6c7dc6Mark Andrews }
bf33eb0b522801792a6663b0360bc94b9e9b77c2Automatic Updater if (mkdirpath(filename, report) == -1)
598da901aba066208ab57ef5a44661f00f6c7dc6Mark Andrews goto error;
fb8db7fc3f3ea597a959e4c8ac42247fd78ca887Mark Andrews /*
fb8db7fc3f3ea597a959e4c8ac42247fd78ca887Mark Andrews * Handle "//", "/./" and "/../" in path.
fb8db7fc3f3ea597a959e4c8ac42247fd78ca887Mark Andrews */
fb8db7fc3f3ea597a959e4c8ac42247fd78ca887Mark Andrews if (!strcmp(slash + 1, "") ||
fb8db7fc3f3ea597a959e4c8ac42247fd78ca887Mark Andrews !strcmp(slash + 1, ".") ||
fb8db7fc3f3ea597a959e4c8ac42247fd78ca887Mark Andrews !strcmp(slash + 1, "..")) {
fb8db7fc3f3ea597a959e4c8ac42247fd78ca887Mark Andrews *slash = '/';
fb8db7fc3f3ea597a959e4c8ac42247fd78ca887Mark Andrews return (0);
fb8db7fc3f3ea597a959e4c8ac42247fd78ca887Mark Andrews }
598da901aba066208ab57ef5a44661f00f6c7dc6Mark Andrews mode = S_IRUSR | S_IWUSR | S_IXUSR; /* u=rwx */
598da901aba066208ab57ef5a44661f00f6c7dc6Mark Andrews mode |= S_IRGRP | S_IXGRP; /* g=rx */
598da901aba066208ab57ef5a44661f00f6c7dc6Mark Andrews mode |= S_IROTH | S_IXOTH; /* o=rx */
598da901aba066208ab57ef5a44661f00f6c7dc6Mark Andrews if (mkdir(filename, mode) == -1) {
598da901aba066208ab57ef5a44661f00f6c7dc6Mark Andrews isc__strerror(errno, strbuf, sizeof(strbuf));
598da901aba066208ab57ef5a44661f00f6c7dc6Mark Andrews (*report)("couldn't mkdir '%s': %s", filename,
598da901aba066208ab57ef5a44661f00f6c7dc6Mark Andrews strbuf);
598da901aba066208ab57ef5a44661f00f6c7dc6Mark Andrews goto error;
598da901aba066208ab57ef5a44661f00f6c7dc6Mark Andrews }
8f196ee82b5465d2060de279f68535076ddbad64Mark Andrews if (runas_pw != NULL &&
8f196ee82b5465d2060de279f68535076ddbad64Mark Andrews chown(filename, runas_pw->pw_uid,
8f196ee82b5465d2060de279f68535076ddbad64Mark Andrews runas_pw->pw_gid) == -1) {
8f196ee82b5465d2060de279f68535076ddbad64Mark Andrews isc__strerror(errno, strbuf, sizeof(strbuf));
8f196ee82b5465d2060de279f68535076ddbad64Mark Andrews (*report)("couldn't chown '%s': %s", filename,
8f196ee82b5465d2060de279f68535076ddbad64Mark Andrews strbuf);
8f196ee82b5465d2060de279f68535076ddbad64Mark Andrews }
598da901aba066208ab57ef5a44661f00f6c7dc6Mark Andrews }
598da901aba066208ab57ef5a44661f00f6c7dc6Mark Andrews *slash = '/';
598da901aba066208ab57ef5a44661f00f6c7dc6Mark Andrews }
598da901aba066208ab57ef5a44661f00f6c7dc6Mark Andrews return (0);
598da901aba066208ab57ef5a44661f00f6c7dc6Mark Andrews
598da901aba066208ab57ef5a44661f00f6c7dc6Mark Andrews error:
598da901aba066208ab57ef5a44661f00f6c7dc6Mark Andrews *slash = '/';
598da901aba066208ab57ef5a44661f00f6c7dc6Mark Andrews return (-1);
598da901aba066208ab57ef5a44661f00f6c7dc6Mark Andrews}
598da901aba066208ab57ef5a44661f00f6c7dc6Mark Andrews
38cd4d14cc341c2663e574035074788bb6f0fce2Evan Huntstatic void
3a875400473e5c06199272a1292ed84646990e2fEvan Huntsetperms(uid_t uid, gid_t gid) {
38cd4d14cc341c2663e574035074788bb6f0fce2Evan Hunt char strbuf[ISC_STRERRORSIZE];
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt#if !defined(HAVE_SETEGID) && defined(HAVE_SETRESGID)
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt gid_t oldgid, tmpg;
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt#endif
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt#if !defined(HAVE_SETEUID) && defined(HAVE_SETRESUID)
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt uid_t olduid, tmpu;
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt#endif
38cd4d14cc341c2663e574035074788bb6f0fce2Evan Hunt#if defined(HAVE_SETEGID)
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt if (getegid() != gid && setegid(gid) == -1) {
3e12c54de2238dc90bae06a2e083e4976120bad5Automatic Updater isc__strerror(errno, strbuf, sizeof(strbuf));
de3200acf43b23858f19f9f45b71a745fb3728c0Mark Andrews ns_main_earlywarning("unable to set effective gid to %ld: %s",
de3200acf43b23858f19f9f45b71a745fb3728c0Mark Andrews (long)gid, strbuf);
3e12c54de2238dc90bae06a2e083e4976120bad5Automatic Updater }
38cd4d14cc341c2663e574035074788bb6f0fce2Evan Hunt#elif defined(HAVE_SETRESGID)
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt if (getresgid(&tmpg, &oldgid, &tmpg) == -1 || oldgid != gid) {
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt if (setresgid(-1, gid, -1) == -1) {
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt isc__strerror(errno, strbuf, sizeof(strbuf));
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt ns_main_earlywarning("unable to set effective "
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt "gid to %d: %s", gid, strbuf);
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt }
3e12c54de2238dc90bae06a2e083e4976120bad5Automatic Updater }
38cd4d14cc341c2663e574035074788bb6f0fce2Evan Hunt#endif
38cd4d14cc341c2663e574035074788bb6f0fce2Evan Hunt
38cd4d14cc341c2663e574035074788bb6f0fce2Evan Hunt#if defined(HAVE_SETEUID)
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt if (geteuid() != uid && seteuid(uid) == -1) {
3e12c54de2238dc90bae06a2e083e4976120bad5Automatic Updater isc__strerror(errno, strbuf, sizeof(strbuf));
de3200acf43b23858f19f9f45b71a745fb3728c0Mark Andrews ns_main_earlywarning("unable to set effective uid to %ld: %s",
de3200acf43b23858f19f9f45b71a745fb3728c0Mark Andrews (long)uid, strbuf);
3e12c54de2238dc90bae06a2e083e4976120bad5Automatic Updater }
38cd4d14cc341c2663e574035074788bb6f0fce2Evan Hunt#elif defined(HAVE_SETRESUID)
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt if (getresuid(&tmpu, &olduid, &tmpu) == -1 || olduid != uid) {
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt if (setresuid(-1, uid, -1) == -1) {
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt isc__strerror(errno, strbuf, sizeof(strbuf));
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt ns_main_earlywarning("unable to set effective "
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt "uid to %d: %s", uid, strbuf);
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt }
3e12c54de2238dc90bae06a2e083e4976120bad5Automatic Updater }
38cd4d14cc341c2663e574035074788bb6f0fce2Evan Hunt#endif
38cd4d14cc341c2663e574035074788bb6f0fce2Evan Hunt}
38cd4d14cc341c2663e574035074788bb6f0fce2Evan Hunt
3a875400473e5c06199272a1292ed84646990e2fEvan HuntFILE *
3a875400473e5c06199272a1292ed84646990e2fEvan Huntns_os_openfile(const char *filename, mode_t mode, isc_boolean_t switch_user) {
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt char strbuf[ISC_STRERRORSIZE], *f;
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt FILE *fp;
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt int fd;
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt /*
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt * Make the containing directory if it doesn't exist.
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt */
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt f = strdup(filename);
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt if (f == NULL) {
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt isc__strerror(errno, strbuf, sizeof(strbuf));
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt ns_main_earlywarning("couldn't strdup() '%s': %s",
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt filename, strbuf);
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt return (NULL);
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt }
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt if (mkdirpath(f, ns_main_earlywarning) == -1) {
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt free(f);
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt return (NULL);
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt }
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt free(f);
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt if (switch_user && runas_pw != NULL) {
88c63fe9c78e60e5e521d095d6e983c211902904Mark Andrews#ifndef HAVE_LINUXTHREADS
88c63fe9c78e60e5e521d095d6e983c211902904Mark Andrews gid_t oldgid = getgid();
88c63fe9c78e60e5e521d095d6e983c211902904Mark Andrews#endif
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt /* Set UID/GID to the one we'll be running with eventually */
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt setperms(runas_pw->pw_uid, runas_pw->pw_gid);
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt fd = safe_open(filename, mode, ISC_FALSE);
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt#ifndef HAVE_LINUXTHREADS
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt /* Restore UID/GID to root */
88c63fe9c78e60e5e521d095d6e983c211902904Mark Andrews setperms(0, oldgid);
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt#endif /* HAVE_LINUXTHREADS */
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt if (fd == -1) {
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt#ifndef HAVE_LINUXTHREADS
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt fd = safe_open(filename, mode, ISC_FALSE);
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt if (fd != -1) {
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt ns_main_earlywarning("Required root "
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt "permissions to open "
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt "'%s'.", filename);
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt } else {
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt ns_main_earlywarning("Could not open "
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt "'%s'.", filename);
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt }
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt ns_main_earlywarning("Please check file and "
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt "directory permissions "
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt "or reconfigure the filename.");
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt#else /* HAVE_LINUXTHREADS */
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt ns_main_earlywarning("Could not open "
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt "'%s'.", filename);
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt ns_main_earlywarning("Please check file and "
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt "directory permissions "
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt "or reconfigure the filename.");
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt#endif /* HAVE_LINUXTHREADS */
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt }
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt } else {
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt fd = safe_open(filename, mode, ISC_FALSE);
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt }
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt if (fd < 0) {
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt isc__strerror(errno, strbuf, sizeof(strbuf));
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt ns_main_earlywarning("could not open file '%s': %s",
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt filename, strbuf);
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt return (NULL);
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt }
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt fp = fdopen(fd, "w");
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt if (fp == NULL) {
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt isc__strerror(errno, strbuf, sizeof(strbuf));
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt ns_main_earlywarning("could not fdopen() file '%s': %s",
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt filename, strbuf);
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt }
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt return (fp);
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt}
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt
9ee5efde7df57cbe70fb9b32c9d898e8ef7eca1eBob Halleyvoid
93e6ebcd0a0f044ba2add424c265b5e0bb4c8afdMark Andrewsns_os_writepidfile(const char *filename, isc_boolean_t first_time) {
d869bc7685f47ba0c18f6343d3eee414aac1ebb5Mark Andrews FILE *fh;
9ee5efde7df57cbe70fb9b32c9d898e8ef7eca1eBob Halley pid_t pid;
4b87939256ede703385e9cab92d3c58d03c31098Mark Andrews char strbuf[ISC_STRERRORSIZE];
93e6ebcd0a0f044ba2add424c265b5e0bb4c8afdMark Andrews void (*report)(const char *, ...);
9ee5efde7df57cbe70fb9b32c9d898e8ef7eca1eBob Halley
9ee5efde7df57cbe70fb9b32c9d898e8ef7eca1eBob Halley /*
9ee5efde7df57cbe70fb9b32c9d898e8ef7eca1eBob Halley * The caller must ensure any required synchronization.
9ee5efde7df57cbe70fb9b32c9d898e8ef7eca1eBob Halley */
9ee5efde7df57cbe70fb9b32c9d898e8ef7eca1eBob Halley
93e6ebcd0a0f044ba2add424c265b5e0bb4c8afdMark Andrews report = first_time ? ns_main_earlyfatal : ns_main_earlywarning;
93e6ebcd0a0f044ba2add424c265b5e0bb4c8afdMark Andrews
9ee5efde7df57cbe70fb9b32c9d898e8ef7eca1eBob Halley cleanup_pidfile();
9ee5efde7df57cbe70fb9b32c9d898e8ef7eca1eBob Halley
8d2b885018e8c8565a8fea56cc01405c93a72aaeAndreas Gustafsson if (filename == NULL)
9bdb01e6c382e897572791b12190472955994d87Mark Andrews return;
8d2b885018e8c8565a8fea56cc01405c93a72aaeAndreas Gustafsson
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt pidfile = strdup(filename);
4b87939256ede703385e9cab92d3c58d03c31098Mark Andrews if (pidfile == NULL) {
4b87939256ede703385e9cab92d3c58d03c31098Mark Andrews isc__strerror(errno, strbuf, sizeof(strbuf));
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt (*report)("couldn't strdup() '%s': %s", filename, strbuf);
93e6ebcd0a0f044ba2add424c265b5e0bb4c8afdMark Andrews return;
4b87939256ede703385e9cab92d3c58d03c31098Mark Andrews }
598da901aba066208ab57ef5a44661f00f6c7dc6Mark Andrews
d869bc7685f47ba0c18f6343d3eee414aac1ebb5Mark Andrews fh = ns_os_openfile(filename, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH,
3a875400473e5c06199272a1292ed84646990e2fEvan Hunt first_time);
d869bc7685f47ba0c18f6343d3eee414aac1ebb5Mark Andrews if (fh == NULL) {
93e6ebcd0a0f044ba2add424c265b5e0bb4c8afdMark Andrews cleanup_pidfile();
93e6ebcd0a0f044ba2add424c265b5e0bb4c8afdMark Andrews return;
4b87939256ede703385e9cab92d3c58d03c31098Mark Andrews }
9ee5efde7df57cbe70fb9b32c9d898e8ef7eca1eBob Halley#ifdef HAVE_LINUXTHREADS
9ee5efde7df57cbe70fb9b32c9d898e8ef7eca1eBob Halley pid = mainpid;
9ee5efde7df57cbe70fb9b32c9d898e8ef7eca1eBob Halley#else
9ee5efde7df57cbe70fb9b32c9d898e8ef7eca1eBob Halley pid = getpid();
9ee5efde7df57cbe70fb9b32c9d898e8ef7eca1eBob Halley#endif
d869bc7685f47ba0c18f6343d3eee414aac1ebb5Mark Andrews if (fprintf(fh, "%ld\n", (long)pid) < 0) {
5d98cf67b32d785aca1a72ea1dc4d559fab39208Mark Andrews (*report)("fprintf() to pid file '%s' failed", filename);
d869bc7685f47ba0c18f6343d3eee414aac1ebb5Mark Andrews (void)fclose(fh);
93e6ebcd0a0f044ba2add424c265b5e0bb4c8afdMark Andrews cleanup_pidfile();
93e6ebcd0a0f044ba2add424c265b5e0bb4c8afdMark Andrews return;
93e6ebcd0a0f044ba2add424c265b5e0bb4c8afdMark Andrews }
d869bc7685f47ba0c18f6343d3eee414aac1ebb5Mark Andrews if (fflush(fh) == EOF) {
5d98cf67b32d785aca1a72ea1dc4d559fab39208Mark Andrews (*report)("fflush() to pid file '%s' failed", filename);
d869bc7685f47ba0c18f6343d3eee414aac1ebb5Mark Andrews (void)fclose(fh);
93e6ebcd0a0f044ba2add424c265b5e0bb4c8afdMark Andrews cleanup_pidfile();
93e6ebcd0a0f044ba2add424c265b5e0bb4c8afdMark Andrews return;
93e6ebcd0a0f044ba2add424c265b5e0bb4c8afdMark Andrews }
d869bc7685f47ba0c18f6343d3eee414aac1ebb5Mark Andrews (void)fclose(fh);
9ee5efde7df57cbe70fb9b32c9d898e8ef7eca1eBob Halley}
9ee5efde7df57cbe70fb9b32c9d898e8ef7eca1eBob Halley
47d837a49967a6a1b290024f5efb0669276013b1Mukund Sivaramanisc_boolean_t
47d837a49967a6a1b290024f5efb0669276013b1Mukund Sivaramanns_os_issingleton(const char *filename) {
7ae96d882326357448f8f440c52f47ac1b1fa455Evan Hunt char strbuf[ISC_STRERRORSIZE];
47d837a49967a6a1b290024f5efb0669276013b1Mukund Sivaraman struct flock lock;
47d837a49967a6a1b290024f5efb0669276013b1Mukund Sivaraman
47d837a49967a6a1b290024f5efb0669276013b1Mukund Sivaraman if (singletonfd != -1)
47d837a49967a6a1b290024f5efb0669276013b1Mukund Sivaraman return (ISC_TRUE);
47d837a49967a6a1b290024f5efb0669276013b1Mukund Sivaraman
7ae96d882326357448f8f440c52f47ac1b1fa455Evan Hunt if (strcasecmp(filename, "none") == 0)
7ae96d882326357448f8f440c52f47ac1b1fa455Evan Hunt return (ISC_TRUE);
7ae96d882326357448f8f440c52f47ac1b1fa455Evan Hunt
7ae96d882326357448f8f440c52f47ac1b1fa455Evan Hunt /*
7ae96d882326357448f8f440c52f47ac1b1fa455Evan Hunt * Make the containing directory if it doesn't exist.
7ae96d882326357448f8f440c52f47ac1b1fa455Evan Hunt */
7ae96d882326357448f8f440c52f47ac1b1fa455Evan Hunt lockfile = strdup(filename);
7ae96d882326357448f8f440c52f47ac1b1fa455Evan Hunt if (lockfile == NULL) {
7ae96d882326357448f8f440c52f47ac1b1fa455Evan Hunt isc__strerror(errno, strbuf, sizeof(strbuf));
7ae96d882326357448f8f440c52f47ac1b1fa455Evan Hunt ns_main_earlyfatal("couldn't allocate memory for '%s': %s",
7ae96d882326357448f8f440c52f47ac1b1fa455Evan Hunt filename, strbuf);
7ae96d882326357448f8f440c52f47ac1b1fa455Evan Hunt } else {
7ae96d882326357448f8f440c52f47ac1b1fa455Evan Hunt int ret = mkdirpath(lockfile, ns_main_earlywarning);
7ae96d882326357448f8f440c52f47ac1b1fa455Evan Hunt if (ret == -1) {
7ae96d882326357448f8f440c52f47ac1b1fa455Evan Hunt ns_main_earlywarning("couldn't create '%s'", filename);
7ae96d882326357448f8f440c52f47ac1b1fa455Evan Hunt cleanup_lockfile();
7ae96d882326357448f8f440c52f47ac1b1fa455Evan Hunt return (ISC_FALSE);
7ae96d882326357448f8f440c52f47ac1b1fa455Evan Hunt }
7ae96d882326357448f8f440c52f47ac1b1fa455Evan Hunt }
7ae96d882326357448f8f440c52f47ac1b1fa455Evan Hunt
47d837a49967a6a1b290024f5efb0669276013b1Mukund Sivaraman /*
47d837a49967a6a1b290024f5efb0669276013b1Mukund Sivaraman * ns_os_openfile() uses safeopen() which removes any existing
47d837a49967a6a1b290024f5efb0669276013b1Mukund Sivaraman * files. We can't use that here.
47d837a49967a6a1b290024f5efb0669276013b1Mukund Sivaraman */
47d837a49967a6a1b290024f5efb0669276013b1Mukund Sivaraman singletonfd = open(filename, O_WRONLY | O_CREAT,
47d837a49967a6a1b290024f5efb0669276013b1Mukund Sivaraman S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
7ae96d882326357448f8f440c52f47ac1b1fa455Evan Hunt if (singletonfd == -1) {
7ae96d882326357448f8f440c52f47ac1b1fa455Evan Hunt cleanup_lockfile();
47d837a49967a6a1b290024f5efb0669276013b1Mukund Sivaraman return (ISC_FALSE);
7ae96d882326357448f8f440c52f47ac1b1fa455Evan Hunt }
47d837a49967a6a1b290024f5efb0669276013b1Mukund Sivaraman
47d837a49967a6a1b290024f5efb0669276013b1Mukund Sivaraman memset(&lock, 0, sizeof(lock));
47d837a49967a6a1b290024f5efb0669276013b1Mukund Sivaraman lock.l_type = F_WRLCK;
47d837a49967a6a1b290024f5efb0669276013b1Mukund Sivaraman lock.l_whence = SEEK_SET;
47d837a49967a6a1b290024f5efb0669276013b1Mukund Sivaraman lock.l_start = 0;
47d837a49967a6a1b290024f5efb0669276013b1Mukund Sivaraman lock.l_len = 1;
47d837a49967a6a1b290024f5efb0669276013b1Mukund Sivaraman
47d837a49967a6a1b290024f5efb0669276013b1Mukund Sivaraman /* Non-blocking (does not wait for lock) */
47d837a49967a6a1b290024f5efb0669276013b1Mukund Sivaraman if (fcntl(singletonfd, F_SETLK, &lock) == -1) {
47d837a49967a6a1b290024f5efb0669276013b1Mukund Sivaraman close(singletonfd);
47d837a49967a6a1b290024f5efb0669276013b1Mukund Sivaraman singletonfd = -1;
47d837a49967a6a1b290024f5efb0669276013b1Mukund Sivaraman return (ISC_FALSE);
47d837a49967a6a1b290024f5efb0669276013b1Mukund Sivaraman }
47d837a49967a6a1b290024f5efb0669276013b1Mukund Sivaraman
47d837a49967a6a1b290024f5efb0669276013b1Mukund Sivaraman return (ISC_TRUE);
47d837a49967a6a1b290024f5efb0669276013b1Mukund Sivaraman}
47d837a49967a6a1b290024f5efb0669276013b1Mukund Sivaraman
9ee5efde7df57cbe70fb9b32c9d898e8ef7eca1eBob Halleyvoid
9ee5efde7df57cbe70fb9b32c9d898e8ef7eca1eBob Halleyns_os_shutdown(void) {
9ee5efde7df57cbe70fb9b32c9d898e8ef7eca1eBob Halley closelog();
9ee5efde7df57cbe70fb9b32c9d898e8ef7eca1eBob Halley cleanup_pidfile();
7ae96d882326357448f8f440c52f47ac1b1fa455Evan Hunt cleanup_lockfile();
9ee5efde7df57cbe70fb9b32c9d898e8ef7eca1eBob Halley}
df7596a03eea7f1c2df89bd63d3bd4b73f274565Mark Andrews
df7596a03eea7f1c2df89bd63d3bd4b73f274565Mark Andrewsisc_result_t
df7596a03eea7f1c2df89bd63d3bd4b73f274565Mark Andrewsns_os_gethostname(char *buf, size_t len) {
5d98cf67b32d785aca1a72ea1dc4d559fab39208Mark Andrews int n;
df7596a03eea7f1c2df89bd63d3bd4b73f274565Mark Andrews
df7596a03eea7f1c2df89bd63d3bd4b73f274565Mark Andrews n = gethostname(buf, len);
df7596a03eea7f1c2df89bd63d3bd4b73f274565Mark Andrews return ((n == 0) ? ISC_R_SUCCESS : ISC_R_FAILURE);
df7596a03eea7f1c2df89bd63d3bd4b73f274565Mark Andrews}
df7596a03eea7f1c2df89bd63d3bd4b73f274565Mark Andrews
cf300e03de3df3ff422db922520bf07c686c86daMark Andrewsstatic char *
cf300e03de3df3ff422db922520bf07c686c86daMark Andrewsnext_token(char **stringp, const char *delim) {
cf300e03de3df3ff422db922520bf07c686c86daMark Andrews char *res;
cf300e03de3df3ff422db922520bf07c686c86daMark Andrews
cf300e03de3df3ff422db922520bf07c686c86daMark Andrews do {
cf300e03de3df3ff422db922520bf07c686c86daMark Andrews res = strsep(stringp, delim);
cf300e03de3df3ff422db922520bf07c686c86daMark Andrews if (res == NULL)
cf300e03de3df3ff422db922520bf07c686c86daMark Andrews break;
cf300e03de3df3ff422db922520bf07c686c86daMark Andrews } while (*res == '\0');
cf300e03de3df3ff422db922520bf07c686c86daMark Andrews return (res);
cf300e03de3df3ff422db922520bf07c686c86daMark Andrews}
cf300e03de3df3ff422db922520bf07c686c86daMark Andrews
cf300e03de3df3ff422db922520bf07c686c86daMark Andrewsvoid
cf300e03de3df3ff422db922520bf07c686c86daMark Andrewsns_os_shutdownmsg(char *command, isc_buffer_t *text) {
cf300e03de3df3ff422db922520bf07c686c86daMark Andrews char *input, *ptr;
cf300e03de3df3ff422db922520bf07c686c86daMark Andrews unsigned int n;
cf300e03de3df3ff422db922520bf07c686c86daMark Andrews pid_t pid;
cf300e03de3df3ff422db922520bf07c686c86daMark Andrews
cf300e03de3df3ff422db922520bf07c686c86daMark Andrews input = command;
cf300e03de3df3ff422db922520bf07c686c86daMark Andrews
cf300e03de3df3ff422db922520bf07c686c86daMark Andrews /* Skip the command name. */
cf300e03de3df3ff422db922520bf07c686c86daMark Andrews ptr = next_token(&input, " \t");
cf300e03de3df3ff422db922520bf07c686c86daMark Andrews if (ptr == NULL)
cf300e03de3df3ff422db922520bf07c686c86daMark Andrews return;
cf300e03de3df3ff422db922520bf07c686c86daMark Andrews
cf300e03de3df3ff422db922520bf07c686c86daMark Andrews ptr = next_token(&input, " \t");
cf300e03de3df3ff422db922520bf07c686c86daMark Andrews if (ptr == NULL)
cf300e03de3df3ff422db922520bf07c686c86daMark Andrews return;
2f012d936b5ccdf6520c96a4de23721dc58a2221Automatic Updater
cf300e03de3df3ff422db922520bf07c686c86daMark Andrews if (strcmp(ptr, "-p") != 0)
cf300e03de3df3ff422db922520bf07c686c86daMark Andrews return;
cf300e03de3df3ff422db922520bf07c686c86daMark Andrews
cf300e03de3df3ff422db922520bf07c686c86daMark Andrews#ifdef HAVE_LINUXTHREADS
cf300e03de3df3ff422db922520bf07c686c86daMark Andrews pid = mainpid;
cf300e03de3df3ff422db922520bf07c686c86daMark Andrews#else
cf300e03de3df3ff422db922520bf07c686c86daMark Andrews pid = getpid();
cf300e03de3df3ff422db922520bf07c686c86daMark Andrews#endif
cf300e03de3df3ff422db922520bf07c686c86daMark Andrews
cf300e03de3df3ff422db922520bf07c686c86daMark Andrews n = snprintf((char *)isc_buffer_used(text),
cf300e03de3df3ff422db922520bf07c686c86daMark Andrews isc_buffer_availablelength(text),
1ccee0aff35cff5a5bd5da41972e29492da3617eMark Andrews "pid: %ld", (long)pid);
cf300e03de3df3ff422db922520bf07c686c86daMark Andrews /* Only send a message if it is complete. */
a360461b34c8cff31c66ef18d872fc2f04be395bMark Andrews if (n > 0 && n < isc_buffer_availablelength(text))
cf300e03de3df3ff422db922520bf07c686c86daMark Andrews isc_buffer_add(text, n);
cf300e03de3df3ff422db922520bf07c686c86daMark Andrews}
6286983c506433d642b23e64845c50be30f2a7f6Mark Andrews
6286983c506433d642b23e64845c50be30f2a7f6Mark Andrewsvoid
6286983c506433d642b23e64845c50be30f2a7f6Mark Andrewsns_os_tzset(void) {
6286983c506433d642b23e64845c50be30f2a7f6Mark Andrews#ifdef HAVE_TZSET
6286983c506433d642b23e64845c50be30f2a7f6Mark Andrews tzset();
6286983c506433d642b23e64845c50be30f2a7f6Mark Andrews#endif
6286983c506433d642b23e64845c50be30f2a7f6Mark Andrews}
f02c22d58ac88777655e0b407b22b07864d39184Evan Hunt
f02c22d58ac88777655e0b407b22b07864d39184Evan Huntstatic char unamebuf[BUFSIZ];
f02c22d58ac88777655e0b407b22b07864d39184Evan Huntstatic char *unamep = NULL;
f02c22d58ac88777655e0b407b22b07864d39184Evan Hunt
f02c22d58ac88777655e0b407b22b07864d39184Evan Huntstatic void
f02c22d58ac88777655e0b407b22b07864d39184Evan Huntgetuname(void) {
f02c22d58ac88777655e0b407b22b07864d39184Evan Hunt#ifdef HAVE_UNAME
f02c22d58ac88777655e0b407b22b07864d39184Evan Hunt struct utsname uts;
f02c22d58ac88777655e0b407b22b07864d39184Evan Hunt
f02c22d58ac88777655e0b407b22b07864d39184Evan Hunt memset(&uts, 0, sizeof(uts));
f02c22d58ac88777655e0b407b22b07864d39184Evan Hunt if (uname(&uts) < 0) {
7cd594b8427fe742d44295790ba367e1de22a47dEvan Hunt snprintf(unamebuf, sizeof(unamebuf), "unknown architecture");
f02c22d58ac88777655e0b407b22b07864d39184Evan Hunt return;
f02c22d58ac88777655e0b407b22b07864d39184Evan Hunt }
f02c22d58ac88777655e0b407b22b07864d39184Evan Hunt
f02c22d58ac88777655e0b407b22b07864d39184Evan Hunt snprintf(unamebuf, sizeof(unamebuf),
f02c22d58ac88777655e0b407b22b07864d39184Evan Hunt "%s %s %s %s",
f02c22d58ac88777655e0b407b22b07864d39184Evan Hunt uts.sysname, uts.machine, uts.release, uts.version);
f02c22d58ac88777655e0b407b22b07864d39184Evan Hunt#else
7cd594b8427fe742d44295790ba367e1de22a47dEvan Hunt snprintf(unamebuf, sizeof(unamebuf), "unknown architecture");
f02c22d58ac88777655e0b407b22b07864d39184Evan Hunt#endif
f02c22d58ac88777655e0b407b22b07864d39184Evan Hunt unamep = unamebuf;
f02c22d58ac88777655e0b407b22b07864d39184Evan Hunt}
f02c22d58ac88777655e0b407b22b07864d39184Evan Hunt
f02c22d58ac88777655e0b407b22b07864d39184Evan Huntchar *
f02c22d58ac88777655e0b407b22b07864d39184Evan Huntns_os_uname(void) {
f02c22d58ac88777655e0b407b22b07864d39184Evan Hunt if (unamep == NULL)
f02c22d58ac88777655e0b407b22b07864d39184Evan Hunt getuname();
f02c22d58ac88777655e0b407b22b07864d39184Evan Hunt return (unamep);
f02c22d58ac88777655e0b407b22b07864d39184Evan Hunt}