log_assert(cfg);
/* daemonize last to be able to print error to user */
- if(cfg->directory && cfg->directory[0]) {
- if(chdir(cfg->directory)) {
- fatal_exit("Could not chdir to %s: %s",
- cfg->directory, strerror(errno));
- }
- verbose(VERB_QUERY, "chdir to %s", cfg->directory);
- }
if(cfg->username && cfg->username[0]) {
struct passwd *pwd;
if((pwd = getpwnam(cfg->username)) == NULL)
endpwent();
}
if(cfg->chrootdir && cfg->chrootdir[0]) {
+ if(chdir(cfg->chrootdir)) {
+ fatal_exit("unable to chdir to chroot %s: %s",
+ cfg->chrootdir, strerror(errno));
+ }
+ verbose(VERB_QUERY, "chdir to %s", cfg->chrootdir);
if(chroot(cfg->chrootdir))
fatal_exit("unable to chroot to %s: %s",
cfg->chrootdir, strerror(errno));
strlen(cfg->chrootdir)) == 0)
(*cfgfile) += strlen(cfg->chrootdir);
}
+ if(cfg->directory && cfg->directory[0]) {
+ char* dir = cfg->directory;
+ if(cfg->chrootdir && cfg->chrootdir[0] &&
+ strncmp(dir, cfg->chrootdir,
+ strlen(cfg->chrootdir)) == 0)
+ dir += strlen(cfg->chrootdir);
+ if(chdir(dir)) {
+ fatal_exit("Could not chdir to %s: %s",
+ dir, strerror(errno));
+ }
+ verbose(VERB_QUERY, "chdir to %s", dir);
+ }
if(cfg->username && cfg->username[0]) {
if(setgid(gid) != 0)
fatal_exit("unable to set group id of %s: %s",
+24 April 2008: Wouter
+ - chroot checks improved. working directory relative to chroot.
+ checks if config file path is inside chroot. Documentation on it.
+
23 April 2008: Wouter
- parseunbound.pl contrib update from Kai Storbeck for threads.
- iana ports update
# if given, a chroot(2) is done to the given directory.
# i.e. you can chroot to the working directory, for example,
# for extra security, but make sure all files are in that directory.
- # If you give "" no chroot is performed.
+ #
+ # If chroot is enabled, you should pass the configfile (from the
+ # commandline) as a full path from the original root. After the
+ # chroot has been performed the now defunct portion of the config
+ # file path is removed to be able to reread the config after a reload.
+ #
+ # All other file paths (working dir, pidfile, logfile, roothints,
+ # key files) can be specified in several ways:
+ # o as an absolute path relative to the new root.
+ # o as a relative path to the working directory.
+ # o as an absolute path relative to the original root.
+ # In the last case the path is adjusted to remove the unused portion.
+ #
+ # Additionally, unbound may need to access /dev/random (for entropy)
+ # and to /dev/log (if you use syslog) from inside the chroot.
+ #
+ # If you give "" no chroot is performed. The path must not end in a /.
# chroot: "/usr/local/etc/unbound"
# if given, user privileges are dropped (after binding port),
# If you give "" no privileges are dropped.
# username: "unbound"
- # the working directory.
+ # the working directory. "" disables.
# directory: "/usr/local/etc/unbound"
# the log file, "" means log to stderr.
result in (possibly excessive) retried queries.
.TP
.B chroot: \fI<directory>
+If chroot is enabled, you should pass the configfile (from the
+commandline) as a full path from the original root. After the
+chroot has been performed the now defunct portion of the config
+file path is removed to be able to reread the config after a reload.
+.IP
+All other file paths (working dir, pidfile, logfile, roothints,
+key files) can be specified in several ways:
+as an absolute path relative to the new root,
+as a relative path to the working directory, or
+as an absolute path relative to the original root.
+In the last case the path is adjusted to remove the unused portion.
+.IP
+Additionally, unbound may need to access /dev/random (for entropy)
+and to /dev/log (if you use syslog) from inside the chroot.
+.IP
If given a chroot is done to the given directory. The default is
-"/etc/unbound". If you give "" no chroot is performed.
+"/usr/local/etc/unbound". If you give "" no chroot is performed.
.TP
.B username: \fI<name>
If given, after binding the port the user privileges are dropped. Default is
The default is to log to syslog.
.TP
.B pidfile: \fI<filename>
-The process id is written to the file. Default is "/etc/unbound/unbound.pid".
+The process id is written to the file. Default is "/usr/local/etc/unbound/unbound.pid".
So,
.nf
-kill \-HUP `cat /etc/unbound/unbound.pid`
+kill \-HUP `cat /usr/local/etc/unbound/unbound.pid`
.fi
triggers a reload,
.nf
-kill \-QUIT `cat /etc/unbound/unbound.pid`
+kill \-QUIT `cat /usr/local/etc/unbound/unbound.pid`
.fi
gracefully terminates.
.TP
.fi
.SH "FILES"
.TP
-.I /etc/unbound
+.I /usr/local/etc/unbound
default unbound working directory and default
\fIchroot\fR(2)
location.
/** check configuration for errors */
static void
-morechecks(struct config_file* cfg)
+morechecks(struct config_file* cfg, char* fname)
{
warn_hosts("stub-host", cfg->stubs);
warn_hosts("forward-host", cfg->forwards);
!is_dir(cfg->chrootdir)) {
fatal_exit("bad chroot directory");
}
- if((cfg->chrootdir && cfg->chrootdir[0])
- && (cfg->directory && cfg->directory[0])
- && strncmp(cfg->chrootdir, cfg->directory,
- strlen(cfg->chrootdir)) != 0) {
- fatal_exit("chdir directory '%s' not inside the chroot "
- "directory '%s'", cfg->directory, cfg->chrootdir);
+ if(cfg->chrootdir && cfg->chrootdir[0]) {
+ char buf[10240];
+ buf[0] = 0;
+ if(fname[0] != '/') {
+ if(getcwd(buf, sizeof(buf)) == NULL)
+ fatal_exit("getcwd: %s", strerror(errno));
+ strncat(buf, "/", sizeof(buf));
+ }
+ strncat(buf, fname, sizeof(buf));
+ if(strncmp(buf, cfg->chrootdir, strlen(cfg->chrootdir)) != 0)
+ fatal_exit("config file %s is not inside chroot %s",
+ buf, cfg->chrootdir);
}
- if(cfg->directory && cfg->directory[0] && !is_dir(cfg->directory)) {
+ if(cfg->directory && cfg->directory[0] && !is_dir(
+ fname_after_chroot(cfg->directory, cfg, 0))) {
fatal_exit("bad chdir directory");
}
if( (cfg->chrootdir && cfg->chrootdir[0]) ||
if(cfg->logfile && cfg->logfile[0] &&
basedir(cfg->logfile, cfg) &&
!is_dir(basedir(cfg->logfile, cfg))) {
- fatal_exit("pidfile directory does not exist");
+ fatal_exit("logfile directory does not exist");
}
}
config_delete(cfg);
exit(1);
}
- morechecks(cfg);
+ morechecks(cfg, cfgfile);
check_mod(cfg, iter_get_funcblock());
check_mod(cfg, val_get_funcblock());
config_delete(cfg);