about summary refs log tree commit diff
path: root/hurd/lookup-retry.c
diff options
context:
space:
mode:
authorSamuel Thibault <samuel.thibault@ens-lyon.org>2018-03-18 19:39:29 +0100
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2018-03-18 19:42:17 +0100
commit489999cc9cb1fab40c308b2e5ede3207e0f7a5be (patch)
tree1b8f11c303fe6b7dbcb1de6241054b2b65563e4e /hurd/lookup-retry.c
parent55325314bf29d6f2430a2ce83368da8281b12f85 (diff)
downloadglibc-489999cc9cb1fab40c308b2e5ede3207e0f7a5be.tar.gz
glibc-489999cc9cb1fab40c308b2e5ede3207e0f7a5be.tar.xz
glibc-489999cc9cb1fab40c308b2e5ede3207e0f7a5be.zip
hurd: Fix O_NOFOLLOW
The error code documented by POSIX for opening a symlink with O_NOFOLLOW
is ELOOP.

Also, if the translator does not expose symlink as a symlink translator but
as a S_IFLNK file, O_NOFOLLOW needs to return ELOOP too.

	* hurd/lookup-retry.c (__hurd_file_name_lookup_retry): Return ELOOP
	when opening a symlink with O_NOFOLLOW.
Diffstat (limited to 'hurd/lookup-retry.c')
-rw-r--r--hurd/lookup-retry.c36
1 files changed, 20 insertions, 16 deletions
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;
+			    }
 			}
 		    }
 		}