mirror of
https://github.com/pi-hole/dnsmasq.git
synced 2025-12-19 18:28:25 +00:00
Fix inotify code to handle dangling symlinks better.
This commit is contained in:
@@ -2,6 +2,9 @@ version 2.74
|
|||||||
Fix reversion in 2.73 where --conf-file would attempt to
|
Fix reversion in 2.73 where --conf-file would attempt to
|
||||||
read the default file, rather than no file.
|
read the default file, rather than no file.
|
||||||
|
|
||||||
|
Fix inotify code to handle dangling symlinks better and
|
||||||
|
not SEGV in some circumstances.
|
||||||
|
|
||||||
|
|
||||||
version 2.73
|
version 2.73
|
||||||
Fix crash at startup when an empty suffix is supplied to
|
Fix crash at startup when an empty suffix is supplied to
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
#ifdef HAVE_INOTIFY
|
#ifdef HAVE_INOTIFY
|
||||||
|
|
||||||
#include <sys/inotify.h>
|
#include <sys/inotify.h>
|
||||||
|
#include <sys/param.h> /* For MAXSYMLINKS */
|
||||||
|
|
||||||
/* the strategy is to set a inotify on the directories containing
|
/* the strategy is to set a inotify on the directories containing
|
||||||
resolv files, for any files in the directory which are close-write
|
resolv files, for any files in the directory which are close-write
|
||||||
@@ -35,10 +36,56 @@
|
|||||||
static char *inotify_buffer;
|
static char *inotify_buffer;
|
||||||
#define INOTIFY_SZ (sizeof(struct inotify_event) + NAME_MAX + 1)
|
#define INOTIFY_SZ (sizeof(struct inotify_event) + NAME_MAX + 1)
|
||||||
|
|
||||||
|
/* If path is a symbolic link, return the path it
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
ssize_t rc;
|
||||||
|
size_t size = 64;
|
||||||
|
char *buf;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
buf = safe_malloc(size);
|
||||||
|
rc = readlink(path, buf, size);
|
||||||
|
|
||||||
|
if (rc == -1)
|
||||||
|
{
|
||||||
|
/* Not link or doesn't exist. */
|
||||||
|
if (errno == EINVAL || errno == ENOENT)
|
||||||
|
return NULL;
|
||||||
|
else
|
||||||
|
die(_("cannot access path %s: %s"), path, EC_MISC);
|
||||||
|
}
|
||||||
|
else if (rc < size-1)
|
||||||
|
{
|
||||||
|
char *d;
|
||||||
|
|
||||||
|
buf[rc] = 0;
|
||||||
|
if (buf[0] != '/' && ((d = strrchr(path, '/'))))
|
||||||
|
{
|
||||||
|
/* Add path to relative link */
|
||||||
|
char *new_buf = safe_malloc((d - path) + strlen(buf) + 2);
|
||||||
|
*(d+1) = 0;
|
||||||
|
strcpy(new_buf, path);
|
||||||
|
strcat(new_buf, buf);
|
||||||
|
free(buf);
|
||||||
|
buf = new_buf;
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Buffer too small, increase and retry */
|
||||||
|
size += 64;
|
||||||
|
free(buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void inotify_dnsmasq_init()
|
void inotify_dnsmasq_init()
|
||||||
{
|
{
|
||||||
struct resolvc *res;
|
struct resolvc *res;
|
||||||
|
|
||||||
inotify_buffer = safe_malloc(INOTIFY_SZ);
|
inotify_buffer = safe_malloc(INOTIFY_SZ);
|
||||||
daemon->inotifyfd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
|
daemon->inotifyfd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
|
||||||
|
|
||||||
@@ -47,19 +94,22 @@ void inotify_dnsmasq_init()
|
|||||||
|
|
||||||
for (res = daemon->resolv_files; res; res = res->next)
|
for (res = daemon->resolv_files; res; res = res->next)
|
||||||
{
|
{
|
||||||
char *d = NULL, *path;
|
char *d, *new_path, *path = safe_malloc(strlen(res->name) + 1);
|
||||||
|
int links = MAXSYMLINKS;
|
||||||
|
|
||||||
if (!(path = realpath(res->name, NULL)))
|
strcpy(path, res->name);
|
||||||
|
|
||||||
|
/* Follow symlinks until we reach a non-symlink, or a non-existant file. */
|
||||||
|
while ((new_path = my_readlink(path)))
|
||||||
{
|
{
|
||||||
/* realpath will fail if the file doesn't exist, but
|
if (links-- == 0)
|
||||||
dnsmasq copes with missing files, so fall back
|
die(_("too many symlinks following %s"), res->name, EC_MISC);
|
||||||
and assume that symlinks are not in use in that case. */
|
free(path);
|
||||||
if (errno == ENOENT)
|
path = new_path;
|
||||||
path = res->name;
|
|
||||||
else
|
|
||||||
die(_("cannot cannonicalise resolv-file %s: %s"), res->name, EC_MISC);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
res->wd = -1;
|
||||||
|
|
||||||
if ((d = strrchr(path, '/')))
|
if ((d = strrchr(path, '/')))
|
||||||
{
|
{
|
||||||
*d = 0; /* make path just directory */
|
*d = 0; /* make path just directory */
|
||||||
@@ -70,10 +120,11 @@ void inotify_dnsmasq_init()
|
|||||||
|
|
||||||
if (res->wd == -1 && errno == ENOENT)
|
if (res->wd == -1 && errno == ENOENT)
|
||||||
die(_("directory %s for resolv-file is missing, cannot poll"), res->name, EC_MISC);
|
die(_("directory %s for resolv-file is missing, cannot poll"), res->name, EC_MISC);
|
||||||
|
|
||||||
if (res->wd == -1)
|
|
||||||
die(_("failed to create inotify for %s: %s"), res->name, EC_MISC);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (res->wd == -1)
|
||||||
|
die(_("failed to create inotify for %s: %s"), res->name, EC_MISC);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user