Florian Festi 6ae193
From 89ce4e7ca592f5abafc3f25aeaa07d36a7b43a61 Mon Sep 17 00:00:00 2001
Florian Festi 6ae193
From: Panu Matilainen <pmatilai@redhat.com>
Florian Festi 6ae193
Date: Tue, 14 Nov 2023 11:37:48 +0200
Florian Festi 6ae193
Subject: [PATCH] Fix wrong return code on O_DIRECTORY open of invalid symlink
Florian Festi 6ae193
Florian Festi 6ae193
The dir argument to fsmOpenpath() is supposed to be a rough O_DIRECTORY
Florian Festi 6ae193
equivalent, and if the path is actually a misowned symlink it should
Florian Festi 6ae193
return ENOTDIR instead of ELOOP. Makes the resulting error messages
Florian Festi 6ae193
at least a little more comprehensible.
Florian Festi 6ae193
---
Florian Festi 6ae193
 lib/fsm.c | 5 +++--
Florian Festi 6ae193
 1 file changed, 3 insertions(+), 2 deletions(-)
Florian Festi 6ae193
Florian Festi 6ae193
diff --git a/lib/fsm.c b/lib/fsm.c
Florian Festi 6ae193
index 51f439ef3..091e90554 100644
Florian Festi 6ae193
--- a/lib/fsm.c
Florian Festi 6ae193
+++ b/lib/fsm.c
Florian Festi 6ae193
@@ -304,6 +304,7 @@ static int fsmOpenat(int dirfd, const char *path, int flags, int dir)
Florian Festi 6ae193
     struct stat lsb, sb;
Florian Festi 6ae193
     int sflags = flags | O_NOFOLLOW;
Florian Festi 6ae193
     int fd = openat(dirfd, path, sflags);
Florian Festi 6ae193
+    int ffd = fd;
Florian Festi 6ae193
 
Florian Festi 6ae193
     /*
Florian Festi 6ae193
      * Only ever follow symlinks by root or target owner. Since we can't
Florian Festi 6ae193
@@ -312,7 +313,7 @@ static int fsmOpenat(int dirfd, const char *path, int flags, int dir)
Florian Festi 6ae193
      * it could've only been the link owner or root.
Florian Festi 6ae193
      */
Florian Festi 6ae193
     if (fd < 0 && errno == ELOOP && flags != sflags) {
Florian Festi 6ae193
-	int ffd = openat(dirfd, path, flags);
Florian Festi 6ae193
+	ffd = openat(dirfd, path, flags);
Florian Festi 6ae193
 	if (ffd >= 0) {
Florian Festi 6ae193
 	    if (fstatat(dirfd, path, &lsb, AT_SYMLINK_NOFOLLOW) == 0) {
Florian Festi 6ae193
 		if (fstat(ffd, &sb) == 0) {
Florian Festi 6ae193
@@ -327,7 +328,7 @@ static int fsmOpenat(int dirfd, const char *path, int flags, int dir)
Florian Festi 6ae193
     }
Florian Festi 6ae193
 
Florian Festi 6ae193
     /* O_DIRECTORY equivalent */
Florian Festi 6ae193
-    if (dir && fd >= 0 && fstat(fd, &sb) == 0 && !S_ISDIR(sb.st_mode)) {
Florian Festi 6ae193
+    if (dir && ((fd != ffd) || (fd >= 0 && fstat(fd, &sb) == 0 && !S_ISDIR(sb.st_mode)))) {
Florian Festi 6ae193
 	errno = ENOTDIR;
Florian Festi 6ae193
 	fsmClose(&fd;;
Florian Festi 6ae193
     }
Florian Festi 6ae193
-- 
Florian Festi 6ae193
2.43.0
Florian Festi 6ae193