hurd: Fix O_NOFOLLOW
authorSamuel Thibault <samuel.thibault@ens-lyon.org>
Sun, 18 Mar 2018 18:39:29 +0000 (19:39 +0100)
committerSamuel Thibault <samuel.thibault@ens-lyon.org>
Sun, 18 Mar 2018 18:42:17 +0000 (19:42 +0100)
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.

ChangeLog
hurd/lookup-retry.c

index af84374..82ddda5 100644 (file)
--- 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>
 
index 319e9c0..12b5c30 100644 (file)
@@ -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;
+                           }
                        }
                    }
                }