From 9fe64023e32ab9e3fbbfeefc2168a49b748a1846 Mon Sep 17 00:00:00 2001 From: Samuel Cabrero 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 Reviewed-by: Sumit Bose (cherry picked from commit d57c67e4efc64a16b874b46eb9670fdc9c73a39f) Reviewed-by: Pavel Březina --- 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