From 9fe64023e32ab9e3fbbfeefc2168a49b748a1846 Mon Sep 17 00:00:00 2001
From: Samuel Cabrero <scabrero@suse.de>
Date: Fri, 19 Jul 2019 12:24:56 +0200
Subject: [PATCH 21/21] MONITOR: Resolve symlinks setting the inotify watchers
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
If resolv.conf is a symlink and sssd starts before getting an address
from dhcp the data provider will remain forever offline, as the watched
parent directory is the directory containing the symlink.
Signed-off-by: Samuel Cabrero <scabrero@suse.de>
Reviewed-by: Sumit Bose <sbose@redhat.com>
(cherry picked from commit d57c67e4efc64a16b874b46eb9670fdc9c73a39f)
Reviewed-by: Pavel Březina <pbrezina@redhat.com>
---
src/util/inotify.c | 55 +++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 52 insertions(+), 3 deletions(-)
diff --git a/src/util/inotify.c b/src/util/inotify.c
index 2e2dc1a6e..ffc15ad4d 100644
--- a/src/util/inotify.c
+++ b/src/util/inotify.c
@@ -381,13 +381,62 @@ static int watch_ctx_destructor(void *memptr)
return 0;
}
+static errno_t resolve_filename(struct snotify_ctx *snctx,
+ const char *filename,
+ char *resolved,
+ size_t resolved_size)
+{
+ /* NOTE: The code below relies in the GNU extensions for realpath,
+ * which will store in 'resolved' the prefix of 'filename' that does
+ * not exists if realpath call fails and errno is set to ENOENT */
+ if (realpath(filename, resolved) == NULL) {
+ char fcopy[PATH_MAX + 1];
+ char *p;
+ struct stat st;
+
+ if (errno != ENOENT) {
+ return errno;
+ }
+
+ /* Check if the unique missing component is the basename. The
+ * dirname must exist to be notified watching the parent dir. */
+ strncpy(fcopy, filename, sizeof(fcopy) - 1);
+ fcopy[PATH_MAX] = '\0';
+
+ p = dirname(fcopy);
+ if (p == NULL) {
+ return EIO;
+ }
+
+ if (stat(p, &st) == -1) {
+ return errno;
+ }
+
+ /* The basedir exist, check the caller requested to watch it.
+ * Otherwise return error as never will be notified. */
+
+ if ((snctx->snotify_flags & SNOTIFY_WATCH_DIR) == 0) {
+ return ENOENT;
+ }
+ }
+
+ return EOK;
+}
+
static errno_t copy_filenames(struct snotify_ctx *snctx,
const char *filename)
{
char *p;
+ char resolved[PATH_MAX + 1];
char fcopy[PATH_MAX + 1];
+ errno_t ret;
+
+ ret = resolve_filename(snctx, filename, resolved, sizeof(resolved));
+ if (ret != EOK) {
+ return ret;
+ }
- strncpy(fcopy, filename, sizeof(fcopy) - 1);
+ strncpy(fcopy, resolved, sizeof(fcopy) - 1);
fcopy[PATH_MAX] = '\0';
p = dirname(fcopy);
@@ -400,7 +449,7 @@ static errno_t copy_filenames(struct snotify_ctx *snctx,
return ENOMEM;
}
- strncpy(fcopy, filename, sizeof(fcopy) - 1);
+ strncpy(fcopy, resolved, sizeof(fcopy) - 1);
fcopy[PATH_MAX] = '\0';
p = basename(fcopy);
@@ -413,7 +462,7 @@ static errno_t copy_filenames(struct snotify_ctx *snctx,
return ENOMEM;
}
- snctx->filename = talloc_strdup(snctx, filename);
+ snctx->filename = talloc_strdup(snctx, resolved);
if (snctx->filename == NULL) {
return ENOMEM;
}
--
2.21.1