autofs-5.1.9 - fix table_lookup_ino() fd reference

From: Ian Kent <raven@themaw.net>

In table_lookup_ino() checking if the passed in paramter fd is valid is
done incorrectly so fix it.

While we are at, since the fd is an essential result for the most common
(probably the only) use case, fail early if it's NULL. And remove the fd
conditional block because there can be only one matching (device, inode)
entry.

Fixes: 30c05ccb68b4 ("autofs-5.1.9 - add function table_lookup_ino()")
Reported-by: Jeff Moyer jmoyer@redhat.com>
Signed-off-by: Ian Kent <raven@themaw.net>
---
 CHANGELOG    |    1 +
 lib/mounts.c |   45 ++++++++++++++++++++++++++-------------------
 2 files changed, 27 insertions(+), 19 deletions(-)

diff --git a/CHANGELOG b/CHANGELOG
index 29db19184..d6d594e9e 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -88,6 +88,7 @@
 - fix some fields not copied in dup_defaults_entry().
 - do_reconnect() expiry check of dclist BEFORE lookup using it.
 - fix mailing list subscription address.
+- fix table_lookup_ino() fd reference.
 
 02/11/2023 autofs-5.1.9
 - fix kernel mount status notification.
diff --git a/lib/mounts.c b/lib/mounts.c
index 6dc7c74b2..0e2152df4 100644
--- a/lib/mounts.c
+++ b/lib/mounts.c
@@ -2389,6 +2389,14 @@ char *table_lookup_ino(struct autofs_point *ap,
 	FILE *tab;
 	int ret = 0;
 
+	/* fd is used to pass back an open fd and path if an entry is
+	 * found. So it needs to be present and valid.
+	 */
+	if (!fd) {
+		errno = EINVAL;
+		return NULL;
+	}
+
 	ops = get_ioctl_ops();
 	if (!ops) {
 		errno = EINVAL;
@@ -2403,6 +2411,7 @@ char *table_lookup_ino(struct autofs_point *ap,
 
 	while ((mnt = local_getmntent_r(tab, &mnt_wrk, tmp, PATH_MAX * 3))) {
 		unsigned int type;
+		struct stat st;
 		int ioctlfd;
 		dev_t devid;
 
@@ -2426,29 +2435,27 @@ char *table_lookup_ino(struct autofs_point *ap,
 		/* errno will be set on fail */
 		if (ioctlfd == -1)
 			break;
-		if (fd > 0) {
-			struct stat st;
-
-			if (fstat(ioctlfd, &st) == -1) {
-				ops->close(ap->logopt, ioctlfd);
-				break;
-			}
-
-			if (strlen(mnt->mnt_dir) >= len) {
-				ops->close(ap->logopt, ioctlfd);
-				errno = ENAMETOOLONG;
-				break;
-			}
+		/* Shouldn't happen as the open succeeded */
+		if (fstat(ioctlfd, &st) == -1) {
+			ops->close(ap->logopt, ioctlfd);
+			break;
+		}
 
-			if (st.st_dev == dev && st.st_ino == ino) {
-				strcpy(buf, mnt->mnt_dir);
-				path = buf;
-				*fd = ioctlfd;
-				break;
-			}
+		if (strlen(mnt->mnt_dir) >= len) {
 			ops->close(ap->logopt, ioctlfd);
+			errno = ENAMETOOLONG;
 			break;
 		}
+
+		if (st.st_dev == dev && st.st_ino == ino) {
+			strcpy(buf, mnt->mnt_dir);
+			path = buf;
+			*fd = ioctlfd;
+			break;
+		}
+
+		ops->close(ap->logopt, ioctlfd);
+		continue;
 	}
 	fclose(tab);
 
