diff --git a/CHANGELOG b/CHANGELOG index 485331b..b74f0d6 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -28,6 +28,12 @@ version 2.93 relay is in use. Many thanks to Jørgen Søvik for help finding this bug. + Modify the inotify implementation so that inotify watches are + only created after dnsmasq has changed permissions and userid. + This means that the permissions used when creating the watches + are the same as used for accessing watched files, which makes + more sense and avoids odd and confusing error conditions. + version 2.92 Redesign the interaction between DNSSEC validation and per-domain diff --git a/src/dnsmasq.c b/src/dnsmasq.c index 2bff016..4f9bf48 100644 --- a/src/dnsmasq.c +++ b/src/dnsmasq.c @@ -437,14 +437,6 @@ int main (int argc, char **argv) daemon->tcp_pipes[i] = -1; } -#ifdef HAVE_INOTIFY - if ((daemon->port != 0 && !option_bool(OPT_NO_RESOLV)) || - daemon->dynamic_dirs) - inotify_dnsmasq_init(); - else - daemon->inotifyfd = -1; -#endif - if (daemon->dump_file) #ifdef HAVE_DUMPFILE dump_init(); @@ -864,6 +856,14 @@ int main (int argc, char **argv) } #endif +#ifdef HAVE_INOTIFY + if ((daemon->port != 0 && !option_bool(OPT_NO_RESOLV)) || + daemon->dynamic_dirs) + inotify_dnsmasq_init(err_pipe[1]); + else + daemon->inotifyfd = -1; +#endif + /* Don't start logging malloc before logging is set up. */ daemon->log_malloc = option_bool(OPT_LOG_MALLOC); @@ -1545,6 +1545,26 @@ static void fatal_event(struct event_desc *ev, char *msg) /* fall through */ case EVENT_TIME_ERR: die(_("cannot create timestamp file %s: %s" ), msg, EC_BADCONF); + + /* fall through */ + case EVENT_LINK_ERR: + die(_("cannot access path %s: %s" ), msg, EC_MISC); + + /* fall through */ + case EVENT_INOTFY_ERR: + die(_("failed to create inotify: %s" ), NULL, EC_MISC); + + /* fall through */ + case EVENT_TMSL_ERR: + die(_("too many symlinks following %s"), msg, EC_MISC); + + /* fall through */ + case EVENT_RESOLV_ERR: + die(_("directory %s for resolv-file is missing, cannot poll"), msg, EC_MISC); + + /* fall through */ + case EVENT_IFILE_ERR: + die(_("failed to create inotify for %s: %s"), msg, EC_MISC); } } diff --git a/src/dnsmasq.h b/src/dnsmasq.h index 42cc4a7..510c88f 100644 --- a/src/dnsmasq.h +++ b/src/dnsmasq.h @@ -201,6 +201,11 @@ struct event_desc { #define EVENT_TIME_ERR 24 #define EVENT_SCRIPT_LOG 25 #define EVENT_TIME 26 +#define EVENT_LINK_ERR 27 +#define EVENT_INOTFY_ERR 28 +#define EVENT_TMSL_ERR 29 +#define EVENT_RESOLV_ERR 30 +#define EVENT_IFILE_ERR 31 /* Exit codes. */ #define EC_GOOD 0 @@ -1907,7 +1912,7 @@ int detect_loop(char *query, int type); /* inotify.c */ #ifdef HAVE_INOTIFY -void inotify_dnsmasq_init(void); +void inotify_dnsmasq_init(int errfd); int inotify_check(time_t now); void set_dynamic_inotify(int flag, int total_size, struct crec **rhash, int revhashsz); #endif diff --git a/src/inotify.c b/src/inotify.c index f70daea..2ec6e39 100644 --- a/src/inotify.c +++ b/src/inotify.c @@ -40,7 +40,7 @@ static char *inotify_buffer; points to, made absolute if relative. If path doesn't exist or is not a symlink, return NULL. Return value is malloc'ed */ -static char *my_readlink(char *path) +static char *my_readlink(int errfd, char *path) { ssize_t rc, size = 64; char *buf; @@ -59,7 +59,10 @@ static char *my_readlink(char *path) return NULL; } else - die(_("cannot access path %s: %s"), path, EC_MISC); + { + send_event(errfd, EVENT_LINK_ERR, errno, path); + _exit(0); + } } else if (rc < size-1) { @@ -85,15 +88,18 @@ static char *my_readlink(char *path) } } -void inotify_dnsmasq_init() +void inotify_dnsmasq_init(int errfd) { struct resolvc *res; inotify_buffer = safe_malloc(INOTIFY_SZ); daemon->inotifyfd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC); if (daemon->inotifyfd == -1) - die(_("failed to create inotify: %s"), NULL, EC_MISC); - + { + send_event(errfd, EVENT_INOTFY_ERR, errno, NULL); + _exit(0); + } + if (daemon->port == 0 || option_bool(OPT_NO_RESOLV)) return; @@ -105,10 +111,13 @@ void inotify_dnsmasq_init() strcpy(path, res->name); /* Follow symlinks until we reach a non-symlink, or a non-existent file. */ - while ((new_path = my_readlink(path))) + while ((new_path = my_readlink(errfd, path))) { if (links-- == 0) - die(_("too many symlinks following %s"), res->name, EC_MISC); + { + send_event(errfd, EVENT_TMSL_ERR, 0, res->name); + _exit(0); + } free(path); path = new_path; } @@ -124,12 +133,18 @@ void inotify_dnsmasq_init() *d = '/'; if (res->wd == -1 && errno == ENOENT) - die(_("directory %s for resolv-file is missing, cannot poll"), res->name, EC_MISC); + { + send_event(errfd, EVENT_RESOLV_ERR, 0, res->name); + _exit(0); + } } if (res->wd == -1) - die(_("failed to create inotify for %s: %s"), res->name, EC_MISC); - + { + send_event(errfd, EVENT_IFILE_ERR, errno, res->name); + _exit(0); + } + } }