about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog2
-rw-r--r--hurd/lookup-retry.c36
2 files changed, 22 insertions, 16 deletions
diff --git a/ChangeLog b/ChangeLog
index af84374b68..82ddda54ba 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -62,6 +62,8 @@
 2018-03-18  Samuel Thibault  <samuel.thibault@ens-lyon.org>
 
 	* sysdeps/mach/hurd/cthreads.c: Include <cthreads.h>.
+	* hurd/lookup-retry.c (__hurd_file_name_lookup_retry): Return ELOOP
+	when opening a symlink with O_NOFOLLOW.
 
 2018-03-17  Samuel Thibault  <samuel.thibault@ens-lyon.org>
 
diff --git a/hurd/lookup-retry.c b/hurd/lookup-retry.c
index 319e9c0a4c..12b5c30962 100644
--- a/hurd/lookup-retry.c
+++ b/hurd/lookup-retry.c
@@ -127,7 +127,7 @@ __hurd_file_name_lookup_retry (error_t (*use_init_port)
 		{
 		  /* In Linux, O_NOFOLLOW means to reject symlinks.  If we
 		     did an O_NOLINK lookup above and io_stat here to check
-		     for S_IFLNK, a translator like firmlink could easily
+		     for S_IFLNK only, a translator like firmlink could easily
 		     spoof this check by not showing S_IFLNK, but in fact
 		     redirecting the lookup to some other name
 		     (i.e. opening the very same holes a symlink would).
@@ -145,23 +145,27 @@ __hurd_file_name_lookup_retry (error_t (*use_init_port)
 		     one exception to our general translator-based rule.  */
 		  struct stat64 st;
 		  err = __io_stat (*result, &st);
-		  if (!err
-		      && (st.st_mode & (S_IPTRANS|S_IATRANS)))
+		  if (!err)
 		    {
-		      if (st.st_uid != 0)
-			err = ENOENT;
-		      else if (st.st_mode & S_IPTRANS)
+		      if (S_ISLNK (st.st_mode))
+			err = ELOOP;
+		      else if (st.st_mode & (S_IPTRANS|S_IATRANS))
 			{
-			  char buf[1024];
-			  char *trans = buf;
-			  size_t translen = sizeof buf;
-			  err = __file_get_translator (*result,
-						       &trans, &translen);
-			  if (!err
-			      && translen > sizeof _HURD_SYMLINK
-			      && !memcmp (trans,
-					  _HURD_SYMLINK, sizeof _HURD_SYMLINK))
-			    err = ENOENT;
+			  if (st.st_uid != 0)
+			    err = ELOOP;
+			  else if (st.st_mode & S_IPTRANS)
+			    {
+			      char buf[1024];
+			      char *trans = buf;
+			      size_t translen = sizeof buf;
+			      err = __file_get_translator (*result,
+							   &trans, &translen);
+			      if (!err
+				  && translen > sizeof _HURD_SYMLINK
+				  && !memcmp (trans,
+					      _HURD_SYMLINK, sizeof _HURD_SYMLINK))
+				err = ELOOP;
+			    }
 			}
 		    }
 		}